diff --git a/2017/day21/day21.go b/2017/day21/day21.go new file mode 100644 index 0000000..1c6c70b --- /dev/null +++ b/2017/day21/day21.go @@ -0,0 +1,317 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "math" + "os" + "strings" + "time" +) + +var allRules []Rule + +func main() { + inp := StdinToStrings() + for i := range inp { + allRules = append(allRules, Rule(inp[i])) + } + //pattern := Pattern(".#./..#/###") + pattern := Pattern("../##") + fmt.Println(pattern) + if !pattern.IsValid() { + fmt.Println("Invalid Pattern Given. Must be square.") + } + ClearScreen() + pattern.PrettyPrint() + time.Sleep(time.Second) + for iters := 0; iters < 5; iters++ { + ClearScreen() + pattern = Tick(pattern) + pattern.PrettyPrint() + time.Sleep(time.Second) + } + fmt.Println("On:", pattern.GetOnCount()) +} + +// Stitch takes a slice of patterns and turns them into one large (square) pattern +func Stitch(inp []Pattern) Pattern { + ppr := int(math.Sqrt(float64(len(inp)))) + newSize := ppr * inp[0].Size() + var currRow int + rows := make(map[int]string) + for i := 0; i < len(inp); i++ { + currRow = (i / ppr) * 2 + for j := 0; j < len(inp[0]); j++ { + if len(rows[currRow+j]) == newSize { + rows[currRow+j] += "/" + } + rows[currRow+j] += inp[i].GetRow(j) + } + } + var lines []string + for i := 0; i < newSize; i++ { + lines = append(lines, rows[i]) + } + + return Pattern(strings.Join(lines, "/")) +} + +// Run the pattern, or all of it's subpatterns +// through the rules and return the new pattern +func Tick(inp Pattern) Pattern { + if inp.SubpatternCount() > 1 { + var subs []Pattern + // Tick each subpattern + for i := 0; i < inp.SubpatternCount(); i++ { + if s := inp.GetSubpattern(i); s.IsValid() { + subs = append(subs, Tick(s)) + } else { + log.Fatal("Error ticking pattern") + } + } + return Stitch(subs) + } + + var foundMatch bool + for i := range allRules { + if allRules[i].Matches(inp) { + inp = allRules[i].Output() + foundMatch = true + } + } + if !foundMatch { + fmt.Println("~ ERROR TICKING ~") + inp.PrettyPrint() + fmt.Println("~ ERROR TICKING ~") + os.Exit(1) + } + return inp +} + +/** + * A pattern is a string with some special methods + */ +type Pattern string + +// Print a pattern prettily. (in a square) +func (p Pattern) PrettyPrint() { + pts := strings.Split(string(p), "/") + for i := range pts { + fmt.Println(pts[i]) + } +} + +func (p Pattern) GetOnCount() int { + return strings.Count(string(p), "#") +} + +// Returns if a pattern is valid. +// A pattern is valid if it has more than 0 rows +// and every row is the same length as the number +// of columns +func (p Pattern) IsValid() bool { + pts := strings.Split(string(p), "/") + if len(pts) == 0 { + return false + } + for i := range pts { + if len(pts[i]) != len(pts) { + return false + } + } + return true +} + +// Returns the "size" of the pattern +// That is, how many rows/columns it has +func (p Pattern) Size() int { + return len(strings.Split(string(p), "/")) +} + +// Flip returns a new pattern that has been flipped horizontally +func (p Pattern) Flip() Pattern { + // We can only flip the smallest patterns (2x2 or 3x3) + if p.SubpatternCount() != 1 { + return p + } + pts := strings.Split(string(p), "/") + for i := range pts { + pts[i] = RevString(pts[i]) + } + return Pattern(strings.Join(pts, "/")) +} + +// Rotate returns a new pattern that has been rotated deg degrees +// Only right-angles +func (p Pattern) Rotate(deg int) Pattern { + // We can only rotate the smallest patterns (2x2 or 3x3) + if p.SubpatternCount() != 1 { + return p + } + + if deg < 0 { + deg += 360 + } else if deg == 0 { + return p + } + + pts := strings.Split(string(p), "/") + ret := make([]string, len(pts)) + use := p + switch deg { + case 90: + if p.Size()%3 == 0 { + ret[0] = RevString(use.GetCol(2)) + ret[1] = RevString(use.GetCol(1)) + ret[2] = RevString(use.GetCol(0)) + } else { + ret[0] = RevString(use.GetCol(1)) + ret[1] = RevString(use.GetCol(0)) + } + case 180: + if p.Size()%3 == 0 { + ret[0] = RevString(use.GetRow(2)) + ret[1] = RevString(use.GetRow(1)) + ret[2] = RevString(use.GetRow(0)) + } else { + ret[0] = RevString(use.GetRow(1)) + ret[1] = RevString(use.GetRow(0)) + } + case 270: + if p.Size()%3 == 0 { + ret[0] = use.GetCol(2) + ret[1] = use.GetCol(1) + ret[2] = use.GetCol(0) + } else { + ret[0] = use.GetCol(1) + ret[1] = use.GetCol(0) + } + + } + use = Pattern(strings.Join(ret, "/")) + return Pattern(strings.Join(ret, "/")) +} + +// GetRow returns a row as a string +func (p Pattern) GetRow(row int) string { + pts := strings.Split(string(p), "/") + if row >= len(pts) { + return "" + } + return pts[row] +} + +// GetCol returns a column as a string +func (p Pattern) GetCol(col int) string { + var ret string + pts := strings.Split(string(p), "/") + if col >= len(pts[0]) { + return "" + } + for i := 0; i < len(pts); i++ { + ret = ret + string(pts[i][col]) + } + return ret +} + +// Counts the number of subpatterns in the pattern +func (p Pattern) SubpatternCount() int { + if p.Size()%2 == 0 { + return (p.Size() / 2) * (p.Size() / 2) + } else { + return (p.Size() / 3) * (p.Size() / 3) + } +} + +// Gets a specific subpattern out of the pattern +func (p Pattern) GetSubpattern(i int) Pattern { + if i > p.SubpatternCount() { + return Pattern("") + } + subSize := 3 // Assume 3x3 subpatterns + if p.Size()%2 == 0 { + // Subpatterns are actually 2x2 + subSize = 2 + } + ppr := p.Size() / subSize + col := i % (p.Size() / subSize) + row := i / ppr + ptString := "" + for j := 0; j < subSize; j++ { + ptString += p.GetRow((row * 2) + j)[(col*subSize):(col*subSize)+subSize] + "/" + } + return Pattern(ptString[:len(ptString)-1]) +} + +/** + * Rule is an interface that can take a pattern and return if it matches, + * report on it's size, or return the resulting pattern from applying itself + * to a pattern + */ +type RuleFace interface { + Matches(inp Pattern) bool + InputSize() int + Apply(inp Pattern) Pattern +} + +/** + * Rule implements the RuleFace interface + * for 2x2 => 3x3 transitions + * or 3x3 => 4x4 transitions + */ +type Rule string + +func (r Rule) Input() Pattern { + pts := strings.Split(string(r), " ") + return Pattern(pts[0]) +} + +func (r Rule) Output() Pattern { + pts := strings.Split(string(r), " ") + return Pattern(pts[2]) +} + +func (r Rule) Matches(inp Pattern) bool { + if inp.Size() != r.InputSize() { + return false + } + // Try it rotated 90,180,270 + for i := 0; i < 360; i += 90 { + if r.Equals(inp.Rotate(i)) || r.Equals(inp.Flip().Rotate(i)) { + return true + } + } + return false +} + +func (r Rule) InputSize() int { + return len(strings.Split(string(r.Input()), "/")) +} + +// Equals is a direct string comparison +func (r Rule) Equals(inp Pattern) bool { + return string(r.Input()) == string(inp) +} + +func RevString(s string) string { + runes := []rune(s) + for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { + runes[i], runes[j] = runes[j], runes[i] + } + return string(runes) +} + +func ClearScreen() { + fmt.Println("\033[H\033[2J") +} + +func StdinToStrings() []string { + var input []string + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + input = append(input, scanner.Text()) + } + return input +} diff --git a/2017/day21/input b/2017/day21/input new file mode 100644 index 0000000..6516274 --- /dev/null +++ b/2017/day21/input @@ -0,0 +1,108 @@ +../.. => .../.../..# +#./.. => #.#/..#/... +##/.. => #.#/..#/#.# +.#/#. => #../.../.## +##/#. => ###/#.#/..# +##/## => #.#/.../#.. +.../.../... => #..#/..../.##./.... +#../.../... => ..../.##./#.../.##. +.#./.../... => .#../####/..##/#... +##./.../... => ##.#/..#./####/...# +#.#/.../... => ##.#/##../#.#./.#.. +###/.../... => #..#/#..#/##../##.# +.#./#../... => #.##/##../.#.#/..## +##./#../... => #.#./..../.###/.#.# +..#/#../... => ..##/####/..##/.... +#.#/#../... => ..##/###./..##/#... +.##/#../... => #.../####/#..#/##.. +###/#../... => ...#/..../..##/#... +.../.#./... => ##../##../..##/.... +#../.#./... => #.../.#.#/.##./#..# +.#./.#./... => ..##/#.../...#/###. +##./.#./... => ####/.#.#/..##/#### +#.#/.#./... => ####/.#../#.##/#..# +###/.#./... => ..#./#..#/.#.#/###. +.#./##./... => ##../.#.#/#..#/#..# +##./##./... => .###/####/#..#/..## +..#/##./... => ###./.#../..#./#.## +#.#/##./... => ##../#.#./#.../.#.# +.##/##./... => #.../#.../.#.#/#### +###/##./... => .#../####/#.../#.#. +.../#.#/... => .#../..../##../.### +#../#.#/... => .##./...#/.###/...# +.#./#.#/... => ...#/#.../...#/#### +##./#.#/... => #.##/..#./#..#/.#.# +#.#/#.#/... => #..#/..../..##/..#. +###/#.#/... => .#.#/#.#./##.#/#.#. +.../###/... => ##../.##./###./###. +#../###/... => ###./..##/.#../##.# +.#./###/... => .#../##../..../..## +##./###/... => #.#./...#/...#/##.. +#.#/###/... => ..../.#../#.../.#.. +###/###/... => ..#./.###/..../##.# +..#/.../#.. => #.#./.#../...#/##.# +#.#/.../#.. => ...#/##.#/#.#./#... +.##/.../#.. => ...#/..##/#.##/##.# +###/.../#.. => #..#/.#.#/.##./..#. +.##/#../#.. => ##../..#./#.##/##.. +###/#../#.. => ..../###./#.#./##.. +..#/.#./#.. => #.#./.##./.##./#... +#.#/.#./#.. => .#../#..#/#.#./#... +.##/.#./#.. => .#.#/#..#/..#./.... +###/.#./#.. => #.##/####/#.../..#. +.##/##./#.. => #.##/.#.#/..../.#.. +###/##./#.. => #.##/####/.###/##.. +#../..#/#.. => ###./#.##/..#./..## +.#./..#/#.. => ##../.#../..#./..## +##./..#/#.. => #..#/.#../..../##.# +#.#/..#/#.. => .###/.##./..#./#.#. +.##/..#/#.. => .#.#/..../####/.#.. +###/..#/#.. => .##./##../...#/.#.. +#../#.#/#.. => #.#./#.##/..../.### +.#./#.#/#.. => ####/#.#./.#../#.## +##./#.#/#.. => ..##/.###/###./..#. +..#/#.#/#.. => .##./..#./..../#.#. +#.#/#.#/#.. => .###/..../..../##.. +.##/#.#/#.. => #.#./#.../####/.### +###/#.#/#.. => #.../..##/###./#..# +#../.##/#.. => ..../#.#./..##/.#.# +.#./.##/#.. => ..##/..##/#..#/###. +##./.##/#.. => #.../.#../#.#./#.## +#.#/.##/#.. => ...#/#.../...#/###. +.##/.##/#.. => ###./..../..##/#..# +###/.##/#.. => #.#./##.#/####/#.#. +#../###/#.. => ##../##../###./#..# +.#./###/#.. => #.##/###./####/..## +##./###/#.. => ..../.###/###./.#.. +..#/###/#.. => .###/..../..#./.... +#.#/###/#.. => ####/#..#/.#.#/..## +.##/###/#.. => ..../##.#/####/##.# +###/###/#.. => #..#/.#.#/###./.##. +.#./#.#/.#. => #.##/...#/###./.... +##./#.#/.#. => #..#/.#../..../#.#. +#.#/#.#/.#. => .#.#/####/..../.#.# +###/#.#/.#. => #.#./#.##/##.#/##.. +.#./###/.#. => ..#./..../##../#### +##./###/.#. => #.##/##.#/#.##/.#.. +#.#/###/.#. => .#.#/..##/##.#/#### +###/###/.#. => .#../...#/#..#/#.#. +#.#/..#/##. => .##./..#./...#/##.# +###/..#/##. => ..#./##.#/#..#/#..# +.##/#.#/##. => ##.#/#.../#..#/...# +###/#.#/##. => ##../.#../..../.##. +#.#/.##/##. => #.##/##.#/.#../.### +###/.##/##. => ..../#.#./##../##.# +.##/###/##. => ###./.#.#/.##./.### +###/###/##. => #..#/.###/#.../#... +#.#/.../#.# => .###/#.##/.#.#/#.#. +###/.../#.# => ...#/##../...#/##.# +###/#../#.# => ..../..#./..#./#### +#.#/.#./#.# => ##../#.##/...#/#... +###/.#./#.# => #.#./...#/.#../#... +###/##./#.# => .#../..#./...#/##.. +#.#/#.#/#.# => ####/#.##/.#../##.. +###/#.#/#.# => #.../#.../###./.#.. +#.#/###/#.# => ####/.#.#/.##./.#.# +###/###/#.# => #.##/.#.#/##.#/..## +###/#.#/### => .###/#.##/..../..#. +###/###/### => .###/#..#/##../.##. diff --git a/2017/day21/testinput b/2017/day21/testinput new file mode 100644 index 0000000..f6d24df --- /dev/null +++ b/2017/day21/testinput @@ -0,0 +1,2 @@ +../.# => ##./#../... +.#./..#/### => #..#/..../..../#..# diff --git a/2017/day22/day22.go b/2017/day22/day22.go new file mode 100644 index 0000000..2fd306e --- /dev/null +++ b/2017/day22/day22.go @@ -0,0 +1,213 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "os" + "strconv" + "strings" +) + +const ( + N = iota + E + S + W +) + +const ( + ST_CLEAN = iota + ST_WEAK + ST_INFECTED + ST_FLAGGED + ST_ERROR +) + +var nodes map[string]int +var cX, cY, cD int +var minX, minY, maxX, maxY int +var tickCount, infectCount int + +func main() { + inp := StdinToStrings() + nodes = make(map[string]int) + cX, cY, cD = len(inp)/2, len(inp[0])/2, N + for y := 0; y < len(inp); y++ { + for x := 0; x < len(inp[y]); x++ { + nodes[cs(x, y)] = ST_CLEAN + if inp[y][x] == '#' { + nodes[cs(x, y)] = ST_INFECTED + } + updateMinMax(x, y) + } + } + + for i := 0; i < 10000000; i++ { + //ClearScreen() + if part1 { + p1Tick() + } else { + p2Tick() + } + //PrettyPrint() + //PrintStatus() + //time.Sleep(time.Second / 5) + } +} + +func p1Tick() { + tickCount++ + switch nodes[cs(cX, cY)] { + case ST_INFECTED: + TurnRight() + nodes[cs(cX, cY)] = ST_CLEAN + infectCount++ + default: + TurnLeft() + nodes[cs(cX, cY)] = ST_INFECTED + infectCount++ + } + cX, cY = getXYInDir() + updateMinMax(cX, cY) +} + +func p2Tick() { + tickCount++ + switch nodes[cs(cX, cY)] { + case ST_CLEAN: + TurnLeft() + nodes[cs(cX, cY)] = ST_WEAK + case ST_WEAK: + nodes[cs(cX, cY)] = ST_INFECTED + infectCount++ + case ST_INFECTED: + TurnRight() + nodes[cs(cX, cY)] = ST_FLAGGED + case ST_FLAGGED: + TurnRight() + TurnRight() + nodes[cs(cX, cY)] = ST_CLEAN + } + cX, cY = getXYInDir() + updateMinMax(cX, cY) +} + +func updateMinMax(x, y int) { + if x < minX { + minX = x + } + if x > maxX { + maxX = x + } + if y < minY { + minY = y + } + if y > maxY { + maxY = y + } +} + +func PrettyPrint() { + for kY := minY; kY <= maxY; kY++ { + for kX := minX; kX <= maxX; kX++ { + if kX == cX && kY == cY { + fmt.Print("[") + } else { + fmt.Print(" ") + } + switch nodes[cs(kX, kY)] { + case ST_CLEAN: + fmt.Print(".") + case ST_WEAK: + fmt.Print("W") + case ST_INFECTED: + fmt.Print("#") + case ST_FLAGGED: + fmt.Print("F") + } + if kX == cX && kY == cY { + fmt.Print("]") + } else { + fmt.Print(" ") + } + } + fmt.Println() + } +} + +func PrintStatus() { + fmt.Println("Ticks:", tickCount) + fmt.Println("Infections:", infectCount) +} + +func TurnRight() { + switch cD { + case N: + cD = E + case E: + cD = S + case S: + cD = W + case W: + cD = N + } +} + +func TurnLeft() { + switch cD { + case N: + cD = W + case E: + cD = N + case S: + cD = E + case W: + cD = S + } +} + +func getXYInDir() (int, int) { + switch cD { + case N: + return cX, cY - 1 + case E: + return cX + 1, cY + case S: + return cX, cY + 1 + case W: + return cX - 1, cY + } + return cX, cY +} + +func cs(x, y int) string { + return fmt.Sprintf("%d;%d", x, y) +} + +func sc(key string) (int, int) { + pts := strings.Split(key, ";") + return Atoi(pts[0]), Atoi(pts[1]) +} + +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 ClearScreen() { + fmt.Println("\033[H\033[2J") +} + +func StdinToStrings() []string { + var input []string + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + input = append(input, scanner.Text()) + } + return input +} diff --git a/2017/day22/input b/2017/day22/input new file mode 100644 index 0000000..a432460 --- /dev/null +++ b/2017/day22/input @@ -0,0 +1,25 @@ +###.#######...#####.#..## +.####...###.##...#..#.... +.#.#...####.###..##..##.# +########.#.#...##.#.##.#. +..#.#...##..#.#.##..####. +..#.#.....#....#####..#.. +#.#..##...#....#.##...### +.#.##########...#......#. +.#...#..##...#...###.#... +......#.###.#..#...#.#### +.#.###.##...###.###.###.# +.##..##...#.#.#####.#...# +#...#..###....#.##....... +####.....######.#.##..#.. +..#...#..##.####.#####.## +#...#.#.#.#.#...##..##.#. +#####.#...#.#.#.#.##.#### +....###...#.##.#.##.####. +.#....###.#####...#.....# +#.....#....#####.#..#.... +.#####.#....#..##.#.#.### +####.#..#..##..#.#..#.### +.##.##.#.#.#.#.#..####.#. +#####..##.#.#..#..#...#.. +#.#..#.###...##....###.## diff --git a/2017/day22/problem b/2017/day22/problem new file mode 100644 index 0000000..a3e1c15 --- /dev/null +++ b/2017/day22/problem @@ -0,0 +1,263 @@ +Advent of Code + +--- Day 22: Sporifica Virus --- + + Diagnostics indicate that the local grid computing cluster has been + contaminated with the Sporifica Virus. The grid computing cluster is a + seemingly-infinite two-dimensional grid of compute nodes. Each node is either + clean or infected by the virus. + + To prevent overloading the nodes (which would render them useless to the + virus) or detection by system administrators, exactly one virus carrier moves + through the network, infecting or cleaning nodes as it moves. The virus + carrier is always located on a single node in the network (the current node) + and keeps track of the direction it is facing. + + To avoid detection, the virus carrier works in bursts; in each burst, it + wakes up, does some work, and goes back to sleep. The following steps are all + executed in order one time each burst: + + * If the current node is infected, it turns to its right. Otherwise, it + turns to its left. (Turning is done in-place; the current node does not + change.) + * If the current node is clean, it becomes infected. Otherwise, it becomes + cleaned. (This is done after the node is considered for the purposes of + changing direction.) + * The virus carrier moves forward one node in the direction it is facing. + + Diagnostics have also provided a map of the node infection status (your + puzzle input). Clean nodes are shown as .; infected nodes are shown as #. + This map only shows the center of the grid; there are many more nodes beyond + those shown, but none of them are currently infected. + + The virus carrier begins in the middle of the map facing up. + + For example, suppose you are given a map like this: + + ..# + #.. + ... + + Then, the middle of the infinite grid looks like this, with the virus + carrier's position marked with [ ]: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . # . . . + . . . #[.]. . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + The virus carrier is on a clean node, so it turns left, infects the node, and + moves left: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . # . . . + . . .[#]# . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + The virus carrier is on an infected node, so it turns right, cleans the node, + and moves up: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . .[.]. # . . . + . . . . # . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + Four times in a row, the virus carrier finds a clean, infects it, turns left, + and moves forward, ending in the same place and still facing up: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . #[#]. # . . . + . . # # # . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + Now on the same node as before, it sees an infection, which causes it to turn + right, clean the node, and move forward: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . # .[.]# . . . + . . # # # . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + After the above actions, a total of 7 bursts of activity had taken place. Of + them, 5 bursts of activity caused an infection. + + After a total of 70, the grid looks like this, with the virus carrier facing + up: + + . . . . . # # . . + . . . . # . . # . + . . . # . . . . # + . . # . #[.]. . # + . . # . # . . # . + . . . . . # # . . + . . . . . . . . . + . . . . . . . . . + + By this time, 41 bursts of activity caused an infection (though most of those + nodes have since been cleaned). + + After a total of 10000 bursts of activity, 5587 bursts will have caused an + infection. + + Given your actual map, after 10000 bursts of activity, how many bursts cause + a node to become infected? (Do not count nodes that begin infected.) + + Your puzzle answer was _______. + + The first half of this puzzle is complete! It provides one gold star: * + +--- Part Two --- + + As you go to remove the virus from the infected nodes, it evolves to resist + your attempt. + + Now, before it infects a clean node, it will weaken it to disable your + defenses. If it encounters an infected node, it will instead flag the node to + be cleaned in the future. So: + + * Clean nodes become weakened. + * Weakened nodes become infected. + * Infected nodes become flagged. + * Flagged nodes become clean. + + Every node is always in exactly one of the above states. + + The virus carrier still functions in a similar way, but now uses the + following logic during its bursts of action: + + * Decide which way to turn based on the current node: + + * If it is clean, it turns left. + * If it is weakened, it does not turn, and will continue moving in the + same direction. + * If it is infected, it turns right. + * If it is flagged, it reverses direction, and will go back the way it + came. + + * Modify the state of the current node, as described above. + * The virus carrier moves forward one node in the direction it is facing. + + Start with the same map (still using . for clean and # for infected) and + still with the virus carrier starting in the middle and facing up. + + Using the same initial state as the previous example, and drawing weakened as + W and flagged as F, the middle of the infinite grid looks like this, with the + virus carrier's position again marked with [ ]: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . # . . . + . . . #[.]. . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + This is the same as before, since no initial nodes are weakened or flagged. + The virus carrier is on a clean node, so it still turns left, instead weakens + the node, and moves left: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . # . . . + . . .[#]W . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + The virus carrier is on an infected node, so it still turns right, instead + flags the node, and moves up: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . .[.]. # . . . + . . . F W . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + This process repeats three more times, ending on the previously-flagged node + and facing right: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . W W . # . . . + . . W[F]W . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + Finding a flagged node, it reverses direction and cleans the node: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . W W . # . . . + . .[W]. W . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + The weakened node becomes infected, and it continues in the same direction: + + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + . . W W . # . . . + .[.]# . W . . . . + . . . . . . . . . + . . . . . . . . . + . . . . . . . . . + + Of the first 100 bursts, 26 will result in infection. Unfortunately, another + feature of this evolved virus is speed; of the first 10000000 bursts, 2511944 + will result in infection. + + Given your actual map, after 10000000 bursts of activity, how many bursts + cause a node to become infected? (Do not count nodes that begin infected.) + + Although it hasn't changed, you can still get your puzzle input. + + Answer: _____________________ [ [Submit] ] + +References + + Visible links + . http://adventofcode.com/ + . http://adventofcode.com/2017/about + . http://adventofcode.com/2017/support + . http://adventofcode.com/2017/events + . http://adventofcode.com/2017/settings + . http://adventofcode.com/2017/auth/logout + . http://adventofcode.com/2017 + . http://adventofcode.com/2017 + . http://adventofcode.com/2017/leaderboard + . http://adventofcode.com/2017/stats + . http://adventofcode.com/2017/sponsors + . http://adventofcode.com/2017/sponsors + . https://en.wikipedia.org/wiki/Morris_worm#The_mistake + . https://www.youtube.com/watch?v=2vj37yeQQHg + . http://adventofcode.com/2017/day/22/input diff --git a/2017/day22/testinput b/2017/day22/testinput new file mode 100644 index 0000000..3105a0b --- /dev/null +++ b/2017/day22/testinput @@ -0,0 +1,3 @@ +..# +#.. +...