Skip to content

Commit

Permalink
Finished day 20
Browse files Browse the repository at this point in the history
  • Loading branch information
devries committed Dec 20, 2023
1 parent a9961c2 commit 8b5081b
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/*.json
run.go
aoc_run
day20p2/relations.gv
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Advent of Code 2023

[![Tests](https://github.com/devries/advent_of_code_2023/actions/workflows/main.yml/badge.svg)](https://github.com/devries/advent_of_code_2023/actions/workflows/main.yml)
[![Stars: 38](https://img.shields.io/badge/⭐_Stars-38-yellow)](https://adventofcode.com/2023)
[![Stars: 40](https://img.shields.io/badge/⭐_Stars-40-yellow)](https://adventofcode.com/2023)

## Plan for This Year

Expand Down Expand Up @@ -76,6 +76,8 @@ the third run of my solution after compilation on my Raspberry Pi.
| 18 | 2 | 3.934349ms |
| 19 | 1 | 3.561334ms |
| 19 | 2 | 4.006922ms |
| 20 | 1 | 25.246853ms |
| 20 | 2 | 2.752046ms |

## Solutions

Expand Down Expand Up @@ -307,3 +309,15 @@ the third run of my solution after compilation on my Raspberry Pi.
final summation, I would just split the available ranges up and perform the
rule action on the part that satisfied the rule, and move on with the part
that didn't.
- [Day 20: Pulse Propagation](https://adventofcode.com/2023/day/20) - [⭐ part 1](day20p1/solution.go), [⭐ part 2](day20p2/solution.go)
The first part of this was straighforward, though I did manage to overengineer
it a bit. I also did finally ask for bing chat to provide some code. I asked
it for an arbitrary length bitfield. For some reason it didn't give me an
unset method and I had to write a serializer and deserializer because I thought
we were going to require memoization. This is one of the many times thinking
ahead just made things harder because it turns out the second part involved
examining the structure of the gates to form a solution. I only did the solution
for my particular arrangement. The code to part two does produce a visualization
which can be used to change the final 4 binary entries in the program.
108 changes: 108 additions & 0 deletions day20p2/solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package day20p2

import (
"fmt"
"io"
"os"
"strings"

"aoc/utils"
)

func Solve(r io.Reader) any {
lines := utils.ReadLines(r)

modules := make(map[string]*module)
for _, ln := range lines {
name, mod := parseLine(ln)
modules[name] = mod
}

// get all sources for modules
for name, mod := range modules {
for _, d := range mod.destinations {
if md, ok := modules[d]; ok {
md.sources = append(md.sources, name)
}
}
}

f, err := os.Create("day20p2/relations.gv")
utils.Check(err, "unable to open visualization file")
defer f.Close()

// write out a graphviz visualization
fmt.Fprintln(f, "digraph G {")

for name, m := range modules {
var shape string
switch m.kind {
case flipflop:
shape = "rect"
case conjunction:
shape = "trapezium"
default:
shape = "circle"
}

fmt.Fprintf(f, " %s [ shape = \"%s\"; ];\n", name, shape)
for _, d := range m.destinations {
fmt.Fprintf(f, " %s -> %s;\n", name, d)
}
}
fmt.Fprintln(f, "}")

// Can deduce that there are 12 bit counters that trigger an and LOW
// and resets the clock. When all ands are low at the same time you get
// your pulse. The counter trip point is when all flip-flops that feed
// into conjunction gate are HIGH, and the ones which receive a signal
// from that AND gate are LOW.
//
// The lSB is next to the button, and the bit order follows the links
// between flip-flops.

val := int64(0b111101011011) // kb
val = utils.Lcm(val, int64(0b111100010111)) // vm
val = utils.Lcm(val, int64(0b111011010101)) // dn
val = utils.Lcm(val, int64(0b111010111001)) // vk

return val
}

type modtype int

const (
flipflop modtype = iota
conjunction
broadcast
)

type module struct {
kind modtype
destinations []string
sources []string
bitnumber int
}

func parseLine(ln string) (string, *module) {
var ret module
var name string

components := strings.Split(ln, " -> ")
ret.destinations = strings.Split(components[1], ", ")

switch components[0][0] {
case '%':
// flip flop
ret.kind = flipflop
name = components[0][1:]
case '&':
ret.kind = conjunction
name = components[0][1:]
default:
ret.kind = broadcast
name = components[0]
}

return name, &ret
}

0 comments on commit 8b5081b

Please sign in to comment.