diff --git a/day20/modules.go b/day20/modules.go index 8b22935..06b02eb 100644 --- a/day20/modules.go +++ b/day20/modules.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "regexp" + "slices" "strings" ) @@ -21,21 +22,49 @@ type Signal struct { type Module interface { Receive(s Signal) []Signal + Outputs() []string } // Modules type FlipFlop struct { Name string OutputNames []string - InOn bool + IsOn bool } +// ignores HighPulse +// on LowPulse - toggle state and send signal func (ff *FlipFlop)Receive(s Signal) []Signal { - return []Signal{} + if s.PulseType == HighPulse { + return []Signal{} + } + + ff.IsOn = !ff.IsOn + outTemplate := Signal{ + From: ff.Name, + } + if ff.IsOn { + outTemplate.PulseType = HighPulse + } else { + outTemplate.PulseType = LowPulse + } + + result := make([]Signal, len(ff.OutputNames)) + for i, outName := range ff.OutputNames { + out := outTemplate + out.To = outName + result[i] = out + } + + return result +} + +func (ff *FlipFlop)Outputs() []string { + return ff.OutputNames } func (ff *FlipFlop)String() string { - return fmt.Sprintf("[flip-flop '%s' (on: %t) -> %s]", ff.Name, ff.InOn, ff.OutputNames) + return fmt.Sprintf("[flip-flop '%s' (on: %t) -> %s]", ff.Name, ff.IsOn, ff.OutputNames) } func IsLineFlipFlop(line string) bool { @@ -57,8 +86,19 @@ type Broadcast struct { OutputNames []string } -func (b *Broadcast)Receive(s Signal) []Signal { - return []Signal{} +// send same pulse to all outputs +func (b *Broadcast)Receive(s Signal) (result []Signal) { + signalTemplate := Signal{From: "broadcast", PulseType: s.PulseType} + for _, out := range b.OutputNames { + outSignal := signalTemplate + outSignal.To = out + result = append(result, outSignal) + } + return +} + +func (b *Broadcast)Outputs() []string { + return b.OutputNames } func (b *Broadcast)String() string { @@ -83,8 +123,47 @@ type Conjunction struct { MostRecentPulseFromInputIsHigh map[string]bool } -func (c *Conjunction)Receive(s Signal) []Signal { - return []Signal{} +// remembers last signal type from all inputs (initial default is Low) +// when receiving pulse, first update memory for that input +// then if for all inputs remembered is high - send LowPulse +// otherwise if some remembers are low - send HighPulse +func (c *Conjunction)Receive(s Signal) (result []Signal) { + c.MostRecentPulseFromInputIsHigh[s.From] = s.PulseType == HighPulse + + allHigh := true + for _, latestImpulseHight := range c.MostRecentPulseFromInputIsHigh { + if !latestImpulseHight { + allHigh = false + break + } + } + + outTemplate := Signal{From: c.Name} + if allHigh { + outTemplate.PulseType = LowPulse + } else { + outTemplate.PulseType = HighPulse + } + + for _, outName := range c.OutputNames { + outSignal := outTemplate + outSignal.To = outName + result = append(result, outSignal) + } + + return +} + +func (c *Conjunction)Outputs() []string { + return c.OutputNames +} + +func (c *Conjunction)RegisterInputs(allModules map[string]Module) { + for name, module := range allModules { + if slices.Contains( module.Outputs(), c.Name) { + c.MostRecentPulseFromInputIsHigh[name] = false + } + } } func (c *Conjunction)String() string { @@ -103,13 +182,21 @@ func ParseConjunction(line string) (result Conjunction) { result.Name = matches[1] result.OutputNames = strings.Split(matches[2], ", ") + result.MostRecentPulseFromInputIsHigh = map[string]bool{} + return } type Button struct {} func (b *Button)Receive(s Signal) []Signal { - return []Signal{} + return []Signal{ + { To: "broadcast", From: "button", PulseType: LowPulse }, + } +} + +func (b *Button)Outputs() []string { + return []string{"broadcast"} } func (b *Button)String() string { @@ -119,9 +206,14 @@ func (b *Button)String() string { type Output struct {} func (o *Output)Receive(s Signal) []Signal { + log.Print("Outut received signal: ", s) return []Signal{} } +func (o *Output)Outputs() []string { + return []string{} +} + func (o *Output)String() string { return "[output]" } diff --git a/day20/modules_test.go b/day20/modules_test.go index 80470e8..3e6cfbb 100644 --- a/day20/modules_test.go +++ b/day20/modules_test.go @@ -48,5 +48,14 @@ func TestReadManyModules(t *testing.T) { filename2 := "example2" modules2 := ReadModules(filename2) t.Logf("> read example2:\n%+v", modules2) - +} + +func TestConjunctionRegisterInputs(t *testing.T) { + filename := "example2" + modules := ReadModules(filename) + + conjunctionInv := modules["inv"].(*Conjunction) + conjunctionInv.RegisterInputs(modules) + + t.Logf("after registering inputs on $inv : %+v", conjunctionInv.MostRecentPulseFromInputIsHigh) } diff --git a/day20/notes.org b/day20/notes.org index 9dce4b6..7846847 100644 --- a/day20/notes.org +++ b/day20/notes.org @@ -33,3 +33,5 @@ have file with `_test.go` and `func Test...(t *testing.T) {}` name #+begin_src bash go test sunshine.industries/aoc2023/day20 -v -run TestParseFlipFlop #+end_src +* yikes. if i don't know the 'inputs' to the conjunction, don't know how to check for 'all high' +let's add registering after the map is read.