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 для отложенной генерации, используя их в скалярном контексте, но это делает программы длиннее ...