2017-day21: sudoku-style grid plus game of life...

This commit is contained in:
alexchao26
2020-12-19 21:51:28 -05:00
parent e5d6e111e4
commit ec9a15afbe
2 changed files with 182 additions and 0 deletions
+147
View File
@@ -0,0 +1,147 @@
package main
import (
"flag"
"fmt"
"strings"
"github.com/alexchao26/advent-of-code-go/mathutil"
"github.com/alexchao26/advent-of-code-go/algos"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
var ans int
if part == 1 {
ans = fractalArt(util.ReadFile("./input.txt"), 5)
} else {
ans = fractalArt(util.ReadFile("./input.txt"), 18)
}
fmt.Println("Output:", ans)
}
var startingPattern = `.#.
..#
###`
func fractalArt(input string, rounds int) int {
var state [][]string
for _, line := range strings.Split(startingPattern, "\n") {
state = append(state, strings.Split(line, ""))
}
rules := parseInput(input)
for i := 0; i < rounds; i++ {
state = tick(state, rules)
}
var count int
for _, row := range state {
for _, v := range row {
if v == "#" {
count++
}
}
}
return count
}
func parseInput(input string) map[string][][]string {
// some helper functions for generating the rules map
// need to parse the left sides of the enhancement rules
// then helper functions that rotate them (util.RotateStringGrid()) and
// one to mirror image it
makeGridFromString := func(str string) [][]string {
var grid [][]string
for _, line := range strings.Split(str, "/") {
grid = append(grid, strings.Split(line, ""))
}
return grid
}
stringifyGrid := func(grid [][]string) (str string) {
for _, row := range grid {
for _, v := range row {
str += v
}
}
return str
}
mirrorImageGrid := func(grid [][]string) (flipped [][]string) {
for i := range grid {
flipped = append(flipped, []string{})
for j := len(grid[i]) - 1; j >= 0; j-- {
flipped[i] = append(flipped[i], grid[i][j])
}
}
return flipped
}
rules := map[string][][]string{}
for _, line := range strings.Split(input, "\n") {
parts := strings.Split(line, " => ")
keyGrid := makeGridFromString(parts[0])
resultGrid := makeGridFromString(parts[1])
for i := 0; i < 4; i++ {
keyGrid = algos.RotateStringGrid(keyGrid)
rules[stringifyGrid(keyGrid)] = resultGrid
rules[stringifyGrid((mirrorImageGrid(keyGrid)))] = resultGrid
}
}
return rules
}
func tick(grid [][]string, rules map[string][][]string) [][]string {
var nextState [][]string
// determine the size of break up the grid by. prioritize 2x2 grids
var edgeSize int
if len(grid)%2 == 0 {
edgeSize = 2
} else if len(grid)%3 == 0 {
edgeSize = 3
} else {
panic("grid is not evenly divisible by 2 or 3, got " + mathutil.IntToStr(len(grid)))
}
// iterate over like a sudoku grid, r and c iterate over the top left corner
// of each sub-square
for r := 0; r < len(grid); r += edgeSize {
// a new row of sub-squares is being iterated over, add edgeSize+1 number
// of empty slices onto the nextState grid
for i := 0; i < edgeSize+1; i++ {
nextState = append(nextState, []string{})
}
for c := 0; c < len(grid[0]); c += edgeSize {
// generate the string to match a key in the rules map
var strToMatch string
for i := 0; i < edgeSize; i++ {
for j := 0; j < edgeSize; j++ {
// r+i and c+j point at coords within the original grid
strToMatch += grid[r+i][c+j]
}
}
// finding the result of the enhancement rule for the string to match
resulting, ok := rules[strToMatch]
if !ok {
panic("No matching pattern found for " + strToMatch)
}
// append the values from the result onto the appropriate nextState row
for i, vals := range resulting {
nextStateIndex := len(nextState) - edgeSize - 1 + i
nextState[nextStateIndex] = append(nextState[nextStateIndex], vals...)
}
}
}
return nextState
}
+35
View File
@@ -0,0 +1,35 @@
package main
import (
"testing"
"github.com/alexchao26/advent-of-code-go/util"
)
var example = `../.# => ##./#../...
.#./..#/### => #..#/..../..../#..#`
func Test_fractalArt(t *testing.T) {
type args struct {
input string
rounds int
}
tests := []struct {
name string
args args
want int
}{
{"example", args{example, 2}, 12},
{"actual_part1", args{util.ReadFile("input.txt"), 5}, 194},
{"actual_part2", args{util.ReadFile("input.txt"), 18}, 2536879},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := fractalArt(tt.args.input, tt.args.rounds); got != tt.want {
t.Logf("Ruleset: %s", tt.args.input)
t.Logf("Rounds: %d", tt.args.rounds)
t.Errorf("fractalArt() = %v, want %v", got, tt.want)
}
})
}
}