Skip to content

Commit

Permalink
Day 16 part 1 (Golang)
Browse files Browse the repository at this point in the history
  • Loading branch information
dwalker109 committed Dec 17, 2020
1 parent 5a20ba4 commit 429b4ad
Show file tree
Hide file tree
Showing 10 changed files with 532 additions and 8 deletions.
4 changes: 2 additions & 2 deletions day10/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import "testing"

func Test_part1(t *testing.T) {
exp := 7 * 5
got := part1("./input_test.txt")
got := part1("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 1: expected %d, got %d", exp, got)
}
}
func Test_part2(t *testing.T) {
exp := 8
got := part2("./input_test.txt")
got := part2("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 2: expected %d, got %d", exp, got)
}
Expand Down
4 changes: 2 additions & 2 deletions day11/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import "testing"

func Test_part1(t *testing.T) {
exp := 37
got := part1("./input_test.txt")
got := part1("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 1: expected %d, got %d", exp, got)
}
}

func Test_part2(t *testing.T) {
exp := 26
got := part2("./input_test.txt")
got := part2("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 2: expected %d, got %d", exp, got)
}
Expand Down
4 changes: 2 additions & 2 deletions day12/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import "testing"

func Test_part1(t *testing.T) {
exp := 25
got := part1("./input_test.txt")
got := part1("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 1: expected %d, got %d", exp, got)
}
}

func Test_part2(t *testing.T) {
exp := 286
got := part2("./input_test.txt")
got := part2("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 2: expected %d, got %d", exp, got)
}
Expand Down
4 changes: 2 additions & 2 deletions day13/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import "testing"

func Test_part1(t *testing.T) {
exp := 295
got := part1("./input_test.txt")
got := part1("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 1: expected %d, got %d", exp, got)
}
}

func Test_part2(t *testing.T) {
exp := 1068781
got := part2("./input_test.txt")
got := part2("./input_test_pt1.txt")
if exp != got {
t.Errorf("Part 2: expected %d, got %d", exp, got)
}
Expand Down
262 changes: 262 additions & 0 deletions day16/input.txt

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions day16/input_test_pt1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class: 1-3 or 5-7
row: 6-11 or 33-44
seat: 13-40 or 45-50

your ticket:
7,1,14

nearby tickets:
7,3,47
40,4,50
55,2,20
38,6,12
14 changes: 14 additions & 0 deletions day16/input_test_pt2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class: 0-1 or 4-19
row: 0-5 or 8-19
seat: 0-13 or 16-19

your ticket:
11,12,13

nearby tickets:
3,9,18
15,1,5
5,14,9
78,79,80
81,82,83
3,9,80
190 changes: 190 additions & 0 deletions day16/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package main

import (
"fmt"
"strconv"
"strings"

"github.com/dwalker109/aoc-2020/util"
)

func main() {
pt1 := part1("./input.txt")
pt2 := part2("./input.txt")

fmt.Println("Part 1: ", pt1)
fmt.Println("Part 2: ", pt2)
}

func part1(p string) int {
rules, _, others := parseNotes(p)
tser := calcTSER(rules, others)

return int(tser)
}

func part2(p string) int {
rules, my, others := parseNotes(p)
valid := withoutInvalid(rules, others)
im := calcIndexMap(rules, append(valid, my))
n := calcDepartureVal(im, my)
return int(n)
}

type rulesValidator map[string]func(n int64) bool
type ticket []int64

func parseNotes(p string) (rulesValidator, ticket, []ticket) {
i := make(chan string)
go util.StreamInputCustomSplit(i, p, util.SplitOnString("\n\n"))

// Rules
rules := make(rulesValidator)
for _, s := range strings.Split(<-i, "\n") {
kv := strings.Split(s, ":")
k, v := kv[0], strings.Fields(kv[1])
r1, r2 := v[0], v[2]
rules[k] = func(n int64) bool {
for _, r := range []string{r1, r2} {
p := strings.Split(r, "-")
lo, _ := strconv.ParseInt(p[0], 10, 64)
hi, _ := strconv.ParseInt(p[1], 10, 64)
if n >= lo && n <= hi {
return true
}
}
return false
}
}

extractTicket := func(s string) ticket {
t := make(ticket, 0)
for _, i := range strings.Split(s, ",") {
j, _ := strconv.ParseInt(i, 10, 64)
t = append(t, j)
}
return t
}

// My ticket
mt := strings.Split(strings.Trim(<-i, "\n"), "\n")[1]
myTicket := extractTicket(mt)

// Other tickets
otherTickets := make([]ticket, 0)
for _, t := range strings.Split(strings.Trim(<-i, "\n"), "\n")[1:] {
otherTickets = append(otherTickets, extractTicket(t))
}

return rules, myTicket, otherTickets
}

func calcTSER(validator rulesValidator, tickets []ticket) (tser int64) {
for _, t := range tickets {
LoopTicketVals:
for _, n := range t {
for _, fn := range validator {
if fn(n) {
continue LoopTicketVals
}
}
tser += n
}
}
return
}

func withoutInvalid(validator rulesValidator, tickets []ticket) []ticket {
valid := make([]ticket, 0)
for _, t := range tickets {
tValid := true
for _, n := range t {
nValid := false
for _, fn := range validator {
if fn(n) {
nValid = true
}
}
if nValid == false {
tValid = false
}
}
if tValid {
valid = append(valid, t)
}
}
return valid
}

func calcIndexMap(validator rulesValidator, tickets []ticket) map[string]int {
indexMap := make(map[string]int)

ticketsByCol := make([][]int64, len(validator))
for i := 0; i < len(ticketsByCol); i++ {
for _, ticket := range tickets {
ticketsByCol[i] = append(ticketsByCol[i], ticket[i])
}
}

for len(indexMap) != len(validator) {
NextCol:
for colNum, colTickets := range ticketsByCol {
matches := make(map[string]bool)

// This col already mapped, move to next
for _, fc := range indexMap {
if fc == colNum {
continue NextCol
}
}

// Test each field
for key, fn := range validator {
// This key already mapped, move to next
if _, found := indexMap[key]; found {
continue
}

// Test each value in this column against the validator
for _, v := range colTickets {
if fn(v) {
// Val valid - signal true exactly once, if nothing else has already signaled something
if _, exists := matches[key]; !exists {
matches[key] = true
}
} else {
// Invalid value encountered - this key isn't for this column
matches[key] = false
}
}
}

// Discount any keys we know aren't for this column
for mk, mv := range matches {
if mv == false {
delete(matches, mk)
}
}

// Exactly one key remains - bingo
if len(matches) == 1 {
for key := range matches {
indexMap[key] = colNum
continue NextCol
}
}
}
}

return indexMap
}

func calcDepartureVal(indexMap map[string]int, t ticket) int64 {
n := int64(1)
for k, i := range indexMap {
if strings.Contains(k, "departure ") {
n *= t[i]
}
}
return n
}
19 changes: 19 additions & 0 deletions day16/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import "testing"

func Test_part1(t *testing.T) {
exp := 23054
got := part1("./input.txt")
if exp != got {
t.Errorf("Part 1: expected %d, got %d", exp, got)
}
}

func Test_part2(t *testing.T) {
exp := 51240700105297
got := part2("./input.txt")
if exp != got {
t.Errorf("Part 1: expected %d, got %d", exp, got)
}
}
27 changes: 27 additions & 0 deletions util/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package util

import (
"bufio"
"bytes"
"os"
)

Expand Down Expand Up @@ -43,3 +44,29 @@ func StreamInputCustomSplit(i chan<- string, fn string, sf func(data []byte, atE
panic("File parse error!")
}
}

func SplitOnString(s string) func(data []byte, atEOF bool) (advance int, token []byte, err error) {
var (
searchBytes = []byte(s)
searchLen = len(searchBytes)
)

return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
dataLen := len(data)

if atEOF && dataLen == 0 {
return 0, nil, nil
}

if i := bytes.Index(data, searchBytes); i >= 0 {
return i + searchLen, data[0:i], nil
}

if atEOF {
return dataLen, data, nil
}

// Moar data
return 0, nil, nil
}
}

0 comments on commit 429b4ad

Please sign in to comment.