Skip to content

Instantly share code, notes, and snippets.

@IISResetMe
Created December 31, 2020 02:28
Show Gist options
  • Select an option

  • Save IISResetMe/3b678370b0eda217f472cb4789f9ed5a to your computer and use it in GitHub Desktop.

Select an option

Save IISResetMe/3b678370b0eda217f472cb4789f9ed5a to your computer and use it in GitHub Desktop.
Nega-fibonacci with (non-optimal) caching
# Z-fibonacci (or nega-fibonacci, see https://en.wikipedia.org/wiki/Fibonacci_number#Sequence_properties):
# F(n-2) = F(n) - F(n-1)
$function:fib = & {
$cache = [System.Collections.Generic.Dictionary[int,bigint]]::new()
-1..1 |Foreach-Object {
$cache.Add($_, $_)
}
return {
param(
[Parameter(Mandatory,ValueFromPipeline)]
[int]$n
)
process {
# This generalization of Fibonacci can be expressed as a
# Jacobstahl binomial (https://www.fq.math.ca/Scanned/35-2/horadam.pdf).
# Fortunately, we don't actually need to know how to calculate
# such an expression - instead, we can use this observation
# to "predict" that negative $n-values results in alternating
# sequence like
#
# [ ..., -1*fib(Abs(-4)), fib(Abs(-3)), -1*fib(Abs(-2)), fib(Abs(-1)) ]
#
# So all we need to know is what fib(Abs($n)) is, and whether
# $n is negative and odd:
Write-Verbose "Fib($n)"
$odd = $n % 2 -ne 0
$negative = $n -lt 0
$n = [Math]::Abs($n)
# always return cached fib($n) values
if($cache.ContainsKey($n)){
Write-Verbose "Cache hit: $n ($($cache[$n]))"
$head = $cache[$n]
}
else {
Write-Verbose "Cache miss: $n"
Write-Verbose "Counting values for `$n = 0..$n"
$tail,$head = 0,1 -as [bigint[]]
$i = 1
while($i++ -lt $n){
$tail,$head = $head,($tail+$head)
$cache.Item($i) = $head
}
}
return $head * (1,-1)[$odd -and $negative]
}
}.GetNewClosure()
}
#
@(
-5..5 |fib -Verbose
)
-10..10 |ForEach-Object {
[PSCustomObject]@{
N = $_
Fib = $_ |fib -Verbose
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment