-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfibonacci_encoding.sf
80 lines (57 loc) · 1.67 KB
/
fibonacci_encoding.sf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/ruby
# Daniel "Trizen" Șuteu
# Date: 24 April 2019
# https://github.com/trizen
# Encode positive integers in binary format, using the Fibonacci numbers.
# Example:
# 30 = "10100010" = 1×21 + 0×13 + 1×8 + 0×5 + 0×3 + 0×2 + 1×1 + 0×1
# See also:
# https://projecteuler.net/problem=473
# https://en.wikipedia.org/wiki/Fibonacci_coding
# https://en.wikipedia.org/wiki/Zeckendorf%27s_theorem
# https://en.wikipedia.org/wiki/Golden_ratio_base
func fibonacci_encoding(n) {
return '0' if (n == 0)
var phi = (sqrt(1.25) + 0.5)
var idx = int((log(n) + log(5)/2) / log(phi))
var (f1, f2) = (fib(idx), fib(idx-1))
if (f1+f2 <= n) {
(f1, f2) = (f1+f2, f1)
}
var enc = ''
while (f1 > 0) {
if (n >= f1) {
n -= f1
enc += '1'
}
else {
enc += '0'
}
(f1, f2) = (f2, f1-f2)
}
return enc
}
func fibonacci_decoding(enc) {
var len = enc.len
var (f1, f2) = (fib(len), fib(len - 1))
var dec = 0
enc.each {|bit|
dec += f1 if bit
(f1, f2) = (f2, f1-f2)
}
return dec
}
say fibonacci_encoding(30) #=> 10100010
say fibonacci_decoding('10100010') #=> 30
say fibonacci_decoding(fibonacci_encoding(144)) #=> 144
say fibonacci_decoding(fibonacci_encoding(144 - 1)) #=> 143
say fibonacci_decoding(fibonacci_encoding(144 + 1)) #=> 145
# Verify the encoding/decoding algorithm
for n in (0..100) {
if (fibonacci_decoding(fibonacci_encoding(n)) != n) {
die "Error for #{n}";
}
}
with (81923489126412312421758612841248123) {|n|
assert_eq(fibonacci_decoding(fibonacci_encoding(n)), n)
}