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, но также может выполнять глобализацию в стиле оболочки (фактически, в древних perl это было реализовано с помощью вызова оболочки).
Например <{a,b}{1,2}>, расширится до"a1","a2","b1","b2"
Поэтому, если у нас есть элементы, @Fнам просто нужно добавить запятые между ними. Символ по умолчанию для интерполяции - это пробел, который хранится в специальной переменной $". Таким образом , установив , $"чтобы ,превратится "{@F}"в {a,b}случае @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 Globs для отложенной генерации, используя их в скалярном контексте, но это делает программы длиннее ...