2023 Complete!
This commit is contained in:
parent
bdba3a2268
commit
6578d5123f
@ -2,21 +2,186 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
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() {
|
func main() {
|
||||||
inp := h.StdinToStringSlice()
|
lines := h.StdinToStringSlice()
|
||||||
part1(inp)
|
|
||||||
fmt.Println()
|
var comps components
|
||||||
part2(inp)
|
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) {
|
total := cutInGroups(&comps, edges)
|
||||||
fmt.Println("# Part 1")
|
fmt.Println(total)
|
||||||
}
|
}
|
||||||
|
|
||||||
func part2(inp []string) {
|
func connect(comps *components, line string) {
|
||||||
fmt.Println("# Part 2")
|
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
|
package aoc
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type Queue[T any] struct {
|
type Queue[T any] struct {
|
||||||
items []T
|
items []T
|
||||||
}
|
}
|
||||||
@ -80,3 +82,11 @@ func (q *Queue[T]) Insert(item T, location int) {
|
|||||||
func (q *Queue[T]) InsertVector(items []T, location int) {
|
func (q *Queue[T]) InsertVector(items []T, location int) {
|
||||||
q.items = append(q.items[:location], append(items, q.items[location:]...)...)
|
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