Skip to content

Instantly share code, notes, and snippets.

@idavis
Last active May 21, 2016 22:17
Show Gist options
  • Save idavis/3b3b019f52d766fe780053930f49e8c6 to your computer and use it in GitHub Desktop.
Save idavis/3b3b019f52d766fe780053930f49e8c6 to your computer and use it in GitHub Desktop.
Implementing APL shape/rank (⍴/⍴⍴) functions in PowerShell. This is a rough first cut.
# APL Rank
filter ⍴⍴ {
param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$false)] $ω
)
process {
if($ω -is [system.array]){
$ω.rank
} else{
"⍬"
}
}
}
# APL Shape and ReShape
function ⍴ {
[CmdletBinding()]
param(
[Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$true)] $α,
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$false)] $ω
)
begin {
$pipeCapture = @()
}
process {
$pipeCapture += $_
}
end {
$α = $pipeCapture
if($α) {
$res = new-object "System.Object[$(',' * ($α.Length-1))]" $α
$sourceIndices = ?: { (⍴⍴ $ω) -eq 1 } { (0..($ω.Length-1)) } { (CartesianProduct ((⍴ $ω) | % { ,(0..($_-1)) })) }
$index = 0
$targetIndices = ?: { $α.Length -eq 1} { ,(0..($α[0]-1)) } { (CartesianProduct ($α | % { ,(0..($_-1)) })) }
foreach($targetIndex in $targetIndices) {
$sourceIndex = $sourceIndices[($index++ % $sourceIndices.Length)]
$res[$targetIndex] = $ω[$sourceIndex]
}
return ,$res
} else {
if(($rank = ⍴⍴ $ω) -ne "⍬") {
@(0..($rank-1) | % {$ω.GetLength($_)})
} else {
"⍬"
}
}
}
}
$a = @(2,3)
$b = new-object "System.Int32[,]" 4,2
$c = new-object "System.Int32[,,]" 5,4,3
$s = 5
Write-Host "The rank of a 1 dim: " (⍴⍴ $a)
Write-Host "The rank of a 2 dim: " (⍴⍴ $b)
Write-Host "The rank of a 3 dim: " (⍴⍴ $c)
Write-Host "The rank of a scalar: " (⍴⍴ $s)
Write-Host ("The shape of the 1 dim: {0}" -f (⍴ $a))
Write-Host ("The shape of the 2 dim: {0} {1}" -f (⍴ $b))
Write-Host ("The shape of the 3 dim: {0} {1} {2}" -f (⍴ $c))
Write-Host ("The shape of the scalar: {0}" -f (⍴ $s))
$shape = @(3,3)
$data = @(1,2,3,4,5,6,7,8,9)
[Object[,]]$result = ($shape | ⍴ $data)
$sb = New-Object -TypeName "System.Text.StringBuilder"
for($i = 0; $i -lt $result.GetLength(0); $i++) {
for($j = 0; $j -lt $result.GetLength(1); $j++) {
$cur = $result[$i,$j]
[void]$sb.Append($cur)
[void]$sb.Append(" ")
}
[void]$sb.Append([Environment]::NewLine)
}
Write-Host $sb.ToString()
$sb = New-Object -TypeName "System.Text.StringBuilder"
$shape2 = @(9)
[Object[]]$result2 = ($shape2 | ⍴ $result)
for($i = 0; $i -lt $result2.GetLength(0); $i++) {
$cur = $result2[$i]
[void]$sb.Append($cur)
[void]$sb.Append(" ")
}
[void]$sb.Append([Environment]::NewLine)
Write-Host $sb.ToString()
set-alias ?: Invoke-Ternary
filter Invoke-Ternary ([scriptblock]$conditional, [scriptblock]$trueBlock, [scriptblock]$falseBlock) {
if (& $conditional) {
& $trueBlock
} else {
& $falseBlock
}
}
filter CartesianProduct($itemSource) {
switch (,$itemSource) {
$null {
break
}
{ $_.Count -eq 1 } {
$_
}
{ $_.Count -gt 1 } {
$res = @()
foreach ($α in $_[0]) {
foreach ($ω in (CartesianProduct $_[1..($_.Count - 1)])) {
$res += ,(?: {$ω -is [Object[]]}{,$α + $ω}{,@($α, $ω)})
}
}
,$res
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment