sequence fib = {1,1} function zeckendorf(atom n) -- Same as [[Zeckendorf_number_representation#Phix]] atom r = 0 while fib[$]2 and n=fib[i] r += r+c n -= c*fib[i] end for return r end function function decimal(object z) -- Convert Zeckendorf number(s) to decimal atom dec = 0, bit = 2 if sequence(z) then for i=1 to length(z) do z[i] = decimal(z[i]) end for return z end if while z do if and_bits(z,1) then dec += fib[bit] end if bit += 1 if bit>length(fib) then fib &= fib[$] + fib[$-1] end if z = floor(z/2) end while return dec end function function to_bits(integer x) -- Simplified copy of int_to_bits(), but in reverse order, -- and +ve only but (also only) as many bits as needed, and -- ensures there are *two* trailing 0 (most significant) sequence bits = {} if x<0 then ?9/0 end if -- sanity/avoid infinite loop while 1 do bits &= remainder(x,2) if x=0 then exit end if x = floor(x/2) end while bits &= 0 -- (since eg 101+101 -> 10000) return bits end function function to_bits2(integer a,b) -- Apply to_bits() to a and b, and pad to the same length sequence sa = to_bits(a), sb = to_bits(b) integer diff = length(sa)-length(sb) if diff!=0 then if diff<0 then sa &= repeat(0,-diff) else sb &= repeat(0,+diff) end if end if return {sa,sb} end function function to_int(sequence bits) -- Copy of bits_to_int(), but in reverse order (lsb last) atom val = 0, p = 1 for i=length(bits) to 1 by -1 do if bits[i] then val += p end if p += p end for return val end function function zstr(object z) if sequence(z) then for i=1 to length(z) do z[i] = zstr(z[i]) end for return z end if return sprintf("%b",z) end function function rep(sequence res, integer ds, sequence was, wth) -- helper for cleanup, validates replacements integer de = ds+length(was)-1 if res[ds..de]!=was then ?9/0 end if if length(was)!=length(wth) then ?9/0 end if res[ds..de] = wth return res end function function zcleanup(sequence res) -- (shared by zadd and zsub) integer l = length(res) -- first stage, left to right, {020x -> 100x', 030x -> 110x', 021x->110x, 012x->101x} for i=1 to l-3 do switch res[i..i+2] case {0,2,0}: res[i..i+2] = {1,0,0} res[i+3] += 1 case {0,3,0}: res[i..i+2] = {1,1,0} res[i+3] += 1 case {0,2,1}: res[i..i+2] = {1,1,0} case {0,1,2}: res[i..i+2] = {1,0,1} end switch end for -- first stage cleanup if l>1 then if res[l-1]=3 then res = rep(res,l-2,{0,3,0},{1,1,1}) -- 030 -> 111 elsif res[l-1]=2 then if res[l-2]=0 then res = rep(res,l-2,{0,2,0},{1,0,1}) -- 020 -> 101 else res = rep(res,l-3,{0,1,2,0},{1,0,1,0}) -- 0120 -> 1010 end if end if end if if res[l]=3 then res = rep(res,l-1,{0,3},{1,1}) -- 03 -> 11 elsif res[l]=2 then if res[l-1]=0 then res = rep(res,l-1,{0,2},{1,0}) -- 02 -> 10 else res = rep(res,l-2,{0,1,2},{1,0,1}) -- 012 -> 101 end if end if -- second stage, pass 1, right to left, 011 -> 100 for i=length(res)-2 to 1 by -1 do if res[i..i+2]={0,1,1} then res[i..i+2] = {1,0,0} end if end for -- second stage, pass 2, left to right, 011 -> 100 for i=1 to length(res)-2 do if res[i..i+2]={0,1,1} then res[i..i+2] = {1,0,0} end if end for return to_int(res) end function function zadd(integer a, b) sequence {sa,sb} = to_bits2(a,b) return zcleanup(reverse(sq_add(sa,sb))) end function function zinc(integer a) return zadd(a,0b1) end function function zsub(integer a, b) sequence {sa,sb} = to_bits2(a,b) sequence res = reverse(sq_sub(sa,sb)) -- (/not/ combined with the first pass of the add routine!) for i=1 to length(res)-2 do switch res[i..i+2] do case {1, 0, 0}: res[i..i+2] = {0,1,1} case {1,-1, 0}: res[i..i+2] = {0,0,1} case {1,-1, 1}: res[i..i+2] = {0,0,2} case {1, 0,-1}: res[i..i+2] = {0,1,0} case {2, 0, 0}: res[i..i+2] = {1,1,1} case {2,-1, 0}: res[i..i+2] = {1,0,1} case {2,-1, 1}: res[i..i+2] = {1,0,2} case {2, 0,-1}: res[i..i+2] = {1,1,0} end switch end for -- copied from PicoLisp: {1,-1} -> {0,1} and {2,-1} -> {1,1} for i=1 to length(res)-1 do switch res[i..i+1] do case {1,-1}: res[i..i+1] = {0,1} case {2,-1}: res[i..i+1] = {1,1} end switch end for if find(-1,res) then ?9/0 end if -- sanity check return zcleanup(res) end function function zdec(integer a) return zsub(a,0b1) end function function zmul(integer a, b) integer res = 0 sequence mult = {a,zadd(a,a)} -- (as per task desc) integer bits = 2 while bits