Створіть портманта!


16

Фон

Три роки тому цей хлопець Том Мерфі взяв його в голову, щоб поширити ідею про портманто до всіх слів мовою і назвав це портмантом ( portmanteau plus tout [французька для всіх ]). Визначивши англійську як список зі 108709 слів, він зумів знайти послідовність 611 820 букв із наступними двома властивостями:

  • Кожне англійське слово міститься в рядку.
  • Деякі околиці, що містять будь-які дві сусідні літери в рядку, - це англійське слово.

Ось посилання на сторінку, на якій цей портмант можна знайти (разом із відео поясненням).

Портмантаут

Перше з двох властивостей портманта легко зрозуміти. Другий може зажадати певних пояснень.

В основному слова повинні перетинатися. "гольф-код" ніколи не з’явиться в портманті англійською мовою, так як там немає жодного слова, яке містить "fc". Однак ви можете знайти "codegolf" у портмантуті, оскільки "его" подолає розрив (а всі інші пари букв знаходяться у "коді" чи "гольфі").

Ваше завдання:

Напишіть програму або функцію, яка займає список рядків і повертає будь-який портмат списку.

Цей код Python 3 перевірить портманта.

Тестові справи

Усі списки не упорядковані; тобто,

{"code", "ego", "golf"} -> "codegolf"
{"more", "elm", "maniac"} -> "morelmaniac" or "morelmorelmaniac" or "morelmorelmorelmaniac" or...
    Would a morelmaniac be some sort of mycologist?
{"ab", "bc", "cd", "de", "ef", "fg", "gh", "hi", "ij", "jk", "kl", "lm", "mn", "no", "op", "pq", "qr", "rs", "st", "tu", "uv", "vw", "wx", "xy", "yz", "za"} -> "abcdefghijklmnopqrstuvwxyza" or "rstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef" or any 27+ letters in order

А чому ні? Масовий на сайті Мерфі, якщо ваш код виконується протягом розумного часу.

Правила

  • Ваш код повинен зупинитися.
  • Вам не потрібно повертати один і той же портматман при кожному виконанні.
  • Ви можете припустити , що всі рядки складаються тільки з малих літер aчерез z.
  • Якщо портмантаут неможливий, ваша програма може зробити все, що завгодно. Наприклад:{"most", "short", "lists"}
  • Застосовуються стандартні правила вводу / виводу та лазівки .

Це , тому найкоротше рішення (в байтах) на кожній мові виграє! Щасливого гольфу!



1
Можливо, якісь тестові випадки?
Адам

{"sic", "bar", "rabbits", "cradle"} -> "barabbitsicradle" {"mauve", "elated", "cast", "electric", "tame"} -> "mauvelectricastamelated"(більше тестових випадків)
sundar - Відновіть Моніку

2
Так, може бути тестова скринька, де слово потрібно вживати двічі
лише для ASCII

2
Чи отримаємо ми колись слова з 1 літери?

Відповіді:


3

Python 2 , 204 202 байт

def f(l,s=''):
 if all(w in s for w in l):return s
 for i,w in enumerate(l):
	a=next((s+w[i:]for i in range(len(w)-1,0,-1)if s[-i:]==w[:i]),0)if s else w;x=a and f(l[:i]+l[i+1:]+[l[i]],a)
	if x:return x

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


Збережено

  • -2 байти, завдяки рекурсивному

Ви можете використовувати вкладки в останніх двох рядках, щоб зберегти 2 байти.
рекурсивний


Це не дає правильного результату для ["ab", "ba", "ca"]. Моє рішення має таку ж помилку.
рекурсивний

1

Pyth, 39 байт

JQW}_1mxbdQ=+J|=b*qKOQ<=T+OP._KOJlKTY)b

Спробуйте тут

Пояснення

JQW}_1mxbdQ=+J|=b*qKOQ<=T+OP._KOJlKTY)b
JQ                                        Get a copy of the input.
  W}_1mxbdQ                          )    While there are words in the input
                                          that aren't in b (initially space)...
                   KOQ    OP._KOJ         ... get a random input word, a random
                                          prefix, and a random joined word...
                       =T+                ... stick them together...
                  q   <          lKT      ... and check if joining them together
                                          is valid...
               =b*                        ... then update b accordingly...
           =+J|                     Y     ... and stick the new word into J.
                                      b   Output the final result.

1

Стакс , 39 36 байт

ä▬│•.k=╠lƒ☺╜00║¿~,▓╕╠7ÉΔB<e┼>☼Θ²└ô┴\

Запустіть і налагоджуйте його

Виконує всі тестові справи детерміновано приблизно за секунду.

Це рекурсивний алгоритм.

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

Ось програму розпаковують, не розгортають і коментують.

FG              for each word in input, call target block
}               unbalanced closing brace represents call target
  x{[#o         sort input words by their number of occurrences in the current candidate
  Y             store it in register Y
  h[#{,}M       if all of the words occur at least once, pop from input stack
                input stack is empty, so this causes immediate termination,
                followed by implicitly printing the top of the main stack
  yF            for each word in register y, do the following
    [n|]_1T|[|& intersect the suffixes of the candidate with prefixes of the current word
    z]+h        get the first fragment in the intersection, or a blank array
    Y           store it in register Y
    %t+         join the candidate with the current word, eliminating the duplicate fragment
    y{G}M       if the fragment was non-blank, recursively call to the call target
    d           pop the top of stack

Виконати цей

Редагувати: це не вдається для класу входів, що має цикл, як ["ab", "ba", "ca"], як і більшість інших розміщених відповідей.


0

JavaScript (ES6), 138 130 байт

f=a=>a[1]?a.map((c,i)=>a.map((w,j,[...b])=>i!=j&&!/0/.test(m=(c+0+w).split(/(.+)0\1/).join``)?t=f(b,b[i]=m,b.splice(j,1)):0))&&t:a

Повертає помилку для списків, які неможливо повністю перетворити на порт.

Безголівки:

f = a =>
  a[1] ?                                        //if more than one element ...
    a.map((c, i)=>                              // for each element
      a.map((w, j, [...b])=>                    //  for each element
        i != j &&                               //   if not the same element
        !/0/.test(m=(c+0+w).split(/(.+)0\1/).join``) &&  //   and the elements overlap
        (t = f(b,                               //   and f recursed is true when
               b[i] = m,    //    replacing the ith element with the 2-element portmanteau
               b.splice(j, 1)                   //    and removing the jth element
              )
        )
      )
    ) &&
    t :                                         //return the recursed function value
    a                                           //else return a

Код зневажливо повільний на прикладі повного алфавіту (не включений з цієї причини у вищенаведений фрагмент).

Це усувається зміною maps на somes, для втрати 2 байт:

f=a=>a[1]?a.some((c,i)=>a.((w,j,[...b])=>i!=j&&!/0/.test(m=(c+0+w).split(/(.+)0\1/).join``)?t=f(b,b[i]=m,b.splice(j,1)):0))&&t:a


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