package main import ( "fmt" "os" "strings" "github.com/kelindar/bitmap" ) func readLines(filename string) []string { raw, err := os.ReadFile(filename) if err != nil { panic(err) } return strings.Split(string(raw), "\n") } func main() { filename := "input0.txt" if len(os.Args) > 1 { filename = os.Args[1] } lines := readLines(filename) m := parseManifold(lines) _, splits := m.eval() fmt.Printf("%v\n", splits) fmt.Printf("%v\n", m.quantumEval()) } type manifold struct { width uint32 source bitmap.Bitmap splitters []bitmap.Bitmap } func (m *manifold) eval() (bitmap.Bitmap, uint64) { splits := uint64(0) active := m.source.Clone(nil) for _, splitter := range m.splitters { activated := active.Clone(nil) activated.And(splitter) var produced bitmap.Bitmap activated.Range(func(i uint32) { splits++ produced.Set(i - 1) produced.Set(i + 1) }) active.AndNot(activated) active.Or(produced) } return active, splits } // set expansion is just too slow // instead, work like eval but use a slice of uints where the // values are the number of timelines that produce a tachyon // at a given position; when a tachyon is split and joins // an existing one, we increment, not just bitwise or. // the total is the sum of all timelines of all positions // in the final frame. // 3141808011 is too low func (m *manifold) quantumEval() uint64 { active := make([]uint64, m.width) m.source.Range(func(i uint32) { active[i] = 1 }) for _, frame := range m.splitters { next := make([]uint64, m.width) copy(next, active) for i, t := range active { if t == 0 { continue } splitter := frame.Contains(uint32(i)) if splitter { next[i] = 0 next[i-1] += t next[i+1] += t } } active = next } total := uint64(0) for _, x := range active { total += x } return total } func parseManifold(lines []string) *manifold { var m manifold m.width = uint32(len(lines[0])) m.source.Set(uint32(strings.Index(lines[0], "S"))) for i := 1; i < len(lines); i++ { var splitter bitmap.Bitmap for j, c := range lines[i] { if c == '^' { splitter.Set(uint32(j)) } } m.splitters = append(m.splitters, splitter) } return &m }