171 lines
3.5 KiB
Go
171 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var rules map[string]string
|
|
|
|
func main() {
|
|
numIters := 18
|
|
rules = make(map[string]string)
|
|
|
|
inp := StdinToStrings()
|
|
for i := range inp {
|
|
pts := strings.Split(inp[i], " ")
|
|
rules[pts[0]] = pts[2]
|
|
rules[Flip(pts[0])] = pts[2]
|
|
rules[Rotate(pts[0], 90)] = pts[2]
|
|
rules[Flip(Rotate(pts[0], 90))] = pts[2]
|
|
rules[Rotate(pts[0], 180)] = pts[2]
|
|
rules[Flip(Rotate(pts[0], 180))] = pts[2]
|
|
rules[Rotate(pts[0], 270)] = pts[2]
|
|
rules[Flip(Rotate(pts[0], 270))] = pts[2]
|
|
}
|
|
|
|
pattern := ".#./..#/###"
|
|
PrettyPrint(pattern)
|
|
for i := 0; i < numIters; i++ {
|
|
ClearScreen()
|
|
PrettyPrint(pattern)
|
|
time.Sleep(time.Second / 2)
|
|
pattern = Tick(pattern)
|
|
}
|
|
fmt.Println("Bits On", strings.Count(pattern, "#"))
|
|
}
|
|
|
|
func PrettyPrint(inp string) {
|
|
for _, v := range strings.Split(inp, "/") {
|
|
fmt.Println(v)
|
|
}
|
|
}
|
|
|
|
func Tick(pt string) string {
|
|
subPatterns := SplitBlocks(pt)
|
|
var tickSubs []string
|
|
for i := range subPatterns {
|
|
tickSubs = append(tickSubs, ApplyRule(subPatterns[i]))
|
|
}
|
|
return CombineBlocks(tickSubs)
|
|
}
|
|
|
|
func ApplyRule(inp string) string {
|
|
if v, ok := rules[inp]; ok {
|
|
return v
|
|
}
|
|
// This is an error.
|
|
fmt.Println("No rule for", inp)
|
|
os.Exit(1)
|
|
return ""
|
|
}
|
|
|
|
func SplitBlocks(pt string) []string {
|
|
var ret []string
|
|
pts := strings.Split(pt, "/")
|
|
if len(pts[0]) <= 3 {
|
|
return []string{pt}
|
|
}
|
|
// Assume 3x3
|
|
blkSize := 3
|
|
if len(pts[0])%2 == 0 {
|
|
// 2x2 blocks
|
|
blkSize = 2
|
|
}
|
|
|
|
for j := 0; j < len(pts); j += blkSize {
|
|
for i := 0; i < len(pts[j]); i += blkSize {
|
|
if blkSize == 2 {
|
|
ret = append(ret, pts[j][i:i+blkSize]+"/"+pts[j+1][i:i+blkSize])
|
|
} else {
|
|
ret = append(ret, pts[j][i:i+blkSize]+"/"+pts[j+1][i:i+blkSize]+"/"+pts[j+2][i:i+blkSize])
|
|
}
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func CombineBlocks(pts []string) string {
|
|
var ret []string
|
|
if len(pts) == 1 {
|
|
return pts[0]
|
|
}
|
|
var subPts [][]string
|
|
for i := range pts {
|
|
subPts = append(subPts, strings.Split(pts[i], "/"))
|
|
}
|
|
subPtSz := len(subPts[0])
|
|
ptSize := int(math.Sqrt(float64(len(subPts) * subPtSz * subPtSz)))
|
|
w, h := (ptSize / subPtSz), (ptSize / subPtSz)
|
|
for i := 0; i < h; i++ {
|
|
st := i * w
|
|
for j := 0; j < subPtSz; j++ {
|
|
var bld string
|
|
for k := 0; k < w; k++ {
|
|
bld += subPts[st+k][j]
|
|
}
|
|
ret = append(ret, bld)
|
|
}
|
|
}
|
|
|
|
return strings.Join(ret, "/")
|
|
}
|
|
|
|
func Flip(pt string) string {
|
|
pts := strings.Split(pt, "/")
|
|
var newPts []string
|
|
for i := range pts {
|
|
newPts = append(newPts, RevString(pts[i]))
|
|
}
|
|
return strings.Join(newPts, "/")
|
|
}
|
|
|
|
func Rotate(pt string, deg int) string {
|
|
if deg == 0 {
|
|
return pt
|
|
}
|
|
if deg%90 != 0 {
|
|
// We can't do this
|
|
fmt.Println("Invalid Rotation:", deg)
|
|
os.Exit(1)
|
|
}
|
|
pts := strings.Split(pt, "/")
|
|
var tst string
|
|
if len(pts[0])%2 == 0 {
|
|
// 2x2 pattern
|
|
tst = string(pts[1][0]) + string(pts[0][0]) + "/"
|
|
tst += string(pts[1][1]) + string(pts[0][1])
|
|
return Rotate(tst, deg-90)
|
|
}
|
|
// 3x3 pattern
|
|
tst = string(pts[2][0]) + string(pts[1][0]) + string(pts[0][0]) + "/"
|
|
tst += string(pts[2][1]) + string(pts[1][1]) + string(pts[0][1]) + "/"
|
|
tst += string(pts[2][2]) + string(pts[1][2]) + string(pts[0][2])
|
|
return Rotate(tst, deg-90)
|
|
}
|
|
|
|
func RevString(s string) string {
|
|
runes := []rune(s)
|
|
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
|
|
runes[i], runes[j] = runes[j], runes[i]
|
|
}
|
|
return string(runes)
|
|
}
|
|
|
|
func ClearScreen() {
|
|
fmt.Println("\033[H\033[2J")
|
|
}
|
|
|
|
func StdinToStrings() []string {
|
|
var input []string
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for scanner.Scan() {
|
|
input = append(input, scanner.Text())
|
|
}
|
|
return input
|
|
}
|