package aoc import ( "bufio" "fmt" "io/ioutil" "log" "os" "strconv" "strings" ) // Some handy Constants const ( BORDER_NS = "\u2502" BORDER_WE = "\u2500" BORDER_NW = "\u250C" BORDER_NE = "\u2510" BORDER_SW = "\u2514" BORDER_SE = "\u2518" FILL_CHAR = "\u2588" CLEAR_SCREEN = "\033[H\033[2J" MAX_INT = int(^uint(0) >> 1) MIN_INT = -MAX_INT - 1 ) // Find the greatest common denominator func Gcd(x, y int) int { for y != 0 { x, y = y, x%y } return x } // Find the least common multiple, using gcd func Lcm(a, b int, integers ...int) int { result := a * b / Gcd(a, b) for i := 0; i < len(integers); i++ { result = Lcm(result, integers[i]) } return result } func AbsInt(i int) int { if i < 0 { return i * -1 } return i } func ArgIsSet(a string) bool { for i := range os.Args { if os.Args[i] == a || strings.HasPrefix(os.Args[i], a+"=") { return true } } return false } func GetArgValue(a string) string { for i := range os.Args { if strings.HasPrefix(os.Args[i], a+"=") { return strings.TrimPrefix(os.Args[i], a+"=") } } return "" } func GetArgNumber(i int) string { if len(os.Args) > i { return os.Args[i] } return "" } func OptArgNumber(i int, def string) string { if len(os.Args) > i { return os.Args[i] } return def } func StdinToIntSlice() []int { var ret []int st := StdinToStringSlice() for _, v := range st { ret = append(ret, Atoi(v)) } return ret } func StdinToStringSlice() []string { var input []string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { input = append(input, scanner.Text()) } return input } func StdinToCoordMap() CoordByteMap { return StringSliceToCoordByteMap(StdinToStringSlice()) } func Atoi(i string) int { var ret int var err error if ret, err = strconv.Atoi(i); err != nil { log.Fatal("Invalid Atoi") } return ret } func Itoa(i int) string { return strconv.Itoa(i) } func StdinToString() string { var input string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { input += scanner.Text() } return input } func FileToStringSlice(fn string) []string { return strings.Split(string(FileToBytes(fn)), "\n") } func FileToString(fn string) string { return string(FileToBytes(fn)) } func FileToBytes(fn string) []byte { var c []byte var err error c, err = ioutil.ReadFile(fn) if err != nil { fmt.Println("Unable to read file: " + fn) os.Exit(1) } return c } func PrintProgress(curr, total int) { pct := int(float64(curr)/float64(total)) * 100 for i := 0; i < 100; i += 10 { if pct > i { fmt.Print(FILL_CHAR) } } } func StringPermutations(str string) []string { perms := stringPermHelper(str, 0) var wrk []string // Now de-dupe for i := range perms { var found bool for j := range wrk { if wrk[j] == perms[i] { found = true } } if !found { wrk = append(wrk, perms[i]) } } return wrk } func stringPermHelper(str string, i int) []string { ret := []string{str} if i != len(str) { r := []rune(str) for j := i; j < len(r); j++ { r[i], r[j] = r[j], r[i] ret = append(ret, stringPermHelper(string(r), i+1)...) r[i], r[j] = r[j], r[i] } } return ret } func IntPermutations(inp []int) [][]int { perms := intPermHelper(inp, 0) var wrk [][]int // Now de-dupe for i := range perms { var found bool for j := range wrk { if IntSlicesAreEqual(perms[i], wrk[j]) { found = true break } } if !found { wrk = append(wrk, perms[i]) } } return wrk } func intPermHelper(inp []int, i int) [][]int { ret := [][]int{inp} if i != len(inp) { r := make([]int, len(inp)) copy(r, inp) for j := i; j < len(r); j++ { r[i], r[j] = r[j], r[i] ret = append(ret, intPermHelper(r, i+1)...) r[i], r[j] = r[j], r[i] } } return ret } func IntSlicesAreEqual(s1 []int, s2 []int) bool { if len(s1) != len(s2) { return false } for k := range s1 { if s1[k] != s2[k] { return false } } return true }