Compare commits
No commits in common. "581e2571de3492de32ce120c66d0bdc06ee52ea0" and "f09b1fc787dcada473ec4d7d87d4bb5ad5c024aa" have entirely different histories.
581e2571de
...
f09b1fc787
134
2020/day21.go
134
2020/day21.go
|
@ -1,134 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.annabunch.es/annabunches/adventofcode/2020/lib/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// could optimize this better with maps, but we'll just do this. Our data set should be small enough
|
|
||||||
func intersection(a, b []string) (result []string) {
|
|
||||||
result = make([]string, 0)
|
|
||||||
for _, av := range a {
|
|
||||||
for _, bv := range b {
|
|
||||||
if av == bv {
|
|
||||||
result = append(result, av)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func includes(list []string, item string) bool {
|
|
||||||
for _, cmp := range list {
|
|
||||||
if cmp == item {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func remove(list []string, item string) []string {
|
|
||||||
for i, cmp := range list {
|
|
||||||
if cmp == item {
|
|
||||||
return append(list[:i], list[i+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseInput(input []string) (ingredients map[string]int, allergens map[string][]string) {
|
|
||||||
re := regexp.MustCompile("^(.*) \\(contains (.*)\\)")
|
|
||||||
allergens = make(map[string][]string)
|
|
||||||
ingredients = make(map[string]int)
|
|
||||||
for _, line := range input {
|
|
||||||
data := re.FindStringSubmatch(line)
|
|
||||||
is := strings.Split(data[1], " ")
|
|
||||||
as := strings.Split(data[2], ", ")
|
|
||||||
|
|
||||||
for _, ingredient := range is {
|
|
||||||
ingredients[ingredient]++
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, allergen := range as {
|
|
||||||
if ingredients, ok := allergens[allergen]; ok {
|
|
||||||
allergens[allergen] = intersection(is, ingredients)
|
|
||||||
} else {
|
|
||||||
allergens[allergen] = is
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func findUniqueSolution(aMap map[string][]string) {
|
|
||||||
done := false
|
|
||||||
for !done {
|
|
||||||
done = true
|
|
||||||
for a1, is1 := range aMap {
|
|
||||||
if len(is1) == 1 {
|
|
||||||
ingredient := is1[0]
|
|
||||||
for a2, is2 := range aMap {
|
|
||||||
if a1 == a2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
aMap[a2] = remove(is2, ingredient)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, is := range aMap {
|
|
||||||
if len(is) > 1 {
|
|
||||||
done = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
step := os.Args[1]
|
|
||||||
values := util.InputParserStrings(os.Args[2])
|
|
||||||
ingredients, allergenMap := parseInput(values)
|
|
||||||
|
|
||||||
switch step {
|
|
||||||
case "1":
|
|
||||||
loose := make([]string, 0)
|
|
||||||
for ingredient, _ := range ingredients {
|
|
||||||
found := false
|
|
||||||
for _, is := range allergenMap {
|
|
||||||
if includes(is, ingredient) {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
loose = append(loose, ingredient)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
total := 0
|
|
||||||
for _, i := range loose {
|
|
||||||
total += ingredients[i]
|
|
||||||
}
|
|
||||||
fmt.Println(total)
|
|
||||||
case "2":
|
|
||||||
findUniqueSolution(allergenMap)
|
|
||||||
keys := make([]string, 0)
|
|
||||||
for k, _ := range allergenMap {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
result := ""
|
|
||||||
sort.Strings(keys)
|
|
||||||
for _, k := range keys {
|
|
||||||
result = result + "," + allergenMap[k][0]
|
|
||||||
}
|
|
||||||
fmt.Println(strings.Trim(result, ","))
|
|
||||||
}
|
|
||||||
}
|
|
122
2020/day22.go
122
2020/day22.go
|
@ -1,122 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.annabunch.es/annabunches/adventofcode/2020/lib/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
func parseInput(input []string) [][]int {
|
|
||||||
decks := make([][]int, 2)
|
|
||||||
decks[0] = make([]int, 0)
|
|
||||||
decks[1] = make([]int, 0)
|
|
||||||
player := 0
|
|
||||||
for _, line := range input {
|
|
||||||
if strings.HasPrefix(line, "Player") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if line == "" {
|
|
||||||
player++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
decks[player] = append(decks[player], util.MustAtoi(line))
|
|
||||||
}
|
|
||||||
|
|
||||||
return decks
|
|
||||||
}
|
|
||||||
|
|
||||||
func playGame(decks [][]int, step string) (int, [][]int) {
|
|
||||||
gameStates := make(map[string]struct{})
|
|
||||||
found := struct{}{}
|
|
||||||
|
|
||||||
for len(decks[0]) > 0 && len(decks[1]) > 0 {
|
|
||||||
state := serializeGame(decks)
|
|
||||||
if _, ok := gameStates[state]; ok && step == "2" {
|
|
||||||
return 0, decks
|
|
||||||
}
|
|
||||||
gameStates[state] = found
|
|
||||||
|
|
||||||
var winner int
|
|
||||||
// take the top cards
|
|
||||||
card0 := decks[0][0]
|
|
||||||
card1 := decks[1][0]
|
|
||||||
decks[0] = decks[0][1:]
|
|
||||||
decks[1] = decks[1][1:]
|
|
||||||
|
|
||||||
// determine the winner, put the cards in order
|
|
||||||
if card0 > card1 {
|
|
||||||
winner = 0
|
|
||||||
} else {
|
|
||||||
winner = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// if each card is >= the number of cards in that deck
|
|
||||||
if step == "2" && card0 <= len(decks[0]) && card1 <= len(decks[1]) {
|
|
||||||
newDecks := make([][]int, 2)
|
|
||||||
newDecks[0] = make([]int, card0)
|
|
||||||
newDecks[1] = make([]int, card1)
|
|
||||||
copy(newDecks[0], decks[0][:card0])
|
|
||||||
copy(newDecks[1], decks[1][:card1])
|
|
||||||
// Recursive Combat throws out the "normal" winner above
|
|
||||||
winner, _ = playGame(newDecks, step)
|
|
||||||
}
|
|
||||||
|
|
||||||
// stack the cards for adding to the winner's bottom
|
|
||||||
cards := make([]int, 2)
|
|
||||||
if winner == 0 {
|
|
||||||
cards[0] = card0
|
|
||||||
cards[1] = card1
|
|
||||||
} else {
|
|
||||||
cards[0] = card1
|
|
||||||
cards[1] = card0
|
|
||||||
}
|
|
||||||
|
|
||||||
// and add them to the winner's bottom
|
|
||||||
decks[winner] = append(decks[winner], cards...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(decks[0]) > 0 {
|
|
||||||
return 0, decks
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1, decks
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeGame(decks [][]int) string {
|
|
||||||
out := ""
|
|
||||||
for _, deck := range decks {
|
|
||||||
for _, card := range deck {
|
|
||||||
out = out + string(card) + ","
|
|
||||||
}
|
|
||||||
out = out + "|"
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func calculateScore(decks [][]int) int {
|
|
||||||
score := 0
|
|
||||||
var index int
|
|
||||||
if len(decks[0]) > 0 {
|
|
||||||
index = 0
|
|
||||||
} else {
|
|
||||||
index = 1
|
|
||||||
}
|
|
||||||
deckSize := len(decks[index])
|
|
||||||
for i := deckSize - 1; i >= 0; i-- {
|
|
||||||
score += decks[index][i] * (deckSize - i)
|
|
||||||
}
|
|
||||||
|
|
||||||
return score
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
step := os.Args[1]
|
|
||||||
values := util.InputParserStrings(os.Args[2])
|
|
||||||
input := parseInput(values)
|
|
||||||
|
|
||||||
_, decks := playGame(input, step)
|
|
||||||
fmt.Println(calculateScore(decks))
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user