adventofcode/2015/day13/main.go

158 lines
2.9 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
var people map[string]person
func main() {
var pplSlice []string
people = make(map[string]person)
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
for i := range input {
p := parseLine(input[i])
people[p.name] = p
}
for i := range people {
pplSlice = append(pplSlice, people[i].name)
}
// Output all preferences
/*
for k, v := range people {
fmt.Println(k)
fmt.Println(" High: " + v.highName + " :: " + strconv.Itoa(v.highVal))
for pk, pv := range v.prefs {
fmt.Println(" " + pk + ": " + strconv.Itoa(pv))
}
}
*/
//getPerms(pplSlice)
first := pplSlice[0]
res := getPerms(pplSlice[1:])
var high int
var arrangement []string
for i := range res {
tstArr := append([]string{first}, res[i]...)
tst := happinessFromStrings(tstArr)
if tst > high {
high = tst
arrangement = tstArr
}
}
fmt.Println("Highest: " + strconv.Itoa(high))
fmt.Println(arrangement)
}
func getPerms(ppl []string) [][]string {
var ret [][]string
if len(ppl) == 1 {
return append(ret, ppl)
}
for j := range ppl {
var bld []string
for i := range ppl {
if i != j {
bld = append(bld, ppl[i])
}
}
perms := getPerms(bld)
for i := range perms {
perms[i] = append([]string{ppl[j]}, perms[i]...)
ret = append(ret, perms[i])
}
}
return ret
}
func happinessFromStrings(pS []string) int {
var ppl []person
for i := range pS {
ppl = append(ppl, people[pS[i]])
}
return happinessValue(ppl)
}
func happinessValue(ppl []person) int {
var ret int
for i := range ppl {
p1, p2 := getNeighbors(ppl[i], ppl)
ret += ppl[i].prefs[p1.name]
ret += ppl[i].prefs[p2.name]
}
return ret
}
func getNeighbors(p person, ppl []person) (person, person) {
var p1, p2 person
for idx := range ppl {
if ppl[idx].name == p.name {
if idx == 0 {
p1 = ppl[len(ppl)-1]
p2 = ppl[idx+1]
} else if idx == len(ppl)-1 {
p1 = ppl[idx-1]
p2 = ppl[0]
} else {
p1 = ppl[idx-1]
p2 = ppl[idx+1]
}
break
}
}
return p1, p2
}
type person struct {
name string
prefs map[string]int
highName string
highVal int
lowName string
lowVal int
}
func parseLine(s string) person {
parts := strings.Split(s, " ")
who := parts[0]
direction := parts[2]
amount := mustAtoi(parts[3])
nextTo := parts[10][:len(parts[10])-1]
if direction == "lose" {
amount = amount * -1
}
var ret person
var ok bool
if ret, ok = people[who]; !ok {
ret = person{name: who}
ret.prefs = make(map[string]int)
}
ret.prefs[nextTo] = amount
if ret.highVal < amount || ret.highName == "" {
ret.highVal, ret.highName = amount, nextTo
}
if ret.lowVal > amount || ret.lowName == "" {
ret.lowVal, ret.lowName = amount, nextTo
}
return ret
}
func mustAtoi(s string) int {
var i int
var err error
if i, err = strconv.Atoi(s); err != nil {
fmt.Println("Tried to atoi " + s)
}
return i
}