cntinverse.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "os"
  6. )
  7. var vects = flag.Uint64("vects", 20, "number of vects (data+parity)")
  8. var data = flag.Uint64("data", 0, "number of data vects; keep it empty if you want to "+
  9. "get the max num of inverse matrix")
  10. func init() {
  11. flag.Usage = func() {
  12. fmt.Printf("Usage of %s:\n", os.Args[0])
  13. fmt.Println(" cntinverse [-flags]")
  14. fmt.Println(" Valid flags:")
  15. flag.PrintDefaults()
  16. }
  17. }
  18. func main() {
  19. flag.Parse()
  20. if *vects > 256 {
  21. fmt.Println("Error: vects must <= 256")
  22. os.Exit(1)
  23. }
  24. if *data == 0 {
  25. n := getMAXCCombination(*vects)
  26. fmt.Println("max num of inverse matrix :", n)
  27. os.Exit(0)
  28. }
  29. n := getCCombination(*vects, *data)
  30. fmt.Println("num of inverse matrix:", n)
  31. os.Exit(0)
  32. }
  33. func getMAXCCombination(a uint64) uint64 {
  34. b := a / 2 // proved in mathtool/combination.jpg
  35. return getCCombination(a, b)
  36. }
  37. func getCCombination(a, b uint64) uint64 {
  38. top := make([]uint64, a-b)
  39. bottom := make([]uint64, a-b-1)
  40. for i := b + 1; i <= a; i++ {
  41. top[i-b-1] = i
  42. }
  43. var i uint64
  44. for i = 2; i <= a-b; i++ {
  45. bottom[i-2] = i
  46. }
  47. for j := 0; j <= 5; j++ {
  48. cleanEven(top, bottom)
  49. clean3(top, bottom)
  50. clean5(top, bottom)
  51. }
  52. cleanCoffeRound1(top, bottom)
  53. if maxBottomBigger5more1(bottom) {
  54. top = shuffTop(top)
  55. cleanCoffeRound1(top, bottom)
  56. cleanCoffeRound1(bottom, top)
  57. cleanCoffeRound1(top, bottom)
  58. cleanCoffeRound1(bottom, top)
  59. cleanCoffeRound1(top, bottom)
  60. cleanCoffeRound1(bottom, top)
  61. }
  62. var topV, bottomV uint64 = 1, 1
  63. for _, t := range top {
  64. topV = topV * t
  65. }
  66. for _, b := range bottom {
  67. bottomV = bottomV * b
  68. }
  69. return topV / bottomV
  70. }
  71. func cleanEven(top, bottom []uint64) {
  72. for i, b := range bottom {
  73. if even(b) {
  74. for j, t := range top {
  75. if even(t) {
  76. top[j] = t / 2
  77. bottom[i] = b / 2
  78. break
  79. }
  80. }
  81. }
  82. }
  83. }
  84. func even(a uint64) bool {
  85. return a&1 == 0
  86. }
  87. func clean3(top, bottom []uint64) {
  88. for i, b := range bottom {
  89. if mod3(b) {
  90. for j, t := range top {
  91. if mod3(t) {
  92. top[j] = t / 3
  93. bottom[i] = b / 3
  94. break
  95. }
  96. }
  97. }
  98. }
  99. }
  100. func mod3(a uint64) bool {
  101. c := a / 3
  102. if 3*c == a {
  103. return true
  104. }
  105. return false
  106. }
  107. func clean5(top, bottom []uint64) {
  108. for i, b := range bottom {
  109. if mod5(b) {
  110. for j, t := range top {
  111. if mod5(t) {
  112. top[j] = t / 5
  113. bottom[i] = b / 5
  114. break
  115. }
  116. }
  117. }
  118. }
  119. }
  120. func mod5(a uint64) bool {
  121. c := a / 5
  122. if 5*c == a {
  123. return true
  124. }
  125. return false
  126. }
  127. func maxBottomBigger5more1(bottom []uint64) bool {
  128. cnt := 0
  129. for _, b := range bottom {
  130. if b >= 5 {
  131. cnt++
  132. }
  133. }
  134. if cnt >= 2 {
  135. return true
  136. }
  137. return false
  138. }
  139. func cleanCoffeRound1(top, bottom []uint64) {
  140. for i, b := range bottom {
  141. for j, t := range top {
  142. if isCoffe(b, t) {
  143. top[j] = t / b
  144. bottom[i] = 1
  145. break
  146. }
  147. }
  148. }
  149. }
  150. func isCoffe(b, t uint64) bool {
  151. c := t / b
  152. if c*b == t {
  153. return true
  154. }
  155. return false
  156. }
  157. func shuffTop(top []uint64) []uint64 {
  158. var tmp uint64 = 1
  159. newLen := len(top) + 1
  160. for i, t := range top {
  161. if t <= 5 {
  162. tmp = tmp * t
  163. newLen--
  164. top[i] = 1
  165. }
  166. }
  167. topNew := make([]uint64, newLen)
  168. topNew[0] = tmp
  169. cnt := 1
  170. for _, t := range top {
  171. if t != 1 {
  172. topNew[cnt] = t
  173. cnt++
  174. }
  175. }
  176. return topNew
  177. }