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 }