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 для лінивого покоління, використовуючи їх у скалярному контексті, але це робить програми довшими ....