2015-day09: traveling salesman/santa

This commit is contained in:
alexchao26
2020-12-26 15:09:38 -05:00
parent 5c5fb7961f
commit f11e4f463b
2 changed files with 111 additions and 0 deletions
+82
View File
@@ -0,0 +1,82 @@
package main
import (
"fmt"
"math"
"strings"
"github.com/alexchao26/advent-of-code-go/mathutil"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
min, max := travelingSalesman(util.ReadFile("./input.txt"))
fmt.Printf("Part1: %d\nPart2: %d\n", min, max)
}
func travelingSalesman(input string) (int, int) {
graph := newGraphFromInput(input)
min := math.MaxInt32
max := 0
for k := range graph {
dfsMin, dfsMax := dfsTotalDistance(graph, k, map[string]bool{k: true})
min = mathutil.MinInt(min, dfsMin)
max = mathutil.MaxInt(max, dfsMax)
}
return min, max
}
func dfsTotalDistance(graph mapGraph, entry string, visited map[string]bool) (min, max int) {
// if all nodes have been visited, return a zero length
if len(visited) == len(graph) {
return 0, 0
}
minDistance := math.MaxInt32
maxDistance := 0
for k := range graph {
if !visited[k] {
visited[k] = true
weight := graph[entry][k]
minRecurse, maxRecurse := dfsTotalDistance(graph, k, visited)
minDistance = mathutil.MinInt(minDistance, weight+minRecurse)
maxDistance = mathutil.MaxInt(maxDistance, weight+maxRecurse)
// backtrack
// delete to so length of visited is accurate
delete(visited, k)
}
}
return minDistance, maxDistance
}
type mapGraph map[string]map[string]int
func newGraphFromInput(input string) (graph mapGraph) {
graph = make(mapGraph)
for _, line := range strings.Split(input, "\n") {
parts := strings.Split(line, " ")
start, end := parts[0], parts[2]
weight := cast.ToInt(parts[4])
// ensure nested map exists
if graph[start] == nil {
graph[start] = make(map[string]int)
}
if graph[end] == nil {
graph[end] = make(map[string]int)
}
// set weight in both directions
graph[start][end] = weight
graph[end][start] = weight
}
return graph
}
+29
View File
@@ -0,0 +1,29 @@
package main
import (
"testing"
"github.com/alexchao26/advent-of-code-go/util"
)
func Test_travelingSalesman(t *testing.T) {
tests := []struct {
name string
input string
wantPart1 int
wantPart2 int
}{
{"actual", util.ReadFile("input.txt"), 117, 909},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got1, got2 := travelingSalesman(tt.input)
if got1 != tt.wantPart1 {
t.Errorf("travelingSalesman() part1 = %v, want %v", got1, tt.wantPart1)
}
if got2 != tt.wantPart2 {
t.Errorf("travelingSalesman() part2 = %v, want %v", got2, tt.wantPart2)
}
})
}
}