day7
This commit is contained in:
parent
40837caa9e
commit
825f608c04
3 changed files with 264 additions and 0 deletions
106
day7/main.go
Normal file
106
day7/main.go
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue