k.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package kata
  2. import (
  3. "fmt"
  4. "math"
  5. "strconv"
  6. "strings"
  7. )
  8. func normalizeRational(s string) (n, d int) {
  9. sl := strings.Split(s, ".")
  10. n, _ = strconv.Atoi(sl[0])
  11. if len(sl) == 1 {
  12. return n, 1
  13. }
  14. var f float64
  15. fmt.Sscanf(s, "%f", &f)
  16. fd := math.Pow10(len(sl[1]))
  17. n = int(f * fd)
  18. d = int(fd)
  19. g := gcd(n, d)
  20. return n / g, d / g
  21. }
  22. func toFraction(s string) (n, d int) {
  23. sl := strings.Split(s, "/")
  24. n, d = normalizeRational(sl[0])
  25. if len(sl) == 1 {
  26. return
  27. }
  28. n2, d2 := normalizeRational(sl[1])
  29. n, d = n * d2, d * n2
  30. g := gcd(n, d)
  31. return n / g, d / g
  32. }
  33. // gcd from runtime/proc.go
  34. // (c) Go Authors - MIT License
  35. func gcd(a, b int) int {
  36. for b != 0 {
  37. a, b = b, a%b
  38. }
  39. return a
  40. }
  41. func fib(divs chan<- int, a, b int) {
  42. if a == 1 || a == 0 {
  43. divs <- b
  44. close(divs)
  45. return
  46. }
  47. // Smallest n larger than b/a or equal to it.
  48. r := int(math.Ceil(float64(b) / float64(a)))
  49. divs <- r
  50. n := a*r - b
  51. d := r * b
  52. g := gcd(n, d)
  53. n /= g
  54. d /= g
  55. fib(divs, n, d)
  56. }
  57. func Decompose(s string) []string {
  58. n, d := toFraction(s)
  59. res := []string{}
  60. // Handle degenerate cases first.
  61. // Just 0.
  62. if n == 0 {
  63. return res
  64. }
  65. // Larger than 1: start by floor(ratio).
  66. if n/d >= 1 {
  67. first := n / d
  68. res = append(res, fmt.Sprintf("%d", first))
  69. if n%d == 0 {
  70. return res
  71. }
  72. n -= first * d
  73. }
  74. // Now code can assume n != 0.
  75. divs := make(chan int)
  76. fmt.Println(s, n, d)
  77. go fib(divs, n, d)
  78. for div := range divs {
  79. res = append(res, fmt.Sprintf("1/%d", div))
  80. }
  81. return res
  82. }