adventofcode/2015/day09/main.go

167 lines
3.3 KiB
Go

package main
import (
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
)
var allTowns map[string]roads
type roads map[string]int
func main() {
allTowns = make(map[string]roads)
var input []string
var readInp, bldInput string
for {
_, err := fmt.Scan(&readInp)
if err != nil {
if err != io.EOF {
log.Fatal(err)
}
break
}
if strings.HasSuffix(bldInput, "=") {
bldInput = bldInput + " " + readInp
input = append(input, bldInput)
bldInput = ""
continue
}
if len(bldInput) > 0 {
bldInput += " "
}
bldInput = bldInput + readInp
}
for i := range input {
dirTowns := strings.Split(input[i], " to ")
secondPart := strings.Split(dirTowns[1], " = ")
town1 := dirTowns[0]
town2 := secondPart[0]
distance := mustAtoi(secondPart[1])
buildRoute(town1, town2, distance)
}
// All routes should be built, find the shortest
var shortestRoute []string
shortestDistance := -1
for i := range allTowns {
var visited []string
lastVisit := i
tripDistance := 0
for len(visited) < len(allTowns) {
var dist int
visited = append(visited, lastVisit)
lastVisit, dist = findShortest(lastVisit, visited)
if dist > 0 {
tripDistance += dist
}
}
if shortestDistance == -1 || tripDistance < shortestDistance {
shortestDistance = tripDistance
shortestRoute = visited
}
}
// Now find the longest
var longestRoute []string
longestDistance := -1
for i := range allTowns {
var visited []string
lastVisit := i
tripDistance := 0
for len(visited) < len(allTowns) {
var dist int
visited = append(visited, lastVisit)
lastVisit, dist = findLongest(lastVisit, visited)
if dist > 0 {
tripDistance += dist
}
}
if longestDistance == -1 || tripDistance > longestDistance {
longestDistance = tripDistance
longestRoute = visited
}
}
fmt.Println("Shortest Route:" + strconv.Itoa(shortestDistance))
fmt.Println(strings.Join(shortestRoute, "->"))
fmt.Println("Longest Route:" + strconv.Itoa(longestDistance))
fmt.Println(strings.Join(longestRoute, "->"))
}
func findShortest(from string, exclude []string) (string, int) {
var toTown string
shortest := -1
for j := range allTowns[from] {
var didIt bool
for ex := range exclude {
if j == exclude[ex] {
didIt = true
break
}
}
if didIt {
continue
}
// Find the quickest trip from here
if shortest == -1 || allTowns[from][j] < shortest {
shortest = allTowns[from][j]
toTown = j
}
}
return toTown, shortest
}
func findLongest(from string, exclude []string) (string, int) {
var toTown string
longest := -1
for j := range allTowns[from] {
var didIt bool
for ex := range exclude {
if j == exclude[ex] {
didIt = true
break
}
}
if didIt {
continue
}
// Find the longest trip from here
if longest == -1 || allTowns[from][j] > longest {
longest = allTowns[from][j]
toTown = j
}
}
return toTown, longest
}
func mustAtoi(i string) int {
var ret int
var err error
if ret, err = strconv.Atoi(i); err != nil {
fmt.Println("Tried to mustAtoi: " + i)
os.Exit(1)
}
return ret
}
func buildRoute(t1, t2 string, dist int) {
if _, ok := allTowns[t1]; !ok {
// Add this town
allTowns[t1] = make(map[string]int)
}
allTowns[t1][t2] = dist
// And the other direction
if _, ok := allTowns[t2]; !ok {
// Add this town
allTowns[t2] = make(map[string]int)
}
allTowns[t2][t1] = dist
}