Pile shuffle
Pile shuffling! If you don't know what that is, the examples below will illustrate.
I wrote this because I wanted to make a function to spread out colours for Power BI. I first wrote it in PowerShell and then I wrote it again in Power Query M for a challenge. Turns out that was a very good exercise, because M is a lot less forgiving than PowerShell in some respects, and forced me to tighten up the code.
Here they are.
$stack = @(
'♠A','♠2','♠3','♠4','♠5','♠6','♠7','♠8','♠9','♠10','♠J','♠Q','♠K',
'♥A','♥2','♥3','♥4','♥5','♥6','♥7','♥8','♥9','♥10','♥J','♥Q','♥K',
'♣A','♣2','♣3','♣4','♣5','♣6','♣7','♣8','♣9','♣10','♣J','♣Q','♣K',
'♦A','♦2','♦3','♦4','♦5','♦6','♦7','♦8','♦9','♦10','♦J','♦Q','♦K'
)
function pileShuffle ([PSCustomObject[]] $stack, [int] $piles ) {
# check if it is an even split. abandon if not
$evensplit = ($stack.length % $piles) -eq 0
if ( $evensplit ) {
$n = $stack.length
# the height of each small stack after dividing
$h = $stack.length / $piles
$a = @(0..$($h - 1))
# indeces of the stack
$b = @(0..$($piles - 1))
return $a.ForEach({
$step = $_
$b.ForEach({
$i = $($_ * $h) + $step
# pick off the i-th element off the stack
$stack[$i]
})
})
} else {
Write-Host stack will not be divided into an even split - choose a different number of piles
}
}
pileShuffle $stack 4
<#
result:
"♠A", "♥A", "♣A", "♦A",
"♠2", "♥2", "♣2", "♦2",
"♠3", "♥3", "♣3", "♦3",
"♠4", "♥4", "♣4", "♦4",
"♠5", "♥5", "♣5", "♦5",
"♠6", "♥6", "♣6", "♦6",
"♠7", "♥7", "♣7", "♦7",
"♠8", "♥8", "♣8", "♦8",
"♠9", "♥9", "♣9", "♦9",
"♠10", "♥10", "♣10", "♦10",
"♠J", "♥J", "♣J", "♦J",
"♠Q", "♥Q", "♣Q", "♦Q",
"♠K", "♥K", "♣K", "♦K"
#>
(stack as list, piles as number ) as list =>
let
// number of elements in the stack
n = List.Count(stack),
// the "height" of each pile
h = n / piles,
// indices the outer loop
a = {0..(h-1)},
// indices the inner loop
b = {0..(piles-1)},
// e.g. stack of 20, and divided into 4 piles
// the outer loop goes 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1...
// the inner loop goes 0, 1, 2, 3, 0, 1, 2, 3, 0, 1...
// put these two together with the formula below, and you get
// 0, 4, 8, 12, 1, 5, 9, 13, 2, 6...
// from this shuffle, we get the element at the i-th position in the stack
outer = List.Transform(
a,
each
let
step = _,
inner = List.Transform(
b,
each let i = _ * h + step in stack{i}
)
in
inner
),
combined = List.Combine(outer)
in
combined