day20, receive functions

This commit is contained in:
efim 2023-12-20 08:54:12 +00:00
parent 4974127cef
commit 1d7a0ef7b8
3 changed files with 112 additions and 9 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"log" "log"
"regexp" "regexp"
"slices"
"strings" "strings"
) )
@ -21,21 +22,49 @@ type Signal struct {
type Module interface { type Module interface {
Receive(s Signal) []Signal Receive(s Signal) []Signal
Outputs() []string
} }
// Modules // Modules
type FlipFlop struct { type FlipFlop struct {
Name string Name string
OutputNames []string OutputNames []string
InOn bool IsOn bool
} }
// ignores HighPulse
// on LowPulse - toggle state and send signal
func (ff *FlipFlop)Receive(s Signal) []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 { 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 { func IsLineFlipFlop(line string) bool {
@ -57,8 +86,19 @@ type Broadcast struct {
OutputNames []string OutputNames []string
} }
func (b *Broadcast)Receive(s Signal) []Signal { // send same pulse to all outputs
return []Signal{} 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 { func (b *Broadcast)String() string {
@ -83,8 +123,47 @@ type Conjunction struct {
MostRecentPulseFromInputIsHigh map[string]bool MostRecentPulseFromInputIsHigh map[string]bool
} }
func (c *Conjunction)Receive(s Signal) []Signal { // remembers last signal type from all inputs (initial default is Low)
return []Signal{} // 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 { func (c *Conjunction)String() string {
@ -103,13 +182,21 @@ func ParseConjunction(line string) (result Conjunction) {
result.Name = matches[1] result.Name = matches[1]
result.OutputNames = strings.Split(matches[2], ", ") result.OutputNames = strings.Split(matches[2], ", ")
result.MostRecentPulseFromInputIsHigh = map[string]bool{}
return return
} }
type Button struct {} type Button struct {}
func (b *Button)Receive(s Signal) []Signal { 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 { func (b *Button)String() string {
@ -119,9 +206,14 @@ func (b *Button)String() string {
type Output struct {} type Output struct {}
func (o *Output)Receive(s Signal) []Signal { func (o *Output)Receive(s Signal) []Signal {
log.Print("Outut received signal: ", s)
return []Signal{} return []Signal{}
} }
func (o *Output)Outputs() []string {
return []string{}
}
func (o *Output)String() string { func (o *Output)String() string {
return "[output]" return "[output]"
} }

View File

@ -48,5 +48,14 @@ func TestReadManyModules(t *testing.T) {
filename2 := "example2" filename2 := "example2"
modules2 := ReadModules(filename2) modules2 := ReadModules(filename2)
t.Logf("> read example2:\n%+v", modules2) 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)
} }

View File

@ -33,3 +33,5 @@ have file with `_test.go` and `func Test...(t *testing.T) {}` name
#+begin_src bash #+begin_src bash
go test sunshine.industries/aoc2023/day20 -v -run TestParseFlipFlop go test sunshine.industries/aoc2023/day20 -v -run TestParseFlipFlop
#+end_src #+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.