-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path21_field_replace.go
104 lines (89 loc) · 2.19 KB
/
21_field_replace.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import (
"fmt"
"log"
"metalim/advent/2017/lib/field"
"metalim/advent/2017/lib/source"
"strings"
. "github.com/logrusorgru/aurora"
)
var test1 = `../.# => ##./#../...
.#./..#/### => #..#/..../..../#..#`
func main() {
var ins source.Inputs
ins = ins.Test(1, test1, `12`)
for par := range ins.Advent(2017, 21) {
fmt.Println(Brown("\n" + par.Name))
sss := par.Lines().Split(" => ")
fmt.Println("rules:", Black(len(sss)).Bold())
rules := map[string]string{}
for _, ss := range sss {
skey := strings.Replace(ss[0], "/", "\n", -1)
sval := strings.Replace(ss[1], "/", "\n", -1)
rules[skey] = sval
// rotate x3, flip, rotate x3
key := &field.Slice{}
field.FillFromString(key, field.Pos{}, skey)
rect := key.Bounds()
for f := 0; f < 2; f++ {
for r := 0; r < 3; r++ {
field.Rotate90(key, rect)
rules[field.ToString(key, rect)] = sval
}
field.FlipVert(key, rect) // there was bug here: flipped unrotated key was not added.
rules[field.ToString(key, rect)] = sval
}
}
if par.Part(1) {
steps := 5
if strings.Contains(par.Name, "test") {
steps = 2
}
steps = steps
par.SubmitInt(1, iterate(rules, steps))
}
if par.Part(2) {
par.SubmitInt(2, iterate(rules, 18))
}
}
}
func iterate(rules map[string]string, steps int) (out int) {
cur := &field.Slice{}
field.FillFromString(cur, field.Pos{}, ".#.\n..#\n###")
for step := 1; step <= steps; step++ {
b := cur.Bounds()
var d int
switch {
case b.Dx()%2 == 0:
d = 2
case b.Dx()%3 == 0:
d = 3
default:
panic("invalid dimensions")
}
next := &field.Slice{}
for y := b.Min.Y; y < b.Max.Y; y += d {
for x := b.Min.X; x < b.Max.X; x += d {
dx := x / d * (d + 1)
dy := y / d * (d + 1)
key := field.ToString(cur, field.Rect{field.Pos{x, y}, field.Pos{x + d, y + d}})
val, ok := rules[key]
if !ok {
log.Fatal("step ", step, " can't find rule for:\n", key)
}
field.FillFromString(next, field.Pos{dx, dy}, val)
}
}
cur = next
}
// count cells.
b := cur.Bounds()
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
if cur.Get(field.Pos{x, y}) == '#' {
out++
}
}
}
return out
}