fibonacci_encoding.sf 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 24 April 2019
  4. # https://github.com/trizen
  5. # Encode positive integers in binary format, using the Fibonacci numbers.
  6. # Example:
  7. # 30 = "10100010" = 1×21 + 0×13 + 1×8 + 0×5 + 0×3 + 0×2 + 1×1 + 0×1
  8. # See also:
  9. # https://projecteuler.net/problem=473
  10. # https://en.wikipedia.org/wiki/Fibonacci_coding
  11. # https://en.wikipedia.org/wiki/Zeckendorf%27s_theorem
  12. # https://en.wikipedia.org/wiki/Golden_ratio_base
  13. func fibonacci_encoding(n) {
  14. return '0' if (n == 0)
  15. var phi = (sqrt(1.25) + 0.5)
  16. var idx = int((log(n) + log(5)/2) / log(phi))
  17. var (f1, f2) = (fib(idx), fib(idx-1))
  18. if (f1+f2 <= n) {
  19. (f1, f2) = (f1+f2, f1)
  20. }
  21. var enc = ''
  22. while (f1 > 0) {
  23. if (n >= f1) {
  24. n -= f1
  25. enc += '1'
  26. }
  27. else {
  28. enc += '0'
  29. }
  30. (f1, f2) = (f2, f1-f2)
  31. }
  32. return enc
  33. }
  34. func fibonacci_decoding(enc) {
  35. var len = enc.len
  36. var (f1, f2) = (fib(len), fib(len - 1))
  37. var dec = 0
  38. enc.each {|bit|
  39. dec += f1 if bit
  40. (f1, f2) = (f2, f1-f2)
  41. }
  42. return dec
  43. }
  44. say fibonacci_encoding(30) #=> 10100010
  45. say fibonacci_decoding('10100010') #=> 30
  46. say fibonacci_decoding(fibonacci_encoding(144)) #=> 144
  47. say fibonacci_decoding(fibonacci_encoding(144 - 1)) #=> 143
  48. say fibonacci_decoding(fibonacci_encoding(144 + 1)) #=> 145
  49. # Verify the encoding/decoding algorithm
  50. for n in (0..100) {
  51. if (fibonacci_decoding(fibonacci_encoding(n)) != n) {
  52. die "Error for #{n}";
  53. }
  54. }
  55. with (81923489126412312421758612841248123) {|n|
  56. assert_eq(fibonacci_decoding(fibonacci_encoding(n)), n)
  57. }