I've gotta stop for now.
This commit is contained in:
parent
3d7ac83d3f
commit
d16cc22158
317
2017/day21/day21.go
Normal file
317
2017/day21/day21.go
Normal file
@ -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
|
||||||
|
}
|
108
2017/day21/input
Normal file
108
2017/day21/input
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
../.. => .../.../..#
|
||||||
|
#./.. => #.#/..#/...
|
||||||
|
##/.. => #.#/..#/#.#
|
||||||
|
.#/#. => #../.../.##
|
||||||
|
##/#. => ###/#.#/..#
|
||||||
|
##/## => #.#/.../#..
|
||||||
|
.../.../... => #..#/..../.##./....
|
||||||
|
#../.../... => ..../.##./#.../.##.
|
||||||
|
.#./.../... => .#../####/..##/#...
|
||||||
|
##./.../... => ##.#/..#./####/...#
|
||||||
|
#.#/.../... => ##.#/##../#.#./.#..
|
||||||
|
###/.../... => #..#/#..#/##../##.#
|
||||||
|
.#./#../... => #.##/##../.#.#/..##
|
||||||
|
##./#../... => #.#./..../.###/.#.#
|
||||||
|
..#/#../... => ..##/####/..##/....
|
||||||
|
#.#/#../... => ..##/###./..##/#...
|
||||||
|
.##/#../... => #.../####/#..#/##..
|
||||||
|
###/#../... => ...#/..../..##/#...
|
||||||
|
.../.#./... => ##../##../..##/....
|
||||||
|
#../.#./... => #.../.#.#/.##./#..#
|
||||||
|
.#./.#./... => ..##/#.../...#/###.
|
||||||
|
##./.#./... => ####/.#.#/..##/####
|
||||||
|
#.#/.#./... => ####/.#../#.##/#..#
|
||||||
|
###/.#./... => ..#./#..#/.#.#/###.
|
||||||
|
.#./##./... => ##../.#.#/#..#/#..#
|
||||||
|
##./##./... => .###/####/#..#/..##
|
||||||
|
..#/##./... => ###./.#../..#./#.##
|
||||||
|
#.#/##./... => ##../#.#./#.../.#.#
|
||||||
|
.##/##./... => #.../#.../.#.#/####
|
||||||
|
###/##./... => .#../####/#.../#.#.
|
||||||
|
.../#.#/... => .#../..../##../.###
|
||||||
|
#../#.#/... => .##./...#/.###/...#
|
||||||
|
.#./#.#/... => ...#/#.../...#/####
|
||||||
|
##./#.#/... => #.##/..#./#..#/.#.#
|
||||||
|
#.#/#.#/... => #..#/..../..##/..#.
|
||||||
|
###/#.#/... => .#.#/#.#./##.#/#.#.
|
||||||
|
.../###/... => ##../.##./###./###.
|
||||||
|
#../###/... => ###./..##/.#../##.#
|
||||||
|
.#./###/... => .#../##../..../..##
|
||||||
|
##./###/... => #.#./...#/...#/##..
|
||||||
|
#.#/###/... => ..../.#../#.../.#..
|
||||||
|
###/###/... => ..#./.###/..../##.#
|
||||||
|
..#/.../#.. => #.#./.#../...#/##.#
|
||||||
|
#.#/.../#.. => ...#/##.#/#.#./#...
|
||||||
|
.##/.../#.. => ...#/..##/#.##/##.#
|
||||||
|
###/.../#.. => #..#/.#.#/.##./..#.
|
||||||
|
.##/#../#.. => ##../..#./#.##/##..
|
||||||
|
###/#../#.. => ..../###./#.#./##..
|
||||||
|
..#/.#./#.. => #.#./.##./.##./#...
|
||||||
|
#.#/.#./#.. => .#../#..#/#.#./#...
|
||||||
|
.##/.#./#.. => .#.#/#..#/..#./....
|
||||||
|
###/.#./#.. => #.##/####/#.../..#.
|
||||||
|
.##/##./#.. => #.##/.#.#/..../.#..
|
||||||
|
###/##./#.. => #.##/####/.###/##..
|
||||||
|
#../..#/#.. => ###./#.##/..#./..##
|
||||||
|
.#./..#/#.. => ##../.#../..#./..##
|
||||||
|
##./..#/#.. => #..#/.#../..../##.#
|
||||||
|
#.#/..#/#.. => .###/.##./..#./#.#.
|
||||||
|
.##/..#/#.. => .#.#/..../####/.#..
|
||||||
|
###/..#/#.. => .##./##../...#/.#..
|
||||||
|
#../#.#/#.. => #.#./#.##/..../.###
|
||||||
|
.#./#.#/#.. => ####/#.#./.#../#.##
|
||||||
|
##./#.#/#.. => ..##/.###/###./..#.
|
||||||
|
..#/#.#/#.. => .##./..#./..../#.#.
|
||||||
|
#.#/#.#/#.. => .###/..../..../##..
|
||||||
|
.##/#.#/#.. => #.#./#.../####/.###
|
||||||
|
###/#.#/#.. => #.../..##/###./#..#
|
||||||
|
#../.##/#.. => ..../#.#./..##/.#.#
|
||||||
|
.#./.##/#.. => ..##/..##/#..#/###.
|
||||||
|
##./.##/#.. => #.../.#../#.#./#.##
|
||||||
|
#.#/.##/#.. => ...#/#.../...#/###.
|
||||||
|
.##/.##/#.. => ###./..../..##/#..#
|
||||||
|
###/.##/#.. => #.#./##.#/####/#.#.
|
||||||
|
#../###/#.. => ##../##../###./#..#
|
||||||
|
.#./###/#.. => #.##/###./####/..##
|
||||||
|
##./###/#.. => ..../.###/###./.#..
|
||||||
|
..#/###/#.. => .###/..../..#./....
|
||||||
|
#.#/###/#.. => ####/#..#/.#.#/..##
|
||||||
|
.##/###/#.. => ..../##.#/####/##.#
|
||||||
|
###/###/#.. => #..#/.#.#/###./.##.
|
||||||
|
.#./#.#/.#. => #.##/...#/###./....
|
||||||
|
##./#.#/.#. => #..#/.#../..../#.#.
|
||||||
|
#.#/#.#/.#. => .#.#/####/..../.#.#
|
||||||
|
###/#.#/.#. => #.#./#.##/##.#/##..
|
||||||
|
.#./###/.#. => ..#./..../##../####
|
||||||
|
##./###/.#. => #.##/##.#/#.##/.#..
|
||||||
|
#.#/###/.#. => .#.#/..##/##.#/####
|
||||||
|
###/###/.#. => .#../...#/#..#/#.#.
|
||||||
|
#.#/..#/##. => .##./..#./...#/##.#
|
||||||
|
###/..#/##. => ..#./##.#/#..#/#..#
|
||||||
|
.##/#.#/##. => ##.#/#.../#..#/...#
|
||||||
|
###/#.#/##. => ##../.#../..../.##.
|
||||||
|
#.#/.##/##. => #.##/##.#/.#../.###
|
||||||
|
###/.##/##. => ..../#.#./##../##.#
|
||||||
|
.##/###/##. => ###./.#.#/.##./.###
|
||||||
|
###/###/##. => #..#/.###/#.../#...
|
||||||
|
#.#/.../#.# => .###/#.##/.#.#/#.#.
|
||||||
|
###/.../#.# => ...#/##../...#/##.#
|
||||||
|
###/#../#.# => ..../..#./..#./####
|
||||||
|
#.#/.#./#.# => ##../#.##/...#/#...
|
||||||
|
###/.#./#.# => #.#./...#/.#../#...
|
||||||
|
###/##./#.# => .#../..#./...#/##..
|
||||||
|
#.#/#.#/#.# => ####/#.##/.#../##..
|
||||||
|
###/#.#/#.# => #.../#.../###./.#..
|
||||||
|
#.#/###/#.# => ####/.#.#/.##./.#.#
|
||||||
|
###/###/#.# => #.##/.#.#/##.#/..##
|
||||||
|
###/#.#/### => .###/#.##/..../..#.
|
||||||
|
###/###/### => .###/#..#/##../.##.
|
2
2017/day21/testinput
Normal file
2
2017/day21/testinput
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
../.# => ##./#../...
|
||||||
|
.#./..#/### => #..#/..../..../#..#
|
213
2017/day22/day22.go
Normal file
213
2017/day22/day22.go
Normal file
@ -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
|
||||||
|
}
|
25
2017/day22/input
Normal file
25
2017/day22/input
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
###.#######...#####.#..##
|
||||||
|
.####...###.##...#..#....
|
||||||
|
.#.#...####.###..##..##.#
|
||||||
|
########.#.#...##.#.##.#.
|
||||||
|
..#.#...##..#.#.##..####.
|
||||||
|
..#.#.....#....#####..#..
|
||||||
|
#.#..##...#....#.##...###
|
||||||
|
.#.##########...#......#.
|
||||||
|
.#...#..##...#...###.#...
|
||||||
|
......#.###.#..#...#.####
|
||||||
|
.#.###.##...###.###.###.#
|
||||||
|
.##..##...#.#.#####.#...#
|
||||||
|
#...#..###....#.##.......
|
||||||
|
####.....######.#.##..#..
|
||||||
|
..#...#..##.####.#####.##
|
||||||
|
#...#.#.#.#.#...##..##.#.
|
||||||
|
#####.#...#.#.#.#.##.####
|
||||||
|
....###...#.##.#.##.####.
|
||||||
|
.#....###.#####...#.....#
|
||||||
|
#.....#....#####.#..#....
|
||||||
|
.#####.#....#..##.#.#.###
|
||||||
|
####.#..#..##..#.#..#.###
|
||||||
|
.##.##.#.#.#.#.#..####.#.
|
||||||
|
#####..##.#.#..#..#...#..
|
||||||
|
#.#..#.###...##....###.##
|
263
2017/day22/problem
Normal file
263
2017/day22/problem
Normal file
@ -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
|
3
2017/day22/testinput
Normal file
3
2017/day22/testinput
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
..#
|
||||||
|
#..
|
||||||
|
...
|
Loading…
Reference in New Issue
Block a user