2023-12-20 06:02:43 +00:00
|
|
|
#!/usr/bin/env tclsh
|
|
|
|
source ../prelude.tcl
|
|
|
|
|
|
|
|
proc read-input input {
|
|
|
|
global next
|
|
|
|
global type
|
|
|
|
global flip
|
|
|
|
global conj
|
2023-12-21 05:02:12 +00:00
|
|
|
global when
|
2023-12-20 06:02:43 +00:00
|
|
|
while {[gets $input line] >= 0} {
|
|
|
|
# oops
|
|
|
|
set line [replace $line ">" > "&" &]
|
|
|
|
#puts $line
|
|
|
|
must_regexp {^([%&]?)([a-z]+) -> (.*)$} $line _ sigil name to
|
|
|
|
set next($name) [replace $to "," ""]
|
|
|
|
if {$sigil eq ""} {
|
|
|
|
set type($name) ""
|
|
|
|
} elseif {$sigil eq "%"} {
|
|
|
|
set type($name) "flip"
|
|
|
|
set flip($name) 0
|
|
|
|
} elseif {$sigil eq "&"} {
|
|
|
|
set type($name) "conj"
|
|
|
|
set conj($name) [dict create]
|
2023-12-21 05:02:12 +00:00
|
|
|
set when($name) [dict create]
|
2023-12-20 06:02:43 +00:00
|
|
|
} else {
|
|
|
|
error "unknown sigil $sigil"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach n [array names type] {
|
|
|
|
foreach to $next($n) {
|
|
|
|
if {![info exists type($to)]} {
|
|
|
|
set type($to) ""
|
|
|
|
}
|
|
|
|
if {$type($to) eq "conj"} {
|
|
|
|
dict set conj($to) $n 0
|
2023-12-21 05:02:12 +00:00
|
|
|
dict set when($to) $n 0
|
2023-12-20 06:02:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-21 05:02:12 +00:00
|
|
|
proc pulse {init i {debug 0}} {
|
2023-12-20 06:02:43 +00:00
|
|
|
global next
|
|
|
|
global type
|
|
|
|
global flip
|
|
|
|
global conj
|
|
|
|
global count
|
2023-12-21 05:02:12 +00:00
|
|
|
global when
|
2023-12-20 06:02:43 +00:00
|
|
|
|
|
|
|
set n $init
|
|
|
|
set pulses {}
|
|
|
|
|
|
|
|
#puts [array get next]
|
|
|
|
|
|
|
|
incr count(0) ;# button
|
|
|
|
foreach to $next($init) {
|
|
|
|
#incr count(0)
|
|
|
|
lappend pulses $init $to 0
|
|
|
|
}
|
|
|
|
|
|
|
|
while {[llen $pulses]} {
|
|
|
|
if {$debug} {
|
|
|
|
puts "#[llen $pulses] : $pulses"
|
|
|
|
}
|
|
|
|
set copy $pulses
|
|
|
|
set pulses {}
|
|
|
|
foreach {from n value} $copy {
|
|
|
|
incr count($value)
|
2023-12-20 06:03:08 +00:00
|
|
|
if {$n eq "rx" && $value == 0} {
|
|
|
|
global solved
|
|
|
|
set solved 1
|
|
|
|
}
|
2023-12-20 06:02:43 +00:00
|
|
|
switch $type($n) {
|
|
|
|
flip {
|
|
|
|
if {$value == 0} {
|
|
|
|
set flip($n) [expr {!$flip($n)}]
|
|
|
|
foreach to $next($n) {
|
|
|
|
lappend pulses $n $to $flip($n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
conj {
|
|
|
|
dict set conj($n) $from $value
|
2023-12-21 05:02:12 +00:00
|
|
|
# remember the last time we saw a high bit from each input
|
|
|
|
if {$value} {
|
|
|
|
dict set when($n) $from $i
|
|
|
|
}
|
2023-12-20 06:02:43 +00:00
|
|
|
set all 1
|
|
|
|
foreach v [dict values $conj($n)] {
|
|
|
|
if {!$v} {
|
|
|
|
set all 0
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
set send [expr {!$all}]
|
|
|
|
foreach to $next($n) {
|
|
|
|
lappend pulses $n $to $send
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#puts $count(0)
|
|
|
|
#puts $count(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
proc solve input {
|
|
|
|
read-input $input
|
|
|
|
|
|
|
|
global count
|
|
|
|
#puts [array get next]
|
|
|
|
#array set count {0 0 1 0}
|
|
|
|
set count(0) 0
|
|
|
|
set count(1) 0
|
|
|
|
|
2023-12-21 05:02:12 +00:00
|
|
|
global when
|
2023-12-20 06:02:43 +00:00
|
|
|
for {set i 1} {$i <= 1000} {incr i} {
|
2023-12-21 05:02:12 +00:00
|
|
|
pulse broadcaster $i
|
2023-12-20 06:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
puts "$count(0)"
|
|
|
|
puts $count(1)
|
|
|
|
puts [expr {$count(0) * $count(1)}]
|
2023-12-20 06:03:08 +00:00
|
|
|
|
|
|
|
global type
|
|
|
|
if {![info exists type(rx)]} return
|
|
|
|
|
2023-12-22 09:11:41 +00:00
|
|
|
set last $when(dn)
|
2023-12-21 05:02:12 +00:00
|
|
|
while {1} {
|
|
|
|
pulse broadcaster $i
|
|
|
|
if {$when(dn) ne $last} {
|
2023-12-22 09:11:41 +00:00
|
|
|
# rx is connected to a conj of 4 circuits
|
|
|
|
# which each emit 1 high pulse on a periodic cycle.
|
|
|
|
#
|
|
|
|
# this could be more difficult but it turns out
|
|
|
|
# that the step when the first output is produced
|
|
|
|
# is also equal to the cycle length,
|
|
|
|
# and all the cycles are a prime number so we don't
|
|
|
|
# even need to do an lcm
|
|
|
|
set a [lmul [dict values $when(dn)]]
|
|
|
|
if {$a != 0} {
|
|
|
|
puts $a
|
|
|
|
break
|
|
|
|
}
|
|
|
|
#puts $when(dn)
|
2023-12-21 05:02:12 +00:00
|
|
|
set last $when(dn)
|
2023-12-20 06:03:08 +00:00
|
|
|
}
|
2023-12-21 05:02:12 +00:00
|
|
|
incr i
|
2023-12-20 06:03:08 +00:00
|
|
|
}
|
2023-12-20 06:02:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
solve stdin
|