From cccd9976dfa9f2801c48b3d762830f0291a080e8 Mon Sep 17 00:00:00 2001 From: Ben Charlton Date: Fri, 15 Dec 2017 12:20:44 +0000 Subject: [PATCH] days 13,14,15 --- 13/13.go | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++ 13/13_test.go | 36 +++++++++++ 14/14.go | 131 +++++++++++++++++++++++++++++++++++++ 15/15.go | 57 ++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 13/13.go create mode 100644 13/13_test.go create mode 100644 14/14.go create mode 100644 15/15.go diff --git a/13/13.go b/13/13.go new file mode 100644 index 0000000..a283395 --- /dev/null +++ b/13/13.go @@ -0,0 +1,176 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "sort" + "strconv" + "strings" + "time" +) + +type firewall struct { + pos int + size int + current int + up bool +} + +// cat input | go run 13.go + +func main() { + + scanner := bufio.NewScanner(os.Stdin) + + var fwdata = make(map[int]firewall) + + for scanner.Scan() { + + s := strings.Split(scanner.Text(), ": ") + pos, _ := strconv.Atoi(s[0]) + size, _ := strconv.Atoi(s[1]) + fwdata[pos] = firewall{pos, size - 1, 0, true} + } + + fmt.Println(RunFirewall(fwdata, 0)) + // We only need to do this once with RunFirewallFast + fwdata = ResetHash(fwdata) + + start := time.Now() + + fmt.Println(FindDelay(fwdata)) + + t := time.Now() + elapsed := t.Sub(start) + fmt.Println(elapsed) + +} + +func ResetHash(fw map[int]firewall) map[int]firewall { + for k, v := range fw { + v.current = 0 + fw[k] = v + } + return fw +} + +func FindDelay(fw map[int]firewall) int { + + // Work out the final position. + var keys []int + for k := range fw { + keys = append(keys, k) + } + sort.Ints(keys) + endpos := keys[len(keys)-1] + + // Using an array instead of hashmap drops from 300ms to 125 on my machine for my solution (3.96 million delay) + var t []int + for x := 0; x <= endpos; x++ { + t = append(t, (fw[x].size * 2)) + } + +Loop: + for i := 0; ; i++ { + // You can see earlier, slower (~300ms) version of this inner loop as a function below. This brings it down to ~100ms. + for j := i; j <= i+endpos; j++ { + p := t[j-i] + if p != 0 && j%p == 0 { + continue Loop + } + } + return i + } + + // slower hashmap version + /* + for i := 0; ; i++ { + _, caught := RunFirewallFast(fw, i, endpos) + if !caught { + fmt.Println(i) + break + } + } + */ +} + +// Well, the obvious solution is incredibly slow, and we don't need +// to resolve the full 'caught' number, so we can make this dramatically faster. +// It took less time to rewrite this than to run the result using RunFirewall... +func RunFirewallFast(fw map[int]firewall, delay int, endpos int) (int, bool) { + for j := delay; j <= delay+endpos; j++ { + a, exists := fw[j-delay] + if exists { + interval := a.size * 2 + if j%interval == 0 { + return 0, true + } + } + } + + return 0, false +} + +func RunFirewall(fw map[int]firewall, delay int) (int, bool) { + caught := 0 + caughtBool := false + + var keys []int + for k := range fw { + keys = append(keys, k) + } + sort.Ints(keys) + + endpos := keys[len(keys)-1] + mypos := -1 + + for i := 0; ; i++ { + + // Start moving after the delay + if i >= delay { + mypos++ + } + + // Have we been caught? + _, exists := fw[mypos] + if exists && mypos >= 0 && fw[mypos].current == 0 { + caught = caught + (fw[mypos].pos * (fw[mypos].size + 1)) + fmt.Println("Caught", mypos, caught, i, delay) + caughtBool = true + // Skip further rounds if we're just looking for the delay + if delay > 0 { + return 0, true + } + } + + // End! + if mypos == endpos { + break + } + + // Move scanners for this round + for _, k := range keys { + c := fw[k] + + if c.current == c.size { + c.up = false + } + if c.current == 0 { + c.up = true + } + + if c.up { + c.current++ + } else { + c.current-- + } + + fw[k] = c + } + + } + + return caught, caughtBool + +} diff --git a/13/13_test.go b/13/13_test.go new file mode 100644 index 0000000..1010351 --- /dev/null +++ b/13/13_test.go @@ -0,0 +1,36 @@ +package main + +import ( + "testing" +) + +var test = map[int]firewall{ + 0: {0, 2, 0, true}, + 1: {1, 1, 0, true}, + 4: {4, 3, 0, true}, + 6: {6, 3, 0, true}, +} + +func TestFindDelay(t *testing.T) { + test = ResetHash(test) + v := FindDelay(test) + if v != 10 { + t.Error( + "For", test, + "expected 10", + "got", v, + ) + } +} + +func TestRunFirewall(t *testing.T) { + test = ResetHash(test) + v, _ := RunFirewall(test, 0) + if v != 24 { + t.Error( + "For", test, + "expected 24", + "got", v, + ) + } +} diff --git a/14/14.go b/14/14.go new file mode 100644 index 0000000..1669b70 --- /dev/null +++ b/14/14.go @@ -0,0 +1,131 @@ +package main + +import ( + "fmt" + "os" + //"strconv" +) + +// go run 14.go "input" + +func main() { + + s := os.Args[1] + ones := 0 + + squareSize := 128 + grid := make([][]int, squareSize) + + for x := 0; x < squareSize; x++ { + lineSeed := fmt.Sprint(s, "-", x) + hash := MakeHash(lineSeed) + ones += CountOnes(hash) + grid[x] = BuildGrid(hash) + } + + regionCount := 1 + for y := 0; y < squareSize; y++ { + for x := 0; x < squareSize; x++ { + grid, regionCount = CountRegions(grid, x, y, regionCount) + } + } + + fmt.Println(ones) + fmt.Println(regionCount-1) + +} + +func CountRegions (grid [][]int, x int, y int, regionCount int) ([][]int, int) { + if x < 0 || x >= len(grid) || y < 0 || y >= len(grid) { + return grid,regionCount + } + + if grid[x][y] == -1 { + return grid, regionCount + } + + if grid[x][y] == 0 { + grid[x][y] = regionCount + grid,_ = CountRegions(grid, x+1, y, regionCount) + grid,_ = CountRegions(grid, x-1, y, regionCount) + grid,_ = CountRegions(grid, x, y+1, regionCount) + grid,_ = CountRegions(grid, x, y-1, regionCount) + regionCount++ + } + + return grid, regionCount +} + +func BuildGrid (s string) []int { + y := make([]int, len(s)) + + for i := range s { + if s[i] == 49 { + y[i] = 0 + } else { + y[i] = -1 + } + } + + return y +} + +func CountOnes (s string) int { + count := 0 + for x := range s { + if s[x] == 49 { + count++ + } + } + return count +} + + +func MakeHash (s string) string { + + size := 256 + appendList := []byte{17, 31, 73, 47, 23} + + s = s + string(appendList) + + list := make([]int, size) + for i := 0; i < size; i++ { + list[i] = i + } + + pos := 0 + skip := 0 + + for j := 0; j < 64; j++ { + for x := range s { + + i := int(s[x]) + + // Reverse the section + r := i/2 + + for y := 0; y < r; y++ { + bottom := (pos+y) % size + top := (pos+i-y-1) % size + tmp := list[bottom] + list[bottom] = list[top] + list[top] = tmp + } + + pos = (pos+i+skip) % size + skip++ + } + } + + ret := "" + for a:=0; a<16; a++ { + r := list[a*16] + for b:=1; b<16; b++ { + xorpos := (a*16)+b + r = r ^ list[xorpos] + } + ret = ret + fmt.Sprintf("%08b", r) //+ " " + } + return ret + +} diff --git a/15/15.go b/15/15.go new file mode 100644 index 0000000..54054bc --- /dev/null +++ b/15/15.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +// go run 15.go inputA inputB + +func main() { + + genA,_ := strconv.Atoi(os.Args[1]) + genB,_ := strconv.Atoi(os.Args[2]) + + rounds1 := 40000000 + rounds2 := 5000000 + + fmt.Println(Calc(genA, genB, 1,1,rounds1)) + fmt.Println(Calc(genA, genB, 4,8,rounds2)) +} + + +func Calc (genA int, genB int, modA int, modB int, rounds int) int { + genAFactor := 16807 + genBFactor := 48271 + div := 2147483647 + judge := 0 + + for i := 0; i < rounds; i++ { + + for { + genA = (genA * genAFactor) % div + if genA % modA == 0 { + break + } + } + + for { + genB = (genB * genBFactor) % div + if genB % modB == 0 { + break + } + } + + tA := genA + tA = tA % 65536 + + tB := genB + tB = tB % 65536 + + if tA == tB { + judge++ + } + } + return judge +}