Учитывая слово abcd
, как бы я построил следующий вложенный список?
[ (abcd) (a bcd) (ab cd) (abc d) (a b cd) (a bc d) (ab c d) (a b c d) ]
Это разбивает слово всеми возможными способами, сохраняя при этом порядок букв.
Nemokosch на #raku-beginner указал мне на .combinations
и модуль snip
, но у меня возникли проблемы с соединением всего этого.
use v6.e.PREVIEW; # for `snip`
my $s = "abcd";
my @ps = $s.comb.pairs;
my $res = (1..^$s.chars
==> combinations()
==> map({ @ps.snip: (&{.key < $OUTER::_} for $_) })
==> map( *>>.value>>.join ));
получить
>>> $res
((abcd) (a bcd) (ab cd) (abc d) (a b cd) (a bc d) (ab c d) (a b c d))
[другой ответ++ более лаконичен, но, насколько я понимаю, он не ленив и работает несколько медленнее на больших строках, например, «abcd» x 5, поэтому я сохраняю этот ответ.]
вот промежуточные результаты:
# enumerated string
>>> @ps = $s.comb.pairs
[0 => a 1 => b 2 => c 3 => d]
# combinations of the enumeration except 0s
# these are the splitting points actually
>>> $combs = (1..^$s.chars).combinations
(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3))
Из этих точек разделения мы можем сгенерировать, например, списки (*.key < 1,)
и (*.key < 1, *.key < 3)
, чтобы мы могли передать их в @ps.snip
, который затем будет смотреть на ключи своих элементов, то есть позиции индекса, и разделять их для нас. Итак, следующий шаг делает это поколение:
# output is actually different but this is for demonstration
>>> $combs.map({ (&{.key < $OUTER::_} for $_) })
((), (*.key < 1), (*.key < 2), (*.key < 3), (*.key < 1, *.key < 2) ... (*.key < 1, *.key < 2, *.key < 3)
(Первое пустое «условие» удобно для создания строки в том виде, в каком оно будет позже, поэтому мы не будем рассматривать этот случай отдельно.)
Для каждой комбинации, например (1, 2), мы перебираем эту (for $_
) и генерируем условия. 1 и 2, в свою очередь, будут $_
в этой пост-форме цикла for, но если бы мы поставили {.key < $_}
в качестве условия, $_
не будет закрываться над этими 1 и 2, а вместо этого будет аргументом, переданным во время вызова, т. е. перечисляемая пара. Но мы этого не хотим, поэтому мы говорим поставить здесь ВНЕШНИЙ блок $_
, который будет 1 и 2 по очереди. Но для .key
нам нужна пара во время звонка, поэтому это $_.key
(без $_
, так как его можно опустить).
На данный момент после снипов у нас есть
>>> $combs.map({ @ps.snip: (&{.key < $OUTER::_} for $_) }).raku
(((0 => "a", 1 => "b", 2 => "c", 3 => "d"),).Seq, ((0 => "a",), (1 => "b", 2 => "c", 3 => "d")).Seq, ((0 => "a", 1 => "b"), (2 => "c", 3 => "d")).Seq, ((0 => "a", 1 => "b", 2 => "c"), (3 => "d",)).Seq, ((0 => "a",), (1 => "b",), (2 => "c", 3 => "d")).Seq...)
У нас есть желаемые разбиения, за исключением того, что есть дополнительный багаж: перечисления и разбиение на символы. Таким образом, мы отменяем .comb.pairs
, сделанное в начале, на >>.value>>.join
в конце, и получается окончательный результат.
Вы можете использовать match
с :exhaustive:
"abcd"
andthen .match: /^ (\w+)+ $/,:ex
andthen .map: *.[0].put