123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- package main
- import (
- "flag"
- "fmt"
- "os"
- )
- var vects = flag.Uint64("vects", 20, "number of vects (data+parity)")
- var data = flag.Uint64("data", 0, "number of data vects; keep it empty if you want to "+
- "get the max num of inverse matrix")
- func init() {
- flag.Usage = func() {
- fmt.Printf("Usage of %s:\n", os.Args[0])
- fmt.Println(" cntinverse [-flags]")
- fmt.Println(" Valid flags:")
- flag.PrintDefaults()
- }
- }
- func main() {
- flag.Parse()
- if *vects > 256 {
- fmt.Println("Error: vects must <= 256")
- os.Exit(1)
- }
- if *data == 0 {
- n := getMAXCCombination(*vects)
- fmt.Println("max num of inverse matrix :", n)
- os.Exit(0)
- }
- n := getCCombination(*vects, *data)
- fmt.Println("num of inverse matrix:", n)
- os.Exit(0)
- }
- func getMAXCCombination(a uint64) uint64 {
- b := a / 2 // proved in mathtool/combination.jpg
- return getCCombination(a, b)
- }
- func getCCombination(a, b uint64) uint64 {
- top := make([]uint64, a-b)
- bottom := make([]uint64, a-b-1)
- for i := b + 1; i <= a; i++ {
- top[i-b-1] = i
- }
- var i uint64
- for i = 2; i <= a-b; i++ {
- bottom[i-2] = i
- }
- for j := 0; j <= 5; j++ {
- cleanEven(top, bottom)
- clean3(top, bottom)
- clean5(top, bottom)
- }
- cleanCoffeRound1(top, bottom)
- if maxBottomBigger5more1(bottom) {
- top = shuffTop(top)
- cleanCoffeRound1(top, bottom)
- cleanCoffeRound1(bottom, top)
- cleanCoffeRound1(top, bottom)
- cleanCoffeRound1(bottom, top)
- cleanCoffeRound1(top, bottom)
- cleanCoffeRound1(bottom, top)
- }
- var topV, bottomV uint64 = 1, 1
- for _, t := range top {
- topV = topV * t
- }
- for _, b := range bottom {
- bottomV = bottomV * b
- }
- return topV / bottomV
- }
- func cleanEven(top, bottom []uint64) {
- for i, b := range bottom {
- if even(b) {
- for j, t := range top {
- if even(t) {
- top[j] = t / 2
- bottom[i] = b / 2
- break
- }
- }
- }
- }
- }
- func even(a uint64) bool {
- return a&1 == 0
- }
- func clean3(top, bottom []uint64) {
- for i, b := range bottom {
- if mod3(b) {
- for j, t := range top {
- if mod3(t) {
- top[j] = t / 3
- bottom[i] = b / 3
- break
- }
- }
- }
- }
- }
- func mod3(a uint64) bool {
- c := a / 3
- if 3*c == a {
- return true
- }
- return false
- }
- func clean5(top, bottom []uint64) {
- for i, b := range bottom {
- if mod5(b) {
- for j, t := range top {
- if mod5(t) {
- top[j] = t / 5
- bottom[i] = b / 5
- break
- }
- }
- }
- }
- }
- func mod5(a uint64) bool {
- c := a / 5
- if 5*c == a {
- return true
- }
- return false
- }
- func maxBottomBigger5more1(bottom []uint64) bool {
- cnt := 0
- for _, b := range bottom {
- if b >= 5 {
- cnt++
- }
- }
- if cnt >= 2 {
- return true
- }
- return false
- }
- func cleanCoffeRound1(top, bottom []uint64) {
- for i, b := range bottom {
- for j, t := range top {
- if isCoffe(b, t) {
- top[j] = t / b
- bottom[i] = 1
- break
- }
- }
- }
- }
- func isCoffe(b, t uint64) bool {
- c := t / b
- if c*b == t {
- return true
- }
- return false
- }
- func shuffTop(top []uint64) []uint64 {
- var tmp uint64 = 1
- newLen := len(top) + 1
- for i, t := range top {
- if t <= 5 {
- tmp = tmp * t
- newLen--
- top[i] = 1
- }
- }
- topNew := make([]uint64, newLen)
- topNew[0] = tmp
- cnt := 1
- for _, t := range top {
- if t != 1 {
- topNew[cnt] = t
- cnt++
- }
- }
- return topNew
- }
|