How can I filter out consecutive repeats in a sequence?

Viewed 163

I'm trying to generate a Seq of random options where consecutive repeats are not allowed:

> (<F R U>.roll(*).grep(* ne *))[^10]
((R F) (F U) (R F) (F R) (U R) (R F) (R F) (U F) (R U) (U R))

Why does using grep in this way result in nested pairs? And how can I achieve what I'm looking for? Using .flat above will still allow consecutive repeats.

( R U F U F U R F R U ... )
2 Answers

how can I achieve what I'm looking for?

I believe the squish method will do what you want:

say <F R U>.roll(*).squish.head(20)

This produces:

(U R F U F R F R F U F R U R F U R U R F)

Why does using grep in this way result in nested pairs?

Because grep (and map too) on something with an arity greater than 1 will work by breaking the list into chunks of that size. Thus given A B C D, the first call to the grep block gets A B, the second C D, and so on. What's really needed in this case, however, is a lagged value. One could use a state variable in the block passed to grep to achieve this, however for this problem squish is a much simpler solution.

You could employ a simple regex using the <same> zero-width matcher. Below in the Raku REPL:

> my $a = (<F R U>.roll(*))[^20].comb(/\w/).join; say $a;
RRFUURFFFFRRFRFUFUUU

> say $/ if  $a ~~ m:g/ \w <!same> /;
(「R」 「F」 「U」 「R」 「F」 「R」 「F」 「R」 「F」 「U」 「F」 「U」)

https://docs.raku.org/language/regexes#Predefined_Regexes

Related