diff --git a/day20/main.go b/day20/main.go index 6b8b413..43daff6 100644 --- a/day20/main.go +++ b/day20/main.go @@ -4,7 +4,6 @@ import ( "bufio" _ "embed" "fmt" - "os" "strings" aoc "go.sour.is/advent-of-code" @@ -23,16 +22,9 @@ type result struct { func (r result) String() string { return fmt.Sprintf("%#v", r) } func run(scan *bufio.Scanner) (*result, error) { - var forever bool - if os.Getenv("AOC_FOREVER") == "1" { - forever = true - } - m := &machine{} receivers := make(map[string][]string) - m.Add("rx", &rx{}) - for scan.Scan() { text := scan.Text() @@ -48,72 +40,50 @@ func run(scan *bufio.Scanner) (*result, error) { case strings.HasPrefix(name, "&"): name = strings.TrimPrefix(name, "&") - m.Add(name, &conjuction{name: name, dest: dest}) + m.Add(name, &conjunction{name: name, dest: dest}) } for _, d := range dest { + // rx is present so enable pt 2 + if d == "rx" { + m.Add("rx", &rx{}) + } receivers[d] = append(receivers[d], name) } } - m.Setup(receivers) + m.setup(receivers) result := &result{} - if forever { - i := 0 - - defer func() { - if p := recover(); p != nil { - fmt.Printf("## Press %d FINISH %v ##", i, p) - os.Exit(1) - } - }() - - for { - if i%12345 == 0 { - fmt.Printf("## Press %d ##\r", i) - } - m.Push(i) - i++ - } - } - - for i := 0; i < 4_0000; i++ { - // fmt.Printf("\n## Press %d ##\n\n", i) + for i := 0; i < 10_000; i++ { // need enough presses to find the best LCM values for each conjunction if i == 1000 { result.valuePT1 = m.highPulses * m.lowPulses } m.Push(i) - } - // fmt.Println("\n## SUMMARY ##") - // fmt.Println("Sent", LOW, m.lowPulses) - // fmt.Println("Sent", HIGH, m.highPulses) - var lvalues []int + // rx is present.. perform part 2. + if rx, ok := receivers["rx"]; ok { + var tip *conjunction + var lvalues []int - for _, p := range m.m { - if p, ok := p.(*conjuction); ok && in(p.name, []string{"bk","tp","pt","vd"}) { - var values []int - for k, v := range p.pushes { - for i, h := range makeHistory(v) { - if i == 1 && len(h) > 3 && h[0] > 0 { //&& all(h[0], h[1:]...) { - fmt.Println(p.name, k, i, h[0]) - values = append(values, h[0]) - } + if p, ok := m.m[rx[0]].(*conjunction); ok { + tip = p + } + + for k, v := range tip.pushes { + for i, h := range makeHistory(v) { + if i == 1 && len(h) > 0 && h[0] > 0 { + fmt.Println(tip.name, k, "frequency", h[0]) + lvalues = append(lvalues, h[0]) } } - max := aoc.Max(values[0], values...) - fmt.Println(p.name, "MAX", max, values) - lvalues = append(lvalues, max) } + + result.valuePT2 = aoc.LCM(lvalues...) + fmt.Println(tip.name, "LCM", result.valuePT2, lvalues) } - result.valuePT2 = aoc.LCM(lvalues...) - fmt.Println("tg", "LCM", result.valuePT2, lvalues) - - // trace("rx", receivers) - return result, nil } @@ -124,36 +94,17 @@ const ( HIGH signal = true ) -func (m signal) String() string { - if m { - return " >>-HIGH-> " - } - return " >>-LOW-> " -} - type message struct { signal from, to string } -func (m message) String() string { - return fmt.Sprint(m.from, m.signal, m.to) -} - -type pulser interface { - Pulse(message) - SetMachine(*machine) -} - type machine struct { m map[string]pulser - press int queue []message - hwm int - - stop bool + press int highPulses int lowPulses int } @@ -176,13 +127,11 @@ func (m *machine) Send(msgs ...message) { } } } - func (m *machine) Push(i int) { m.press = i m.Send(generate(LOW, "button", "broadcaster")...) m.processQueue(i) } - func (m *machine) processQueue(i int) { // look for work and process up to the queue length. repeat. hwm := 0 @@ -204,7 +153,7 @@ func (m *machine) processQueue(i int) { // fmt.Println("") } } -func (m *machine) Setup(receivers map[string][]string) { +func (m *machine) setup(receivers map[string][]string) { for name, recv := range receivers { if p, ok := m.m[name]; ok { if p, ok := p.(interface{ Receive(...string) }); ok { @@ -214,10 +163,12 @@ func (m *machine) Setup(receivers map[string][]string) { } } -func (m *machine) Stop() { - m.stop = true +type pulser interface { + Pulse(message) + SetMachine(*machine) } +// IsModule implements the machine registration for each module. type IsModule struct { *machine } @@ -232,7 +183,6 @@ type broadcaster struct { func (b *broadcaster) Pulse(msg message) { b.Send(generate(msg.signal, "broadcaster", b.dest...)...) } -func (b *broadcaster) String() string { return "br" } type flipflop struct { name string @@ -248,70 +198,41 @@ func (b *flipflop) Pulse(msg message) { b.Send(generate(b.state, b.name, b.dest...)...) } } -func (b *flipflop) String() string { - return fmt.Sprintf("%s(%v)", b.name, b.state) -} -type conjuction struct { +type conjunction struct { name string state map[string]signal dest []string pushes map[string][]int - activate []int - last map[string]int - max map[string]int - lcm int IsModule } -func (b *conjuction) Receive(names ...string) { +func (b *conjunction) Receive(names ...string) { if b.state == nil { b.state = make(map[string]signal) - b.last = make(map[string]int) - b.max = make(map[string]int) b.pushes = make(map[string][]int) } for _, name := range names { b.state[name] = false - b.max[name] = int(^uint(0)>>1) b.pushes[name] = []int{} - } } -func (b *conjuction) Pulse(msg message) { - if b.state == nil { - b.state = make(map[string]signal) - b.last = make(map[string]int) - b.max = make(map[string]int) - } - +func (b *conjunction) Pulse(msg message) { b.state[msg.from] = msg.signal if msg.signal { + // collect frequency of pushes to esti,ate rate b.pushes[msg.from] = append(b.pushes[msg.from], b.press) - b.last[msg.from] = b.press - b.last[msg.from] - - - // vals := maps.Values(b.max) - // if aoc.Min(vals[0], vals...) != 0 { - // if lcm := aoc.LCM(vals...); lcm > 0 { - // fmt.Printf("\nfound loop %s = %d %v\n", b.name, lcm, vals) - // } - // } } if all(HIGH, maps.Values(b.state)...) { - b.activate = append(b.activate, b.press) b.Send(generate(LOW, b.name, b.dest...)...) return } b.Send(generate(HIGH, b.name, b.dest...)...) } -func (b *conjuction) String() string { - return fmt.Sprintf("%s(%v)", b.name, b.state) -} type rx struct { IsModule @@ -319,16 +240,12 @@ type rx struct { func (rx *rx) Pulse(msg message) { if !msg.signal { - panic("pulse received") + panic("pulse received") // will never happen... } } -func (rx *rx) String() string { return "rx" } - -func all[T ~int|~bool](match T, lis ...T) bool { - if len(lis) == 0 { - return true - } +// helper funcs +func all[T comparable](match T, lis ...T) bool { for _, b := range lis { if b != match { return false @@ -345,35 +262,25 @@ func generate(t signal, from string, destinations ...string) []message { return msgs } -func in(n string, haystack []string) bool { - for _, h := range haystack { - if n == h { - return true - } - } - return false -} - +// makeHistory from day 9 func makeHistory(in []int) [][]int { var history [][]int history = append(history, in) - for { - var diffs []int - + // for { + var diffs []int - current := history[len(history)-1] - if len(current) == 0 { return nil } + current := history[len(history)-1] - for i := range current[1:] { - diffs = append(diffs, current[i+1]-current[i]) - } - - history = append(history, diffs) - - if len(diffs) == 0 || aoc.Max(diffs[0], diffs[1:]...) == 0 && aoc.Min(diffs[0], diffs[1:]...) == 0 { - break - } + for i := range current[1:] { + diffs = append(diffs, current[i+1]-current[i]) } + + history = append(history, diffs) + + // if len(diffs) == 0 || aoc.Max(diffs[0], diffs[1:]...) == 0 && aoc.Min(diffs[0], diffs[1:]...) == 0 { + // break + // } + // } return history } diff --git a/day20/main_test.go b/day20/main_test.go index 8af5bb6..1ab6824 100644 --- a/day20/main_test.go +++ b/day20/main_test.go @@ -52,5 +52,5 @@ func TestSolution(t *testing.T) { t.Log(result) is.Equal(result.valuePT1, 819397964) - is.Equal(result.valuePT2, 0) + is.Equal(result.valuePT2, 252667369442479) }