adventofcode/2017/day15/day15.go

118 lines
2.1 KiB
Go
Raw Normal View History

2017-12-15 13:15:23 +00:00
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
}