Add 2021-12 in Go (not Python this time!)

Signed-off-by: AKU <tom@tdpain.net>
This commit is contained in:
akp 2021-12-12 14:50:07 +00:00
parent 41f60123e7
commit e2a08ae5db
No known key found for this signature in database
GPG key ID: AA5726202C8879B7
7 changed files with 228 additions and 0 deletions

View file

@ -0,0 +1,2 @@
# [Day 12: Passage Pathing](https://adventofcode.com/2021/day/12)

View file

@ -0,0 +1,15 @@
{
"day": 12,
"dir": "challenges/2021/12-passagePathing",
"implementations": {
"Golang": {
"part.1.avg": 0.004089135783000003,
"part.1.max": 0.015094977,
"part.1.min": 0.002771765,
"part.2.avg": 0.090934005394,
"part.2.max": 0.250616487,
"part.2.min": 0.065061159
}
},
"numRuns": 1000
}

View file

@ -0,0 +1,123 @@
package challenge
import (
"strings"
"github.com/codemicro/adventOfCode/lib/aocgo"
)
type node struct {
isSmall bool
name string
}
func newNode(x string) *node {
return &node{
isSmall: x == strings.ToLower(x),
name: x,
}
}
type graph struct {
nodes map[string]*node
edges map[*node][]*node
}
func newGraph() *graph {
return &graph{
nodes: make(map[string]*node),
edges: make(map[*node][]*node),
}
}
func parse(instr string) *graph {
g := newGraph()
for _, line := range strings.Split(strings.TrimSpace(instr), "\n") {
sp := strings.Split(line, "-")
from := sp[0]
to := sp[1]
fromNode := g.nodes[from]
toNode := g.nodes[to]
if fromNode == nil {
fromNode = newNode(from)
g.nodes[from] = fromNode
}
if toNode == nil {
toNode = newNode(to)
g.nodes[to] = toNode
}
g.edges[fromNode] = append(g.edges[fromNode], toNode)
g.edges[toNode] = append(g.edges[toNode], fromNode)
}
return g
}
func countRoutesA(cave *graph, fromNode *node, visited *aocgo.Set) int {
if fromNode.name == "end" {
return 1
}
var total int
for _, nextNode := range cave.edges[fromNode] {
if visited.Contains(nextNode) || nextNode.name == "start" {
continue
}
s := visited.ShallowCopy()
if fromNode.isSmall {
s.Add(fromNode)
}
total += countRoutesA(cave, nextNode, s)
}
return total
}
func countRoutesB(cave *graph, fromNode *node, visited *aocgo.Set, extraUsed bool) int {
if fromNode.name == "end" {
return 1
}
var total int
for _, nextNode := range cave.edges[fromNode] {
if nextNode.name == "start" {
continue
}
var y bool
if x := visited.Contains(nextNode); x && extraUsed {
continue
} else if x {
y = true
} else {
y = extraUsed
}
s := visited.ShallowCopy()
if fromNode.isSmall {
s.Add(fromNode)
}
total += countRoutesB(cave, nextNode, s, y)
}
return total
}
type Challenge struct {
aocgo.BaseChallenge
}
func (c Challenge) One(instr string) (interface{}, error) {
cave := parse(instr)
return countRoutesA(cave, cave.nodes["start"], aocgo.NewSet()), nil
}
func (c Challenge) Two(instr string) (interface{}, error) {
cave := parse(instr)
return countRoutesB(cave, cave.nodes["start"], aocgo.NewSet(), false), nil
}

View file

@ -0,0 +1,20 @@
import networkx as nx
import matplotlib.pyplot as plt
edges = []
nodes = []
with open("input.txt") as f:
for line in f.read().strip().splitlines():
f, t = line.split("-")
edges.append((f,t))
for x in [f, t]:
if x not in nodes:
nodes.append(x)
graph = nx.Graph()
graph.add_edges_from(edges)
pos = nx.kamada_kawai_layout(graph)
nx.draw_networkx_nodes(graph, pos, nodelist=nodes)
nx.draw_networkx_labels(graph, pos)
nx.draw_networkx_edges(graph, pos, edgelist=graph.edges())
plt.show()

View file

@ -0,0 +1,33 @@
{
"inputFile": "input.txt",
"testCases": {
"one": [
{
"input": "start-A\nstart-b\nA-c\nA-b\nb-d\nA-end\nb-end",
"expected": "10"
},
{
"input": "dc-end\nHN-start\nstart-kj\ndc-start\ndc-HN\nLN-dc\nHN-end\nkj-sa\nkj-HN\nkj-dc\n",
"expected": "19"
},
{
"input": "fs-end\nhe-DX\nfs-he\nstart-DX\npj-DX\nend-zg\nzg-sl\nzg-pj\npj-he\nRW-he\nfs-DX\npj-RW\nzg-RW\nstart-pj\nhe-WI\nzg-he\npj-fs\nstart-RW",
"expected": "226"
}
],
"two": [
{
"input": "start-A\nstart-b\nA-c\nA-b\nb-d\nA-end\nb-end",
"expected": "36"
},
{
"input": "dc-end\nHN-start\nstart-kj\ndc-start\ndc-HN\nLN-dc\nHN-end\nkj-sa\nkj-HN\nkj-dc\n",
"expected": "103"
},
{
"input": "fs-end\nhe-DX\nfs-he\nstart-DX\npj-DX\nend-zg\nzg-sl\nzg-pj\npj-he\nRW-he\nfs-DX\npj-RW\nzg-RW\nstart-pj\nhe-WI\nzg-he\npj-fs\nstart-RW",
"expected": "3509"
}
]
}
}

View file

@ -21,6 +21,7 @@ Solutions to the [2021 Advent of Code](https://adventofcode.com/2021).
| 09 - Smoke Basin \* | Complete | [Python](09-smokeBasin/py) | Schmokey! Also, as it turns out, I struggle to implement basic logic. Fun. |
| 10 - Syntax Scoring | Complete | [Python](10-syntaxScoring/py) | I can't say I've ever broken something so thoroughly that it has a syntax error on *every* line... |
| 11 - Dumbo Octopus | Complete | [Python](11-dumboOctopus/py), [Nim](11-dumboOctopus/nim) | Cellular automata my beloved <3 |
| 12 - Passage Pathing | Complete | [Go][12-passagePathing/go] | I couldn't tell you how it works, but it does kinda work and I think I have a vague idea (external help was used). |
<!-- PARSE END -->

34
lib/aocgo/set.go Normal file
View file

@ -0,0 +1,34 @@
package aocgo
type Set []interface{}
func NewSet() *Set {
return new(Set)
}
func (s *Set) Contains(x interface{}) bool {
for _, item := range *s {
if item == x {
return true
}
}
return false
}
func (s *Set) Add(x interface{}) {
if !s.Contains(x) {
*s = append(*s, x)
}
}
func (s *Set) Union(t *Set) {
for _, item := range *t {
s.Add(item)
}
}
func (s *Set) ShallowCopy() *Set {
ns := NewSet()
*ns = append(*ns, *s...)
return ns
}