mirror of
https://github.com/Threnklyn/advent-of-code-go.git
synced 2026-06-07 20:53:30 +02:00
2020 day 10 - memoized or dynamic programming to calculate paths/possibilities, ~830
This commit is contained in:
+87
-6
@@ -3,8 +3,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alexchao26/advent-of-code-go/algo"
|
||||||
"github.com/alexchao26/advent-of-code-go/util"
|
"github.com/alexchao26/advent-of-code-go/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,17 +28,34 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func part1(input string) int {
|
func part1(input string) int {
|
||||||
parsed := parseInput(input)
|
nums := parseInput(input)
|
||||||
_ = parsed
|
nums = append(nums, util.MaxInts(nums...)+3)
|
||||||
|
sort.Ints(nums)
|
||||||
|
|
||||||
return 0
|
var oneDiff, threeDiff int
|
||||||
|
var currentJoltage int
|
||||||
|
for _, v := range nums {
|
||||||
|
switch v - currentJoltage {
|
||||||
|
case 1: // check for 1 diff first, so no adapters are skipped
|
||||||
|
oneDiff++
|
||||||
|
case 3:
|
||||||
|
threeDiff++
|
||||||
|
default:
|
||||||
|
panic("adpaters not connected by 3 or 1")
|
||||||
|
}
|
||||||
|
currentJoltage = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return oneDiff * threeDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
func part2(input string) int {
|
func part2(input string) int {
|
||||||
parsed := parseInput(input)
|
nums := parseInput(input)
|
||||||
_ = parsed
|
nums = append(nums, util.MaxInts(nums...)+3)
|
||||||
|
sort.Ints(nums)
|
||||||
|
|
||||||
return 0
|
// return dynamicProgramming(input)
|
||||||
|
return memoCountPossibilities(nums, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseInput(input string) []int {
|
func parseInput(input string) []int {
|
||||||
@@ -49,3 +68,65 @@ func parseInput(input string) []int {
|
|||||||
|
|
||||||
return ans
|
return ans
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// storing memo in global state isn't ideal... but it's fastser to code
|
||||||
|
var memo = map[string]int{}
|
||||||
|
|
||||||
|
func memoCountPossibilities(nums []int, lastJolt int) int {
|
||||||
|
// if in memo, return that value
|
||||||
|
str := makeMemoKey(nums, lastJolt)
|
||||||
|
if v, ok := memo[str]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// if all adapters used up, return 1
|
||||||
|
if len(nums) == 0 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a recursive call for each adapter within 3 of the lastJoltage
|
||||||
|
var count int
|
||||||
|
for i, v := range nums {
|
||||||
|
if v-lastJolt <= 3 {
|
||||||
|
count += memoCountPossibilities(nums[i+1:], v)
|
||||||
|
} else { // stop counting if the joltage diff is too larger (>3)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update memo
|
||||||
|
memo[str] = count
|
||||||
|
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
func makeMemoKey(nums []int, lastJolt int) string {
|
||||||
|
ans := algo.IntToStr(lastJolt) + "x"
|
||||||
|
for _, v := range nums {
|
||||||
|
ans += algo.IntToStr(v)
|
||||||
|
}
|
||||||
|
return ans
|
||||||
|
}
|
||||||
|
|
||||||
|
func dynamicProgramming(input string) int {
|
||||||
|
nums := parseInput(input)
|
||||||
|
nums = append(nums, util.MaxInts(nums...)+3, 0)
|
||||||
|
sort.Ints(nums)
|
||||||
|
|
||||||
|
// initialize table with "1 way" to get to zero jolts
|
||||||
|
table := make([]int, len(nums))
|
||||||
|
table[0] = 1
|
||||||
|
|
||||||
|
for i := 1; i < len(nums); i++ {
|
||||||
|
currentJolts := nums[i]
|
||||||
|
for j := i - 1; j >= 0; j-- {
|
||||||
|
// add the ways to get to currentJolts that are within 3 jolts
|
||||||
|
if currentJolts-nums[j] <= 3 {
|
||||||
|
table[i] += table[j]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return table[len(table)-1]
|
||||||
|
}
|
||||||
|
|||||||
+74
-5
@@ -1,14 +1,63 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/alexchao26/advent-of-code-go/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
var exampleInputs = []string{`16
|
||||||
|
10
|
||||||
|
15
|
||||||
|
5
|
||||||
|
1
|
||||||
|
11
|
||||||
|
7
|
||||||
|
19
|
||||||
|
6
|
||||||
|
12
|
||||||
|
4`,
|
||||||
|
`28
|
||||||
|
33
|
||||||
|
18
|
||||||
|
42
|
||||||
|
31
|
||||||
|
14
|
||||||
|
46
|
||||||
|
20
|
||||||
|
48
|
||||||
|
47
|
||||||
|
24
|
||||||
|
23
|
||||||
|
49
|
||||||
|
45
|
||||||
|
19
|
||||||
|
38
|
||||||
|
39
|
||||||
|
11
|
||||||
|
1
|
||||||
|
32
|
||||||
|
25
|
||||||
|
35
|
||||||
|
8
|
||||||
|
17
|
||||||
|
7
|
||||||
|
9
|
||||||
|
4
|
||||||
|
2
|
||||||
|
34
|
||||||
|
10
|
||||||
|
3`,
|
||||||
|
}
|
||||||
|
|
||||||
var tests1 = []struct {
|
var tests1 = []struct {
|
||||||
name string
|
name string
|
||||||
want int
|
want int
|
||||||
input string
|
input string
|
||||||
// add extra args if needed
|
|
||||||
}{
|
}{
|
||||||
// {"actual", ACTUAL_ANSWER, util.ReadFile("input.txt")},
|
{"example 1", 35, exampleInputs[0]},
|
||||||
|
{"example 2", 220, exampleInputs[1]},
|
||||||
|
{"actual", 2176, util.ReadFile("input.txt")},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPart1(t *testing.T) {
|
func TestPart1(t *testing.T) {
|
||||||
@@ -25,9 +74,10 @@ var tests2 = []struct {
|
|||||||
name string
|
name string
|
||||||
want int
|
want int
|
||||||
input string
|
input string
|
||||||
// add extra args if needed
|
|
||||||
}{
|
}{
|
||||||
// {"actual", ACTUAL_ANSWER, util.ReadFile("input.txt")},
|
{"example 1", 8, exampleInputs[0]},
|
||||||
|
{"example 2", 19208, exampleInputs[1]},
|
||||||
|
{"actual", 18512297918464, util.ReadFile("input.txt")},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPart2(t *testing.T) {
|
func TestPart2(t *testing.T) {
|
||||||
@@ -39,3 +89,22 @@ func TestPart2(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_dynamicProgramming(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
want int
|
||||||
|
input string
|
||||||
|
}{
|
||||||
|
{"example 1", 8, exampleInputs[0]},
|
||||||
|
{"example 2", 19208, exampleInputs[1]},
|
||||||
|
{"actual", 18512297918464, util.ReadFile("input.txt")},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := dynamicProgramming(tt.input); got != tt.want {
|
||||||
|
t.Errorf("dynamicProgramming() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user