128 lines
2.4 KiB
Go
128 lines
2.4 KiB
Go
package day20
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
type PulseType int
|
|
|
|
const (
|
|
HighPulse PulseType = iota
|
|
LowPulse
|
|
)
|
|
|
|
type Signal struct {
|
|
To, From string
|
|
PulseType PulseType
|
|
}
|
|
|
|
type Module interface {
|
|
Receive(s Signal) []Signal
|
|
}
|
|
|
|
// Modules
|
|
type FlipFlop struct {
|
|
Name string
|
|
OutputNames []string
|
|
InOn bool
|
|
}
|
|
|
|
func (ff *FlipFlop)Receive(s Signal) []Signal {
|
|
return []Signal{}
|
|
}
|
|
|
|
func (ff *FlipFlop)String() string {
|
|
return fmt.Sprintf("[flip-flop '%s' (on: %t) -> %s]", ff.Name, ff.InOn, ff.OutputNames)
|
|
}
|
|
|
|
func IsLineFlipFlop(line string) bool {
|
|
return strings.HasPrefix(line, "%")
|
|
}
|
|
|
|
func ParseFlipFlop(line string) (result FlipFlop) {
|
|
re := regexp.MustCompile(`%(?P<NAME>\D+) -> (?P<OUTPUTS>.+)`)
|
|
matches := re.FindStringSubmatch(line)
|
|
|
|
log.Printf("matching %s getting '%s' and '%s'\n", line, matches[1], matches[2])
|
|
result.Name = matches[1]
|
|
result.OutputNames = strings.Split(matches[2], ", ")
|
|
|
|
return
|
|
}
|
|
|
|
type Broadcast struct {
|
|
OutputNames []string
|
|
}
|
|
|
|
func (b *Broadcast)Receive(s Signal) []Signal {
|
|
return []Signal{}
|
|
}
|
|
|
|
func (b *Broadcast)String() string {
|
|
return fmt.Sprintf("[broadcast -> %+v]", b.OutputNames)
|
|
}
|
|
|
|
func IsLineBroadcast(line string) bool {
|
|
return strings.HasPrefix(line, "broadcaster")
|
|
}
|
|
|
|
func ParseBroadcast(line string) (result Broadcast) {
|
|
re := regexp.MustCompile(`broadcaster -> (?P<OUTPUTS>.+)`)
|
|
matches := re.FindStringSubmatch(line)
|
|
|
|
result.OutputNames = strings.Split(matches[1], ", ")
|
|
return
|
|
}
|
|
|
|
type Conjunction struct {
|
|
Name string
|
|
OutputNames []string
|
|
MostRecentPulseFromInputIsHigh map[string]bool
|
|
}
|
|
|
|
func (c *Conjunction)Receive(s Signal) []Signal {
|
|
return []Signal{}
|
|
}
|
|
|
|
func (c *Conjunction)String() string {
|
|
return fmt.Sprintf("[conjunction '%s' -> %+v]", c.Name, c.OutputNames)
|
|
}
|
|
|
|
func IsLineConjunction(line string) bool {
|
|
return strings.HasPrefix(line, "&")
|
|
}
|
|
|
|
func ParseConjunction(line string) (result Conjunction) {
|
|
re := regexp.MustCompile(`&(?P<NAME>\D+) -> (?P<OUTPUTS>.+)`)
|
|
matches := re.FindStringSubmatch(line)
|
|
|
|
log.Printf("matching %s getting '%s' and '%s'\n", line, matches[1], matches[2])
|
|
result.Name = matches[1]
|
|
result.OutputNames = strings.Split(matches[2], ", ")
|
|
|
|
return
|
|
}
|
|
|
|
type Button struct {}
|
|
|
|
func (b *Button)Receive(s Signal) []Signal {
|
|
return []Signal{}
|
|
}
|
|
|
|
func (b *Button)String() string {
|
|
return "[button]"
|
|
}
|
|
|
|
type Output struct {}
|
|
|
|
func (o *Output)Receive(s Signal) []Signal {
|
|
return []Signal{}
|
|
}
|
|
|
|
func (o *Output)String() string {
|
|
return "[output]"
|
|
}
|