Перевірте, чи струна - це перетасування близнюків


10

Пояснення

Два рядки можна перетасувати, перекресливши їхні букви, щоб утворити новий рядок, подібно до того, що дві купи карт можна перетасувати, щоб утворити одну купу.

Наприклад, рядок HELLOі WORLDможе бути перемішуються з утворенням HWEOLRLLOD, або HEWORLLLDO, або , можливо , просто HELLOWORLD.

Це не перетасування, якщо не збережено початковий порядок букв. Наприклад, Dв WORLDбудь-коли може постати перед Rпісля того , як перемішуються. Це означає , що EHLLOWRDLO, наприклад, не є перетасування HELLOі WORLD, навіть якщо він містить всі оригінальні листи.

Рядок - це перетасування близнюків, якщо його можна утворити перетасуванням двох однакових струн. Наприклад, ABACBDECDEце перетасування близнюків, оскільки воно може утворюватися шляхом переміщення ABCDEта ABCDE. DBEACBCADEне є перетасуванням близнюків, оскільки його неможливо утворити шляхом переміщення двох однакових струн.

Деталі програми

З огляду на рядок введення, виведіть, 0якщо це не переміщення близнюків, і виведіть одну з рядків близнюків, якщо це перетасування близнюків.

Ви можете припустити, що вхідний рядок має довжину включно між чотирма та двадцятьма символами і повністю складається з великих букв. Він повинен мати можливість працювати протягом розумної кількості часу, скажімо, за 10 хвилин.

Це кодовий гольф, тому найкоротше рішення виграє.

Приклад вводу / виводу

> ABACBDECDE
ABCDE

> DBEACBCADE
0

> FFFFFF
FFF

> FFGGG
0

> ABBA
0

> AABB
AB

> AABAAB
AAB

У мене є приклад реалізації (без гольфу) .


Приклад рядка FGG порушує твердження that the input string has a length inclusively between four and twenty characters, і не кажіть мені "ніколи не довіряйте вводу користувача!", "Ніколи не довіряйте специфікаціям!"
користувач невідомий

@userunknown Це так бентежно! Я відредагував це, FFGGGщоб зробити його послідовним.
Пітер Олсон

1
Хтось із цікавості може хтось придумати рішення із субекспоненціальною складністю у гіршому випадку або довести, що його немає?
Ільмарі Каронен

Відповіді:


4

Хаскелл, 114

main=getLine>>=putStrLn.f.p;f x=head$[a|(a,b)<-x,a==b]++["0"]
p[]=[([],[])];p(x:y)=do(a,b)<-p y;[(x:a,b),(a,x:b)]

Безголівки:

main :: IO ()
main = getLine >>= putStrLn . findMatch . partitions

-- | Find the first partition where the two subsequences are
-- equal. If none are, return "0".
findMatch :: [(String, String)] -> String
findMatch ps = head $ [a | (a,b) <- ps, a == b] ++ ["0"]

-- | Return all possible partitions of the input into two
-- subsequences. Preserves the order of each subsequence.
--
-- Example:
-- partitions "AB" == [("AB",""),("B","A"),("A","B"),("","AB")]
partitions :: [a] -> [([a], [a])]
partitions []     = [([], [])]
partitions (x:xs) = do (a, b) <- partitions xs
                       [(x:a, b), (a, x:b)]

Пояснення:

Більшість робіт виконується у partitionsфункції. Він працює шляхом рекурсивного генерування всіх розділів (a, b)хвоста списку, а потім за допомогою монади списку, щоб додати початковий елемент xдо кожного з них та зібрати всі результати.

findMatchпрацює, фільтруючи цей список, так що залишаються лише розділи, у яких підлеглі рівні. Потім він повертає першу послідовність у першому розділі. Якщо жодного не залишиться, список порожній, тому "0"доданий в кінці повертається замість нього.

main просто читає вхід, подає його через ці дві функції і друкує його.


Тим із нас, хто не може прочитати Haskell, ви дасте пояснення?
Mr.Wizard

1
@ Mr.Wizard: Див. Редагування.
хаммар

Я думаю, що я придумав щось досить схоже, хоч і не таке коротке, але я кинув у дурний вид, який зробив це повним провалом. Ви не заперечуєте, якщо я реалізую цей алгоритм в Mathematica?
Mr.Wizard

4

R, 113 символів

l=length(x<-charToRaw(scan(,'')));max(apply(combn(l,l/2),2,function(i)if(all(x[i]==x[-i]))rawToChar(x[i])else 0))

Ungolfed (а замість цього функція, яка приймає рядок):

untwin <- function(x) {
  x <- charToRaw(x)
  indMtx <- combn(length(x),length(x)/2)
  res <- apply(indMtx, 2, function(i) {
    if (all(x[i]==x[-i]))
      rawToChar(x[i])
    else
      0
  })
  max(res)
}

untwin("ABACBDECDE") # "ABCDE"
untwin("DBEACBCADE") # 0

Рішення спирається на combnфункцію, яка генерує всі комбінації індексів у вигляді стовпців у матриці. applyпотім застосовує функцію до кожного стовпця (розмірності 2) в матриці і повертає вектор рядків або нулів. maxпотім знайдіть найбільшу струну (яка козирє 0).

Класною особливістю в R є можливість вибору підмножини вектора, заданого вектором індексів, а потім вибору доповнення цього підмножини шляхом відхилення індексів:x[i] == x[-i]


Деякі додаткові покращення та зменшення кількості знаків
Томмі

3

Математика, 87

Це безпосередньо базується на публікації Хаммара, але, сподіваємось, це досить виразно, щоб заслужити публікацію.

<<Combinatorica`

f=Catch[Cases[Characters@#~KSetPartitions~2,{x_,x_}:>Throw[""<>x]];0]&

Тест:

f /@ {"ABACBDECDE", "DBEACBCADE", "FFFFFF", "FGG", "ABBA", "AABB", "AABAAB"}
{"ABCDE", 0, "FFF", 0, 0, "AB", "AAB"}

1

D

string c(string in,string a=[],string b=[]){
    if(in.length==0)return a==b?a;"0";
    auto r=c(in[1..$],a~in[0],b);
    return r=="0"?c(in[1..$],a,b~in[0]):r;
}
void main(){writeln(c(readline));}

використовуючи глибину першого рекурсивного пошуку

Я можу зробити це швидше int i = min(a.length,b.length);if(a[0..i]!=b[0..i])return "0";застережним пунктом


У IDEONE мені не вдалося спробувати запустити програму void main(){writeln(c("ABCADABCAD"));}- просто інша версія D, моя вина, щось інше? Що про "ABCABCA"?
користувач невідомий

вам потрібно імпортувати std.stdio; для IO
храповик урод

1

Рубі, 89 символів

s=->a,x,y{a=="\n"?x==y ?x:?0:[s[b=a[1..-1],x+c=a[0],y],s[b,x,y+c]].max}
$><<s[gets,'','']

Цей код реалізує звичайний алгоритм рекурсивного пошуку. Вхід повинен бути вказаний на STDIN.


1

Perl, 68 символів

/^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0

Рядок введення, що передбачається у $_змінній, вихід - значення виразу. Останні рядки для введення даних ігноруються. Ви можете запустити це з командного рядка так:

perl -lne 'print /^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0'

Цей код використовує механізм regexp Perl (а саме його функцію виконання вбудованого коду ) для зворотного відстеження. В основному, він відповідає вхідному рядку проти регулярного виразу ^((.+))+$, відстежуючи непарні $xі парні підмножини в і $,, і відхиляючи відповідність в кінці, якщо два не рівні.


Чи має це правильний результат AABAAB?
Пітер Олсон

Так. (Насправді AABAABце простого випадку для цього рішення, оскільки зовнішній групі потрібно збігатися лише двічі. Мені знадобилося набагато більше часу, щоб змусити його правильно впоратися AABB.)
Ільмарі Каронен

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.