diff --git a/fifteen/day_fifteen.go b/fifteen/day_fifteen.go new file mode 100644 index 0000000..ece482c --- /dev/null +++ b/fifteen/day_fifteen.go @@ -0,0 +1,83 @@ +package fifteen + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +type game struct { + starting []int + numbers []int + spoken map[int]int + lastIndex map[int]int +} + +func (g *game) load(filename string) error { + file, err := os.Open(filename) + if err != nil { + return err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + input := strings.Split(scanner.Text(), ",") + + for _, i := range input { + v, err := strconv.Atoi(i) + if err != nil { + return err + } + + g.starting = append(g.starting, v) + } + } + + return nil +} + +func (g *game) valueAt(index int) int { + g.spoken = make(map[int]int, index) + g.lastIndex = make(map[int]int, index) + for i, n := range g.starting { + if i != len(g.starting)-1 { + g.spoken[n]++ + } + g.lastIndex[n] = i + g.numbers = append(g.numbers, n) + } + + for i := len(g.starting); i < index; i++ { + last := g.numbers[i-1] + g.spoken[last]++ + lastIndex := g.lastIndex[last] + g.lastIndex[last] = i - 1 + + next := 0 + + if g.spoken[last] > 1 { + next = i - 1 - lastIndex + } + + g.numbers = append(g.numbers, next) + } + + if len(g.numbers) != index { + return -1 + } + + return g.numbers[index-1] +} + +// PartOne What is the 2020th number given my input +func PartOne() string { + g := game{} + if err := g.load("fifteen/input.txt"); err != nil { + return err.Error() + } + + return fmt.Sprintf("The 2020th number is %d", g.valueAt(2020)) +} diff --git a/fifteen/day_fifteen_test.go b/fifteen/day_fifteen_test.go new file mode 100644 index 0000000..75ab77b --- /dev/null +++ b/fifteen/day_fifteen_test.go @@ -0,0 +1,45 @@ +package fifteen + +import "testing" + +func Test_load_input(t *testing.T) { + g := game{} + if err := g.load("sample.txt"); err != nil { + t.Logf(err.Error()) + t.FailNow() + } + + if len(g.numbers) != 3 { + t.Logf("Expected 3 starting numbers, got %d", len(g.numbers)) + t.FailNow() + } +} + +func Test_get_guess1(t *testing.T) { + g := game{} + if err := g.load("sample.txt"); err != nil { + t.Logf(err.Error()) + t.FailNow() + } + + r := g.valueAt(9) + if r != 4 { + t.Logf("Expected 4, but got %d", r) + t.FailNow() + } +} + +func Test_get_guess2(t *testing.T) { + g := game{} + if err := g.load("sample.txt"); err != nil { + t.Logf(err.Error()) + t.FailNow() + } + + r := g.valueAt(2020) + if r != 436 { + t.Logf("Expected 436, but got %d", r) + t.FailNow() + } +} + diff --git a/fifteen/input.txt b/fifteen/input.txt new file mode 100644 index 0000000..689f8dd --- /dev/null +++ b/fifteen/input.txt @@ -0,0 +1 @@ +18,8,0,5,4,1,20 \ No newline at end of file diff --git a/fifteen/sample.txt b/fifteen/sample.txt new file mode 100644 index 0000000..d743421 --- /dev/null +++ b/fifteen/sample.txt @@ -0,0 +1 @@ +0,3,6 \ No newline at end of file diff --git a/main.go b/main.go index 42a6551..4b74d30 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "github.com/thatguygriff/aoc2020/fourteen" + "github.com/thatguygriff/aoc2020/fifteen" ) func main() { @@ -60,6 +60,9 @@ func main() { // fmt.Println(thirteen.PartTwo()) // Day 14 - fmt.Println(fourteen.PartOne()) - fmt.Println(fourteen.PartTwo()) + // fmt.Println(fourteen.PartOne()) + // fmt.Println(fourteen.PartTwo()) + + // Day 15 + fmt.Println(fifteen.PartOne()) }