Day 14 (Golang)
This commit is contained in:
parent
bc46b28ae5
commit
23e755c34f
6 changed files with 332 additions and 1 deletions
2
.github/README.md
vendored
2
.github/README.md
vendored
|
@ -29,7 +29,7 @@ Puzzle inputs and descriptions are not included in this repository. You'll have
|
||||||
| [11](/11-seatingSystem) \* | ![Completed][check] | [Link](/11-seatingSystem/python) | [Link](/11-seatingSystem/python) |
|
| [11](/11-seatingSystem) \* | ![Completed][check] | [Link](/11-seatingSystem/python) | [Link](/11-seatingSystem/python) |
|
||||||
| [12](/12-rainRisk) \* | ![Completed][check] | [Link](/12-rainRisk/python) | [Link](/12-rainRisk/go) |
|
| [12](/12-rainRisk) \* | ![Completed][check] | [Link](/12-rainRisk/python) | [Link](/12-rainRisk/go) |
|
||||||
| [13](/13-shuttleSearch) | ![Partially complete][partial] | [Link](/13-shuttleSearch/python) | |
|
| [13](/13-shuttleSearch) | ![Partially complete][partial] | [Link](/13-shuttleSearch/python) | |
|
||||||
| [14](/14-dockingData) | ![Partially complete][partial] | [Link](/14-dockingData/python) | |
|
| [14](/14-dockingData) | ![Completed][check] | [Link](/14-dockingData/python) | [Link](/14-dockingData/go) |
|
||||||
| 15 | | | |
|
| 15 | | | |
|
||||||
| 16 | | | |
|
| 16 | | | |
|
||||||
| 17 | | | |
|
| 17 | | | |
|
||||||
|
|
|
@ -11,6 +11,18 @@ Test cases
|
||||||
1.1 pass
|
1.1 pass
|
||||||
2.1 pass
|
2.1 pass
|
||||||
|
|
||||||
|
Answers
|
||||||
|
Part 1: 8570568288597
|
||||||
|
Part 2: 3289441921203
|
||||||
|
|
||||||
|
❯ go run .\go\
|
||||||
|
AoC 2020: day 14 - Docking Data
|
||||||
|
Go go1.15.2
|
||||||
|
|
||||||
|
Test cases
|
||||||
|
1.1 pass
|
||||||
|
2.1 pass
|
||||||
|
|
||||||
Answers
|
Answers
|
||||||
Part 1: 8570568288597
|
Part 1: 8570568288597
|
||||||
Part 2: 3289441921203
|
Part 2: 3289441921203
|
||||||
|
|
77
14-dockingData/go/challenge/common.go
Normal file
77
14-dockingData/go/challenge/common.go
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
package challenge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Instruction struct {
|
||||||
|
Address int
|
||||||
|
Value int
|
||||||
|
Mask string
|
||||||
|
}
|
||||||
|
|
||||||
|
var instructionRegex = regexp.MustCompile(`mem\[(\d+)\] ?= ?(\d+)`)
|
||||||
|
|
||||||
|
func NewInstruction(instruction, mask string) Instruction {
|
||||||
|
if mask == "" {
|
||||||
|
panic(errors.New("bad mask"))
|
||||||
|
}
|
||||||
|
if !instructionRegex.MatchString(instruction) {
|
||||||
|
panic(fmt.Errorf("unable to parse input instruction '%s'", instruction))
|
||||||
|
}
|
||||||
|
matches := instructionRegex.FindAllStringSubmatch(instruction, -1)
|
||||||
|
address, err := strconv.Atoi(matches[0][1])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
value, err := strconv.Atoi(matches[0][2])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return Instruction{
|
||||||
|
Address: address,
|
||||||
|
Value: value,
|
||||||
|
Mask: mask,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(instr string) (retval []Instruction) {
|
||||||
|
|
||||||
|
var currentMask string
|
||||||
|
for _, line := range strings.Split(strings.TrimSpace(instr), "\n") {
|
||||||
|
if strings.Contains(line, "mask") {
|
||||||
|
currentMask = strings.TrimSpace(strings.Split(line, "=")[1])
|
||||||
|
} else {
|
||||||
|
retval = append(retval, NewInstruction(line, currentMask))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberToBase(n, b int) string {
|
||||||
|
if n == 0 {
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
var digits []int
|
||||||
|
for n != 0 {
|
||||||
|
digits = append(digits, n%b)
|
||||||
|
n /= b
|
||||||
|
}
|
||||||
|
var sarr []string
|
||||||
|
for i := len(digits) - 1; i >= 0; i -= 1 {
|
||||||
|
sarr = append(sarr, strconv.Itoa(digits[i]))
|
||||||
|
}
|
||||||
|
return strings.Join(sarr, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func zfill(instr string, n int) string {
|
||||||
|
for i := 0; i < n; i += 1 {
|
||||||
|
instr = "0" + instr
|
||||||
|
}
|
||||||
|
return instr
|
||||||
|
}
|
43
14-dockingData/go/challenge/partOne.go
Normal file
43
14-dockingData/go/challenge/partOne.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package challenge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func applyMask(number int, mask string) int {
|
||||||
|
mask = strings.ToLower(mask)
|
||||||
|
value := numberToBase(number, 2)
|
||||||
|
value = zfill(value, len(mask)-len(value))
|
||||||
|
var combi string
|
||||||
|
for i := 0; i < len(value); i += 1 {
|
||||||
|
v := string(value[i])
|
||||||
|
m := string(mask[i])
|
||||||
|
|
||||||
|
if m == "x" {
|
||||||
|
combi += v
|
||||||
|
} else {
|
||||||
|
combi += m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ix, err := strconv.ParseInt(combi, 2, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return int(ix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PartOne(instr string) int {
|
||||||
|
inputInstructions := parse(instr)
|
||||||
|
memory := make(map[int]int)
|
||||||
|
|
||||||
|
for _, instruction := range inputInstructions {
|
||||||
|
memory[instruction.Address] = applyMask(instruction.Value, instruction.Mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sigma int
|
||||||
|
for _, v := range memory {
|
||||||
|
sigma += v
|
||||||
|
}
|
||||||
|
return sigma
|
||||||
|
}
|
99
14-dockingData/go/challenge/partTwo.go
Normal file
99
14-dockingData/go/challenge/partTwo.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package challenge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The following two functions were taken from https://stackoverflow.com/a/19249957
|
||||||
|
func generateCombinations(alphabet string, length int) <-chan string {
|
||||||
|
c := make(chan string)
|
||||||
|
go func(c chan string) {
|
||||||
|
defer close(c)
|
||||||
|
addLetter(c, "", alphabet, length)
|
||||||
|
}(c)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
func addLetter(c chan string, combo string, alphabet string, length int) {
|
||||||
|
if length <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var newCombo string
|
||||||
|
for _, ch := range alphabet {
|
||||||
|
newCombo = combo + string(ch)
|
||||||
|
c <- newCombo
|
||||||
|
addLetter(c, newCombo, alphabet, length-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end taken functions
|
||||||
|
|
||||||
|
func getMemoryAddresses(number int, mask string) []int {
|
||||||
|
mask = strings.ToLower(mask)
|
||||||
|
value := numberToBase(number, 2)
|
||||||
|
value = zfill(value, len(mask)-len(value))
|
||||||
|
|
||||||
|
var combi []string
|
||||||
|
|
||||||
|
for i := 0; i < len(value); i += 1 {
|
||||||
|
v := string(value[i])
|
||||||
|
m := string(mask[i])
|
||||||
|
|
||||||
|
var av string
|
||||||
|
|
||||||
|
if m == "0" {
|
||||||
|
av = v
|
||||||
|
} else if m == "1" {
|
||||||
|
av = "1"
|
||||||
|
} else {
|
||||||
|
av = m
|
||||||
|
}
|
||||||
|
|
||||||
|
combi = append(combi, av)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xns []int
|
||||||
|
|
||||||
|
n := strings.Count(mask, "x")
|
||||||
|
for valstring := range generateCombinations("01", n) {
|
||||||
|
if len(valstring) != n {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val_combo := strings.Split(valstring, "")
|
||||||
|
msk := make([]string, len(combi))
|
||||||
|
copy(msk, combi)
|
||||||
|
var val_counter int
|
||||||
|
for i, char := range msk {
|
||||||
|
if char == "x" {
|
||||||
|
msk[i] = val_combo[val_counter]
|
||||||
|
val_counter += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ix, err := strconv.ParseInt(strings.Join(msk, ""), 2, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
xns = append(xns, int(ix))
|
||||||
|
}
|
||||||
|
|
||||||
|
return xns
|
||||||
|
}
|
||||||
|
|
||||||
|
func PartTwo(instr string) int {
|
||||||
|
inputInstructions := parse(instr)
|
||||||
|
memory := make(map[int]int)
|
||||||
|
|
||||||
|
for _, instruction := range inputInstructions {
|
||||||
|
addresses := getMemoryAddresses(instruction.Address, instruction.Mask)
|
||||||
|
for _, address := range addresses {
|
||||||
|
memory[address] = instruction.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sigma int
|
||||||
|
for _, v := range memory {
|
||||||
|
sigma += v
|
||||||
|
}
|
||||||
|
return sigma
|
||||||
|
}
|
100
14-dockingData/go/main.go
Normal file
100
14-dockingData/go/main.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"adventOfCode/14-dockingData/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()
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue