day20: whelp.

This commit is contained in:
efim 2023-12-20 11:14:45 +00:00
parent 1e32ec0988
commit 57fdfb01cb
6 changed files with 272 additions and 17 deletions

View File

@ -28,6 +28,7 @@ type Module interface {
Receive(s Signal) []Signal Receive(s Signal) []Signal
Outputs() []string Outputs() []string
StateSnapshot() string StateSnapshot() string
MermaidFlow() string
} }
// Modules // Modules
@ -76,6 +77,14 @@ func (ff *FlipFlop)StateSnapshot() string {
return ff.String() return ff.String()
} }
func (ff *FlipFlop)MermaidFlow() string {
result := "\n"
for _, toName := range ff.OutputNames {
result += fmt.Sprintf("%s --> %s\n", ff.Name, toName)
}
return result
}
func IsLineFlipFlop(line string) bool { func IsLineFlipFlop(line string) bool {
return strings.HasPrefix(line, "%") return strings.HasPrefix(line, "%")
} }
@ -117,6 +126,14 @@ func (b *Broadcast)StateSnapshot() string {
return b.String() return b.String()
} }
func (b *Broadcast)MermaidFlow() string {
result := "\n"
for _, toName := range b.OutputNames {
result += fmt.Sprintf("%s --> %s\n", "broadcast", toName)
}
return result
}
func IsLineBroadcast(line string) bool { func IsLineBroadcast(line string) bool {
return strings.HasPrefix(line, "broadcaster") return strings.HasPrefix(line, "broadcaster")
} }
@ -186,6 +203,15 @@ func (c *Conjunction)StateSnapshot() string {
return fmt.Sprintf("[conjunction '%s' -> %+v]", c.Name, c.MostRecentPulseFromInputIsHigh) return fmt.Sprintf("[conjunction '%s' -> %+v]", c.Name, c.MostRecentPulseFromInputIsHigh)
} }
func (c *Conjunction)MermaidFlow() string {
result := "\n"
for _, toName := range c.OutputNames {
result += fmt.Sprintf("%s --> %s\n", c.Name, toName)
}
return result
}
func IsLineConjunction(line string) bool { func IsLineConjunction(line string) bool {
return strings.HasPrefix(line, "&") return strings.HasPrefix(line, "&")
} }
@ -223,6 +249,10 @@ func (b *Button)StateSnapshot() string {
return b.String() return b.String()
} }
func (b *Button)MermaidFlow() string {
return "button --> broadcast\n"
}
type Output struct {} type Output struct {}
func (o *Output)Receive(s Signal) []Signal { func (o *Output)Receive(s Signal) []Signal {
@ -241,3 +271,7 @@ func (o *Output)String() string {
func (o *Output)StateSnapshot() string { func (o *Output)StateSnapshot() string {
return o.String() return o.String()
} }
func (o *Output)MermaidFlow() string {
return ""
}

170
day20/my-mermaid.mmd Normal file
View File

@ -0,0 +1,170 @@
flowchart LR
zd --> ln
zd --> gf
vz --> cr
vz --> vc
ch --> db
ch --> mc
qm --> gm
cc --> nn
qk --> vc
sr --> gf
sr --> vl
lr --> sb
hv --> lr
cl --> qx
cl --> bf
xm --> db
sf --> bp
tj --> lc
tj --> gf
rz --> qx
rz --> cv
vc --> lr
vc --> hd
vc --> ks
vc --> qn
vc --> gx
vc --> nh
vc --> hv
bf --> qx
bf --> pf
jd --> qx
jd --> vm
ds --> cc
vm --> cl
ff --> pl
th --> rx
gm --> tj
gm --> gf
fj --> zd
mc --> ds
mc --> db
ks --> vz
button --> broadcast
cv --> xz
kt --> qx
kt --> rz
qj --> xm
qj --> db
bx --> qx
bx --> qp
fn --> pr
fn --> gf
qp --> cb
qp --> qx
cd --> pm
cd --> vc
nh --> hv
pl --> sf
pl --> db
qq --> qm
qq --> gf
xf --> th
zl --> th
pf --> qx
qn --> th
jz --> qj
jz --> db
pr --> gf
vl --> gf
vl --> fj
sb --> ks
sb --> vc
cr --> gx
cr --> vc
lc --> gf
lc --> fn
xn --> th
nn --> ff
nn --> db
ln --> gf
ln --> qq
pm --> vc
pm --> qk
xz --> jd
gx --> cd
broadcast --> sr
broadcast --> ch
broadcast --> hd
broadcast --> bx
qx --> cb
qx --> cv
qx --> bx
qx --> xz
qx --> vm
qx --> zl
db --> ff
db --> ds
db --> sf
db --> ch
db --> cc
db --> xf
cb --> kt
bp --> db
bp --> jz
gf --> fj
gf --> qm
gf --> xn
gf --> sr
hd --> vc
hd --> nh

1
day20/my-mermaid.mmd.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -15,10 +15,10 @@ we will take snapshot of state, String() repr of all executors should be enough,
and save amount of signals sent so far and save amount of signals sent so far
* also, i suppose i'd want to have entry points for fiddling with single executors to be test cases. * also, i suppose i'd want to have entry points for fiddling with single executors to be test cases.
* modules to implement * modules to implement
** TODO Broadcast ** DONE Broadcast
** TODO Flip-Flop ** DONE Flip-Flop
** TODO Conjunction ** DONE Conjunction
** TODO Button ** DONE Button
* i guess each module could test if string is it's a representation of this type * i guess each module could test if string is it's a representation of this type
and would be able to parse it? into it's own struct? and would be able to parse it? into it's own struct?
well, those are just functions, since only methods are associated, so ok well, those are just functions, since only methods are associated, so ok
@ -35,3 +35,35 @@ 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' * 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. let's add registering after the map is read.
* well. for part 2 brute force doesn't work.
how could i examine inputs to the 'rx' to see when it will receive 'low'?
i suppose inputs could be on prime cycles, which would align to all required values only on a very big step?
let's do some kind of visualiztion?
how would i do graphql or mermaidjs?
flowchard in mermaid should be it
go run . > day20/my-mermaid.mmd
* so, looking at the thingy.
rx is produced by &th
which has inputs of
11:&xn -> th
14:&qn -> th
16:&xf -> th
32:&zl -> th
for rx to receive a low pulse.
&th should receive High Pulse, while all other inputs alse remembered as high.
this is not too easy.
but first let's check if loops over
- xn
- qn
- xh
- zl
are manageable.

View File

@ -10,7 +10,7 @@ func TestPropagateButtonPressExample1(t *testing.T) {
modules := ReadModules(filename) modules := ReadModules(filename)
t.Log("got modules:\n", modules) t.Log("got modules:\n", modules)
low, high := PropagateButtonPress(modules) low, high := PropagateButtonPress(modules, 0)
t.Logf("got low %d and high %d\n", low, high) t.Logf("got low %d and high %d\n", low, high)
t.Log("modules after single button press:\n", modules) t.Log("modules after single button press:\n", modules)
@ -26,7 +26,7 @@ func TestPropagateButtonPressExample2(t *testing.T) {
t.Log("got modules:\n", modules) t.Log("got modules:\n", modules)
InitStuffs(modules) InitStuffs(modules)
low, high := PropagateButtonPress(modules) low, high := PropagateButtonPress(modules, 0)
t.Logf("got low %d and high %d\n", low, high) t.Logf("got low %d and high %d\n", low, high)
t.Log("modules after single button press:\n", modules) t.Log("modules after single button press:\n", modules)
@ -44,7 +44,7 @@ func TestPropagateButtonPressExample2FourSteps(t *testing.T) {
initialModulesState := ModulesState(modules) initialModulesState := ModulesState(modules)
low, high := PropagateButtonPress(modules) low, high := PropagateButtonPress(modules, 0)
t.Logf("got low %d and high %d\n", low, high) t.Logf("got low %d and high %d\n", low, high)
t.Log("#1 button press:\n", modules) t.Log("#1 button press:\n", modules)
success := low == 4 && high == 4 success := low == 4 && high == 4
@ -52,7 +52,7 @@ func TestPropagateButtonPressExample2FourSteps(t *testing.T) {
t.Errorf("expected low 4 got %d, high 4 got %d", low, high) t.Errorf("expected low 4 got %d, high 4 got %d", low, high)
} }
low, high = PropagateButtonPress(modules) low, high = PropagateButtonPress(modules, 0)
t.Logf("got low %d and high %d\n", low, high) t.Logf("got low %d and high %d\n", low, high)
t.Log("#2 button press:\n", modules) t.Log("#2 button press:\n", modules)
success = low == 4 && high == 2 success = low == 4 && high == 2
@ -64,7 +64,7 @@ func TestPropagateButtonPressExample2FourSteps(t *testing.T) {
t.Error("initial state should be different from second") t.Error("initial state should be different from second")
} }
low, high = PropagateButtonPress(modules) low, high = PropagateButtonPress(modules, 0)
t.Logf("got low %d and high %d\n", low, high) t.Logf("got low %d and high %d\n", low, high)
t.Log("#3 button press:\n", modules) t.Log("#3 button press:\n", modules)
success = low == 5 && high == 3 success = low == 5 && high == 3
@ -76,7 +76,7 @@ func TestPropagateButtonPressExample2FourSteps(t *testing.T) {
t.Error("initial state should be different from third") t.Error("initial state should be different from third")
} }
low, high = PropagateButtonPress(modules) low, high = PropagateButtonPress(modules, 0)
t.Logf("got low %d and high %d\n", low, high) t.Logf("got low %d and high %d\n", low, high)
t.Log("#4 button press:\n", modules) t.Log("#4 button press:\n", modules)
success = low == 4 && high == 2 success = low == 4 && high == 2

View File

@ -8,16 +8,19 @@ import (
) )
func Run() int { func Run() int {
fmt.Println("hello from dya 20") // fmt.Println("hello from dya 20")
filename := "day20/input" filename := "day20/input"
modules := ReadModules(filename) modules := ReadModules(filename)
InitStuffs(modules) InitStuffs(modules)
log.Print("got modules:\n", modules) log.Print("got modules:\n", modules)
low, high := Count10000ButtonPresses(modules) var low, high int
// low, high = Count10000ButtonPresses(modules)
log.Printf("got low %d and high %d\n", low, high) log.Printf("got low %d and high %d\n", low, high)
fmt.Println(AllMermaidFlowChard(modules))
return low * high return low * high
} }
@ -35,10 +38,13 @@ func Count10000ButtonPresses(modules map[string]Module) (lowSignalsCount, highSi
// for now let's just print the info on loop // for now let's just print the info on loop
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
stepLow, stepHigh := PropagateButtonPress(modules) if i % 10000 == 0 {
log.Println("done button presses: ", i)
}
stepLow, stepHigh := PropagateButtonPress(modules, i)
lowSignalsCount += stepLow lowSignalsCount += stepLow
highSignalsCount += stepHigh highSignalsCount += stepHigh
log.Printf("after step %d low is %d and high is %d", i, lowSignalsCount, highSignalsCount) // log.Printf("after step %d low is %d and high is %d", i, lowSignalsCount, highSignalsCount)
state := ModulesState(modules) state := ModulesState(modules)
prevCounts, found := countsAfterState[state] prevCounts, found := countsAfterState[state]
@ -65,7 +71,7 @@ func Count10000ButtonPresses(modules map[string]Module) (lowSignalsCount, highSi
return return
} }
func PropagateButtonPress(modules map[string]Module) (lowSignalsCount, highSignalsCount int) { func PropagateButtonPress(modules map[string]Module, i int) (lowSignalsCount, highSignalsCount int) {
signals := []Signal{{From: "button", To: "broadcast", PulseType: LowPulse}} signals := []Signal{{From: "button", To: "broadcast", PulseType: LowPulse}}
lowSignalsCount += 1 lowSignalsCount += 1
@ -73,11 +79,14 @@ func PropagateButtonPress(modules map[string]Module) (lowSignalsCount, highSigna
curSignal := signals[0] curSignal := signals[0]
signals = signals[1:] signals = signals[1:]
log.Printf("%s -%s-> %s", curSignal.From, curSignal.PulseType, curSignal.To) // log.Printf("%s -%s-> %s", curSignal.From, curSignal.PulseType, curSignal.To)
receivingModule, found := modules[curSignal.To] receivingModule, found := modules[curSignal.To]
if !found { if !found {
log.Print(fmt.Sprintf("signal %+v can't find it's recepient\n", curSignal)) // log.Print(fmt.Sprintf("signal %+v can't find it's recepient\n", curSignal))
if curSignal.To == "rx" && curSignal.PulseType == LowPulse {
panic(fmt.Sprintf("getting low signal to rx, on step %d", i))
}
continue continue
} }
@ -153,3 +162,12 @@ func ModulesState(allModules map[string]Module) string {
return fmt.Sprint(states) return fmt.Sprint(states)
} }
func AllMermaidFlowChard(allModules map[string]Module) (result string) {
result = "flowchart LR\n"
for _, module := range allModules {
result += module.MermaidFlow()
}
return
}