day20: more reading
This commit is contained in:
@@ -3,7 +3,7 @@ package day20
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -12,81 +12,37 @@ func Run() int {
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
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 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 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 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 {}
|
||||
// process sends single `low pulse` directly to "broadcast"
|
||||
|
||||
func ReadModules(filename string) map[string]Module {
|
||||
result := make(map[string]Module)
|
||||
bytes, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(fmt.Sprint("error reading file: ", filename))
|
||||
}
|
||||
|
||||
text := strings.TrimSpace(string(bytes))
|
||||
|
||||
for _, line := range strings.Split(text, "\n") {
|
||||
switch {
|
||||
case IsLineBroadcast(line):
|
||||
parsed := ParseBroadcast(line)
|
||||
result["broadcast"] = &parsed
|
||||
case IsLineFlipFlop(line):
|
||||
parsed := ParseFlipFlop(line)
|
||||
result[parsed.Name] = &parsed
|
||||
case IsLineConjunction(line):
|
||||
parsed := ParseConjunction(line)
|
||||
result[parsed.Name] = &parsed
|
||||
}
|
||||
|
||||
log.Println(line)
|
||||
}
|
||||
|
||||
buttonModule := Button{}
|
||||
result["button"] = &buttonModule
|
||||
outputModule := Output{}
|
||||
result["output"] = &outputModule
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user