Assuming we have the principal winds to hand:
my @principals = <N NE E SE S SW W NW>;
Then we can follow the definition a la Wikipedia:
The name of each half-wind is constructed by combining the names of the principal winds to either side
This means we want to take principal winds in overlapping pairs, which rotor
could do fairly neatly:
say @principals.rotor(2 => -1);
Which gives us:
((N NE) (NE E) (E SE) (SE S) (S SW) (SW W) (W NW))
Which sadly has an off by one problem, because it misses (NW, N)
. OK, we can include N
again, at the cost of a little beauty:
say @principals[*,0].flat.rotor(2 => -1)
Giving:
((N NE) (NE E) (E SE) (SE S) (S SW) (SW W) (W NW) (NW N))
If we join them:
say @principals[*,0].flat.rotor(2 => -1).map(*.join)
We get:
(NNE NEE ESE SES SSW SWW WNW NWN)
Which isn't right yet, because the next thing the article says is:
with the cardinal wind coming first and the intercardinal wind second
The cardinal winds are the one character ones, which can be fixed with a sort:
say @principals[*,0].flat.rotor(2 => -1).map(*.sort(*.chars).join)
Which finally looks about right:
(NNE ENE ESE SSE SSW WSW WNW NNW)
Except that the half winds are these placed between the principal winds, which can be solved with zipping them and flattening the result:
say flat @principals Z @principals[*,0].flat.rotor(2 => -1).map(*.sort(*.chars).join)
Finally giving us:
(N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW)
If we want it shorter, the duplicate mention of @principals
can go away with a given
:
say flat $_ Z .[*,0].flat.rotor(2 => -1).map(*.sort(*.chars).join) given @principals
The .join
can just become list stringification:
say flat $_ Z .[*,0].flat.rotor(2 => -1).map(~*.sort(*.chars)) given @principals:
And the inner flattening can be replaced with a use of the |
slip operator:
say flat $_ Z (|$_,.[0]).rotor(2 => -1).map(~*.sort(*.chars)) given @principals;
Which is still longer than just listing them out in the first place, which is what I'd probably do, but it was fun trying to beat that anyway...