This commit is contained in:
akp 2020-12-10 22:10:46 +00:00
parent 9747f89779
commit 56df7dcf85
No known key found for this signature in database
GPG key ID: D3E7EAA31B39637E
9 changed files with 469 additions and 1 deletions

2
.github/README.md vendored
View file

@ -25,7 +25,7 @@ Puzzle inputs and descriptions are not included in this repository. You'll have
| [7](/07-handyHaversacks) | ![Completed][check] | [Link](/07-handyHaversacks/python) | [Link](/07-handyHaversacks/go) |
| [8](/08-handheldHalting) | ![Completed][check] | [Link](/08-handheldHalting/python) | [Link](/08-handheldHalting/go) |
| [9](/09-encodingError) | ![Completed][check] | [Link](/09-encodingError/python) | [Link](/09-encodingError/go) |
| 10 | ![Not yet attempted][pending] | | |
| [10](/10-adapterArray) | ![Completed][check] | [Link](/10-adapterArray/python) | [Link](/10-adapterArray/go) |
| 11 | | | |
| 12 | | | |
| 13 | | | |

35
10-adapterArray/README.md Normal file
View file

@ -0,0 +1,35 @@
# [Day 10: Adapter Array](https://adventofcode.com/2020/day/10)
<details><summary>Script output</summary>
```
python .\python\
AoC 2020: day 10 - Adapter Array
Python 3.8.5
Test cases
1.1 pass
1.2 pass
2.1 pass
2.2 pass
Answers
Part 1: 3000
Part 2: 193434623148032
go run .\go\
AoC 2020: day 10 - Adapter Array
Go go1.15.2
Test cases
1.1 pass
1.2 pass
2.1 pass
2.2 pass
Answers
Part 1: 3000
Part 2: 193434623148032
```
</details>

View file

@ -0,0 +1,114 @@
package challenge
import (
"sort"
"strconv"
"strings"
)
type Adaptor struct {
Output int
MinInput int
MaxInput int
}
func (a Adaptor) IsCompatible(inputJoltage int) bool {
return (a.MinInput <= inputJoltage) && (a.MaxInput >= inputJoltage)
}
func NewAdaptor(outputJoltage int) Adaptor {
return Adaptor{
Output: outputJoltage,
MinInput: outputJoltage - 3,
MaxInput: outputJoltage - 1,
}
}
func parse(instr string) []Adaptor {
var aslc []Adaptor
for _, v := range strings.Split(strings.TrimSpace(instr), "\n") {
i, err := strconv.Atoi(v)
if err != nil {
panic(err)
}
aslc = append(aslc, NewAdaptor(i))
}
// If I don't sort it, the recusrion in part one takes impossibly long to run
sort.Slice(aslc, func(p, q int) bool {
return aslc[p].Output < aslc[q].Output
})
return aslc
}
type ac struct {
idx int
adp Adaptor
}
func findChain(adaptors []Adaptor, currentJoltage int) (bool, int, int) {
if len(adaptors) == 0 {
return true, 0, 0
}
var candidates []ac
for i, a := range adaptors {
if a.IsCompatible(currentJoltage) {
candidates = append(candidates, ac{i, a})
}
}
if len(candidates) == 0 {
return false, 0, 0
}
for _, possibleAdaptor := range candidates {
lc := make([]Adaptor, len(adaptors))
copy(lc, adaptors)
lc = append(lc[:possibleAdaptor.idx], lc[possibleAdaptor.idx+1:]...)
foundChain, numOneDiff, numThreeDiff := findChain(lc, possibleAdaptor.adp.Output)
if foundChain {
od := 0
td := 0
diff := possibleAdaptor.adp.Output - currentJoltage
if diff == 1 {
od += 1
} else if diff == 3 {
td += 1
}
return true, od + numOneDiff, td + numThreeDiff
}
}
return false, 0, 0
}
func PartOne(instr string) int {
adaptors := parse(instr)
// Add integreated device adaptor
var maxJ int
{
for _, adaptor := range adaptors {
if maxJ < adaptor.Output {
maxJ = adaptor.Output
}
}
}
adaptors = append(adaptors, NewAdaptor(maxJ + 3))
s, oj, tj := findChain(adaptors, 0)
if s {
return oj * tj
}
return 0
}

View file

@ -0,0 +1,35 @@
package challenge
import (
"sort"
"strconv"
"strings"
)
func PartTwo(instr string) int {
var joltages []int
for _, x := range strings.Split(strings.TrimSpace(instr), "\n") {
i, err := strconv.Atoi(x)
if err != nil {
panic(err)
}
joltages = append(joltages, i)
}
sort.Ints(joltages)
routeLengths := map[int]int{0: 1}
for _, joltage := range joltages {
var totalRoutes int
for _, n := range []int{1, 2, 3} {
v, exists := routeLengths[joltage-n]
if !exists {
v = 0
}
totalRoutes += v
}
routeLengths[joltage] = totalRoutes
}
return routeLengths[joltages[len(joltages)-1]]
}

100
10-adapterArray/go/main.go Normal file
View file

@ -0,0 +1,100 @@
package main
import (
"adventOfCode/10-adapterArray/go/challenge"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"runtime"
"strconv"
"github.com/fatih/color"
)
func main() {
var infoStruct info
{
inb, err := ioutil.ReadFile("info.json")
if err != nil {
fmt.Println("Error: could not open info.json")
os.Exit(-1)
}
err = json.Unmarshal(inb, &infoStruct)
if err != nil {
fmt.Println("Error: could not parse info.json")
os.Exit(-1)
}
}
var (
year = infoStruct.Year
day = infoStruct.Day
title = infoStruct.Title
)
fmt.Fprintf(color.Output, "%s: day %s - %s\n", color.YellowString("AoC "+year), color.BlueString(day), title)
fmt.Fprintf(color.Output, "Go %s\n\n", color.BlueString(runtime.Version()))
var challengeInput string
{
inb, err := ioutil.ReadFile("input.txt")
if err != nil {
fmt.Println("Error: could not open input.txt")
os.Exit(-1)
}
challengeInput = string(inb)
}
runTests(infoStruct)
fmt.Println("Answers")
fmt.Fprintf(color.Output, "Part %s: %s\n", color.BlueString("1"), color.BlueString(strconv.Itoa(challenge.PartOne(challengeInput))))
fmt.Fprintf(color.Output, "Part %s: %s\n", color.BlueString("2"), color.BlueString(strconv.Itoa(challenge.PartTwo(challengeInput))))
}
type tc struct {
Input string `json:"input"`
Expected int `json:"expected"`
}
type info struct {
Year string `json:"year"`
Day string `json:"day"`
Title string `json:"title"`
TestCases struct {
One []tc `json:"one"`
Two []tc `json:"two"`
} `json:"testCases"`
}
func runTests(infoStruct info) {
if len(infoStruct.TestCases.One) == 0 && len(infoStruct.TestCases.Two) == 0 {
fmt.Println("Info: no test cases specified. Skipping tests")
fmt.Println()
return
}
fmt.Println("Test cases")
rt := func(tcs []tc, f func(string) int, n string) {
for i, tc := range tcs {
fmt.Fprintf(color.Output, "%s ", color.BlueString(n+"."+strconv.Itoa(i+1)))
result := f(tc.Input)
if result == tc.Expected {
fmt.Fprintf(color.Output, "%s", color.GreenString("pass"))
} else {
fmt.Fprintf(color.Output, "%s (got %s, expected %s)", color.RedString("fail"), color.BlueString(strconv.Itoa(result)), color.BlueString(strconv.Itoa(tc.Expected)))
}
fmt.Println()
}
}
rt(infoStruct.TestCases.One, challenge.PartOne, "1")
rt(infoStruct.TestCases.Two, challenge.PartTwo, "2")
fmt.Println()
}

27
10-adapterArray/info.json Normal file
View file

@ -0,0 +1,27 @@
{
"year": "2020",
"day": "10",
"title": "Adapter Array",
"testCases": {
"one": [
{
"input": "16\n10\n15\n5\n1\n11\n7\n19\n6\n12\n4",
"expected": 35
},
{
"input": "28\n33\n18\n42\n31\n14\n46\n20\n48\n47\n24\n23\n49\n45\n19\n38\n39\n11\n1\n32\n25\n35\n8\n17\n7\n9\n4\n2\n34\n10\n3",
"expected": 220
}
],
"two": [
{
"input": "16\n10\n15\n5\n1\n11\n7\n19\n6\n12\n4",
"expected": 8
},
{
"input": "28\n33\n18\n42\n31\n14\n46\n20\n48\n47\n24\n23\n49\n45\n19\n38\n39\n11\n1\n32\n25\n35\n8\n17\n7\n9\n4\n2\n34\n10\n3",
"expected": 19208
}
]
}
}

View file

@ -0,0 +1,69 @@
import json
import platform
import sys
from rich import print
from partOne import partOne
from partTwo import partTwo
def run_tests(test_cases):
do_tests = True
if len(test_cases) == 0:
do_tests = False
elif len(test_cases["one"]) == 0 and len(test_cases["two"]) == 0:
do_tests = False
if not do_tests:
print("Info: no test cases specified. Skipping tests\n")
return
print("Test cases")
def rt(tcs, f, n):
for i, tc in enumerate(tcs):
print(f"{n}.{i+1} ", end="")
expectedInt = tc["expected"]
result = f(str(tc["input"]))
if result == expectedInt:
print("[green]pass[/green]")
else:
print(f"[red]fail[/red] (got {result}, expected {expectedInt})")
rt(test_cases["one"], partOne, 1)
rt(test_cases["two"], partTwo, 2)
print()
if __name__ == "__main__":
try:
info = open("info.json").read()
except FileNotFoundError:
print("Error: could not open info.json")
sys.exit(-1)
info = json.loads(info)
year = info["year"]
day = info["day"]
title = info["title"]
print(f"[yellow]AoC {year}[/yellow]: day {day} - {title}")
print(f"Python {platform.python_version()}\n")
try:
challenge_input = open("input.txt").read()
except FileNotFoundError:
print("Error: could not open input.txt")
sys.exit(-1)
run_tests(info["testCases"])
if "debug" in sys.argv:
sys.exit()
print("Answers")
print("Part 1:", partOne(challenge_input))
print("Part 2:", partTwo(challenge_input))

View file

@ -0,0 +1,75 @@
import copy
import sys
from typing import List, Tuple
class Adaptor:
output: int
min_input: int
max_input: int
def __init__(self, output_joltage: int) -> None:
self.output = output_joltage
self.min_input = output_joltage - 3
self.max_input = output_joltage - 1
def is_compatible(self, input_joltage: int) -> bool:
return (self.min_input <= input_joltage) and (self.max_input >= input_joltage)
def parse(instr: str) -> List[Adaptor]:
# If I don't sort it, the recusrion in part one takes impossibly long to run
return sorted(
[Adaptor(int(x)) for x in instr.strip().split("\n")], key=lambda x: x.output
)
def find_chain(adaptors: List[Adaptor], current_joltage: int) -> Tuple[bool, int, int]:
# Returns if found a chain, and a delta for the one diff and three diff
if len(adaptors) == 0:
return True, 0, 0
candidates = [
(i, a) for i, a in enumerate(adaptors) if a.is_compatible(current_joltage)
]
if len(candidates) == 0:
return False, 0, 0
for possible_adaptor in candidates:
lc = copy.deepcopy(adaptors)
lc.pop(possible_adaptor[0])
found_chain, num_one_diff, num_three_diff = find_chain(
lc, possible_adaptor[1].output
)
if found_chain:
od = 0
td = 0
diff = possible_adaptor[1].output - current_joltage
if diff == 1:
od += 1
elif diff == 3:
td += 1
return True, od + num_one_diff, td + num_three_diff
return False, 0, 0
def partOne(instr: str) -> int:
adaptors = parse(instr)
# Add device adaptor
max_j_adaptor = max(adaptors, key=lambda x: x.output)
adaptors.append(Adaptor(max_j_adaptor.output + 3))
s, oj, tj = find_chain(adaptors, 0)
if s:
return oj * tj
else:
return 0

View file

@ -0,0 +1,13 @@
def partTwo(instr: str) -> int:
joltages = sorted([int(x) for x in instr.strip().split("\n")])
route_lengths = {0: 1}
for joltage in joltages:
total_routes = 0
# Get the route lengths for the three previous joltages
for n in [1, 2, 3]:
total_routes += route_lengths.get(joltage - n, 0)
print(joltage, total_routes)
route_lengths[joltage] = total_routes
return route_lengths[max(joltages)]