From 4974127cef867cb468411a22b042859f3f1c2f94 Mon Sep 17 00:00:00 2001 From: efim Date: Wed, 20 Dec 2023 08:10:10 +0000 Subject: [PATCH] day20: more reading --- .gitignore | 3 +- day19/example | 17 +++++ day20/example1 | 5 ++ day20/example2 | 5 ++ day20/modules.go | 127 ++++++++++++++++++++++++++++++++++++++ day20/modules_test.go | 18 ++++-- day20/pulsePropagation.go | 112 ++++++++++----------------------- 7 files changed, 202 insertions(+), 85 deletions(-) create mode 100644 day19/example create mode 100644 day20/example1 create mode 100644 day20/example2 create mode 100644 day20/modules.go diff --git a/.gitignore b/.gitignore index 5888b12..e22d7e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ /.direnv/ /.go -example -/day19/input +input diff --git a/day19/example b/day19/example new file mode 100644 index 0000000..e5b5d64 --- /dev/null +++ b/day19/example @@ -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} diff --git a/day20/example1 b/day20/example1 new file mode 100644 index 0000000..2dc1bab --- /dev/null +++ b/day20/example1 @@ -0,0 +1,5 @@ +broadcaster -> a, b, c +%a -> b +%b -> c +%c -> inv +&inv -> a diff --git a/day20/example2 b/day20/example2 new file mode 100644 index 0000000..2738ceb --- /dev/null +++ b/day20/example2 @@ -0,0 +1,5 @@ +broadcaster -> a +%a -> inv, con +&inv -> b +%b -> con +&con -> output diff --git a/day20/modules.go b/day20/modules.go new file mode 100644 index 0000000..8b22935 --- /dev/null +++ b/day20/modules.go @@ -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\D+) -> (?P.+)`) + 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.+)`) + 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\D+) -> (?P.+)`) + 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]" +} diff --git a/day20/modules_test.go b/day20/modules_test.go index 3d70b6e..80470e8 100644 --- a/day20/modules_test.go +++ b/day20/modules_test.go @@ -16,7 +16,7 @@ func TestParseFlipFlop(t *testing.T) { func TestParseBroadcast(t *testing.T) { broadcastLine := "broadcaster -> a, b, c" - if !isLineBroadcast(broadcastLine) { + if !IsLineBroadcast(broadcastLine) { t.Error("expected line to pass broadcast check") } module := ParseBroadcast(broadcastLine) @@ -29,16 +29,24 @@ func TestParseBroadcast(t *testing.T) { func TestParseConjunction(t *testing.T) { conjunctionLine := "&inv -> b" - if !isLineConjunction(conjunctionLine) { + if !IsLineConjunction(conjunctionLine) { t.Errorf("line '%s' should be flip flop\n", conjunctionLine) } module := ParseConjunction(conjunctionLine) 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() } } -func TestPanic(t *testing.T) { - panic("hehe") +func TestReadManyModules(t *testing.T) { + filename := "example1" + modules := ReadModules(filename) + t.Logf("> read example1:\n%+v", modules) + + filename2 := "example2" + modules2 := ReadModules(filename2) + t.Logf("> read example2:\n%+v", modules2) + } diff --git a/day20/pulsePropagation.go b/day20/pulsePropagation.go index c00bfa9..6ebb715 100644 --- a/day20/pulsePropagation.go +++ b/day20/pulsePropagation.go @@ -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\D+) -> (?P.+)`) - 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.+)`) - 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\D+) -> (?P.+)`) - 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 +}