diff --git a/2018/day12-1.go b/2018/day12-1.go new file mode 100644 index 0000000..6186d74 --- /dev/null +++ b/2018/day12-1.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + "internal/day12" + "internal/util" +) + +const NumGenerations = 20 + +func main() { + data := util.ReadInput() + plants, rules := day12.ParseInput(data) + + for i := 0; i < NumGenerations; i++ { + plants = day12.RunGeneration(plants, rules) + } + + fmt.Println(day12.SumPlants(plants)) +} diff --git a/2018/internal/day12/debug.go b/2018/internal/day12/debug.go new file mode 100644 index 0000000..d4be955 --- /dev/null +++ b/2018/internal/day12/debug.go @@ -0,0 +1,20 @@ +package day12 + +import ( + "fmt" +) + +func DebugPrintPlants(plants map[int]bool) { + low, high := getPlantBounds(plants) + + for i := low; i < high+1; i++ { + fmt.Print(plantString(plants[i])) + } + fmt.Println() +} + +func DebugPrintRules(rules []*Rule) { + for _, rule := range rules { + fmt.Println(rule) + } +} diff --git a/2018/internal/day12/input.go b/2018/internal/day12/input.go new file mode 100644 index 0000000..8c82a2a --- /dev/null +++ b/2018/internal/day12/input.go @@ -0,0 +1,42 @@ +package day12 + +import ( + "strings" +) + +func ParseInput(data []string) (map[int]bool, []*Rule) { + stateStrings := strings.Split(data[0], " ") + state := stateStrings[len(stateStrings)-1] + ruleStrings := data[2:] + + // Populate plant map + plants := make(map[int]bool) + for i, byte := range []byte(state) { + if byte == '#' { + plants[i] = true + } + } + + // Create rules + rules := []*Rule{} + for _, ruleStr := range ruleStrings { + ruleData := strings.Split(ruleStr, " ") + + rule := &Rule{} + positions := []byte(ruleData[0]) + + for i := 0; i < 5; i++ { + rule.Positions[i] = positions[i] == '#' + } + + if ruleData[2] == "#" { + rule.Result = true + } else { + rule.Result = false + } + + rules = append(rules, rule) + } + + return plants, rules +} diff --git a/2018/internal/day12/plants.go b/2018/internal/day12/plants.go new file mode 100644 index 0000000..0a09db4 --- /dev/null +++ b/2018/internal/day12/plants.go @@ -0,0 +1,80 @@ +package day12 + +type Rule struct { + Positions [5]bool + Result bool +} + +func (r Rule) String() string { + res := "" + for _, p := range r.Positions { + res += plantString(p) + } + res += " => " + res += plantString(r.Result) + return res +} + +func plantString(isPlant bool) string { + if isPlant { + return "#" + } + return "." +} + +func getPlantBounds(plants map[int]bool) (int, int) { + keys := make([]int, len(plants)) + i := 0 + for key, _ := range plants { + keys[i] = key + i++ + } + + low := keys[0] + high := keys[0] + for _, key := range keys { + if key < low { + low = key + } + if key > high { + high = key + } + } + + return low, high +} + +func RunGeneration(plants map[int]bool, rules []*Rule) map[int]bool { + newGen := make(map[int]bool) + + low, high := getPlantBounds(plants) + + for i := low - 2; i < high+3; i++ { + for _, rule := range rules { + if checkRule(plants, rule, i) { + newGen[i] = rule.Result + } + } + } + + return newGen +} + +func checkRule(plants map[int]bool, rule *Rule, i int) bool { + for j := 0; j < 5; j++ { + if plants[i+j-2] != rule.Positions[j] { + return false + } + } + return true +} + +func SumPlants(plants map[int]bool) int { + sum := 0 + for key, value := range plants { + if value { + sum += key + } + } + return sum +}