Sometimes you need to view a sequence as a series of pieces
rather than element-by-element. The grouping,
splitting, and
splitting.monotonic vocabularies give
you four ways to do that.
group — disjoint chunks of size n
group ( seq n -- groups )
USING: grouping ;
{ 1 2 3 4 5 6 7 } 3 group .
! => { { 1 2 3 } { 4 5 6 } { 7 } }
If the sequence length isn't a multiple of n, the final group is shorter than n.
clump — overlapping sliding window of size n
clump ( seq n -- clumps )
USING: grouping ;
{ 1 2 3 4 5 } 2 clump .
! => { { 1 2 } { 2 3 } { 3 4 } { 4 5 } }
If the sequence is shorter than n, the result is empty.
split-when — break wherever a predicate firessplit-when ( seq quot: ( elt -- ? ) -- pieces )
USING: splitting ;
{ 1 2 0 3 4 0 5 } [ zero? ] split-when .
! => { { 1 2 } { 3 4 } { 5 } }
Each element gets its own predicate call; truthy elements are the break points and aren't kept in the result.
monotonic-split — break runs where an adjacent-pair check failsmonotonic-split ( seq quot: ( a b -- ? ) -- pieces )
USING: splitting.monotonic ;
{ 1 1 2 2 2 3 } [ = ] monotonic-split .
! => { { 1 1 } { 2 2 2 } { 3 } }
The predicate runs on adjacent pairs. While it returns truthy,
the run continues; when it returns f, a new piece starts. With
[ = ] you get runs of equal elements; with [ <= ] you get
non-decreasing runs; and so on.
group/clump: you know the size you want.split-when: you know what a break element looks like.monotonic-split: you know what makes two adjacent
elements still belong together.It's another busy night at the Antwerp marshalling yard. You're the dispatcher on duty: incoming freight cars need to be regrouped into outbound trains, couplings inspected, routes split at junctions, and identical cargo coalesced for billing.
Each car is a string naming what it's carrying:
"coal", "timber", "crates", etc.
Define couple to take an array of cars and a length n, and
return non-overlapping trains of n cars each. The final train
may be shorter if the count doesn't divide evenly.
{ "coal" "coal" "coke" "ore" "ore" "timber" "timber" } 3 couple .
! => { { "coal" "coal" "coke" } { "ore" "ore" "timber" } { "timber" } }
Define peek-couplings to take an array of cars and return every
adjacent pair, so the inspector can examine each coupling.
{ "coal" "ore" "timber" "crates" } peek-couplings .
! => { { "coal" "ore" } { "ore" "timber" } { "timber" "crates" } }
Define split-at-junctions to take an array of cars and an
array of junctions (cars that mark a break point), and return
the legs between junction cars. The junction cars themselves
aren't kept.
{ "coal" "coal" "switch" "ore" "switch" "timber" }
{ "switch" } split-at-junctions .
! => { { "coal" "coal" } { "ore" } { "timber" } }
Define coalesce-cargo to take an array of cars and group
consecutive cars carrying the same cargo into runs.
{ "coal" "coal" "ore" "ore" "ore" "timber" "coal" } coalesce-cargo .
! => { { "coal" "coal" } { "ore" "ore" "ore" } { "timber" } { "coal" } }
Sign up to Exercism to learn and master Factor with 47 concepts163 exercises, and real human mentoring, all for free.