Виведіть всі рядки


34

Враховуючи набір букв, виведіть усі рядки з цих літер. (Це зірка Клейна у наборі.) Наприклад, для {'a','b'}струн:

'', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', ...

Введення: Непорожня колекція різних літер a..z. Це можуть бути символи або односимвольні рядки.

Вихідні дані: Усі рядки з цих літер у будь-якому порядку, без повторів. Ви можете використовувати списки знаків як рядки.

Це нескінченний список, тому ви можете вивести його за допомогою:

  • Завічно працює все більше і більше рядків. Ці рядки можуть бути записані у будь-якому плоскому розділеному форматі, тобто вони можуть вказати, де закінчується кожна рядок, але рядки не поділяються на групи.
  • Приймаючи число nяк введення та виведення перших nрядків у будь-якому плоскому розділеному форматі
  • Поступаючись кожній струні по черзі від об'єкта-генератора
  • Виробляючи нескінченний предмет

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

Ви не можете вивести його

  • Вироблення даного nрядкаn
  • Надання оракулу членства, який вирішує, чи належить заданий рядок до набору

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


@Cyoce Не впевнений, що ти маєш на увазі. Я уточнив, що рядки повинні бути відокремленими, так що ви можете сказати порожній рядок з нічого.
xnor

Будь ласка, поясніть, чому "створення N-го рядка, заданого N", не дозволено.
CalculatorFeline

4
@CatsAreFluffy Це був вирок суду. Я думаю, що створити N-ту рядок було б занадто просто в порівнянні з альтернативами і зробить виклик менш цікавим, тим більше, що деякі мови мають вбудовану довільну конверсію. Крім того, я не думав, що це захоплювало ідею генерувати нескінченний набір, а не запитувати його.
xnor

Чи можете ви пояснити "створення нескінченного об'єкта"? Це означає, що ми можемо, наприклад, натиснути кожну рядок на стек (для мов стека) і дозволити їй працювати "назавжди", навіть якщо жодного результату не буде вироблено, оскільки програма не закінчиться?
Луїс Мендо

@DonMuesli Чи виводиться в стек прийнятим методом виводу для таких мов? І чи буде стек містити лише ці рядки в будь-який момент часу?
xnor

Відповіді:


26

Пітон 2, 53 56

-3 після усвідомлення того, що yield xможе бути використаний як вираз.

def f(s):yield'';[(yield w+c)for w in f(s)for c in s]

Один байт коротше, але починається з , 'aa'а не на '': S=lambda s:(c+w for f in[str,S]for w in f(s)for c in s). Також не працює для порожнього вводу.
orlp

20

Haskell, 24 байти

f s=[]:[b:a|a<-f s,b<-s]

Створює нескінченний список.

*Main> f "abc"
["","a","b","c","aa","ba","ca","ab","bb","cb","ac","bc","cc","aaa","baa","caa","aba","bba","cba",…

Дуже погано (:)<$>s<*>f sдав би неправильний наказ. Є, f s="":(flip(:)<$>f s<*>s)але це довше.
xnor

Так. Я знайшов 23-байт, f s=[]:(f s<**>map(:)s)окрім цього <**>немає в Prelude.
Anders Kaseorg

11

JavaScript (ES6), 61 байт

function*g(s){yield'';for(let r of g(s))for(c of s)yield c+r}

Порт генератора Python @ feersum. letНеобхідно. Збережіть 2 байти за допомогою розуміння масиву (невдала пропозиція ES7, але працює у Firefox 30-57):

function*g(s){yield'';[for(r of g(s))for(c of s)yield c+r]}

Альтернативна версія для 73 байтів, яка повертає перші nелементи, отримані вищевказаним генератором:

(s,n)=>Array(n).fill('').map(g=(r,i)=>i--?g(r+s[i%l],i/l|0):r,l=s.length)

JS має генератори? : 0000000
кіт

10

Математика, 32 31 байт

Do[Echo/@#~Tuples~n,{n,0,∞}]&

Редагувати:

CatsAreFluffy зішкребв один байт.


8

Perl, 39 37 35 байт

(Спочатку описується старша версія. У кінці нова коротша програма)

Включає +3 для -alp

Виконати з набором символів на STDIN, наприклад perl -alp kleene.pl <<< "a b c"

kleene.pl (ця версія становить 34 + 3 байти):

$#a=$"=","}for(@a){push@a,<{@F}$_>

Додайте +2 для -F(крапка неявна, -aякщо між вхідними символами немає пробілів, або -6 (лише @a=""раніше }), якщо ми вже ставимо коси між символами на STDIN

Пояснення:

Ці -alpпараметри ефективно зробити код:

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    our @F = split(' ', $_, 0);
    $#a = $" = ',';
}
foreach $_ (@a) {
    use File::Glob ();
    push @a, glob('{' . join($", @F) . '}' . $_);
}

Як ви бачите, <>в perl використовується не тільки для readline, але й може робити глобальний стиль оболонки (адже в древніх perls це було реалізовано за допомогою виклику shell).

Наприклад, <{a,b}{1,2}>буде розширено до"a1","a2","b1","b2"

Отже, якщо у нас є елементи, @Fнам просто потрібно додати коми між ними. Типовим символом між інтерполяцією є пробіл, який зберігається в спеціальній змінній $". Тож налаштування $"на ,перетвориться "{@F}"на {a,b}if @F=qw(a b)(глобуси розширюються як рядки)

Насправді мені б дуже хотілося циклічно щось подібне glob"{@F}"x$n++, але я постійно стикався з проблемою, що перший порожній рядок не генерується, і всі обхідні способи, які я знайшов, зробили код занадто довгим.

Отже, ще однією важливою частиною цього коду є те, що якщо ви використовуєте forцикл через масив, ви можете фактично натиснути на нього додаткові елементи під час циклу, і цикл також підбере ці нові елементи. Отже, якщо в циклі ми знаходимося, наприклад, в елементі "ab", то <{@F}$_>розширимося до того, <{a,b}ab>що в списку стає контекстом ("aab", "bab"). Так що, якщо я штовхаю їх на @aте рядки протяжної вліво стають доступними занадто

Все, що мені ще потрібно зробити, це прострочити цикл із порожньою рядком. Це робиться за допомогою $#a = 0( ,у числовому контексті стає 0), що призводить до того, що перший і єдиний елемент @aстане undef, який буде вести себе як ""коли я його використовую

Поліпшення

Насправді, роблячи тести на це пояснення, я знайшов короткий спосіб використовувати зростаючий глобус, який належним чином обробляє перший порожній запис. Запустити як perl -ap kleene0.pl <<< "a b"(тому додайте 2 байти для -ap)

kleene0.pl (ця версія 33 + 2 байти):

$"=",";print<$z,>;$z.="{@F}";redo

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


Чи можете ви поясніть, що відбувається навколо <{@F}$_>? Спасибі!
andlrc

6

Піта, 7

<s^LzQQ

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

Це обчислює декартовий добуток вводу з кожним числом з 0..n-1, приєднується до них, а потім зберігає лише перше n. Це вичерпає час в Інтернеті для чисел чи рядків, які значно перевищують 3-4.

Крім того, щоб отримати нескінченний вихід, подивіться на відповідь Якубе .


5

Желе, 8 6 байт

⁷³p$Ȯ¿

Це монадичне посилання, яке приймає алфавіт і друкує нескінченний список рядків. Спробуйте в Інтернеті!

Як це працює

⁷³p$Ȯ¿    Monadic link. Argument: A (alphabet)

⁷         Set the return value to '\n'.
     ¿    While loop.
            Condition:
    Ȯ         Print the current return value and return it (always truthy).
            Body:
   $          Combine the two links to the left into a single, monadic link.
 ³              Yield A.
  p             Perform the Cartesian product of A and the current return value,
                updating the return value in the process.

Альтернативна версія, 6 байт (неконкурентна)

R’ḃL}ị

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

Я вважаю цю версію неконкурентоспроможною, оскільки вона використовує біективну базову конверсію, яка була реалізована після того, як цей виклик був пісочницею. Спробуйте в Інтернеті!

Як це працює

R’ḃL}ị    Dyadic link. Arguments: n (integer), A (alphabet)

R         Range; yield [1, ..., n].
 ’        Decrement; yield [0, ..., n-1].
   L}     Yield l, the length of A.
  ḃ       Convert every i in [0, ..., n-1] to bijective base l.
     ị    For each array of digits, retrieve the corresponding characters of A.


4

CJam, 16 10 байт

Завдяки jimmy23013 за збереження 6 байт.

N{eam*_o}h

Введення - це один аргумент командного рядка на символ. Вихід - один рядок у кожному рядку.

Спробуйте в Інтернеті! (Але вбий його негайно ...)

Пояснення

N      e# Push [\n]. At each step this array will contain all strings of length N,
       e# each followed by a linefeed.
{      e# Infinite loop...
  ea   e#   Read command-line arguments.
  m*   e#   Cartesian product: pairs each letter with each string in the list.
  _o   e#   Output all the strings of the current length.
}h

3

Pyth, 7 байт

.V0j^zb

Альтернатива @fry. Ця програма читає рядок і продовжує друкувати рядки до нескінченності.

Пояснення:

.V0      for b in (0 to infinity):
    ^zb     compute all strings of length b consisting of the input alphabet
   j        print each one on a separate line

Крім того, наступне також буде працювати. Трохи більше хакі.

u
M^zH7

3

Хаскелл, 33 байти

k u=do s<-[0..];mapM(\_->u)[1..s]

Для іспиту k "xyz"- це нескінченний список["","x","y","z","xx","xy","xz","yx","yy","yz","zx","zy","zz","xxx",...]


3

MATL , 10 байт

0cD`G@Z^DT

Спробуйте в Інтернеті! Але не залишайте його довго працювати, щоб уникнути великих обчислювальних навантажень на сервер.

Програма відображає рядки динамічно, кожен рядок в іншому рядку.

0cD             % force display of a newline to represent the empty string
   `      T     % infinite do-while loop
    G           % push input, or nothing if no input has been taken yet
     @          % push iteration. Gives 1, 2,... in each iteration
      Z^        % Cartesian power. In the first iteration takes input implicitly 
       D        % display

2

Пітон 3, 95

from itertools import*
def f(x,l=0):
 while 1:print(*combinations_with_replacement(x*l,l));l+=1

Чому функції itertools повинні мати такі довгі назви.


3
combinations_with_replacementніколи цього не варто. Я впевнений, що коротше використовувати петлі. Завжди.
mbomb007

2

Ruby, 65 60 байт

->a{n=-1;loop{puts a.repeated_permutation(n+=1).map &:join}}

Такі довгі вбудовані назви ...


1
AFAIK Не потрібно місця перед &, а ви можете використовувати p замість путів.
Фонд позову Моніки

@QPaysTaxes Простір не можна скинути, і він pзакликає inspectсвої аргументи, які дають результат, наприклад[] ["a","b"] ["aa", "ab", ...
Doorknob

Я неправильно зрозумів вашу відповідь. Я думав, що це генерує нескінченний масив і друкує його. Однак я цілком впевнений, що для Array, to_s є інспектором для перевірки, тому пути і p мають однаковий вихід. ruby-doc.org/core-2.2.0/Array.html#method-i-to_s WRT the space: Ви перевіряли? Зізнаюся, я не впевнений, але в цьому я досить впевнений.
Фонд позову Моніки

1

Пайк ( фіксує 31), 10 9 байт

=blR.fbtp

Пояснення:

=b         -    set characters for base conversion to eval_or_not(input())
  l        -   len(^)
   R      -  [^, eval_or_not(input()]
    .f    - first_n(^)
      b   -    conv_base(^)
       t  -   ^[-1]
        p -  print(^)

1

Скала, 69

def f[A](s:Set[A]):Stream[List[A]]=Nil#::f(s).flatMap(x=>s.map(_::x))

Ледачі потоки досить приємні для подібних речей.


1

Japt, 50 40 34 28 байт

V²o ®s1+Ul)£UgXnH)¯X¦0}Ãâ ¯V

Введення є "string", number of items. Вихід сортується за довжиною, потім зворотним порядком алфавіту. Перевірте його онлайн!

Як це працює

V²  o ®   s1+Ul)£  UgXnH)¯  X¦ 0}Ã â ¯  V
Vp2 o mZ{Zs1+Ul)mX{UgXnH)s0,X!=0}} â s0,V

Vp2 o      // Create the range [0..V²).
mZ{     }  // Map each item Z in this range to:
Zs1+Ul)    //  Take the base-(1+U.length) representation of Z.
mX{     }  //  Map each char X in this to:
XnH        //   Parse X as a base-32 number.
Ug   )     //   Take the char at index -^ in U.
s0,X!=0    //   If X is 0, slice it to an empty string.
â          // Uniquify the result.
s0,V       // Slice to the first V items.

Ця версія займає деякий час, якщо ви хочете зробити більше 100 предметів. Якщо ви хочете більш швидкої версії, спробуйте цю 32-байтну :

V*2 o ms1+Ul)f@!Xf'0î£UgXnH}ïV

1

Кориця гумка, 6 байт

0000000: 6801 301c e74b                           h.0..K

Не конкуруючий, оскільки Коричнева жуйка була зроблена після цього виклику.

Спробуйте в Інтернеті (TIO обмежує вихід).

Пояснення

hСтавить Cinnamon Gum в форматі і режим генерації . Решта рядка декомпресується до [%s]*. %sПотім замінюються на вході, і генератор створюються , який виводить всі можливі рядки , відповідні регулярний вираз.



0

Пітон, 55 байт

s=input();l=['']
for x in l:print x;l+=[x+c for c in s]

Це довше, ніж 53-байтне рішення feersum , але воно ілюструє інший метод з друкованим виводом. Список lоновлюється під час його перегляду, додаючи кожен односимвольний суфікс кожного прочитаного рядка.

Використовувати однаково довго map:

s=input();l=['']
for x in l:print x;l+=map(x.__add__,s) 

Таку ж довжину можна виконати і в Python 3, втративши значок print()та зберегти його, розпакувавши вхід.

s,*l=input(),''
for x in l:print(x);l+=[x+c for c in s]

0

Zsh , 31 байт

f(){<<<${(F)a};a=($^a$^@);f $@}

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

Роздрукуйте масив, а потім зафіксуйте аргументи перед повторним повторенням. Незважаючи на включення назви функції, цей байт коротший, ніж ітеративна версія:

for ((;;))<<<${(F)a}&&a=($^a$^@)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.