day20, receive functions
This commit is contained in:
parent
4974127cef
commit
1d7a0ef7b8
106
day20/modules.go
106
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 {
|
||||
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]"
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue