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