Добові струни


28

Рядок є дозволеним, якщо його можна розділити на підрядки, кожен з яких є рядком, повтореним двічі поспіль. Наприклад, aabaaababbbabaдобовий як:

aaba aaba
b b
ba ba

Враховуючи не порожній рядок a's and b' s, виведіть значення Truthy, якщо воно є добовим, і значення Falsey, якщо це не так.

Добові:

aa
abaaba
bbababbb
aabaaababbbaba
babababa
bbbbbbbbbbbb
aaababbabbabbbababbaabaabaababaaba
aaaabaab

Не дозволено:

a
ba
baab
abaabaaba
bbbbbbbbbbbbbbb
baababbabaaaab
aaaaabbaaaaa

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


Табло:


Чи можемо ми використовувати що-небудь, крім ab?
Ерік Аутгольфер

Якщо bbababbb небажаний, чому baab та aaaaabbaaaaa не є?
rnso

@rnso З мого розуміння, bbababbb може бути розбитий у вигляді 3-х пар: bb, abab і bb, які з'єднуються в такому порядку, щоб утворити початковий рядок, тоді як інші два не можуть.
Сонячний Pun

Запитанням "кожна з яких (підрядка) є рядком, повтореним двічі КОНСЕКЦІЙНО", і це не задоволено bbababbb. В іншому випадку baab також може бути розділений на baab, а aaaaabbaaaaa на aaaaa bb aaaaa.
rnso

@rnso Не впевнений, що ти там маєш на увазі. Послідовно маю на увазі, що два повторення знаходяться поруч. У "baa b" два b розділені знаками "a", так що це не працює.
xnor

Відповіді:


11

Python 2, 68 63 байт

f=lambda s,n=1:s==2*s[:n]or''<s[n:]>-f(s,n+1)<f(s[n:])*f(s[:n])

Повертає істинне чи помилкове . Перевірте це на Ideone .


4
Це дійсно чиста рекурсія, використовуючи індекс як для центру подвійного, так і для центру до розділу. Смішно, що правдивість перевіряється як менша, ніж щось. Я бачу деякі покращення ...
xnor

8

Сітківка , 11 байт

^((.+)\2)+$

Спробуйте всі тестові випадки. Перші два байти роблять його багаторядковим.

Досить буквальне тлумачення правил, очевидно, використовує регулярний вираз, як і всі програми Retina.


2
Dangit, я чекав 3 тижні, щоб опублікувати це ...
ETHproductions

2
Мартін теж чекав .
xnor

5
Ого! Я бив його лише за 10 секунд ... Ну, я впевнений, що коли напишу відповідь "Гексагоні", він пробачить мене!
FryAmTheEggman

5
@FryAmTheEggman Я з нетерпінням чекаю цього. :)
Мартін Ендер

2
Точно так само і з Perl:perl -pE '$_=/^((.+)\2)+$/'
Dada

8

Желе , 10 байт

ẆŒPẋ€€2F€ċ

Не зовсім ефективно ... Спробуйте в Інтернеті!

Як це працює

ẆŒPẋ€€2F€ċ  Main link. Argument: s (string)

Ẇ           Window, generate the array of all substrings of s.
 ŒP         Powerset; generate all subarrays of substrings of s.
   ẋ€€2     Repeat each substring in each subarray twice.
            For example, ["ab", "a", "b"] becomes ["abab", "aa", "bb"].
       F€   Flatten the subarrays by concatenating their strings.
         ċ  Count how many times s appears in the generated strings.

Це ... здається неефективним. Як довго вхідні дані можуть вирішуватись за розумні часові рамки?
Джон Дворак

1
Це вкрай неефективно ( O (2 ^ n ^ 2) , я думаю). Мені доведеться перевірити місцево. У TIO вичерпано пам'ять для рядків довжиною 6 .
Денніс

8
Рядок довжиною 6 займає 3:20 хвилин на моїй машині і вимагає 6 Гб пам'яті.
Денніс

1
@Dennis Давайте не робити вхід довжиною 100 , тому що все вийде з ладу. Так, навіть TIO.
Ерік Аутгольфер

@EriktheGolfer Це гарна ідея, оскільки вона зайво сповільнить TIO для інших цілей, але не вийде з ладу. Як тільки в системі не вистачає пам'яті, процес просто вбивається OOM.
Денніс

5

Haskell, 72 69 байт (без регулярного вираження)

g(a:b:c)|a==b=g c
g x=x==[]
any(g.words.concat).mapM(\c->[[c],c:" "])

Підхід грубої сили. Спробуйте це на Ideone .

Завдяки BlackCap за -3 байти.

Пояснення

Функція helper gбере список рядків і перевіряє, чи складається він з пар однакових рядків, як ["aa","aa","bba","bba","ab","ab"]. Основна функція (анонім) розбиває рядок усіма можливими способами та перевіряє, що принаймні одне розбиття призводить до списку, який gприймає.

g(a:b:c)                                  g on list with elements a, b and tail c,
        |a==b                              in the case that a==b,
             =g c                          recurses to the tail c.
g x=                                      g on any other list x
    x==[]                                  checks that x is empty.
                                           This includes the case where a is not equal
                                           to b, resulting in False.
any(g.words.concat).mapM(\c->[[c],c:" "]) The main function:
                    mapM(\c->[[c],c:" "])  Replace each letter c with either "c" or "c "
                                           in all possible ways, return list of results.
any(              ).                       Check that at least one result satisfies this:
            concat                          Concatenate the 1- or 2-letter strings,
      words.                                split again at each space,
    g.                                      apply g.

Ви можете замінити or.mapнаany
BlackCap

@BlackCap Звичайно, дякую! Я спочатку мав any g.map(words.concat)і думав: "Ей, я можу anyвзяти участь у гольф or" ...
Згарб

5

Python 2, 60 байт

f=lambda s,t='':''<s>f(s[1:],t+s[0])|f(t and s)*f(t)>-(s==t)

Я сподіваюся, що це правильно. Він працює досить повільно і andне виглядає оптимально.


1
Я спробував використовувати рядки, але мені не вдалося дістатись до моєї оцінки на основі індексу. Це один розумний у andвас там.
Денніс

Вітаю! Повтор на розділі був хитрістю, яку я мав на увазі.
xnor

4

Желе , 12 байт

ŒṖµœs€2ZEµ€S

На два байти довше моєї відповіді , але цей підхід є набагато ефективнішим і обробляє всі, крім одного з тестових випадків.

Спробуйте в Інтернеті!

Як це працює

ŒṖµœs€2ZEµ€S  Main link. Argument: s (string)

ŒṖ            Generate all partitions of s.
  µ      µ€   Map the monadic chain between the µ's over the partitions.
   œs€2         Split each string in the partition into two chunks of equal length.
       Z        Zip/transpose, collecting the first halves in one array and the
                second halves in another.
        E       Test the arrays of halves for equality.
           S  Return the sum of the results, counting the number of different
              ways s can be paired.

3

Pyth - No Regex - 13 12 байт

Перевіряє, чи будь-який з розділів складається з усіх рядків, які дорівнюють один одному, коли вони розбиваються на два.

sm.AqMcL2d./

Тестовий сюїт .


3

Брахілог , 14 байт (без регулярного вираження)

lye~l:1j@2zcc?

Спробуйте в Інтернеті!

Це занадто повільно для деяких тестових випадків

Пояснення

ly                  The list [0, …, length(Input)]
  e~l               A list whose length is an element of the previous list
     :1j            Append itself to this list
        @2zc        Split in half, zip and concatenate so that the list contains pairs of
                      consecutive identical elements
            c?      The concatenation of that list must result in the Input

3

JavaScript (ES6), відсутність регулярного вираження, 75 74 байт

f=s=>!s|[...s].some((_,i)=>i&&s[e='slice'](0,i)==s[e](i,i+=i)&&f(s[e](i)))

Повертається 1за можливим інакше 0. Редагувати: Збережено 1 байт завдяки @ edc65.


Приємно! Один і той самий рахунок, substrне змінюючи i. Але при sliceповторному 3-х разів ви можете зберегти 1 байт з псевдонімом
edc65

@ edc65 Як отримати однаковий підрахунок без зміни i? Я усвідомлюю, що s.substr(i,i+i)повертає те саме, що s.slice(i,i+=i)я, але потім використовую змінене значення iпізніше ...
Ніл

це на s.substr(i,i)2 байти менше, то на s.slice(i+i)2 байти більше
edc65

@ edc65 О, звичайно, так, мені потрібно більше кави ...
Ніл

3

Пітон, 58 байт

f=lambda s,p='':s>''and(f(p)>-(s==p)<f(s))|f(s[1:],p+s[0])

Це засновано на рекурсивному методі Денніса . Буловий фокус заперечення також взято звідти.

Нова ідея полягає в повторному переході на розділи (p,s)оригінального рядка, починаючи з ('',s)та повторного переміщення першого символу, sщоб бути останнім символом p. Це дозволяє безпосередньо посилатись на деталі без нарізки рядків. Але, оскільки розділ починається з pпорожнього, ми повинні бути обережними, щоб уникнути нескінченних циклів f(s)виклику f(s).


2

JavaScript (ES6), 24 байти

x=>/^((.+)\2)+$/.test(x)

Напевно, не коротше цього.


Чи не повинно бути це \2?
Ніл

@Neil З якихось причин я подумав, що це працює \1, але aabповертається true... дякую за виправлення.
ETHproductions



1

Ракетка 230 байт

(let((sl string-length)(ss substring))(if(odd?(sl s))(printf ".~n")(begin(let p((s s))(if(equal? s "")(printf "!")
(for((i(range 1(add1(/(sl s)2)))))(when(equal?(ss s 0 i)(ss s i(* 2 i)))(p(ss s(* 2 i)(sl s)))))))(printf ".~n"))))

Друкує "!" для кожного способу, в якому рядок є добовим. Друкує "." в кінці.

Безголівки:

(define (f s)
  (let ((sl string-length)                              ; create short names of built-in fns
        (ss substring))
    (if (odd? (sl s))  (printf ".~n")                   ; odd length strings cannot be pairable; end here.
        (begin
          (let loop ((s s))                             ; start testing here
            (if (equal? s "") (printf "!")              ; if no remaining string, it must be pairable
                (for ((i (range 1 (add1 (/(sl s)2)))))  ; ch lengths varying from 1 to half of string length
                  (when (equal? (ss s 0 i)              ; ch if substrings are same
                                (ss s i (* 2 i)))
                    (loop (ss s (* 2 i) (sl s) ))))))   ; if yes, loop to check remaining string.
          (printf ".~n")))))                            ; End of testing.

Тестування:

(println "Following should be pairable")
(f "bbaabbaa")            ; should produce 2 '!' since 2 ways are possible.
(f "aa")
(f "abaaba")
(f "bbababbb")
(f "aabaaababbbaba")
(f "babababa")                    ; should be pairable in 2 ways.
(f "bbbbbbbbbbbb")                ; should be pairable in many ways.
(f "aaababbabbabbbababbaabaabaababaaba")
(f "aaaabaab")
(println "Following should be unpairable")
; (f "a")
(f "ba")
(f "baab")
(f "abaabaaba")
(f "bbbbbbbbbbbbbbb")
(f "baababbabaaaab")
(f "aaaaabbaaaaa")

Вихід:

"Following should be pairable"
!!.
!.
!.
!.
!.
!!.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.
!.
!.
"Following should be unpairable"
.
.
.
.
.
.

1

Perl, 16 +2 = 18 байт (з регулярним виразом)

Біжи з -nlпрапорами. -Eє безкоштовним.

say/^((.+)\2)+$/

Виконувати як:

perl -nlE 'say/^((.+)\2)+$/'

Повертає список груп захоплення (truthy), якщо невірно, нульовий рядок, якщо не паверує.

Пояснення

Ці -nlпрапори будуть виконувати код в циклі ( -n), поміщаючи вхід (з задньої новим рядком видалена з -l) в змінну $_кожен раз, а потім оцінити код кожного разу , коли вхід вводиться, поки програма не вручну припинена. -EПрапор дозволяє оцінювати код в командному рядку, і дозволяє sayкоманду.

say/^((.+)\2)+$/

   /^((.+)\2)+$/  #The regex engine
      (.+)\2      #Find any set of at least one character, followed by itself
     (      )+    #Do this at least one time
   /^         $/  #Make sure that this matches the entire string from start to end
say               #Output the result of the regex

Якщо буде знайдено збіг (наприклад, якщо рядок є добовим), то регулярний вираз повертає список груп захоплення, який оцінює форму, яка потім передається sayта виводить. Якщо не знайдено відповідності, то регулярний вираз повертає порожню рядок, який оцінюється у помилковий, який потім передається sayта виводиться.

Зразок:

$ perl -nlE 'say/^((.+)\2)+$/'
aaababbabbabbbababbaabaabaababaaba
baababaababaaba                      #Truthy
baababbabaaaab
                                     #Falsy
bbababbb
bbb                                  #Truthy
aabaaababbbaba
bababa                               #Truthy
abaabaaba
                                     #Falsy

1

GNU Prolog, 49 46 байт

Напевно, працює і в інших варіантах, хоча вони не представляють рядки однаково; Представлення GNU Prolog є корисним для цієї проблеми.

Незрозуміло, чи вважається це використанням регулярного вираження чи ні. Тут не використовується жодна функція, що нагадує регулярні виразки, але вся семантика мови схожа з такою у регулярного вираження.

Нова версія (використовує хитрість рекурсії, яку бачите в деяких інших відповідях):

s(X):-append(A,B,X),(A=B;A\=X,B\=X,s(A),s(B)).

Старіша версія:

s(X):-X=[];append(A,B,X),B\=X,append(C,C,A),s(B).

Це предикат (еквівалент функції Prolog), який називається s, а не повна програма. Використовуйте його так:

| ?- s("aa").
true ?
yes
| ?- s("aaababbabbabbbababbaabaabaababaaba").
true ?
yes
| ?- s("baababbabaaaab").
no
| ?- s("bbbbbbbbbbbbbbb").
no

Цікава особливість старого рішення полягає в тому, що якщо ви запитаєте перекладача, "чи більше рішень?" через використання ;в тій true ?рядку (а не питати «є якесь - яке рішення» з допомогою натискання повернення в командному рядку, як я зробив вище), вона повертає «істини» число раз , дорівнює кількості різних способів рядки може бути виражена у даній формі (наприклад, він повертає "true" двічі s("aaaa")., оскільки це може бути проаналізовано як (a a)(a a)або як (aa aa)).

Програми Prolog часто оборотна ( що дозволяє , sщоб сформувати список рядків із заданою властивістю). Старший - це не (він переходить у нескінченний цикл), але це через метод гольфу, який я використовував, щоб переконатися, що C не порожній; якщо ви перезаписуєте програму, щоб явно вказати C як порожній, вона генерує рядки форми "aa", "aabb", "aabbcc" і так далі (Prolog, будучи Prolog, не визначає ідентичності символів, які їх складають вгору, лише уточнення, які символи однакові). Новіший генерує рядки форми "aa", "abab", "abcabc" тощо; це сам по собі нескінченний цикл, і тому ніколи не потрапляє в точку, в якій він застрягне через невдачу виявити рядок нульової довжини.


1

Brainfuck, 177 байт

+[<<<<,]>>>>[>+[>+[[>>]<+<[<<]>+>-]<[>+<-]>>>,>>[>>]+<<[<+>>-<-]<[>+<-]>>[,>[-<<
<<]<[<<<<]>]<[[<<]>]>>]>>[[>+>>>]>>>[>]<<<<[>+[-<<<,<]<[<<<[[<<<<]>>]<]>]>>]<[[-
>>>>]>>[<]<]<<]<.

Відформатовано:

+[<<<<,]
>>>>
[
  >+
  [
    >+
    [
      [>>]
      <+<[<<]
      >+>-
    ]
    <[>+<-]>
    >>,>>[>>]
    +<<[<+> >-<-]
    <[>+<-]>
    >
    [
      not equal
      ,>[-<<<<]
      <[<<<<]
      >
    ]
    <
    [
      equal
      [<<]
      >
    ]
    >>
  ]
  >>
  [
    mismatch
    [>+>>>]
    >>>[>]
    <<<<
    [
      backtrack
      >+[-<<<,<]
      <
      [
        not done yet
        <<<
        [
          [<<<<]
          >>
        ]
        <
      ]
      >
    ]
    >>
  ]
  <
  [
    match
    [->>>>]
    >>[<]
    <
  ]
  <<
]
<.

Очікує введення без зворотного нового рядка. Друкується \x00за помилкові та \x01правдиві.

Спробуйте в Інтернеті.

Це реалізує перший поглиблений пошук. Зокрема: перевірте наявність повторних префіксів збільшення довжини, починаючи з поточного суфіксу, а потім перейдіть до наступного суфікса, якщо знайдено збіг, інакше зворотний шлях.

На початку рядок обернено і \x01на кінці розміщено дозорну .

Стрічка ділиться на 4-клітинні вузли. Макет вузла пам'яті:

c h x 0

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

Якщо рядок є добовим, вказівник розташовується поруч із дозорною в кінці основного циклу; в іншому випадку вказівник падає з лівого боку рядка під час зворотного відстеження.


1

Брахілог , 5 байт

~c~jᵐ

Спробуйте в Інтернеті!

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

Пояснення

~c     Reversed concatenate: find a list that, when concatenated, results in the input string
       This examines all partitions of the input
  ~jᵐ  Map reversed juxtapose: for each string in that list, is it the result of concatenating
       a string to itself?

Для вхідного рядка , як "ababcc", ~cнамагається різні розділи , поки не приходить ["abab", "cc"], і в цей момент ~jуспішно для обох елементів списку, виходів ["ab", "c"], і предикат завершується успішно.



0

Літп , 57 символів

#S::((? (!= (null) (match S "^((.+)\\2)+$")) true false))

Використання зразка:

% pairable_strings.lithp
(
    (def f #S::((? (!= (null) (match S "^((.+)\\2)+$")) true false)))
    (print (f "aa"))
    (print (f "aabaaababbbaba"))
    (print (f "aaababbabbabbbababbaabaabaababaaba"))
    (print (f "ba"))
)

# ./run.js pairable_strings.lithp
AtomValue { value: 2, type: 'Atom', name: 'true' }
AtomValue { value: 2, type: 'Atom', name: 'true' }
AtomValue { value: 2, type: 'Atom', name: 'true' }
AtomValue { value: 3, type: 'Atom', name: 'false' }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.