diff --git a/2017/day15/day15.go b/2017/day15/day15.go new file mode 100644 index 0000000..18e4a32 --- /dev/null +++ b/2017/day15/day15.go @@ -0,0 +1,117 @@ +package main + +import ( + "fmt" + "os" + "strings" + "log" + "strconv" + "time" +) + +var aFact, bFact int +var doPart1, judgeIsDone bool +var score int + +func main() { + var doPart1 bool + // My input + aStart := 679 + bStart := 771 + for i := range os.Args { + if strings.HasPrefix(os.Args[i], "-a") { + pts := strings.Split(os.Args[i], "=") + if len(pts) == 2 { + aStart = Atoi(pts[1]) + } + } else if strings.HasPrefix(os.Args[i], "-b") { + pts := strings.Split(os.Args[i], "=") + if len(pts) == 2 { + bStart = Atoi(pts[1]) + } + } + if os.Args[i] == "-test" { + aStart = 65 + bStart = 8921 + } + if os.Args[i] == "-1" { + doPart1 = true + } + } + + aFact = 16807 + bFact = 48271 + + if doPart1 { + solve(aStart, 1, bStart, 1, 40000000) + } else { + solve(aStart, 4, bStart, 8, 5000000) + } +} + +func solve(aStart, aMod, bStart, bMod, target int) { + fmt.Println("= Part 2 =") + fmt.Print("(A ",aStart,"; B ",bStart,")\n") + + judgeChanA := make(chan int) + judgeChanB := make(chan int) + + // The Judge Process + go judgeWork(target, judgeChanA, judgeChanB) + + // Generator A Process + go genWork(aStart, aFact, aMod, judgeChanA) + // Generator B Process + go genWork(bStart, bFact, bMod, judgeChanB) + + // Wait for the judge to say he's done + for !judgeIsDone { + time.Sleep(500) + } + fmt.Println("\nFinal",score) +} + +func judgeWork(target int, judgeChanA, judgeChanB chan int) { + for i := 0; i < target; i++ { + aVal := <-judgeChanA + bVal := <-judgeChanB + if i % (target / 25) == 0 { + fmt.Print(".") + } + if judge(aVal, bVal) { + score++ + } + } + judgeIsDone = true +} + +func genWork(start, fact, mod int, judgeChan chan int) { + for !judgeIsDone { + start = getNextVal(start, fact) + if start % mod == 0 { + judgeChan <- start + } + } +} + +func getNextVal(prev, fact int) int { + return (prev * fact) % 2147483647 +} + +func judge(aVal, bVal int) bool { + aBin, bBin := GetBinaryString(aVal), GetBinaryString(bVal) + return aBin[len(aBin)-16:] == bBin[len(bBin)-16:] +} + +func GetBinaryString(inp int) string { + return fmt.Sprintf("%032b", inp) +} + +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 +}