2023 Complete!
This commit is contained in:
parent
bdba3a2268
commit
6578d5123f
@ -2,21 +2,186 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
type component struct {
|
||||
id string
|
||||
connections map[string]component
|
||||
conns map[string]bool
|
||||
}
|
||||
|
||||
type components struct {
|
||||
all map[string]component
|
||||
edges []connections
|
||||
}
|
||||
|
||||
type connections struct {
|
||||
from, to string
|
||||
track []string
|
||||
}
|
||||
|
||||
func main() {
|
||||
inp := h.StdinToStringSlice()
|
||||
part1(inp)
|
||||
fmt.Println()
|
||||
part2(inp)
|
||||
lines := h.StdinToStringSlice()
|
||||
|
||||
var comps components
|
||||
var edges []connections
|
||||
var counter int
|
||||
var tries int
|
||||
for tries < 100 {
|
||||
counter = 0
|
||||
for {
|
||||
counter++
|
||||
compsS := components{all: make(map[string]component)}
|
||||
for _, line := range lines {
|
||||
connect(&compsS, line)
|
||||
}
|
||||
cc := minCut(compsS)
|
||||
cuts := len(cc.edges)
|
||||
edges = cc.edges
|
||||
comps = compsS
|
||||
if cuts == 3 {
|
||||
break
|
||||
}
|
||||
if counter >= 100 {
|
||||
break
|
||||
}
|
||||
}
|
||||
tries++
|
||||
if counter < 100 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func part1(inp []string) {
|
||||
fmt.Println("# Part 1")
|
||||
total := cutInGroups(&comps, edges)
|
||||
fmt.Println(total)
|
||||
}
|
||||
|
||||
func part2(inp []string) {
|
||||
fmt.Println("# Part 2")
|
||||
func connect(comps *components, line string) {
|
||||
split := strings.Split(line, ": ")
|
||||
nodeName := split[0]
|
||||
connectionsNames := strings.Split(split[1], " ")
|
||||
|
||||
node := component{id: nodeName, connections: make(map[string]component), conns: make(map[string]bool)}
|
||||
if _, ok := comps.all[nodeName]; !ok {
|
||||
comps.all[nodeName] = node
|
||||
}
|
||||
for _, neighborName := range connectionsNames {
|
||||
neighbor := component{id: neighborName, connections: make(map[string]component), conns: make(map[string]bool)}
|
||||
if _, ok := comps.all[neighborName]; !ok {
|
||||
comps.all[neighborName] = neighbor
|
||||
}
|
||||
comps.all[nodeName].connections[neighborName] = neighbor
|
||||
comps.all[nodeName].conns[neighborName] = true
|
||||
comps.all[neighborName].connections[nodeName] = node
|
||||
comps.all[neighborName].conns[nodeName] = true
|
||||
comps.edges = append(comps.edges, connections{
|
||||
from: nodeName,
|
||||
to: neighborName,
|
||||
track: []string{nodeName, neighborName},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func minCut(comps components) components {
|
||||
cc := components{
|
||||
all: make(map[string]component),
|
||||
edges: comps.edges,
|
||||
}
|
||||
for key, val := range comps.all {
|
||||
cc.all[key] = val
|
||||
}
|
||||
|
||||
for len(cc.all) > 2 {
|
||||
u, v := randomComps(&cc)
|
||||
contract(&cc, u, v)
|
||||
}
|
||||
|
||||
return cc
|
||||
}
|
||||
|
||||
func randomComps(comps *components) (component, component) {
|
||||
randomN := rand.Intn(len(comps.edges))
|
||||
edge := comps.edges[randomN]
|
||||
comps.edges = append(comps.edges[:randomN], comps.edges[randomN+1:]...)
|
||||
randCorn := rand.Intn(2)
|
||||
var nameU, nameV string
|
||||
if randCorn == 0 {
|
||||
nameU = edge.from
|
||||
nameV = edge.to
|
||||
} else {
|
||||
nameU = edge.to
|
||||
nameV = edge.from
|
||||
}
|
||||
u, v := comps.all[nameU], comps.all[nameV]
|
||||
return u, v
|
||||
}
|
||||
|
||||
func contract(comps *components, u component, v component) {
|
||||
delete(comps.all, v.id)
|
||||
delete(comps.all[u.id].connections, v.id)
|
||||
for _, node := range comps.all {
|
||||
if _, ok := node.connections[v.id]; ok {
|
||||
delete(node.connections, v.id)
|
||||
node.connections[u.id] = u
|
||||
comps.all[u.id].connections[node.id] = node
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(comps.edges); {
|
||||
if comps.edges[i].from == v.id {
|
||||
comps.edges[i].from = u.id
|
||||
}
|
||||
if comps.edges[i].to == v.id {
|
||||
comps.edges[i].to = u.id
|
||||
}
|
||||
if comps.edges[i].from == comps.edges[i].to {
|
||||
comps.edges = append(comps.edges[:i], comps.edges[i+1:]...)
|
||||
continue
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func cutInGroups(comps *components, edges []connections) int {
|
||||
var final1, final2 string
|
||||
for i, edge := range edges {
|
||||
cut1 := edge.track[0]
|
||||
cut2 := edge.track[1]
|
||||
delete(comps.all[cut1].conns, cut2)
|
||||
delete(comps.all[cut2].conns, cut1)
|
||||
if i == len(edges)-1 {
|
||||
final1 = cut1
|
||||
final2 = cut2
|
||||
}
|
||||
}
|
||||
group1 := countN(comps, final1)
|
||||
group2 := countN(comps, final2)
|
||||
return group1 * group2
|
||||
}
|
||||
|
||||
func countN(comps *components, start string) int {
|
||||
visited := make(map[string]bool)
|
||||
counter := 0
|
||||
entry := start
|
||||
path := []string{entry}
|
||||
for len(path) > 0 {
|
||||
currentPath := path[0]
|
||||
path = path[1:]
|
||||
if _, ok := visited[currentPath]; ok {
|
||||
continue
|
||||
}
|
||||
counter++
|
||||
currentcomponent := comps.all[currentPath]
|
||||
visited[currentPath] = true
|
||||
for key := range currentcomponent.conns {
|
||||
if _, ok := visited[key]; ok {
|
||||
continue
|
||||
}
|
||||
path = append(path, key)
|
||||
}
|
||||
}
|
||||
return counter
|
||||
}
|
||||
|
13
2023/day25/testinput
Normal file
13
2023/day25/testinput
Normal file
@ -0,0 +1,13 @@
|
||||
jqt: rhn xhk nvd
|
||||
rsh: frs pzl lsr
|
||||
xhk: hfx
|
||||
cmg: qnr nvd lhk bvb
|
||||
rhn: xhk bvb hfx
|
||||
bvb: xhk hfx
|
||||
pzl: lsr hfx nvd
|
||||
qnr: nvd
|
||||
ntq: jqt hfx bvb xhk
|
||||
nvd: lhk
|
||||
lsr: lhk
|
||||
rzs: qnr cmg lsr rsh
|
||||
frs: qnr lhk lsr
|
@ -1,5 +1,7 @@
|
||||
package aoc
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Queue[T any] struct {
|
||||
items []T
|
||||
}
|
||||
@ -80,3 +82,11 @@ func (q *Queue[T]) Insert(item T, location int) {
|
||||
func (q *Queue[T]) InsertVector(items []T, location int) {
|
||||
q.items = append(q.items[:location], append(items, q.items[location:]...)...)
|
||||
}
|
||||
|
||||
func (q Queue[T]) String() string {
|
||||
res := "[ "
|
||||
for i := range q.items {
|
||||
res = fmt.Sprintf("%s %v", res, q.items[i])
|
||||
}
|
||||
return fmt.Sprintf("%s ]", res)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user