186 lines
2.8 KiB
Go
186 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
var row map[int]bool
|
|
var transitions []*Transition
|
|
|
|
func main() {
|
|
inp := StdinToStringSlice()
|
|
BuildRow(inp[0])
|
|
for _, v := range inp[2:] {
|
|
transitions = append(transitions, NewTransition(v))
|
|
}
|
|
fmt.Print("St: ")
|
|
PrintState()
|
|
for i := 0; i < 20; i++ {
|
|
Tick()
|
|
fmt.Printf("%2d: ", i)
|
|
PrintState()
|
|
}
|
|
fmt.Println("Total:", GetSum())
|
|
}
|
|
|
|
func Tick() {
|
|
m := make(map[int]bool)
|
|
lowest, highest := 0, 0
|
|
for i := range row {
|
|
if i < lowest {
|
|
lowest = i
|
|
}
|
|
if i > highest {
|
|
highest = i
|
|
}
|
|
}
|
|
for i := lowest - 2; i <= highest+2; i++ {
|
|
m[i] = GetNextValue(i)
|
|
}
|
|
lowest, highest = 0, 0
|
|
for k := range m {
|
|
if k < lowest && m[k] {
|
|
lowest = k
|
|
}
|
|
if k > highest && m[k] {
|
|
highest = k
|
|
}
|
|
}
|
|
row = make(map[int]bool)
|
|
for i := lowest; i <= highest; i++ {
|
|
row[i] = m[i]
|
|
}
|
|
}
|
|
|
|
func GetSum() int {
|
|
var ret int
|
|
lowest, highest := 0, 0
|
|
for i := range row {
|
|
if i < lowest {
|
|
lowest = i
|
|
}
|
|
if i > highest {
|
|
highest = i
|
|
}
|
|
}
|
|
for i := lowest; i <= highest; i++ {
|
|
if row[i] {
|
|
ret += i
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func BuildRow(inp string) {
|
|
inp = strings.Split(inp, ": ")[1]
|
|
row = make(map[int]bool)
|
|
for i, v := range inp {
|
|
row[i] = rb(v)
|
|
}
|
|
}
|
|
|
|
func GetIdxValue(idx int) byte {
|
|
var ret byte
|
|
for i := idx + 2; i >= idx-2; i-- {
|
|
ret = ret << 1
|
|
if row[i] {
|
|
ret = ret | 1
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func GetNextValue(idx int) bool {
|
|
idxVal := GetIdxValue(idx)
|
|
for _, v := range transitions {
|
|
if v.GetValue() == idxVal {
|
|
return v.next
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func GetValueString(b byte) string {
|
|
var ret string
|
|
for i := 0; i < 5; i++ {
|
|
if (b & 1) == 1 {
|
|
ret = ret + "#"
|
|
} else {
|
|
ret = ret + "."
|
|
}
|
|
b = b >> 1
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func PrintState() {
|
|
lowest, highest := -2, 30
|
|
for i := range row {
|
|
if i < lowest {
|
|
lowest = i
|
|
}
|
|
if i > highest {
|
|
highest = i
|
|
}
|
|
}
|
|
fmt.Print("(", lowest, ") ")
|
|
for i := lowest; i <= highest; i++ {
|
|
if row[i] {
|
|
fmt.Print("#")
|
|
} else {
|
|
fmt.Print(".")
|
|
}
|
|
}
|
|
fmt.Println(" (", highest, ") ")
|
|
}
|
|
|
|
type Transition struct {
|
|
state []bool
|
|
next bool
|
|
}
|
|
|
|
func NewTransition(inp string) *Transition {
|
|
var state []bool
|
|
var next bool
|
|
pts := strings.Split(inp, " => ")
|
|
for i := len(pts[0]) - 1; i >= 0; i-- {
|
|
state = append(state, bb(pts[0][i]))
|
|
}
|
|
next = bb(pts[1][0])
|
|
t := &Transition{
|
|
state: state,
|
|
next: next,
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t *Transition) GetValue() byte {
|
|
var ret byte
|
|
for _, v := range t.state {
|
|
ret = ret << 1
|
|
if v {
|
|
ret = ret | 1
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func rb(r rune) bool {
|
|
return bb(byte(r))
|
|
}
|
|
func bb(b byte) bool {
|
|
return b == '#'
|
|
}
|
|
|
|
func StdinToStringSlice() []string {
|
|
var input []string
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for scanner.Scan() {
|
|
input = append(input, scanner.Text())
|
|
}
|
|
return input
|
|
}
|