day20: more reading
This commit is contained in:
		
							parent
							
								
									9dbc2ca205
								
							
						
					
					
						commit
						4974127cef
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,4 +1,3 @@ | |||||||
| /.direnv/ | /.direnv/ | ||||||
| /.go | /.go | ||||||
| example | input | ||||||
| /day19/input |  | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								day19/example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								day19/example
									
									
									
									
									
										Normal file
									
								
							| @ -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} | ||||||
							
								
								
									
										5
									
								
								day20/example1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day20/example1
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | broadcaster -> a, b, c | ||||||
|  | %a -> b | ||||||
|  | %b -> c | ||||||
|  | %c -> inv | ||||||
|  | &inv -> a | ||||||
							
								
								
									
										5
									
								
								day20/example2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								day20/example2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | broadcaster -> a | ||||||
|  | %a -> inv, con | ||||||
|  | &inv -> b | ||||||
|  | %b -> con | ||||||
|  | &con -> output | ||||||
							
								
								
									
										127
									
								
								day20/modules.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								day20/modules.go
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user