package main

import (
    "fmt"
    "math/rand"
    "strconv"
    "strings"
    "time"
)

func factorial(n int) int {
    fact := 1
    for i := 2; i <= n; i++ {
        fact *= i
    }
    return fact
}

func genFactBaseNums(size int, countOnly bool) ([][]int, int) {
    var results [][]int
    count := 0
    for n := 0; ; n++ {
        radix := 2
        var res []int = nil
        if !countOnly { 
            res = make([]int, size)
        }
        k := n
        for k > 0 {
            div := k / radix
            rem := k % radix
            if !countOnly {
                if radix <= size+1 {
                    res[size-radix+1] = rem
                }
            }
            k = div
            radix++
        }
        if radix > size+2 {
            break
        }
        count++
        if !countOnly {
            results = append(results, res)
        }
    }
    return results, count
}

func mapToPerms(factNums [][]int) [][]int {
    var perms [][]int
    psize := len(factNums[0]) + 1
    start := make([]int, psize)
    for i := 0; i < psize; i++ {
        start[i] = i
    }
    for _, fn := range factNums {
        perm := make([]int, psize)
        copy(perm, start)
        for m := 0; m < len(fn); m++ {
            g := fn[m]
            if g == 0 {
                continue
            }
            first := m
            last := m + g
            for i := 1; i <= g; i++ {
                temp := perm[first]
                for j := first + 1; j <= last; j++ {
                    perm[j-1] = perm[j]
                }
                perm[last] = temp
            }
        }
        perms = append(perms, perm)
    }
    return perms
}

func join(is []int, sep string) string {
    ss := make([]string, len(is))
    for i := 0; i < len(is); i++ {
        ss[i] = strconv.Itoa(is[i])
    }
    return strings.Join(ss, sep)
}

func undot(s string) []int {
    ss := strings.Split(s, ".")
    is := make([]int, len(ss))
    for i := 0; i < len(ss); i++ {
        is[i], _ = strconv.Atoi(ss[i])
    }
    return is
}

func main() {
    rand.Seed(time.Now().UnixNano())