Big update: Adding all advent of codes to same repo
This commit is contained in:
7
AdventOfCode2021/README.md
Normal file
7
AdventOfCode2021/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Advent Of Code 2021
|
||||
|
||||
The challenge for me this year is to use VIM as a text editor alone, as well as Golang for the programming language.
|
||||
|
||||
## Update
|
||||
|
||||
I have now given up on vim as I like VSCode too much and know it too well.
|
||||
41
AdventOfCode2021/day1/day1.go
Normal file
41
AdventOfCode2021/day1/day1.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package day1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
|
||||
increase := 0
|
||||
increaseWindow := 0
|
||||
|
||||
for i := 0; i < len(lines) - 1; i++ {
|
||||
|
||||
num1, _ := strconv.Atoi(string(lines[i]))
|
||||
num2, _ := strconv.Atoi(string(lines[i + 1]))
|
||||
|
||||
if num1 < num2 {
|
||||
increase++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for i := 0; i < len(lines) - 3; i++ {
|
||||
|
||||
num1, _ := strconv.Atoi(string(lines[i]))
|
||||
num2, _ := strconv.Atoi(string(lines[i + 1]))
|
||||
num3, _ := strconv.Atoi(string(lines[i + 2]))
|
||||
num4, _ := strconv.Atoi(string(lines[i + 3]))
|
||||
|
||||
if num1 + num2 + num3 < num2 + num3 + num4 {
|
||||
increaseWindow++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return increase, increaseWindow
|
||||
|
||||
}
|
||||
91
AdventOfCode2021/day13/day13.go
Normal file
91
AdventOfCode2021/day13/day13.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package day13
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type coord struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
splitBytes := bytes.Split(dat, []byte{10, 10})
|
||||
stringCoords := strings.Split(string(splitBytes[0]), "\n")
|
||||
stringInstructions := strings.Split(string(splitBytes[1]), "\n")
|
||||
|
||||
coordMap := make(map[coord]int)
|
||||
|
||||
for _, line := range stringCoords {
|
||||
splitLine := strings.Split(line, ",")
|
||||
x, _ := strconv.Atoi(splitLine[0])
|
||||
y, _ := strconv.Atoi(splitLine[1])
|
||||
coordMap[coord{x: x, y: y}] = coordMap[coord{x: x, y: y}] + 1
|
||||
}
|
||||
|
||||
part1 := 0
|
||||
part2 := 0
|
||||
|
||||
for i := 0; i < len(stringInstructions); i++ {
|
||||
splitInstruction := strings.Split(stringInstructions[i], "fold along ")
|
||||
number, _ := strconv.Atoi(string(splitInstruction[1][2:]))
|
||||
if splitInstruction[1][0] == 'y' {
|
||||
|
||||
for k, _ := range coordMap {
|
||||
if k.y > number {
|
||||
delete(coordMap, k)
|
||||
coordMap[coord{x: k.x, y: k.y - ((k.y - number) * 2)}] += 1
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for k, _ := range coordMap {
|
||||
if k.x > number {
|
||||
delete(coordMap, k)
|
||||
coordMap[coord{x: k.x - ((k.x - number) * 2), y: k.y}] = 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
for k, _ := range coordMap {
|
||||
if coordMap[k] > 0 {
|
||||
part1++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
highestX := 0
|
||||
highestY := 0
|
||||
for k, _ := range coordMap {
|
||||
if k.x > highestX {
|
||||
highestX = k.x
|
||||
}
|
||||
if k.y > highestY {
|
||||
highestY = k.y
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for i := 0; i <= highestY; i++ {
|
||||
for j := 0; j <= highestX; j++ {
|
||||
|
||||
if coordMap[coord{x: j, y: i}] > 0 {
|
||||
fmt.Print("#")
|
||||
} else {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
return part1, part2
|
||||
}
|
||||
47
AdventOfCode2021/day14/day14.go
Normal file
47
AdventOfCode2021/day14/day14.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package day14
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int64, int64) {
|
||||
|
||||
lines := strings.Split(string(dat), "\n")
|
||||
template := lines[0]
|
||||
patterns := lines[2 : len(lines) - 1]
|
||||
|
||||
pairInsertions := make(map[string]string, len(patterns))
|
||||
for i := 0; i < len(patterns); i++ {
|
||||
pairSplit := strings.Split(patterns[i], " ")
|
||||
pairInsertions[pairSplit[0]] = pairSplit[2]
|
||||
}
|
||||
|
||||
for round := 0; round < 40; round++ {
|
||||
|
||||
newTemplate := string(template[0])
|
||||
for i := 0; i < len(template) - 1; i++ {
|
||||
pair := template[i:i + 2]
|
||||
newLetter := pairInsertions[pair]
|
||||
newTemplate += newLetter + string(pair[1])
|
||||
}
|
||||
template = newTemplate
|
||||
|
||||
}
|
||||
|
||||
letterMap := make(map[byte]int64, 0)
|
||||
for i := 0; i < len(template); i++ {
|
||||
letterMap[template[i]] += 1
|
||||
}
|
||||
|
||||
highest := int64(0)
|
||||
lowest := int64(999999)
|
||||
for _, v := range letterMap {
|
||||
if v > highest {
|
||||
highest = v
|
||||
} else if v < lowest {
|
||||
lowest = v
|
||||
}
|
||||
}
|
||||
|
||||
return (highest - lowest), 0
|
||||
}
|
||||
44
AdventOfCode2021/day2/day2.go
Normal file
44
AdventOfCode2021/day2/day2.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package day2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
dat = dat[:len(dat) - 1]
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
|
||||
vertical := 0
|
||||
horizontal := 0
|
||||
|
||||
part2vertical := 0
|
||||
part2horizontal := 0
|
||||
aim := 0
|
||||
|
||||
for _, value := range lines {
|
||||
|
||||
splitInstruction := bytes.Split(value, []byte(" "))
|
||||
|
||||
direction := string(splitInstruction[0])
|
||||
scale, _ := strconv.Atoi(string(splitInstruction[1]))
|
||||
|
||||
if direction == "forward" {
|
||||
horizontal += scale
|
||||
part2horizontal += scale
|
||||
part2vertical += aim * scale
|
||||
} else if direction == "up" {
|
||||
vertical -= scale
|
||||
aim -= scale
|
||||
} else if direction == "down" {
|
||||
vertical += scale
|
||||
aim += scale
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return vertical * horizontal, part2vertical * part2horizontal
|
||||
|
||||
}
|
||||
101
AdventOfCode2021/day3/day3.go
Normal file
101
AdventOfCode2021/day3/day3.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package day3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
lineLength := len(lines[0])
|
||||
|
||||
commonMap := make(map[int]int)
|
||||
|
||||
for _, line := range lines {
|
||||
|
||||
splitLine := bytes.Split(line, []byte(""))
|
||||
|
||||
for i := 0; i < len(splitLine); i++ {
|
||||
|
||||
//Negative means that 0 is more common
|
||||
if splitLine[i][0] == 0x31 {
|
||||
commonMap[i] = commonMap[i] - 1
|
||||
} else {
|
||||
commonMap[i] = commonMap[i] + 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gamma := 0
|
||||
epsilon := 0
|
||||
|
||||
for key, value := range commonMap {
|
||||
if value > 0 {
|
||||
gamma += intExponent(2, lineLength - key - 1)
|
||||
} else {
|
||||
epsilon += intExponent(2, lineLength - key - 1)
|
||||
}
|
||||
}
|
||||
|
||||
return gamma * epsilon, part2(lines[:len(lines) - 1], true, 0) *
|
||||
part2(lines[:len(lines) - 1], false, 0)
|
||||
|
||||
}
|
||||
|
||||
func part2(givenLines [][]byte, higher bool, checkPosition int) int {
|
||||
|
||||
if len(givenLines) == 1 {
|
||||
returnValue := 0
|
||||
|
||||
for i := len(givenLines[0]) - 1; i >= 0; i-- {
|
||||
|
||||
if givenLines[0][len(givenLines[0]) - 1 - i] == 0x31 {
|
||||
returnValue += intExponent(2, i)
|
||||
}
|
||||
|
||||
}
|
||||
return returnValue
|
||||
} else {
|
||||
|
||||
oneLines := make([][]byte, 0)
|
||||
zeroLines := make([][]byte, 0)
|
||||
|
||||
for _, line := range givenLines {
|
||||
if line[checkPosition] == 0x31 {
|
||||
oneLines = append(oneLines, line)
|
||||
} else {
|
||||
zeroLines = append(zeroLines, line)
|
||||
}
|
||||
}
|
||||
|
||||
if higher {
|
||||
|
||||
if len(oneLines) >= len(zeroLines) {
|
||||
return part2(oneLines, higher, checkPosition + 1)
|
||||
} else if len(oneLines) < len(zeroLines) {
|
||||
return part2(zeroLines, higher, checkPosition + 1)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if len(oneLines) >= len(zeroLines) {
|
||||
return part2(zeroLines, higher, checkPosition + 1)
|
||||
} else if len(oneLines) < len(zeroLines) {
|
||||
return part2(oneLines, higher, checkPosition + 1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func intExponent(base int, power int) int {
|
||||
result := 1
|
||||
for i := 1; i <= power; i++ {
|
||||
result *= base
|
||||
}
|
||||
return result
|
||||
}
|
||||
199
AdventOfCode2021/day4/day4.go
Normal file
199
AdventOfCode2021/day4/day4.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package day4
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
stringData := string(dat)
|
||||
|
||||
lines := strings.Split(stringData, "\n")
|
||||
|
||||
numbersDrawn := strings.Split(lines[0], ",")
|
||||
lines = lines[2:]
|
||||
|
||||
currentBoard := make([][]int, 0)
|
||||
boards := make([][][]int, 0)
|
||||
|
||||
for _, line := range lines {
|
||||
|
||||
if len(line) == 0 {
|
||||
boards = append(boards, currentBoard)
|
||||
currentBoard = make([][]int, 0)
|
||||
} else {
|
||||
currentLine := strings.Split(line, " ")
|
||||
intLine := make([]int, 5)
|
||||
|
||||
counter := 0
|
||||
|
||||
for i := 0; i < len(currentLine); i++ {
|
||||
if (len(currentLine[i]) > 0) {
|
||||
intLine[counter], _ = strconv.Atoi(currentLine[i])
|
||||
counter++
|
||||
}
|
||||
}
|
||||
currentBoard = append(currentBoard, intLine)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* There is probably a better way of doing this
|
||||
*/
|
||||
boardCheck := make([][][]int, 0)
|
||||
for i := 0; i < len(boards); i++ {
|
||||
boardCheck = append(boardCheck, [][]int{{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0}})
|
||||
}
|
||||
|
||||
boardComplete := false
|
||||
winningIndex := 0
|
||||
calledNumber := 0
|
||||
|
||||
//Part 1
|
||||
for i := 0; i < len(numbersDrawn) && !boardComplete; i++ {
|
||||
|
||||
intNumber, _ := strconv.Atoi(numbersDrawn[i])
|
||||
|
||||
for i, board := range boards {
|
||||
checkBoard(board, intNumber, &boardCheck[i])
|
||||
if checkComplete(boardCheck[i]) {
|
||||
boardComplete = true
|
||||
winningIndex = i
|
||||
calledNumber = intNumber
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boardCheck = make([][][]int, 0)
|
||||
for i := 0; i < len(boards); i++ {
|
||||
boardCheck = append(boardCheck, [][]int{{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0}})
|
||||
}
|
||||
|
||||
completedBoards := make([]int, 0)
|
||||
lastFound := -1
|
||||
part2Num := 0
|
||||
|
||||
for i := 0; i < len(numbersDrawn) && lastFound == -1; i++ {
|
||||
|
||||
intNumber, _ := strconv.Atoi(numbersDrawn[i])
|
||||
for i, board := range boards {
|
||||
|
||||
if !contains(completedBoards, i) {
|
||||
checkBoard(board, intNumber, &boardCheck[i])
|
||||
|
||||
if checkComplete(boardCheck[i]) {
|
||||
completedBoards = append(completedBoards, i)
|
||||
|
||||
if len(completedBoards) == len(boards) {
|
||||
part2Num = intNumber
|
||||
lastFound = i
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unmarkedNumbers := 0
|
||||
partUnmarkedNumbers := 0
|
||||
|
||||
for i := 0; i < len(boards[winningIndex]); i++ {
|
||||
for j := 0; j < len(boards[winningIndex][0]); j++ {
|
||||
|
||||
if boardCheck[winningIndex][i][j] == 0 {
|
||||
unmarkedNumbers += boards[winningIndex][i][j]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(boards[lastFound]); i++ {
|
||||
for j := 0; j < len(boards[lastFound][0]); j++ {
|
||||
|
||||
if boardCheck[lastFound][i][j] == 0 {
|
||||
partUnmarkedNumbers += boards[lastFound][i][j]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return calledNumber * unmarkedNumbers, part2Num * partUnmarkedNumbers
|
||||
|
||||
}
|
||||
|
||||
func contains(arr []int, num int) bool {
|
||||
for _, e := range arr {
|
||||
if e == num {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func checkBoard(board [][]int, numberDrawn int, boardCheck *[][]int) {
|
||||
|
||||
for i := 0; i < len(board); i++ {
|
||||
for j := 0; j < len(board[0]); j++ {
|
||||
|
||||
if board[i][j] == numberDrawn {
|
||||
(*boardCheck)[i][j] = 1
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Return -1 if board is not complete
|
||||
func checkComplete(boardCheck [][]int) bool {
|
||||
|
||||
//Check rows
|
||||
for i := 0; i < len(boardCheck); i++ {
|
||||
|
||||
rowComplete := true
|
||||
for j := 0; j < len(boardCheck[0]); j++ {
|
||||
if boardCheck[i][j] == 0 {
|
||||
rowComplete = false
|
||||
}
|
||||
}
|
||||
|
||||
if rowComplete {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Check cols
|
||||
for i := 0; i < len(boardCheck); i++ {
|
||||
|
||||
colComplete := true
|
||||
for j := 0; j < len(boardCheck[0]); j++ {
|
||||
if boardCheck[j][i] == 0 {
|
||||
colComplete = false
|
||||
}
|
||||
}
|
||||
|
||||
if colComplete {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
119
AdventOfCode2021/day5/day5.go
Normal file
119
AdventOfCode2021/day5/day5.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package day5
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Coord struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
type coordPairs struct {
|
||||
point1 Coord
|
||||
point2 Coord
|
||||
}
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
stringDat := strings.Split(string(dat), "\n")
|
||||
|
||||
coordList := make([]coordPairs, len(stringDat))
|
||||
|
||||
for i := 0; i < len(stringDat); i++ {
|
||||
|
||||
coords := strings.Split(stringDat[i], " -> ")
|
||||
|
||||
firstCoord := strings.Split(coords[0], ",")
|
||||
secondCoord := strings.Split(coords[1], ",")
|
||||
|
||||
x1, _ := strconv.Atoi(firstCoord[0])
|
||||
y1, _ := strconv.Atoi(firstCoord[1])
|
||||
x2, _ := strconv.Atoi(secondCoord[0])
|
||||
y2, _ := strconv.Atoi(secondCoord[1])
|
||||
|
||||
coordList[i] = coordPairs{Coord{x: x1, y: y1}, Coord{x: x2, y: y2}}
|
||||
|
||||
}
|
||||
|
||||
coordMap := make(map[Coord]int)
|
||||
part2CoordMap := make(map[Coord]int)
|
||||
|
||||
for _, c := range coordList {
|
||||
if (c.point1.x == c.point2.x) {
|
||||
|
||||
lowY := int(math.Min(float64(c.point1.y), float64(c.point2.y)))
|
||||
highY := int(math.Max(float64(c.point1.y), float64(c.point2.y)))
|
||||
|
||||
for i := lowY; i <= highY; i++ {
|
||||
coordMap[Coord{x: c.point1.x, y: i}] = coordMap[Coord{x: c.point1.x, y: i}] + 1
|
||||
part2CoordMap[Coord{x: c.point1.x, y: i}] = part2CoordMap[Coord{x: c.point1.x, y: i}] + 1
|
||||
}
|
||||
|
||||
} else if (c.point1.y == c.point2.y) {
|
||||
|
||||
lowX := int(math.Min(float64(c.point1.x), float64(c.point2.x)))
|
||||
highX := int(math.Max(float64(c.point1.x), float64(c.point2.x)))
|
||||
|
||||
for i := lowX; i <= highX; i++ {
|
||||
coordMap[Coord{x: i, y: c.point1.y}] = coordMap[Coord{x: i, y: c.point1.y}] + 1
|
||||
part2CoordMap[Coord{x: i, y: c.point1.y}] = part2CoordMap[Coord{x: i, y: c.point1.y}] + 1
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if c.point1.x < c.point2.x {
|
||||
|
||||
step := 0
|
||||
|
||||
if c.point1.y - c.point2.y > 0 {
|
||||
step = -1
|
||||
} else {
|
||||
step = 1
|
||||
}
|
||||
|
||||
counter := c.point1.y
|
||||
for i := c.point1.x; i <= c.point2.x; i++ {
|
||||
part2CoordMap[Coord{x: i, y: counter}] = part2CoordMap[Coord{x: i, y: counter}] + 1
|
||||
counter += step
|
||||
}
|
||||
} else {
|
||||
|
||||
step := 0
|
||||
|
||||
if c.point2.y - c.point1.y > 0 {
|
||||
step = -1
|
||||
} else {
|
||||
step = 1
|
||||
}
|
||||
|
||||
counter := c.point2.y
|
||||
for i := c.point2.x; i <= c.point1.x; i++ {
|
||||
part2CoordMap[Coord{x: i, y: counter}] = part2CoordMap[Coord{x: i, y: counter}] + 1
|
||||
counter += step
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
part1 := 0
|
||||
part2 := 0
|
||||
|
||||
for _, value := range coordMap {
|
||||
if value > 1 {
|
||||
part1++
|
||||
}
|
||||
}
|
||||
|
||||
for _, value := range part2CoordMap {
|
||||
if value > 1 {
|
||||
part2++
|
||||
}
|
||||
}
|
||||
|
||||
return part1, part2
|
||||
|
||||
}
|
||||
69
AdventOfCode2021/day6/day6.go
Normal file
69
AdventOfCode2021/day6/day6.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package day6
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
stringDat := string(dat)
|
||||
|
||||
fish := strings.Split(stringDat, ",")
|
||||
|
||||
/**
|
||||
* We do not need to keep track of every fish,
|
||||
* We only need to keep track of the number of fish at a certain age.
|
||||
* Which is much more efficient than an exponentially increasing array.
|
||||
*/
|
||||
fishMap := make(map[int]int)
|
||||
|
||||
part2FishMap := make(map[int]int)
|
||||
|
||||
for _, value := range fish {
|
||||
age, _ := strconv.Atoi(value)
|
||||
fishMap[age] = fishMap[age] + 1
|
||||
part2FishMap[age] = part2FishMap[age] + 1
|
||||
}
|
||||
|
||||
for day := 1; day <= 80; day++ {
|
||||
|
||||
readyFish := fishMap[0]
|
||||
|
||||
for i := 1; i <= 8; i++ {
|
||||
fishMap[i - 1] = fishMap[i]
|
||||
}
|
||||
|
||||
fishMap[6] = fishMap[6] + readyFish
|
||||
fishMap[8] = readyFish
|
||||
|
||||
}
|
||||
|
||||
var part1 int = 0
|
||||
for _, num := range fishMap {
|
||||
part1 += num
|
||||
}
|
||||
|
||||
//-------------------
|
||||
|
||||
for day := 1; day <= 256; day++ {
|
||||
|
||||
readyFish := part2FishMap[0]
|
||||
|
||||
for i := 1; i <= 8; i++ {
|
||||
part2FishMap[i - 1] = part2FishMap[i]
|
||||
}
|
||||
|
||||
part2FishMap[6] = part2FishMap[6] + readyFish
|
||||
part2FishMap[8] = readyFish
|
||||
|
||||
}
|
||||
|
||||
var part2 int = 0
|
||||
for _, num := range part2FishMap {
|
||||
part2 += num
|
||||
}
|
||||
|
||||
return part1, part2
|
||||
|
||||
}
|
||||
53
AdventOfCode2021/day7/day7.go
Normal file
53
AdventOfCode2021/day7/day7.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package day7
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
fmt.Println("Day 7")
|
||||
|
||||
stringDat := strings.Split(string(dat), ",")
|
||||
|
||||
crabList := make([]int, len(stringDat))
|
||||
for i, value := range stringDat {
|
||||
num, _ := strconv.Atoi(value)
|
||||
crabList[i] = num
|
||||
}
|
||||
|
||||
sort.Ints(crabList)
|
||||
|
||||
median := crabList[len(crabList) / 2]
|
||||
|
||||
lowest := 100000000000
|
||||
part2lowest := 10000000000000
|
||||
|
||||
for i := median - 200; i <= median + 200; i++ {
|
||||
|
||||
difference := 0
|
||||
part2difference := 0
|
||||
|
||||
for _, n := range crabList {
|
||||
currentDifference := math.Abs(float64(i) - float64(n))
|
||||
difference += int(currentDifference)
|
||||
part2difference += int((currentDifference / 2) * (currentDifference + 1))
|
||||
}
|
||||
|
||||
if difference < lowest {
|
||||
lowest = difference
|
||||
}
|
||||
|
||||
if part2difference < part2lowest {
|
||||
part2lowest = part2difference
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return lowest, part2lowest
|
||||
|
||||
}
|
||||
314
AdventOfCode2021/day8/day8.go
Normal file
314
AdventOfCode2021/day8/day8.go
Normal file
@@ -0,0 +1,314 @@
|
||||
package day8
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Line struct {
|
||||
signals []string
|
||||
answer []string
|
||||
}
|
||||
|
||||
//
|
||||
// This struct will be used to store the possible corresponding patterns
|
||||
// A = Top line, B = Left top, ..., I used the same pattern in the AoC problem
|
||||
//
|
||||
type Possible struct {
|
||||
possible []string
|
||||
}
|
||||
|
||||
func Run(dat []byte) (int, int) {
|
||||
|
||||
lines := strings.Split(string(dat), "\n")
|
||||
lineArray := make([]Line, len(lines))
|
||||
|
||||
for i, v := range lines {
|
||||
splitLine := strings.Split(v, " | ")
|
||||
lineArray[i] = Line{signals: strings.Split(splitLine[0], " "),
|
||||
answer: strings.Split(splitLine[1], " ")}
|
||||
}
|
||||
|
||||
part1 := 0
|
||||
for _, value := range lineArray {
|
||||
|
||||
for _, signal := range value.answer {
|
||||
if len(signal) == 2 || len(signal) == 3 || len(signal) == 4 || len(signal) == 7 {
|
||||
part1++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
part2 := 0
|
||||
for _, line := range lineArray {
|
||||
|
||||
currentPossible := make(map[string]Possible)
|
||||
|
||||
//#1 - Get the unique ones.
|
||||
|
||||
//#1.1 - Get the number one
|
||||
one := getFromLength(line.signals, 2)[0]
|
||||
currentPossible[string(one[0])] = Possible{possible: []string{"C", "F"}}
|
||||
currentPossible[string(one[1])] = Possible{possible: []string{"C", "F"}}
|
||||
|
||||
//#1.2 - Get number 7 to work out first link
|
||||
seven := getFromLength(line.signals, 3)[0]
|
||||
topLink := getOddLetter(seven, one)[0]
|
||||
currentPossible[topLink] = Possible{possible: []string{"A"}}
|
||||
|
||||
//#1.3 - Get the number 4.
|
||||
four := getFromLength(line.signals, 4)[0]
|
||||
oddLetters := getOddLetter(four, one)
|
||||
currentPossible[oddLetters[0]] = Possible{possible: []string{"B", "D"}}
|
||||
currentPossible[oddLetters[1]] = Possible{possible: []string{"B", "D"}}
|
||||
|
||||
//#1.4 - Get the number 8.
|
||||
//The 8 will contain the top link which we already know.
|
||||
eight := getFromLength(line.signals, 7)[0]
|
||||
oddLetters = getOddLetter(eight, four)
|
||||
|
||||
for _, c := range oddLetters {
|
||||
if c != topLink {
|
||||
currentPossible[c] = Possible{possible: []string{"E", "G"}}
|
||||
}
|
||||
}
|
||||
|
||||
//#2 - Get a number with 5 segments on.
|
||||
// We want to get a 3, which contains all of the 7s
|
||||
// Choose one that thas the top segment.
|
||||
fiveLengthNum := getFromLength(line.signals, 5)
|
||||
three := ""
|
||||
for _, s := range fiveLengthNum {
|
||||
|
||||
contains := true
|
||||
for _, c := range seven {
|
||||
if !strings.Contains(s, string(c)) {
|
||||
contains = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if contains {
|
||||
three = s
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//#2.1 Extra segments in 3 but not in 7
|
||||
extraLetters := ""
|
||||
commonLetters := ""
|
||||
for _, c := range three {
|
||||
if !strings.Contains(seven, string(c)) {
|
||||
extraLetters += string(c)
|
||||
} else {
|
||||
if string(c) != topLink {
|
||||
commonLetters += string(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c1 := currentPossible[string(extraLetters[0])].possible[0]
|
||||
c2 := currentPossible[string(extraLetters[0])].possible[1]
|
||||
c3 := currentPossible[string(extraLetters[1])].possible[0]
|
||||
c4 := currentPossible[string(extraLetters[1])].possible[1]
|
||||
|
||||
//D first then G
|
||||
if c1 == "D" && c3 == "G" {
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"G"}}
|
||||
} else if c1 == "G" && c3 == "D" {
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"G"}}
|
||||
} else if c1 == "D" && c4 == "G" {
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"G"}}
|
||||
} else if c1 == "G" && c4 == "D" {
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"G"}}
|
||||
} else if c2 == "D" && c3 == "G" {
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"G"}}
|
||||
} else if c2 == "G" && c3 == "D" {
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"G"}}
|
||||
} else if c2 == "D" && c4 == "G" {
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"G"}}
|
||||
} else if c2 == "G" && c4 == "D" {
|
||||
currentPossible[string(extraLetters[1])] = Possible{possible: []string{"D"}}
|
||||
currentPossible[string(extraLetters[0])] = Possible{possible: []string{"G"}}
|
||||
}
|
||||
|
||||
purgeMap(currentPossible)
|
||||
|
||||
//#3 - Now all that is left is to find C & F
|
||||
//We can use 6 which contains only contains F
|
||||
|
||||
//Get letters of remaining
|
||||
remainingNotFound := make([]string, 0)
|
||||
for k, v := range currentPossible {
|
||||
if len(v.possible) > 1 {
|
||||
remainingNotFound = append(remainingNotFound, k)
|
||||
}
|
||||
}
|
||||
|
||||
sixLengthNum := getFromLength(line.signals, 6)
|
||||
remainingNotFoundLetter := ""
|
||||
remainingNotFoundLetter2 := ""
|
||||
|
||||
for _, possibleNum := range sixLengthNum {
|
||||
|
||||
reminingNotFoundNum := 0
|
||||
for i := 0; i < len(possibleNum); i++ {
|
||||
if string(possibleNum[i]) == remainingNotFound[0] {
|
||||
reminingNotFoundNum++
|
||||
remainingNotFoundLetter = remainingNotFound[0]
|
||||
remainingNotFoundLetter2 = remainingNotFound[1]
|
||||
} else if string(possibleNum[i]) == remainingNotFound[1] {
|
||||
reminingNotFoundNum++
|
||||
remainingNotFoundLetter = remainingNotFound[1]
|
||||
remainingNotFoundLetter2 = remainingNotFound[0]
|
||||
}
|
||||
}
|
||||
|
||||
if reminingNotFoundNum == 1 {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
currentPossible[remainingNotFoundLetter] = Possible{possible: []string{"F"}}
|
||||
currentPossible[remainingNotFoundLetter2] = Possible{possible: []string{"C"}}
|
||||
|
||||
answer := ""
|
||||
for _, testNum := range line.answer {
|
||||
|
||||
testNumArray := make([]string, 0)
|
||||
for i := 0; i < len(testNum); i++ {
|
||||
testNumArray = append(testNumArray, currentPossible[string(testNum[i])].possible[0])
|
||||
}
|
||||
|
||||
answer += getNum(testNumArray)
|
||||
}
|
||||
|
||||
numAnswer, _ := strconv.Atoi(answer)
|
||||
part2 += numAnswer
|
||||
|
||||
}
|
||||
|
||||
return part1, part2
|
||||
|
||||
}
|
||||
|
||||
func purgeMap(givenMap map[string]Possible) {
|
||||
|
||||
singleValues := make([]string, 0)
|
||||
for _, v := range givenMap {
|
||||
if len(v.possible) == 1 {
|
||||
singleValues = append(singleValues, v.possible[0])
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range givenMap {
|
||||
|
||||
//Check that any of the single values are in v
|
||||
newValues := make([]string, 0)
|
||||
for _, singleValue := range v.possible {
|
||||
if !containsInArray(singleValues, singleValue) {
|
||||
newValues = append(newValues, singleValue)
|
||||
}
|
||||
}
|
||||
|
||||
if len(newValues) > 0 {
|
||||
givenMap[k] = Possible{possible: newValues}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getNum(arr []string) string {
|
||||
|
||||
sort.Strings(arr)
|
||||
if equals(arr, []string{"A", "B", "C", "E", "F", "G"}) {
|
||||
return "0"
|
||||
} else if equals(arr, []string{"C", "F"}) {
|
||||
return "1"
|
||||
} else if equals(arr, []string{"A", "C", "D", "E", "G"}) {
|
||||
return "2"
|
||||
} else if equals(arr, []string{"A", "C", "D", "F", "G"}) {
|
||||
return "3"
|
||||
} else if equals(arr, []string{"B", "D", "C", "F"}) {
|
||||
return "4"
|
||||
} else if equals(arr, []string{"A", "B", "D", "F", "G"}) {
|
||||
return "5"
|
||||
} else if equals(arr, []string{"A", "B", "D", "E", "F", "G"}) {
|
||||
return "6"
|
||||
} else if equals(arr, []string{"A", "C", "F"}) {
|
||||
return "7"
|
||||
} else if equals(arr, []string{"A", "B", "C", "D", "E", "F", "G"}) {
|
||||
return "8"
|
||||
} else if equals(arr, []string{"A", "B", "C", "D", "F", "G"}) {
|
||||
return "9"
|
||||
}
|
||||
|
||||
return ""
|
||||
|
||||
}
|
||||
|
||||
func getFromLength(arr []string, length int) []string {
|
||||
returnArray := make([]string, 0)
|
||||
for _, v := range arr {
|
||||
if len(v) == length {
|
||||
returnArray = append(returnArray, v)
|
||||
}
|
||||
}
|
||||
return returnArray
|
||||
}
|
||||
|
||||
//First parameter is the bigger array
|
||||
func getOddLetter(string1 string, string2 string) []string {
|
||||
|
||||
returnArray := make([]string, 0)
|
||||
for _, v := range string1 {
|
||||
if !contains(string2, v) {
|
||||
returnArray = append(returnArray, string(v))
|
||||
}
|
||||
}
|
||||
return returnArray
|
||||
|
||||
}
|
||||
|
||||
func contains(givenString string, value rune) bool {
|
||||
for _, v := range givenString {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func containsInArray(givenArr []string, char string) bool {
|
||||
for _, v := range givenArr {
|
||||
if v == char {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func equals(arr1 []string, arr2 []string) bool {
|
||||
|
||||
sort.Strings(arr1)
|
||||
sort.Strings(arr2)
|
||||
|
||||
for i, v := range arr1 {
|
||||
if v != arr2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
3
AdventOfCode2021/go.mod
Normal file
3
AdventOfCode2021/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module johncosta.tech/AdventOfCode2021
|
||||
|
||||
go 1.17
|
||||
75
AdventOfCode2021/main.go
Normal file
75
AdventOfCode2021/main.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"johncosta.tech/AdventOfCode2021/day14"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("---------------------------------------")
|
||||
fmt.Println("Advent of Code 2021")
|
||||
fmt.Println("---------------------------------------")
|
||||
|
||||
start := time.Now()
|
||||
|
||||
/*day1input, _ := ioutil.ReadFile("day1/day1.txt")
|
||||
day2input, _ := ioutil.ReadFile("day2/day2.txt")
|
||||
day3input, _ := ioutil.ReadFile("day3/day3.txt")
|
||||
day4input, _ := ioutil.ReadFile("day4/day4.txt")
|
||||
day5input, _ := ioutil.ReadFile("day5/day5.txt")
|
||||
day6input, _ := ioutil.ReadFile("day6/day6.txt")
|
||||
day7input, _ := ioutil.ReadFile("day7/day7.txt")
|
||||
day8input, _ := ioutil.ReadFile("day8/day8.txt")
|
||||
day13input, _ := ioutil.ReadFile("day13/day13.txt")*/
|
||||
day14input, _ := ioutil.ReadFile("day14/day14.txt")
|
||||
|
||||
dayTime := time.Now()
|
||||
/*day1part1, day1part2 := day1.Run(day1input)
|
||||
printAnswers(1, time.Since(dayTime), day1part1, day1part2)
|
||||
|
||||
day2part1, day2part2 := day2.Run(day2input)
|
||||
printAnswers(2, time.Since(dayTime), day2part1, day2part2)
|
||||
|
||||
day3part1, day3part2 := day3.Run(day3input)
|
||||
printAnswers(3, time.Since(dayTime), day3part1, day3part2)
|
||||
|
||||
day4part1, day4part2 := day4.Run(day4input)
|
||||
printAnswers(4, time.Since(dayTime), day4part1, day4part2)
|
||||
|
||||
day5part1, day5part2 := day5.Run(day5input)
|
||||
printAnswers(5, time.Since(dayTime), day5part1, day5part2)
|
||||
|
||||
day6part1, day6part2 := day6.Run(day6input)
|
||||
printAnswers(6, time.Since(dayTime), day6part1, day6part2)
|
||||
|
||||
day7part1, day7part2 := day7.Run(day7input)
|
||||
printAnswers(7, time.Since(dayTime), day7part1, day7part2)
|
||||
|
||||
day8part1, day8part2 := day6.Run(day8input)
|
||||
printAnswers(8, time.Since(dayTime), day8part1, day8part2)
|
||||
|
||||
day13part1, _ := day13.Run(day13input)
|
||||
printAnswers(13, time.Since(dayTime), day13part1, 0)*/
|
||||
|
||||
day14part1, day14part2 := day14.Run(day14input)
|
||||
printAnswers(8, time.Since(dayTime), day14part1, day14part2)
|
||||
|
||||
elapsed := time.Since(start)
|
||||
|
||||
fmt.Printf("Total Time taken: %v \n", elapsed)
|
||||
fmt.Println("---------------------------------------")
|
||||
|
||||
}
|
||||
|
||||
func printAnswers(day int, time time.Duration, part1 int64, part2 int64) {
|
||||
fmt.Println("---------------------------------------")
|
||||
fmt.Printf("Day %v \n", day)
|
||||
fmt.Printf("Part 1: %v \n", part1)
|
||||
fmt.Printf("Part 2: %v \n", part2)
|
||||
fmt.Printf("Time Taken: %v \n", time)
|
||||
fmt.Println("---------------------------------------")
|
||||
}
|
||||
Reference in New Issue
Block a user