day20: more reading
This commit is contained in:
parent
9dbc2ca205
commit
4974127cef
|
@ -1,4 +1,3 @@
|
||||||
/.direnv/
|
/.direnv/
|
||||||
/.go
|
/.go
|
||||||
example
|
input
|
||||||
/day19/input
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
px{a<2006:qkq,m>2090:A,rfg}
|
||||||
|
pv{a>1716:R,A}
|
||||||
|
lnx{m>1548:A,A}
|
||||||
|
rfg{s<537:gd,x>2440:R,A}
|
||||||
|
qs{s>3448:A,lnx}
|
||||||
|
qkq{x<1416:A,crn}
|
||||||
|
crn{x>2662:A,R}
|
||||||
|
in{s<1351:px,qqz}
|
||||||
|
qqz{s>2770:qs,m<1801:hdj,R}
|
||||||
|
gd{a>3333:R,R}
|
||||||
|
hdj{m>838:A,pv}
|
||||||
|
|
||||||
|
{x=787,m=2655,a=1222,s=2876}
|
||||||
|
{x=1679,m=44,a=2067,s=496}
|
||||||
|
{x=2036,m=264,a=79,s=2244}
|
||||||
|
{x=2461,m=1339,a=466,s=291}
|
||||||
|
{x=2127,m=1623,a=2188,s=1013}
|
|
@ -0,0 +1,5 @@
|
||||||
|
broadcaster -> a, b, c
|
||||||
|
%a -> b
|
||||||
|
%b -> c
|
||||||
|
%c -> inv
|
||||||
|
&inv -> a
|
|
@ -0,0 +1,5 @@
|
||||||
|
broadcaster -> a
|
||||||
|
%a -> inv, con
|
||||||
|
&inv -> b
|
||||||
|
%b -> con
|
||||||
|
&con -> output
|
|
@ -0,0 +1,127 @@
|
||||||
|
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]"
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ func TestParseFlipFlop(t *testing.T) {
|
||||||
|
|
||||||
func TestParseBroadcast(t *testing.T) {
|
func TestParseBroadcast(t *testing.T) {
|
||||||
broadcastLine := "broadcaster -> a, b, c"
|
broadcastLine := "broadcaster -> a, b, c"
|
||||||
if !isLineBroadcast(broadcastLine) {
|
if !IsLineBroadcast(broadcastLine) {
|
||||||
t.Error("expected line to pass broadcast check")
|
t.Error("expected line to pass broadcast check")
|
||||||
}
|
}
|
||||||
module := ParseBroadcast(broadcastLine)
|
module := ParseBroadcast(broadcastLine)
|
||||||
|
@ -29,16 +29,24 @@ func TestParseBroadcast(t *testing.T) {
|
||||||
|
|
||||||
func TestParseConjunction(t *testing.T) {
|
func TestParseConjunction(t *testing.T) {
|
||||||
conjunctionLine := "&inv -> b"
|
conjunctionLine := "&inv -> b"
|
||||||
if !isLineConjunction(conjunctionLine) {
|
if !IsLineConjunction(conjunctionLine) {
|
||||||
t.Errorf("line '%s' should be flip flop\n", conjunctionLine)
|
t.Errorf("line '%s' should be flip flop\n", conjunctionLine)
|
||||||
}
|
}
|
||||||
module := ParseConjunction(conjunctionLine)
|
module := ParseConjunction(conjunctionLine)
|
||||||
t.Logf("got module %+v\n", module)
|
t.Logf("got module %+v\n", module)
|
||||||
if module.Name != "inv" || slices.Equal(module.OutputNames, []string{"b"}) {
|
moduleAsExpected := module.Name != "inv" || slices.Equal(module.OutputNames, []string{"b"})
|
||||||
|
if !moduleAsExpected {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPanic(t *testing.T) {
|
func TestReadManyModules(t *testing.T) {
|
||||||
panic("hehe")
|
filename := "example1"
|
||||||
|
modules := ReadModules(filename)
|
||||||
|
t.Logf("> read example1:\n%+v", modules)
|
||||||
|
|
||||||
|
filename2 := "example2"
|
||||||
|
modules2 := ReadModules(filename2)
|
||||||
|
t.Logf("> read example2:\n%+v", modules2)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package day20
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"regexp"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,81 +12,37 @@ func Run() int {
|
||||||
|
|
||||||
return 0
|
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"
|
// 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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue