day20, starting to read in data

with using tests as entry points for checking things
This commit is contained in:
efim 2023-12-20 07:35:51 +00:00
parent e771ac9d9b
commit 9dbc2ca205
4 changed files with 179 additions and 15 deletions

44
day20/modules_test.go Normal file
View File

@ -0,0 +1,44 @@
package day20
import (
"slices"
"testing"
)
func TestParseFlipFlop(t *testing.T) {
flipFlopLine := "%a -> inv, con"
if !IsLineFlipFlop(flipFlopLine) {
t.Errorf("line '%s' should be flip flop\n", flipFlopLine)
}
module := ParseFlipFlop(flipFlopLine)
t.Logf("got module %+v\n", module)
}
func TestParseBroadcast(t *testing.T) {
broadcastLine := "broadcaster -> a, b, c"
if !isLineBroadcast(broadcastLine) {
t.Error("expected line to pass broadcast check")
}
module := ParseBroadcast(broadcastLine)
t.Logf("got module %+v\n", module)
if !slices.Equal(module.OutputNames, []string{"a", "b", "c"}) {
t.Errorf("got unexpected outputs: %+v\n", module.OutputNames)
}
}
func TestParseConjunction(t *testing.T) {
conjunctionLine := "&inv -> b"
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"}) {
t.Fail()
}
}
func TestPanic(t *testing.T) {
panic("hehe")
}

35
day20/notes.org Normal file
View File

@ -0,0 +1,35 @@
#+title: Notes
* ok. only thought i had was to simulate the thing
have single executor, that takes head of the queue,
signals would be (to, from, type)
take 'to' out of the map, call it's 'process(from, type)'
and different types of executors would implement this differently.
and return a slice of new signals in order, to be appended.
if queue is empty - the single button press is propagated and all is well.
we will take snapshot of state, String() repr of all executors should be enough,
and save amount of signals sent so far
* also, i suppose i'd want to have entry points for fiddling with single executors to be test cases.
* modules to implement
** TODO Broadcast
** TODO Flip-Flop
** TODO Conjunction
** TODO Button
* i guess each module could test if string is it's a representation of this type
and would be able to parse it? into it's own struct?
well, those are just functions, since only methods are associated, so ok
* how do i run single tests?
** running tests from the module
#+begin_src bash
go test sunshine.industries/aoc2023/day20 -v
#+end_src
have file with `_test.go` and `func Test...(t *testing.T) {}` name
** running single test
#+begin_src bash
go test sunshine.industries/aoc2023/day20 -v -run TestParseFlipFlop
#+end_src

92
day20/pulsePropagation.go Normal file
View File

@ -0,0 +1,92 @@
package day20
import (
"fmt"
"log"
"regexp"
"strings"
)
func Run() int {
fmt.Println("hello from dya 20")
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"

23
main.go
View File

@ -2,25 +2,18 @@ package main
import (
"log"
"time"
"sunshine.industries/aoc2023/day19"
"sunshine.industries/aoc2023/day20"
)
func main() {
startTime := time.Now()
log.Print("> starting run:")
// lnx{m>1548:A,A}
// qqz{s>2770:qs,m<1801:hdj,R}
// kt{m>2215:R,x>3386:A,x<3107:R,R}
testSorter := day19.ReadSorterLine("kt{m>2215:R,x>3386:A,x<3107:R,R}")
log.Printf("my test sorter is %+v", testSorter)
simplified := day19.SimplifyOperation(testSorter)
log.Printf("> simplivied %+v", simplified)
detail := day19.ReadDetailLine("{x=787,m=2655,a=1222,s=2876}")
log.Printf("> detail %+v", detail)
result := day19.Run()
log.Printf("\n\nday19 result: %d\n****\n", result)
result := day20.Run()
log.Printf("\n\nday20 result: %d\n****\n", result)
endTime := time.Now()
diff := endTime.Sub(startTime)
log.Printf("execution took %s", diff.String())
}