Big update: Adding all advent of codes to same repo
This commit is contained in:
14
AdventOfCode2015/README.md
Normal file
14
AdventOfCode2015/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Advent Of Code 2015
|
||||
|
||||
I started doing AoC puzzles in 2020. I have a few more days to finish in 2020, but I wanted to start on 2015 as a way to learn more about Golang.
|
||||
A language which I want to properly learn, and this is a brilliant way of doing just that.
|
||||
|
||||
## Day 6
|
||||
Brute forced solution, it would be good to get a real solution which takes less than a few milliseconds.
|
||||
|
||||
## Day 7
|
||||
Partial solution, misread the instructions, need to rethink it entirely. I actually wrote an emulator for the second set of example instructions
|
||||
|
||||
## Day 8
|
||||
Just started it, not finished as I have to do something else right now.
|
||||
- Finished it, solution takes less than 1ms to complete. Could have finished it much quicker if I didn't forget to add regular characters onto the end result.
|
39
AdventOfCode2015/day1/day1.go
Normal file
39
AdventOfCode2015/day1/day1.go
Normal file
@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 1")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day1.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var floor int64 = 0
|
||||
basement := -1
|
||||
|
||||
for i, value := range dat {
|
||||
|
||||
if basement == -1 && floor == -1 {
|
||||
basement = i
|
||||
}
|
||||
|
||||
if value == 40 {
|
||||
floor++
|
||||
} else if value == 41 {
|
||||
floor--
|
||||
}
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", floor, elapsed)
|
||||
fmt.Printf("Part 2: %v %v", basement, elapsed)
|
||||
|
||||
}
|
49
AdventOfCode2015/day10/day10.go
Normal file
49
AdventOfCode2015/day10/day10.go
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 9")
|
||||
start := time.Now()
|
||||
|
||||
inputString := "1113122113"
|
||||
input := []int64{}
|
||||
|
||||
for _, c := range inputString {
|
||||
stringChar, _ := strconv.Atoi(string(c))
|
||||
input = append(input, int64(stringChar))
|
||||
}
|
||||
|
||||
//Change 40 to 50 for part 2
|
||||
for rounds := 0; rounds < 40; rounds++ {
|
||||
|
||||
lastNum := input[0]
|
||||
var counter int64 = 1
|
||||
|
||||
newNumbers := []int64{}
|
||||
|
||||
for i := 1; i < len(input); i++ {
|
||||
if input[i] != lastNum {
|
||||
newNumbers = append(newNumbers, counter)
|
||||
newNumbers = append(newNumbers, lastNum)
|
||||
counter = 1
|
||||
lastNum = input[i]
|
||||
} else {
|
||||
counter++
|
||||
}
|
||||
}
|
||||
newNumbers = append(newNumbers, counter)
|
||||
newNumbers = append(newNumbers, lastNum)
|
||||
input = newNumbers
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", len(input), elapsed)
|
||||
fmt.Printf("Part 2: %v %v \n", len(input), elapsed)
|
||||
|
||||
}
|
64
AdventOfCode2015/day12/day12.go
Normal file
64
AdventOfCode2015/day12/day12.go
Normal file
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Day 12")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day12.json")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
json.Unmarshal(dat, &result)
|
||||
fmt.Printf("Input: %v | %T \n", result, result)
|
||||
|
||||
var count float64 = solver(result)
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", count, elapsed)
|
||||
|
||||
}
|
||||
|
||||
func solver(json map[string]interface{}) float64 {
|
||||
var counter float64
|
||||
for _, value := range json {
|
||||
switch valueType := value.(type) {
|
||||
case bool:
|
||||
case float64:
|
||||
counter += valueType
|
||||
case string:
|
||||
case []interface{}:
|
||||
counter += interfaceArraySolver(valueType)
|
||||
case map[string]interface{}:
|
||||
counter += solver(valueType)
|
||||
}
|
||||
|
||||
}
|
||||
return counter
|
||||
}
|
||||
|
||||
func interfaceArraySolver(json []interface{}) float64 {
|
||||
var counter float64
|
||||
for _, value := range json {
|
||||
switch valueType := value.(type) {
|
||||
case bool:
|
||||
case float64:
|
||||
counter += valueType
|
||||
case string:
|
||||
case []interface{}:
|
||||
counter += interfaceArraySolver(valueType)
|
||||
case map[string]interface{}:
|
||||
counter += solver(valueType)
|
||||
}
|
||||
|
||||
}
|
||||
return counter
|
||||
}
|
55
AdventOfCode2015/day12/day12.js
Normal file
55
AdventOfCode2015/day12/day12.js
Normal file
@ -0,0 +1,55 @@
|
||||
const fs = require('fs');
|
||||
const obj = JSON.parse(fs.readFileSync('day12.json', 'utf8'));
|
||||
|
||||
console.log("Part 1: " + solver(obj));
|
||||
console.log("Part 2: ", + solverPart2(obj));
|
||||
|
||||
function solver(json) {
|
||||
|
||||
let counter = 0;
|
||||
|
||||
for (let value in json) {
|
||||
if (typeof json[value] == 'number') {
|
||||
counter += json[value]
|
||||
} else if (typeof json[value] == 'boolean') {
|
||||
|
||||
} else if (typeof json[value] == 'string') {
|
||||
|
||||
} else if (typeof json[value] == 'object') {
|
||||
counter += solver(json[value]);
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
|
||||
}
|
||||
|
||||
function solverPart2(json) {
|
||||
let counter = 0;
|
||||
let redFound = false;
|
||||
let toSolver = [];
|
||||
|
||||
for (let value in json) {
|
||||
if (typeof json[value] == 'number') {
|
||||
counter += json[value]
|
||||
} else if (typeof json[value] == 'boolean') {
|
||||
|
||||
} else if (typeof json[value] == 'string') {
|
||||
if (json[value] == 'red' && !Array.isArray(json)) {
|
||||
redFound = true;
|
||||
break;
|
||||
}
|
||||
} else if (typeof json[value] == 'object') {
|
||||
toSolver.push(json[value]);
|
||||
}
|
||||
}
|
||||
|
||||
if (redFound) {
|
||||
return 0;
|
||||
} else {
|
||||
for (let e of toSolver) {
|
||||
counter += solverPart2(e);
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
}
|
143
AdventOfCode2015/day13/day13.go
Normal file
143
AdventOfCode2015/day13/day13.go
Normal file
@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Combination struct {
|
||||
subject string
|
||||
nextTo string
|
||||
}
|
||||
|
||||
type Average struct {
|
||||
person1 string
|
||||
person2 string
|
||||
average int
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("Day 13")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day13.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
combinationMap := make(map[Combination]int)
|
||||
people := make([]string, 0)
|
||||
|
||||
for _, line := range lines {
|
||||
stringLine := string(line)
|
||||
stringLine = stringLine[:len(stringLine)-1]
|
||||
lineWordArray := strings.Split(string(stringLine), " ")
|
||||
gained, _ := strconv.Atoi(lineWordArray[3])
|
||||
|
||||
if !contains(people, lineWordArray[0]) {
|
||||
people = append(people, lineWordArray[0])
|
||||
}
|
||||
|
||||
if lineWordArray[2] == "lose" {
|
||||
gained = -gained
|
||||
}
|
||||
combinationMap[Combination{subject: lineWordArray[0], nextTo: lineWordArray[10]}] = gained
|
||||
}
|
||||
|
||||
averageCombinations := make([]Average, 0)
|
||||
for _, person := range people {
|
||||
|
||||
for i := 0; i < len(people); i++ {
|
||||
nextPerson := people[i]
|
||||
if nextPerson != person {
|
||||
average := combinationMap[Combination{subject: person, nextTo: nextPerson}] + combinationMap[Combination{subject: nextPerson, nextTo: person}]
|
||||
averageCombinations = append(averageCombinations, Average{person1: person, person2: nextPerson, average: average})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
startingPerson := people[0]
|
||||
remaining := make([]string, 0)
|
||||
for _, value := range people {
|
||||
if value != startingPerson {
|
||||
remaining = append(remaining, value)
|
||||
}
|
||||
}
|
||||
|
||||
part1 := travellingSalesMan(averageCombinations, startingPerson, startingPerson, remaining)
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
|
||||
|
||||
start = time.Now()
|
||||
|
||||
for _, person := range people {
|
||||
averageCombinations = append(averageCombinations, Average{person1: "me", person2: person, average: 0})
|
||||
averageCombinations = append(averageCombinations, Average{person1: person, person2: "me", average: 0})
|
||||
}
|
||||
|
||||
people = append(people, "me")
|
||||
startingPerson = people[0]
|
||||
remaining = make([]string, 0)
|
||||
for _, value := range people {
|
||||
if value != startingPerson {
|
||||
remaining = append(remaining, value)
|
||||
}
|
||||
}
|
||||
|
||||
part2 := travellingSalesMan(averageCombinations, startingPerson, startingPerson, remaining)
|
||||
elapsed = time.Since(start)
|
||||
fmt.Printf("Part 2: %v %v \n", part2, elapsed)
|
||||
|
||||
}
|
||||
|
||||
func travellingSalesMan(averages []Average, startingPerson string, currentPerson string, remainingPeople []string) int {
|
||||
|
||||
//*Needs to return to the beginning
|
||||
if len(remainingPeople) == 0 {
|
||||
return getAverage(averages, startingPerson, currentPerson)
|
||||
} else {
|
||||
|
||||
distances := make([]int, 0)
|
||||
for _, person := range remainingPeople {
|
||||
newRemaining := make([]string, 0)
|
||||
for _, p := range remainingPeople {
|
||||
if p != person {
|
||||
newRemaining = append(newRemaining, p)
|
||||
}
|
||||
}
|
||||
distances = append(distances, getAverage(averages, currentPerson, person)+travellingSalesMan(averages, startingPerson, person, newRemaining))
|
||||
}
|
||||
max := 0
|
||||
for _, value := range distances {
|
||||
if value > max {
|
||||
max = value
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func contains(array []string, person string) bool {
|
||||
for _, v := range array {
|
||||
if v == person {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getAverage(array []Average, person1 string, person2 string) int {
|
||||
for _, p := range array {
|
||||
if p.person1 == person1 && p.person2 == person2 {
|
||||
return p.average
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
89
AdventOfCode2015/day14/day14.go
Normal file
89
AdventOfCode2015/day14/day14.go
Normal file
@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Day 13")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day14.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
|
||||
part1 := 0
|
||||
total := 2503
|
||||
for _, line := range lines {
|
||||
stringLine := string(line)
|
||||
splitLine := strings.Split(stringLine, " ")
|
||||
|
||||
v, _ := strconv.Atoi(splitLine[3])
|
||||
s, _ := strconv.Atoi(splitLine[6])
|
||||
r, _ := strconv.Atoi(splitLine[13])
|
||||
|
||||
currentDistance := (total / (s + r)) * v * s
|
||||
remaining := total % (s + r)
|
||||
if remaining >= s {
|
||||
currentDistance += v * s
|
||||
} else {
|
||||
currentDistance += v * remaining
|
||||
}
|
||||
if currentDistance > part1 {
|
||||
part1 = currentDistance
|
||||
}
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
|
||||
|
||||
start = time.Now()
|
||||
|
||||
horses := make(map[int]int)
|
||||
for i := 1; i <= total; i++ {
|
||||
|
||||
longest := 0
|
||||
fastestHorse := 0
|
||||
for index, line := range lines {
|
||||
stringLine := string(line)
|
||||
splitLine := strings.Split(stringLine, " ")
|
||||
|
||||
v, _ := strconv.Atoi(splitLine[3])
|
||||
s, _ := strconv.Atoi(splitLine[6])
|
||||
r, _ := strconv.Atoi(splitLine[13])
|
||||
|
||||
currentDistance := (i / (s + r)) * v * s
|
||||
remaining := i % (s + r)
|
||||
if remaining >= s {
|
||||
currentDistance += v * s
|
||||
} else {
|
||||
currentDistance += v * remaining
|
||||
}
|
||||
if currentDistance > longest {
|
||||
longest = currentDistance
|
||||
fastestHorse = index
|
||||
}
|
||||
}
|
||||
|
||||
horses[fastestHorse] = horses[fastestHorse] + 1
|
||||
|
||||
}
|
||||
|
||||
fastest := 0
|
||||
for _, value := range horses {
|
||||
if value > fastest {
|
||||
fastest = value
|
||||
}
|
||||
}
|
||||
|
||||
elapsed = time.Since(start)
|
||||
fmt.Printf("Part 2: %v %v \n", fastest, elapsed)
|
||||
|
||||
}
|
93
AdventOfCode2015/day15/day15.go
Normal file
93
AdventOfCode2015/day15/day15.go
Normal file
@ -0,0 +1,93 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 15")
|
||||
dat, err := ioutil.ReadFile("day15.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
ingredients := make([][]int, 4)
|
||||
for i := range ingredients {
|
||||
ingredients[i] = make([]int, 5)
|
||||
}
|
||||
|
||||
for index, line := range lines {
|
||||
|
||||
stringLine := string(line)
|
||||
splitString := strings.Split(stringLine, " ")
|
||||
ingredients[index][0], _ = strconv.Atoi(strings.TrimRight(splitString[2], ","))
|
||||
ingredients[index][1], _ = strconv.Atoi(strings.TrimRight(splitString[4], ","))
|
||||
ingredients[index][2], _ = strconv.Atoi(strings.TrimRight(splitString[6], ","))
|
||||
ingredients[index][3], _ = strconv.Atoi(strings.TrimRight(splitString[8], ","))
|
||||
ingredients[index][4], _ = strconv.Atoi(splitString[10])
|
||||
|
||||
}
|
||||
|
||||
best := 0
|
||||
part2 := 0
|
||||
for a := 0; a <= 100; a++ {
|
||||
for b := 0; b <= 100-a; b++ {
|
||||
for c := 0; c <= 100-a-b; c++ {
|
||||
for d := 0; d <= 100-a-b-c; d++ {
|
||||
|
||||
calculation := calc_cookie(ingredients, a, b, c, d)
|
||||
totalCalories := a*ingredients[0][4] + b*ingredients[1][4] + c*ingredients[2][4] + d*ingredients[3][4]
|
||||
|
||||
if calculation > best {
|
||||
best = calculation
|
||||
}
|
||||
|
||||
if totalCalories == 500 && calculation > part2 {
|
||||
part2 = calculation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(best)
|
||||
fmt.Println(part2)
|
||||
|
||||
}
|
||||
|
||||
func calc_cookie(ingredients [][]int, sprinkles int, peanut int, frosting int, sugar int) int {
|
||||
|
||||
capacity := sprinkles*ingredients[0][0] +
|
||||
peanut*ingredients[1][0] +
|
||||
frosting*ingredients[2][0] +
|
||||
sugar*ingredients[3][0]
|
||||
|
||||
durability := sprinkles*ingredients[0][1] +
|
||||
peanut*ingredients[1][1] +
|
||||
frosting*ingredients[2][1] +
|
||||
sugar*ingredients[3][1]
|
||||
|
||||
flavor := sprinkles*ingredients[0][2] +
|
||||
peanut*ingredients[1][2] +
|
||||
frosting*ingredients[2][2] +
|
||||
sugar*ingredients[3][2]
|
||||
|
||||
texture := sprinkles*ingredients[0][3] +
|
||||
peanut*ingredients[1][3] +
|
||||
frosting*ingredients[2][3] +
|
||||
sugar*ingredients[3][3]
|
||||
|
||||
if capacity <= 0 || durability <= 0 || flavor <= 0 || texture <= 0 {
|
||||
return 0
|
||||
} else {
|
||||
return capacity * durability * flavor * texture
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2015/day16/Aunt.class
Normal file
BIN
AdventOfCode2015/day16/Aunt.class
Normal file
Binary file not shown.
BIN
AdventOfCode2015/day16/Main.class
Normal file
BIN
AdventOfCode2015/day16/Main.class
Normal file
Binary file not shown.
118
AdventOfCode2015/day16/Main.java
Normal file
118
AdventOfCode2015/day16/Main.java
Normal file
@ -0,0 +1,118 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException {
|
||||
|
||||
File myFile = new File("day16.txt");
|
||||
Scanner in = new Scanner(myFile);
|
||||
int index = 1;
|
||||
|
||||
while (in.hasNext()) {
|
||||
|
||||
String[] input = in.nextLine().replaceAll("\\s+", "").split(":");
|
||||
|
||||
Map<String, Integer> currentAunt = new HashMap<>();
|
||||
|
||||
String[] secondLineSplit = input[2].split(",");
|
||||
String[] thirdLineSplit = input[3].split(",");
|
||||
|
||||
currentAunt.put(input[1], Integer.parseInt(secondLineSplit[0]));
|
||||
currentAunt.put(secondLineSplit[1], Integer.parseInt(thirdLineSplit[0]));
|
||||
currentAunt.put(thirdLineSplit[1], Integer.parseInt(input[4]));
|
||||
|
||||
int counter = 0;
|
||||
int part2counter = 0;
|
||||
|
||||
for (String key : currentAunt.keySet()) {
|
||||
|
||||
switch (key) {
|
||||
case "children":
|
||||
if (currentAunt.get(key) == 3) {
|
||||
counter++;
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "cats":
|
||||
if (currentAunt.get(key) == 7) {
|
||||
counter++;
|
||||
}
|
||||
if (currentAunt.get(key) > 7) {
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "samoyeds":
|
||||
if (currentAunt.get(key) == 2) {
|
||||
counter++;
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "pomeranians":
|
||||
if (currentAunt.get(key) == 3) {
|
||||
counter++;
|
||||
}
|
||||
if (currentAunt.get(key) < 3) {
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "akitas":
|
||||
if (currentAunt.get(key) == 0) {
|
||||
counter++;
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "vizslas":
|
||||
if (currentAunt.get(key) == 0) {
|
||||
counter++;
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "goldfish":
|
||||
if (currentAunt.get(key) == 5) {
|
||||
counter++;
|
||||
}
|
||||
if (currentAunt.get(key) < 5) {
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "trees":
|
||||
if (currentAunt.get(key) == 3) {
|
||||
counter++;
|
||||
}
|
||||
if (currentAunt.get(key) > 3) {
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "cars":
|
||||
if (currentAunt.get(key) == 2) {
|
||||
counter++;
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
case "perfumes":
|
||||
if (currentAunt.get(key) == 1) {
|
||||
counter++;
|
||||
part2counter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (counter == 3) {
|
||||
System.out.printf("Part 1: %d \n", index);
|
||||
} else if (part2counter == 3) {
|
||||
System.out.printf("Part 2: %d \n", index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
in.close();
|
||||
|
||||
}
|
||||
|
||||
}
|
53
AdventOfCode2015/day2/day2.go
Normal file
53
AdventOfCode2015/day2/day2.go
Normal file
@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 2")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day2.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
total := 0
|
||||
totalPart2 := 0
|
||||
|
||||
for _, value := range lines {
|
||||
|
||||
splitLine := bytes.Split(value, []byte("x"))
|
||||
l, _ := strconv.Atoi(string(splitLine[0]))
|
||||
w, _ := strconv.Atoi(string(splitLine[1]))
|
||||
h, _ := strconv.Atoi(string(splitLine[2]))
|
||||
|
||||
total += 2*l*w + 2*l*h + 2*w*h + MinOf(l*w, w*h, h*l)
|
||||
totalPart2 += MinOf(l*2+w*2, w*2+h*2, h*2+l*2) + l*w*h
|
||||
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", total, elapsed)
|
||||
fmt.Printf("Part 2: %v %v", totalPart2, elapsed)
|
||||
|
||||
}
|
||||
|
||||
func MinOf(vars ...int) int {
|
||||
min := vars[0]
|
||||
|
||||
for _, i := range vars {
|
||||
if min > i {
|
||||
min = i
|
||||
}
|
||||
}
|
||||
|
||||
return min
|
||||
}
|
69
AdventOfCode2015/day3/day3.go
Normal file
69
AdventOfCode2015/day3/day3.go
Normal file
@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Coords struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 3")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day3.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
position := Coords{x: 0, y: 0}
|
||||
visited := make(map[Coords]int)
|
||||
visited[position] = 1
|
||||
|
||||
for _, value := range dat {
|
||||
solve(visited, &position, value)
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", len(visited), elapsed)
|
||||
|
||||
start = time.Now()
|
||||
position = Coords{x: 0, y: 0}
|
||||
visited = make(map[Coords]int)
|
||||
visited[position] = 1
|
||||
|
||||
for i := 0; i < len(dat); i = i + 2 {
|
||||
solve(visited, &position, dat[i])
|
||||
}
|
||||
|
||||
position.x = 0
|
||||
position.y = 0
|
||||
|
||||
for i := 1; i < len(dat); i = i + 2 {
|
||||
solve(visited, &position, dat[i])
|
||||
}
|
||||
|
||||
fmt.Printf("Part 2: %v %v", len(visited), elapsed)
|
||||
|
||||
}
|
||||
|
||||
func solve(visited map[Coords]int, position *Coords, value byte) {
|
||||
if value == []byte("<")[0] {
|
||||
position.x--
|
||||
visited[*position]++
|
||||
} else if value == []byte(">")[0] {
|
||||
position.x++
|
||||
visited[*position]++
|
||||
} else if value == []byte("^")[0] {
|
||||
position.y++
|
||||
visited[*position]++
|
||||
} else if value == []byte("v")[0] {
|
||||
position.y--
|
||||
visited[*position]++
|
||||
}
|
||||
}
|
53
AdventOfCode2015/day4/day4.go
Normal file
53
AdventOfCode2015/day4/day4.go
Normal file
@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Coords struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 3")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day4.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
input := string(dat)
|
||||
|
||||
part1 := ""
|
||||
var hash [16]byte
|
||||
for i := 1; part1 == ""; i++ {
|
||||
hashString := input + strconv.Itoa(i)
|
||||
hash = md5.Sum([]byte(hashString))
|
||||
if hash[0] == 0x00 && hash[1] == 0x00 && hash[2] <= 0x0f {
|
||||
part1 = hashString
|
||||
}
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
|
||||
start = time.Now()
|
||||
|
||||
part2 := ""
|
||||
for i := 1; part2 == ""; i++ {
|
||||
hashString := input + strconv.Itoa(i)
|
||||
hash = md5.Sum([]byte(hashString))
|
||||
if hash[0] == 0x00 && hash[1] == 0x00 && hash[2] == 0x00 {
|
||||
part2 = hashString
|
||||
}
|
||||
}
|
||||
|
||||
elapsed = time.Since(start)
|
||||
fmt.Printf("Part 2: %v %v", part2, elapsed)
|
||||
|
||||
}
|
107
AdventOfCode2015/day5/day5.go
Normal file
107
AdventOfCode2015/day5/day5.go
Normal file
@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 5")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day5.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
part1 := 0
|
||||
part2 := 0
|
||||
|
||||
for _, value := range lines {
|
||||
|
||||
vowels := 0
|
||||
twiceInARow := false
|
||||
forbiddenPhrases := false
|
||||
|
||||
for i := 0; i < len(value); i++ {
|
||||
current := value[i]
|
||||
if current == []byte("a")[0] || current == []byte("e")[0] || current == []byte("i")[0] || current == []byte("o")[0] || current == []byte("u")[0] {
|
||||
vowels++
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
if value[i-1] == value[i] {
|
||||
twiceInARow = true
|
||||
}
|
||||
|
||||
last2 := []byte{value[i-1], value[i]}
|
||||
if compare(last2, []byte("ab")) || compare(last2, []byte("cd")) || compare(last2, []byte("pq")) || compare(last2, []byte("xy")) {
|
||||
forbiddenPhrases = true
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if !forbiddenPhrases {
|
||||
if twiceInARow && vowels >= 3 {
|
||||
part1++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
|
||||
|
||||
start = time.Now()
|
||||
|
||||
for _, value := range lines {
|
||||
|
||||
repeatedPair := false
|
||||
repeatedLetterWithGap := false
|
||||
|
||||
var pairs [][]byte
|
||||
for i := 0; i < len(value)-1; i++ {
|
||||
pairs = append(pairs, value[i:i+2])
|
||||
}
|
||||
|
||||
for i := 0; i < len(pairs)-1; i++ {
|
||||
for j := i + 2; j < len(pairs); j++ {
|
||||
if compare(pairs[i], pairs[j]) {
|
||||
repeatedPair = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(value)-2; i++ {
|
||||
if value[i] == value[i+2] {
|
||||
repeatedLetterWithGap = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if repeatedLetterWithGap && repeatedPair {
|
||||
part2++
|
||||
}
|
||||
}
|
||||
|
||||
elapsed = time.Since(start)
|
||||
fmt.Printf("Part 2: %v %v", part2, elapsed)
|
||||
|
||||
}
|
||||
|
||||
func compare(slice1 []byte, slice2 []byte) bool {
|
||||
for i := 0; i < len(slice1) && i < len(slice2); i++ {
|
||||
if slice1[i] != slice2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
130
AdventOfCode2015/day6/day6.go
Normal file
130
AdventOfCode2015/day6/day6.go
Normal file
@ -0,0 +1,130 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Square struct {
|
||||
x int64
|
||||
y int64
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 6")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day6.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
lights := make(map[Square]bool)
|
||||
lights2 := make(map[Square]int64)
|
||||
|
||||
SwitchTheLights(lights, false, false, 0, 0, 1000, 1000)
|
||||
|
||||
part1 := 0
|
||||
var part2 int64 = 0
|
||||
|
||||
for _, value := range lines {
|
||||
|
||||
words := bytes.Split(value, []byte(" "))
|
||||
if len(words) == 4 {
|
||||
|
||||
start := bytes.Split(words[1], []byte(","))
|
||||
end := bytes.Split(words[3], []byte(","))
|
||||
|
||||
startX, _ := strconv.Atoi(string(start[0]))
|
||||
startY, _ := strconv.Atoi(string(start[1]))
|
||||
endX, _ := strconv.Atoi(string(end[0]))
|
||||
endY, _ := strconv.Atoi(string(end[1]))
|
||||
|
||||
SwitchTheLights(lights, false, true, int64(startX), int64(startY), int64(endX), int64(endY))
|
||||
SwitchTheLights2(lights2, false, true, int64(startX), int64(startY), int64(endX), int64(endY))
|
||||
|
||||
} else {
|
||||
|
||||
start := bytes.Split(words[2], []byte(","))
|
||||
end := bytes.Split(words[4], []byte(","))
|
||||
|
||||
startX, _ := strconv.Atoi(string(start[0]))
|
||||
startY, _ := strconv.Atoi(string(start[1]))
|
||||
endX, _ := strconv.Atoi(string(end[0]))
|
||||
endY, _ := strconv.Atoi(string(end[1]))
|
||||
|
||||
SwitchTheLights(lights, compare(words[1], []byte("on")), false, int64(startX), int64(startY), int64(endX), int64(endY))
|
||||
SwitchTheLights2(lights2, compare(words[1], []byte("on")), false, int64(startX), int64(startY), int64(endX), int64(endY))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for _, v := range lights {
|
||||
if v {
|
||||
part1++
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range lights2 {
|
||||
part2 += v
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
|
||||
fmt.Printf("Part 2: %v %v \n", part2, elapsed)
|
||||
|
||||
}
|
||||
|
||||
func SwitchTheLights(lights map[Square]bool, state bool, toggle bool, startX int64, startY int64, endX int64, endY int64) {
|
||||
|
||||
for i := startX; i <= endX; i++ {
|
||||
for j := startY; j <= endY; j++ {
|
||||
if toggle {
|
||||
lights[Square{x: i, y: j}] = !lights[Square{x: i, y: j}]
|
||||
} else {
|
||||
lights[Square{x: i, y: j}] = state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func SwitchTheLights2(lights map[Square]int64, state bool, toggle bool, startX int64, startY int64, endX int64, endY int64) {
|
||||
|
||||
for i := startX; i <= endX; i++ {
|
||||
for j := startY; j <= endY; j++ {
|
||||
|
||||
var brighness int64 = lights[Square{x: i, y: j}]
|
||||
if toggle {
|
||||
lights[Square{x: i, y: j}] = brighness + 2
|
||||
} else {
|
||||
|
||||
if state {
|
||||
lights[Square{x: i, y: j}] = brighness + 1
|
||||
} else {
|
||||
lights[Square{x: i, y: j}] = brighness - 1
|
||||
if lights[Square{x: i, y: j}] < 0 {
|
||||
lights[Square{x: i, y: j}] = 0
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func compare(slice1 []byte, slice2 []byte) bool {
|
||||
for i := 0; i < len(slice1) && i < len(slice2); i++ {
|
||||
if slice1[i] != slice2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
155
AdventOfCode2015/day7/day7.zig
Normal file
155
AdventOfCode2015/day7/day7.zig
Normal file
@ -0,0 +1,155 @@
|
||||
const std = @import("std");
|
||||
const utils = @import("./utils.zig");
|
||||
|
||||
const InstructionType = enum { LITERAL, REASSIGN, NOT, AND, HACKY_AND, OR, LSHIFT, RSHIFT };
|
||||
|
||||
const Instruction = struct {
|
||||
type: InstructionType,
|
||||
|
||||
// To be used with LITERAL
|
||||
num: ?u16,
|
||||
|
||||
firstLetter: ?[]const u8,
|
||||
secondLetter: ?[]const u8,
|
||||
};
|
||||
|
||||
fn getOp(op: []const u8) InstructionType {
|
||||
if (std.mem.eql(u8, op, "AND")) {
|
||||
return InstructionType.AND;
|
||||
}
|
||||
if (std.mem.eql(u8, op, "OR")) {
|
||||
return InstructionType.OR;
|
||||
}
|
||||
if (std.mem.eql(u8, op, "LSHIFT")) {
|
||||
return InstructionType.LSHIFT;
|
||||
}
|
||||
if (std.mem.eql(u8, op, "RSHIFT")) {
|
||||
return InstructionType.RSHIFT;
|
||||
}
|
||||
|
||||
unreachable;
|
||||
}
|
||||
|
||||
fn getLetter(map: std.StringHashMap(Instruction), cache: *std.StringHashMap(u16), letter: []const u8) !u16 {
|
||||
if (cache.contains(letter)) {
|
||||
return cache.*.get(letter).?;
|
||||
}
|
||||
|
||||
var op = map.get(letter).?;
|
||||
|
||||
if (op.type == InstructionType.LITERAL) {
|
||||
try cache.*.put(letter, op.num.?);
|
||||
return op.num.?;
|
||||
}
|
||||
|
||||
if (op.type == InstructionType.NOT) {
|
||||
var notRes = ~(try getLetter(map, cache, op.firstLetter.?));
|
||||
try cache.*.put(letter, notRes);
|
||||
return notRes;
|
||||
}
|
||||
|
||||
if (op.type == InstructionType.REASSIGN) {
|
||||
var reassignRes = try getLetter(map, cache, op.firstLetter.?);
|
||||
try cache.*.put(letter, reassignRes);
|
||||
return reassignRes;
|
||||
}
|
||||
|
||||
var first = try getLetter(map, cache, op.firstLetter.?);
|
||||
|
||||
if (op.type == InstructionType.HACKY_AND) {
|
||||
try cache.*.put(letter, op.num.? & first);
|
||||
return op.num.? & first;
|
||||
}
|
||||
|
||||
if (op.type == InstructionType.AND or op.type == InstructionType.OR) {
|
||||
var second = try getLetter(map, cache, op.secondLetter.?);
|
||||
if (op.type == InstructionType.AND) {
|
||||
try cache.*.put(letter, first & second);
|
||||
return first & second;
|
||||
}
|
||||
try cache.*.put(letter, first | second);
|
||||
return first | second;
|
||||
}
|
||||
|
||||
if (op.type == InstructionType.LSHIFT) {
|
||||
var shortNum: u4 = @truncate(op.num.?);
|
||||
try cache.*.put(letter, first << shortNum);
|
||||
return first << shortNum;
|
||||
}
|
||||
var shortNum: u4 = @truncate(op.num.?);
|
||||
try cache.*.put(letter, first >> shortNum);
|
||||
return first >> shortNum;
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var allocator = std.heap.page_allocator;
|
||||
var lines = try utils.splitLines("input.txt", allocator);
|
||||
defer lines.deinit();
|
||||
|
||||
var wireMap = std.StringHashMap(Instruction).init(allocator);
|
||||
defer wireMap.deinit();
|
||||
|
||||
var resultCache = std.StringHashMap(u16).init(allocator);
|
||||
defer resultCache.deinit();
|
||||
|
||||
for (lines.items) |line| {
|
||||
var instructionAndOutput = std.mem.tokenizeSequence(u8, line, " -> ");
|
||||
|
||||
var op = instructionAndOutput.next().?;
|
||||
var output = instructionAndOutput.next().?;
|
||||
|
||||
var instructionParts = std.mem.tokenizeSequence(u8, op, " ");
|
||||
var first = instructionParts.next().?;
|
||||
|
||||
if (std.mem.eql(u8, first, "NOT")) {
|
||||
var notOp = Instruction{ .type = InstructionType.NOT, .firstLetter = instructionParts.next().?, .num = undefined, .secondLetter = undefined };
|
||||
try wireMap.put(output, notOp);
|
||||
continue;
|
||||
}
|
||||
|
||||
var firstNumber = std.fmt.parseInt(u16, first, 10) catch {
|
||||
// Must be a regular double operation (a AND b)
|
||||
|
||||
if (instructionParts.next()) |rawOperator| {
|
||||
var operator = getOp(rawOperator);
|
||||
var second = instructionParts.next().?;
|
||||
|
||||
var myOp = switch (operator) {
|
||||
InstructionType.AND, InstructionType.OR => Instruction{ .type = operator, .firstLetter = first, .secondLetter = second, .num = undefined },
|
||||
InstructionType.LSHIFT, InstructionType.RSHIFT => Instruction{ .type = operator, .firstLetter = first, .secondLetter = undefined, .num = try std.fmt.parseInt(u4, second, 10) },
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
try wireMap.put(output, myOp);
|
||||
|
||||
continue;
|
||||
}
|
||||
// x -> y
|
||||
var reassign = Instruction{ .type = InstructionType.REASSIGN, .firstLetter = first, .secondLetter = undefined, .num = undefined };
|
||||
try wireMap.put(output, reassign);
|
||||
continue;
|
||||
};
|
||||
|
||||
// Edge case. and gates can have numbers too (seems to be limited to first argument).
|
||||
if (instructionParts.next()) |_| {
|
||||
// an and operation with a 1 in front.
|
||||
var second = instructionParts.next().?;
|
||||
var hackyAnd = Instruction{ .type = InstructionType.HACKY_AND, .firstLetter = second, .secondLetter = undefined, .num = firstNumber };
|
||||
try wireMap.put(output, hackyAnd);
|
||||
continue;
|
||||
}
|
||||
|
||||
var literalOp = Instruction{ .type = InstructionType.LITERAL, .num = firstNumber, .firstLetter = undefined, .secondLetter = undefined };
|
||||
try wireMap.put(output, literalOp);
|
||||
}
|
||||
|
||||
var part1 = try getLetter(wireMap, &resultCache, "a");
|
||||
std.debug.print("Part 1: {}\n", .{part1});
|
||||
|
||||
var resetResultCache = std.StringHashMap(u16).init(allocator);
|
||||
defer resetResultCache.deinit();
|
||||
try resetResultCache.put("b", part1);
|
||||
|
||||
var part2 = try getLetter(wireMap, &resetResultCache, "a");
|
||||
std.debug.print("Part 2: {}\n", .{part2});
|
||||
}
|
1
AdventOfCode2015/day7/utils.zig
Symbolic link
1
AdventOfCode2015/day7/utils.zig
Symbolic link
@ -0,0 +1 @@
|
||||
../../zig/utils.zig
|
83
AdventOfCode2015/day8/day8.go
Normal file
83
AdventOfCode2015/day8/day8.go
Normal file
@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Square struct {
|
||||
x int64
|
||||
y int64
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
fmt.Println("Day 8")
|
||||
start := time.Now()
|
||||
|
||||
dat, err := ioutil.ReadFile("day8.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
lines := bytes.Split(dat, []byte("\n"))
|
||||
|
||||
part2 := 0
|
||||
totalCharacters := 0
|
||||
realCharacters := 0
|
||||
|
||||
for _, value := range lines {
|
||||
line := string(value)
|
||||
totalCharacters += len(line)
|
||||
|
||||
newLine := line[1 : len(line)-1]
|
||||
currentReal := 0
|
||||
|
||||
for i := 0; i < len(newLine); i++ {
|
||||
char := string(newLine[i])
|
||||
if char == `\` {
|
||||
nextChar := string(newLine[i+1])
|
||||
if nextChar == "x" {
|
||||
i = i + 2
|
||||
} else if nextChar == `"` || nextChar == `\` {
|
||||
i++
|
||||
currentReal++
|
||||
}
|
||||
} else {
|
||||
currentReal++
|
||||
}
|
||||
}
|
||||
realCharacters += currentReal
|
||||
|
||||
currentPart2 := 0
|
||||
|
||||
for i := 0; i < len(line); i++ {
|
||||
char := string(line[i])
|
||||
if char == `"` || char == `\` {
|
||||
currentPart2 += 2
|
||||
} else {
|
||||
currentPart2++
|
||||
}
|
||||
}
|
||||
//Double quotes around the string
|
||||
currentPart2 += 2
|
||||
part2 += currentPart2
|
||||
|
||||
}
|
||||
|
||||
elapsed := time.Since(start)
|
||||
fmt.Printf("Part 1: %v %v \n", totalCharacters-realCharacters, elapsed)
|
||||
fmt.Printf("Part 2: %v %v \n", part2-totalCharacters, elapsed)
|
||||
|
||||
}
|
||||
|
||||
func compare(slice1 []byte, slice2 []byte) bool {
|
||||
for i := 0; i < len(slice1) && i < len(slice2); i++ {
|
||||
if slice1[i] != slice2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
3
AdventOfCode2020/README.md
Normal file
3
AdventOfCode2020/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Advent of Code 2020
|
||||
|
||||
These are my solutions, currently all in Java.
|
BIN
AdventOfCode2020/day1/day1.class
Normal file
BIN
AdventOfCode2020/day1/day1.class
Normal file
Binary file not shown.
41
AdventOfCode2020/day1/day1.java
Normal file
41
AdventOfCode2020/day1/day1.java
Normal file
@ -0,0 +1,41 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
class day1 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
Scanner in = new Scanner(myFile);
|
||||
|
||||
int[] input = new int[200];
|
||||
for (int i = 0; i < 200; i++) {
|
||||
input[i] = Integer.parseInt(in.next());
|
||||
}
|
||||
|
||||
for (int i = 0; i < 198; i++) {
|
||||
for (int j = i + 1; j < 199; j++) {
|
||||
//Following is for part1
|
||||
//if (input[i] + input[j] == 2020) {
|
||||
//System.out.println(input[i] * input[j]);
|
||||
//}
|
||||
for (int k = j + 1; k < 200; k++) {
|
||||
if (input[i] + input[j] + input[k] == 2020) {
|
||||
System.out.println(input[i] * input[j] * input[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in.close();
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day10/day10.class
Normal file
BIN
AdventOfCode2020/day10/day10.class
Normal file
Binary file not shown.
140
AdventOfCode2020/day10/day10.java
Normal file
140
AdventOfCode2020/day10/day10.java
Normal file
@ -0,0 +1,140 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
class day10 {
|
||||
|
||||
static HashMap<ArrayList<Integer>, Long> cache = new HashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
ArrayList<Integer> nums = new ArrayList<>();
|
||||
|
||||
while (in.hasNext()) {
|
||||
nums.add(Integer.parseInt(in.nextLine()));
|
||||
}
|
||||
|
||||
nums.add(0);
|
||||
|
||||
Collections.sort(nums);
|
||||
|
||||
nums.add(nums.get(nums.size() - 1) + 3);
|
||||
|
||||
//Part 1 code
|
||||
|
||||
int one = 0;
|
||||
int two = 0;
|
||||
int three = 0;
|
||||
|
||||
for (int i = 1; i < nums.size(); i++) {
|
||||
|
||||
int diff = nums.get(i) - nums.get(i - 1);
|
||||
|
||||
if (diff == 1) {
|
||||
one++;
|
||||
} else if (diff == 2) {
|
||||
two++;
|
||||
} else if (diff == 3) {
|
||||
three++;;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (nums.get(0) == 1) one++; //From the plug to the first adaptor
|
||||
three++; //Build in adaptor
|
||||
|
||||
//System.out.printf("One: %d | Two: %d | Three: %d \n", one, two, three);
|
||||
//System.out.printf("Multiplied: %d", one * three);
|
||||
|
||||
//System.out.println(isValid(nums, nums.size()));
|
||||
|
||||
|
||||
|
||||
System.out.println(getSum(nums));
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Recursive method for part 2 solution
|
||||
There is likely a method which has o(N) complexity, but seeing as this is a daily thing, and I don't have
|
||||
all that much time this is still an elegant solution.
|
||||
*/
|
||||
public static long getSum(ArrayList<Integer> nums) {
|
||||
|
||||
long sum = 0;
|
||||
if (nums.size() == 1) {
|
||||
//System.out.println("Size 1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ArrayList<Integer> newNums = new ArrayList<>(nums);
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
|
||||
int pointer = nums.size() - 1 - i;
|
||||
//System.out.println("Pointer: " + pointer);
|
||||
//System.out.println("DSADS: " + nums.get(pointer));
|
||||
if (pointer >= 0) {
|
||||
if (nums.get(nums.size() - 1) - nums.get(pointer) <= 3) {
|
||||
newNums.remove(pointer + 1);
|
||||
|
||||
/*System.out.println("============SENT==========");
|
||||
for (int c : nums) System.out.println(c);
|
||||
System.out.println("==========================");
|
||||
|
||||
System.out.println("==========================");
|
||||
for (int c : newNums) System.out.println(c);
|
||||
System.out.println("==========================");*/
|
||||
|
||||
if (cache.containsKey(newNums)) {
|
||||
sum += cache.get(newNums);
|
||||
} else {
|
||||
long treeSum = getSum(newNums);
|
||||
//System.out.println("Tree sum: " + treeSum);
|
||||
cache.put(newNums, treeSum);
|
||||
sum += treeSum;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return sum;
|
||||
|
||||
}
|
||||
|
||||
public static boolean isValid(ArrayList<Integer> nums) {
|
||||
for (int i = 1; i < nums.size(); i++) {
|
||||
int diff = nums.get(i) - nums.get(i - 1);
|
||||
if (diff > 3) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int nCr(int n, int r) {
|
||||
return fact(n) / (fact(r) *
|
||||
fact(n - r));
|
||||
}
|
||||
|
||||
// Returns factorial of n
|
||||
static int fact(int n) {
|
||||
int res = 1;
|
||||
for (int i = 2; i <= n; i++)
|
||||
res = res * i;
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day11/day11.class
Normal file
BIN
AdventOfCode2020/day11/day11.class
Normal file
Binary file not shown.
157
AdventOfCode2020/day11/day11.java
Normal file
157
AdventOfCode2020/day11/day11.java
Normal file
@ -0,0 +1,157 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
class day11 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
char[][] seats = new char[91][94];
|
||||
int index = 0;
|
||||
|
||||
while (in.hasNext()) {
|
||||
seats[index] = in.nextLine().toCharArray();
|
||||
index++;
|
||||
}
|
||||
|
||||
boolean stable = false;
|
||||
|
||||
while (!stable) {
|
||||
|
||||
//char[][] newSeats = part1(seats);
|
||||
char[][] newSeats = part2(seats);
|
||||
boolean notEqual = false;
|
||||
|
||||
for (int i = 0; i < seats.length; i++) {
|
||||
for (int j = 0; j < seats[0].length; j++) {
|
||||
if (newSeats[i][j] != seats[i][j]) notEqual = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (notEqual) {
|
||||
seats = newSeats;
|
||||
} else {
|
||||
stable = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int occupiedSeats = 0;
|
||||
|
||||
for (int i = 0; i < seats.length; i++) {
|
||||
for (int j = 0; j < seats[0].length; j++) {
|
||||
if (seats[i][j] == '#') occupiedSeats++;
|
||||
System.out.print(seats[i][j]);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.println("Answer: " + occupiedSeats);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static char[][] part1(char[][] seats) {
|
||||
|
||||
char[][] newSeats = new char[seats.length][seats[0].length];
|
||||
|
||||
for (int i = 0; i < seats.length; i++) {
|
||||
for (int j = 0; j < seats[0].length; j++) {
|
||||
|
||||
int emptySeats = 0;
|
||||
int occupiedSeats = 0;
|
||||
|
||||
if (seats[i][j] != '.') {
|
||||
|
||||
for (int checkX = -1; checkX <= 1; checkX++) {
|
||||
for (int checkY = -1; checkY <= 1; checkY++) {
|
||||
|
||||
if (j + checkX >= 0 && i + checkY >= 0 &&
|
||||
j + checkX < seats[0].length && i + checkY < seats.length &&
|
||||
!(checkX == 0 && checkY == 0)) {
|
||||
|
||||
if (seats[i + checkY][j + checkX] == 'L') emptySeats++;
|
||||
else if (seats[i + checkY][j + checkX] == '#') occupiedSeats++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (occupiedSeats == 0 && seats[i][j] == 'L') newSeats[i][j] = '#';
|
||||
else if (occupiedSeats >= 4 && seats[i][j] == '#') newSeats[i][j] = 'L';
|
||||
else newSeats[i][j] = seats[i][j];
|
||||
|
||||
} else newSeats[i][j] = '.';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newSeats;
|
||||
|
||||
}
|
||||
|
||||
static char[][] part2(char[][] seats) {
|
||||
|
||||
char[][] newSeats = new char[seats.length][seats[0].length];
|
||||
|
||||
for (int i = 0; i < seats.length; i++) {
|
||||
for (int j = 0; j < seats[0].length; j++) {
|
||||
|
||||
int occupiedSeats = 0;
|
||||
|
||||
//System.out.print(seats[i][j]);
|
||||
|
||||
if (seats[i][j] != '.') {
|
||||
for (int checkX = -1; checkX <= 1; checkX++) {
|
||||
for (int checkY = -1; checkY <= 1; checkY++) {
|
||||
|
||||
if (!(checkX == 0 && checkY == 0)) {
|
||||
|
||||
int multipliedX = checkX;
|
||||
int multipliedY = checkY;
|
||||
|
||||
boolean foundSeat = false;
|
||||
|
||||
while (j + multipliedX >= 0 && i + multipliedY >= 0 && j + multipliedX < seats[0].length && i + multipliedY < seats.length && foundSeat == false) {
|
||||
|
||||
if(seats[i + multipliedY][j + multipliedX] == 'L') {
|
||||
foundSeat = true;
|
||||
} else if (seats[i + multipliedY][j + multipliedX] == '#') {
|
||||
occupiedSeats++;
|
||||
foundSeat = true;
|
||||
}
|
||||
|
||||
multipliedX += checkX;
|
||||
multipliedY += checkY;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//System.out.print(occupiedSeats);
|
||||
|
||||
if (occupiedSeats >= 5 && seats[i][j] == '#') newSeats[i][j] = 'L';
|
||||
else if (occupiedSeats == 0 && seats[i][j] == 'L') newSeats[i][j] = '#';
|
||||
else newSeats[i][j] = seats[i][j];
|
||||
|
||||
} else newSeats[i][j] = '.';
|
||||
}
|
||||
//System.out.println();
|
||||
}
|
||||
|
||||
return newSeats;
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day13/day13.class
Normal file
BIN
AdventOfCode2020/day13/day13.class
Normal file
Binary file not shown.
50
AdventOfCode2020/day13/day13.java
Normal file
50
AdventOfCode2020/day13/day13.java
Normal file
@ -0,0 +1,50 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class day13 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
|
||||
double timestamp = Double.parseDouble(in.nextLine());
|
||||
String[] secondLine = in.nextLine().split(",");
|
||||
ArrayList<Double> buses = new ArrayList<>();
|
||||
|
||||
for (String i : secondLine) {
|
||||
if (!i.equals("x")) buses.add(Double.parseDouble(i));
|
||||
}
|
||||
|
||||
double shortestTime = Double.MAX_VALUE;
|
||||
double shortestBus = 0;
|
||||
|
||||
for (double i : buses) {
|
||||
|
||||
double closestTime = Math.ceil(timestamp / i) * i;
|
||||
System.out.printf("Time: %f | Closest Time: %f \n", i, closestTime);
|
||||
|
||||
if (closestTime < shortestTime) {
|
||||
shortestTime = closestTime;
|
||||
shortestBus = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.printf("Part 1: %f \n", (shortestTime - timestamp) * shortestBus);
|
||||
|
||||
in.close();
|
||||
|
||||
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day14/day14.class
Normal file
BIN
AdventOfCode2020/day14/day14.class
Normal file
Binary file not shown.
136
AdventOfCode2020/day14/day14.java
Normal file
136
AdventOfCode2020/day14/day14.java
Normal file
@ -0,0 +1,136 @@
|
||||
import java.io.File;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class day14 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File inputFile = new File("input.txt");
|
||||
Scanner in = new Scanner(inputFile);
|
||||
|
||||
HashMap<Long, Long> memory = new HashMap<>();
|
||||
String mask = "";
|
||||
|
||||
while (in.hasNext()) {
|
||||
|
||||
String[] line = in.nextLine().split(" = ");
|
||||
if (line[0].equals("mask")) {
|
||||
mask = line[1];
|
||||
System.out.println("Mask: " + mask);
|
||||
} else {
|
||||
int address = Integer.parseInt(line[0].substring(line[0].indexOf("[") + 1, line[0].indexOf("]")));
|
||||
long value = Long.parseLong(line[1]);
|
||||
//memory.put(address, maskedValue(mask, value));
|
||||
long[] addresses = maskedAddresses(mask, address);
|
||||
for (long a : addresses) {
|
||||
System.out.printf("Address: %d | Value: %d \n", a, value);
|
||||
memory.put(a, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
long sumLong = 0;
|
||||
|
||||
for (long key : memory.keySet()) {
|
||||
sumLong += memory.get(key);
|
||||
}
|
||||
|
||||
System.out.println("Answer: " + sumLong);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static long maskedValue(String mask, int value) {
|
||||
|
||||
String binaryString = Integer.toBinaryString(value);
|
||||
|
||||
while (binaryString.length() != 36) binaryString = "0" + binaryString;
|
||||
|
||||
String returnString = new String();
|
||||
System.out.println("Binary String: " + binaryString);
|
||||
for (int i = binaryString.length() - 1; i >= 0; i--) {
|
||||
|
||||
if (binaryString.charAt(i) != mask.charAt(i) && mask.charAt(i) != 'X') {
|
||||
returnString = mask.charAt(i) + returnString;
|
||||
} else {
|
||||
returnString = binaryString.charAt(i) + returnString;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Return String: " + returnString);
|
||||
|
||||
return toDenary(returnString);
|
||||
|
||||
}
|
||||
|
||||
static long[] maskedAddresses(String mask, int value) {
|
||||
String binaryString = Integer.toBinaryString(value);
|
||||
|
||||
while (binaryString.length() != 36) binaryString = "0" + binaryString;
|
||||
|
||||
String returnString = new String();
|
||||
ArrayList<Integer> xlist = new ArrayList<>();
|
||||
System.out.println("Binary String: " + binaryString);
|
||||
for (int i = binaryString.length() - 1; i >= 0; i--) {
|
||||
|
||||
if (mask.charAt(i) == 'X') xlist.add(i);
|
||||
|
||||
if (binaryString.charAt(i) != mask.charAt(i) && mask.charAt(i) != '0') {
|
||||
returnString = mask.charAt(i) + returnString;
|
||||
} else {
|
||||
returnString = binaryString.charAt(i) + returnString;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Return string: " + returnString);
|
||||
|
||||
String[] binaryStrings = new String[(int) Math.pow(2, xlist.size())];
|
||||
|
||||
for (int i = 0; i < Math.pow(2, xlist.size()); i++) {
|
||||
|
||||
String currentI = Integer.toBinaryString(i);
|
||||
while (currentI.length() < xlist.size()) currentI = "0" + currentI;
|
||||
|
||||
String newAddress = returnString;
|
||||
for (int j = 0; j < currentI.length(); j++) {
|
||||
newAddress = newAddress.replaceFirst(Pattern.quote("X"), Matcher.quoteReplacement(Character.toString(currentI.charAt(j))));
|
||||
}
|
||||
|
||||
System.out.println("New address: " + newAddress);
|
||||
binaryStrings[i] = newAddress;
|
||||
|
||||
}
|
||||
|
||||
long[] newAddresses = new long[binaryStrings.length];
|
||||
for (int i = 0; i < newAddresses.length; i++) {
|
||||
newAddresses[i] = toDenary(binaryStrings[i]);
|
||||
}
|
||||
|
||||
return newAddresses;
|
||||
|
||||
}
|
||||
|
||||
static long toDenary(String binary) {
|
||||
long value = 0;
|
||||
for (int i = 0; i < binary.length(); i++) {
|
||||
if (binary.charAt(i) == '1') {
|
||||
value += Math.pow(2, (35 - i));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day15/NumberTurns.class
Normal file
BIN
AdventOfCode2020/day15/NumberTurns.class
Normal file
Binary file not shown.
BIN
AdventOfCode2020/day15/day15.class
Normal file
BIN
AdventOfCode2020/day15/day15.class
Normal file
Binary file not shown.
40
AdventOfCode2020/day15/day15.java
Normal file
40
AdventOfCode2020/day15/day15.java
Normal file
@ -0,0 +1,40 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
class day15 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
int[] startingNumbers = {17,1,3,16,19,0};
|
||||
ArrayList<Integer> spokenNums = new ArrayList<>();
|
||||
HashMap<Integer, Integer> seenLast = new HashMap<>();
|
||||
int lastNumber = 0;
|
||||
|
||||
for (int i = 0; i < startingNumbers.length; i++) {
|
||||
spokenNums.add(startingNumbers[i]);
|
||||
lastNumber = startingNumbers[i];
|
||||
if (i + 1 != startingNumbers.length) {
|
||||
seenLast.put(startingNumbers[i], i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
while (spokenNums.size() < 30000000) {
|
||||
|
||||
if (!seenLast.containsKey(lastNumber)) {
|
||||
seenLast.put(lastNumber, spokenNums.size());
|
||||
spokenNums.add(0);
|
||||
lastNumber = 0;
|
||||
} else {
|
||||
int diff = spokenNums.size() - seenLast.get(lastNumber);
|
||||
seenLast.put(lastNumber, spokenNums.size());
|
||||
lastNumber = diff;
|
||||
spokenNums.add(lastNumber);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Number: " + spokenNums.get(spokenNums.size() - 1));
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day16/Field.class
Normal file
BIN
AdventOfCode2020/day16/Field.class
Normal file
Binary file not shown.
BIN
AdventOfCode2020/day16/day16.class
Normal file
BIN
AdventOfCode2020/day16/day16.class
Normal file
Binary file not shown.
197
AdventOfCode2020/day16/day16.java
Normal file
197
AdventOfCode2020/day16/day16.java
Normal file
@ -0,0 +1,197 @@
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.print.attribute.standard.MediaSize.Other;
|
||||
|
||||
class day16 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File inputFile = new File("input.txt");
|
||||
Scanner in = new Scanner(inputFile);
|
||||
List<String> input = new ArrayList<>();
|
||||
|
||||
while (in.hasNext()) input.add(in.nextLine());
|
||||
|
||||
List<String> fields = input.subList(0, input.indexOf("your ticket:") - 1);
|
||||
String ticket = input.get(input.indexOf("your ticket:") + 1);
|
||||
List<String> otherTickets = input.subList(input.indexOf("nearby tickets:") + 1, input.size());
|
||||
|
||||
HashMap<Integer, Integer> ranges = new HashMap<>();
|
||||
|
||||
List<Field> formattedFields = new ArrayList<>();
|
||||
|
||||
for (String field : fields) {
|
||||
|
||||
//Part 1 uses the hasmap, part 2 doesnot
|
||||
String[] currentRanges = field.substring(field.indexOf(":") + 2).split(" or ");
|
||||
String[] currentUpperAndLower = currentRanges[0].split("-");
|
||||
ranges.put(Integer.parseInt(currentUpperAndLower[0]), Integer.parseInt(currentUpperAndLower[1]));
|
||||
int[] range1 = {Integer.parseInt(currentUpperAndLower[0]), Integer.parseInt(currentUpperAndLower[1])};
|
||||
|
||||
currentUpperAndLower = currentRanges[1].split("-");
|
||||
ranges.put(Integer.parseInt(currentUpperAndLower[0]), Integer.parseInt(currentUpperAndLower[1]));
|
||||
int[] range2 = {Integer.parseInt(currentUpperAndLower[0]), Integer.parseInt(currentUpperAndLower[1])};
|
||||
|
||||
String category = field.substring(0, field.indexOf(":"));
|
||||
|
||||
formattedFields.add(new Field(category, range1, range2));
|
||||
|
||||
}
|
||||
|
||||
long errorRate = 0;
|
||||
List<Integer> toRemove = new ArrayList<>();
|
||||
|
||||
for (String value : otherTickets) {
|
||||
|
||||
String[] values = value.split(",");
|
||||
int[] singleTicketValues = Arrays.stream(values).mapToInt(Integer::parseInt).toArray();
|
||||
|
||||
for (int singleValue : singleTicketValues) {
|
||||
boolean valid = false;
|
||||
for (int lower : ranges.keySet()) {
|
||||
int upper = ranges.get(lower);
|
||||
if (singleValue >= lower && singleValue <= upper) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
toRemove.add(otherTickets.indexOf(value));
|
||||
errorRate += singleValue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<String> newOtherTickets = new ArrayList<>();
|
||||
for (int i = 0; i < otherTickets.size(); i++) {
|
||||
if (!toRemove.contains(i)) newOtherTickets.add(otherTickets.get(i));
|
||||
}
|
||||
|
||||
HashMap<Integer, List<Field>> possibleCombinations = new HashMap<>();
|
||||
for (Field f : formattedFields) possibleCombinations.put(formattedFields.indexOf(f), new ArrayList<>());
|
||||
|
||||
for (int i = 0; i < newOtherTickets.size(); i++) {
|
||||
|
||||
String[] firstValues = newOtherTickets.get(i).split(",");
|
||||
|
||||
for (int j = 0; j < firstValues.length; j++) {
|
||||
|
||||
int currentValue = Integer.parseInt(firstValues[j]);
|
||||
List<Field> possible = new ArrayList<>();
|
||||
|
||||
for (Field f : formattedFields) {
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
if (f.range1[0] <= currentValue && f.range1[1] >= currentValue ||
|
||||
f.range2[0] <= currentValue && f.range2[1] >= currentValue) {
|
||||
possibleCombinations.get(j).add(f);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
//Compare to this field;
|
||||
if (f.range1[0] <= currentValue && f.range1[1] >= currentValue ||
|
||||
f.range2[0] <= currentValue && f.range2[1] >= currentValue) {
|
||||
possible.add(f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Compare withoutDuplicate and "possible"
|
||||
|
||||
if (i != 0) {
|
||||
|
||||
List<Field> newList = new ArrayList<>();
|
||||
for (Field f : possible) if (possibleCombinations.get(j).contains(f) && possible.contains(f)) {
|
||||
newList.add(f);
|
||||
}
|
||||
|
||||
possibleCombinations.put(j, newList);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Part 2
|
||||
|
||||
boolean done = false;
|
||||
|
||||
while (!done) {
|
||||
|
||||
for (int i : possibleCombinations.keySet()) {
|
||||
|
||||
if (possibleCombinations.get(i).size() == 1) {
|
||||
Field knownField = possibleCombinations.get(i).get(0);
|
||||
for (int j = 0; j < possibleCombinations.size(); j++) {
|
||||
|
||||
if (i != j && possibleCombinations.get(j).size() > 1) {
|
||||
possibleCombinations.get(j).remove(knownField);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
done = true;
|
||||
for (int i : possibleCombinations.keySet()) {
|
||||
|
||||
if (possibleCombinations.get(i).size() != 1) done = false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
long multiplication = 1;
|
||||
String[] myTicket = ticket.split(",");
|
||||
|
||||
for (int i : possibleCombinations.keySet()) {
|
||||
Field currentField = possibleCombinations.get(i).get(0);
|
||||
if (currentField.name.contains("departure")) {
|
||||
multiplication *= Long.parseLong(myTicket[i]);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Part 1: " + errorRate);
|
||||
System.out.println("Part 2: " + multiplication);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Field {
|
||||
|
||||
public String name;
|
||||
public int[] range1;
|
||||
public int[] range2;
|
||||
public int col = -1;
|
||||
|
||||
public Field(String name, int[] range1, int[] range2) {
|
||||
this.name = name;
|
||||
this.range1 = range1;
|
||||
this.range2 = range2;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Category: " + name + " | Range 1: " + range1[0] + "-" + range1[1] + " | Range 2: " + range2[0] + "-" + range2[1];
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day17/day17.class
Normal file
BIN
AdventOfCode2020/day17/day17.class
Normal file
Binary file not shown.
243
AdventOfCode2020/day17/day17.java
Normal file
243
AdventOfCode2020/day17/day17.java
Normal file
@ -0,0 +1,243 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class day17 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
List<int[]> points = new ArrayList<>();
|
||||
List<int[]> pointsPart2 = new ArrayList<>();
|
||||
|
||||
char[][] input = {{'.', '.', '#', '.', '.', '#', '.', '.'},
|
||||
{'#', '.', '#', '.', '.', '.', '#', '.'},
|
||||
{'.', '.', '#', '.', '.', '.', '.', '.'},
|
||||
{'#', '#', '.', '.', '.', '.', '#', '#'},
|
||||
{'#', '.', '.', '#', '.', '#', '#', '#'},
|
||||
{'.', '#', '.', '.', '#', '.', '.', '.'},
|
||||
{'#', '#', '#', '.', '.', '#', '.', '.'},
|
||||
{'.', '.', '.', '.', '#', '.', '.', '#'}};
|
||||
|
||||
/*char[][] input = {{'.', '#', '.'},
|
||||
{'.', '.', '#'},
|
||||
{'#', '#', '#'}};*/
|
||||
|
||||
//Part 1
|
||||
|
||||
//initialise
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
for (int j = 0; j < input[0].length; j++) {
|
||||
int[] newPoint = {j, i, 0, 0};
|
||||
int[] newPointPart2 = {j, i, 0, 0, 0};
|
||||
if (input[i][j] == '#') {
|
||||
newPoint[3] = 1;
|
||||
newPointPart2[4] = 1;
|
||||
}
|
||||
points.add(newPoint);
|
||||
pointsPart2.add(newPointPart2);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
points = step(points);
|
||||
pointsPart2 = stepPart2(pointsPart2);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
for (int[] p : points) {
|
||||
if (p[3] == 1) counter++;
|
||||
//System.out.printf("x: %d | y: %d | z: %d | State: %d \n", p[0], p[1], p[2], p[3]);
|
||||
}
|
||||
System.out.println("Part 1: " + counter);
|
||||
|
||||
counter = 0;
|
||||
for (int[] p : pointsPart2) {
|
||||
if (p[4] == 1) counter++;
|
||||
//System.out.printf("x: %d | y: %d | z: %d | State: %d \n", p[0], p[1], p[2], p[3]);
|
||||
}
|
||||
System.out.println("Part 2: " + counter);
|
||||
|
||||
}
|
||||
|
||||
static List<int[]> step(List<int[]> points) {
|
||||
|
||||
List<int[]> newPoints = new ArrayList<>();
|
||||
List<int[]> pointsToCheck = new ArrayList<>();
|
||||
|
||||
for (int[] p : points) {
|
||||
|
||||
int active = 0;
|
||||
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int z = -1; z <= 1; z++) {
|
||||
|
||||
if (!(x == 0 && y == 0 && z == 0)) {
|
||||
|
||||
int[] potentialNeighboor = {p[0] + x, p[1] + y, p[2] + z, 0};
|
||||
int index = contains(potentialNeighboor, points);
|
||||
if (index != -1) {
|
||||
int[] foundPoint = points.get(index);
|
||||
if (foundPoint[3] == 1) {
|
||||
active++;
|
||||
}
|
||||
} else {
|
||||
if (contains(potentialNeighboor, pointsToCheck) == -1) pointsToCheck.add(potentialNeighboor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] newPoint = {p[0], p[1], p[2], p[3]};
|
||||
|
||||
if (p[3] == 1) {
|
||||
if (active != 2 && active != 3) newPoint[3] = 0;
|
||||
} else {
|
||||
if (active == 3) newPoint[3] = 1;
|
||||
}
|
||||
|
||||
newPoints.add(newPoint);
|
||||
|
||||
}
|
||||
|
||||
for (int[] p : pointsToCheck) {
|
||||
|
||||
int active = 0;
|
||||
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int z = -1; z <= 1; z++) {
|
||||
|
||||
if (!(x == 0 && y == 0 && z == 0)) {
|
||||
|
||||
int[] potentialNeighboor = {p[0] + x, p[1] + y, p[2] + z, 0};
|
||||
int index = contains(potentialNeighboor, points);
|
||||
if (index != -1) {
|
||||
int[] foundPoint = points.get(index);
|
||||
if (foundPoint[3] == 1) active++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] newPoint = {p[0], p[1], p[2], p[3]};
|
||||
|
||||
if (active == 3){
|
||||
newPoint[3] = 1;
|
||||
//System.out.printf("x: %d | y: %d | z: %d | State: %d \n", newPoint[0], newPoint[1], newPoint[2], newPoint[3]);
|
||||
}
|
||||
|
||||
newPoints.add(newPoint);
|
||||
|
||||
}
|
||||
|
||||
return newPoints;
|
||||
|
||||
}
|
||||
|
||||
static List<int[]> stepPart2(List<int[]> points) {
|
||||
|
||||
System.out.println(points.size());
|
||||
|
||||
List<int[]> newPoints = new ArrayList<>();
|
||||
List<int[]> pointsToCheck = new ArrayList<>();
|
||||
|
||||
for (int[] p : points) {
|
||||
|
||||
int active = 0;
|
||||
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int z = -1; z <= 1; z++) {
|
||||
for (int w = -1; w <= 1; w++) {
|
||||
|
||||
if (!(x == 0 && y == 0 && z == 0 && w == 0)) {
|
||||
int[] potentialNeighboor = {p[0] + x, p[1] + y, p[2] + z, p[3] + w, 0};
|
||||
int index = containsPart2(potentialNeighboor, points);
|
||||
if (index != -1) {
|
||||
int[] foundPoint = points.get(index);
|
||||
if (foundPoint[4] == 1) active++;
|
||||
} else {
|
||||
if (containsPart2(potentialNeighboor, pointsToCheck) == -1) pointsToCheck.add(potentialNeighboor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] newPoint = {p[0], p[1], p[2], p[3], p[4]};
|
||||
|
||||
if (p[4] == 1) {
|
||||
if (active != 2 && active != 3) newPoint[4] = 0;
|
||||
} else {
|
||||
if (active == 3) newPoint[4] = 1;
|
||||
}
|
||||
|
||||
newPoints.add(newPoint);
|
||||
|
||||
}
|
||||
|
||||
for (int[] p : pointsToCheck) {
|
||||
|
||||
int active = 0;
|
||||
|
||||
for (int x = -1; x <= 1; x++) {
|
||||
for (int y = -1; y <= 1; y++) {
|
||||
for (int z = -1; z <= 1; z++) {
|
||||
for (int w = -1; w <= 1; w++) {
|
||||
if (!(x == 0 && y == 0 && z == 0 && w == 0)) {
|
||||
|
||||
int[] potentialNeighboor = {p[0] + x, p[1] + y, p[2] + z, p[3] + w, 0};
|
||||
int index = containsPart2(potentialNeighboor, points);
|
||||
if (index != -1) {
|
||||
int[] foundPoint = points.get(index);
|
||||
if (foundPoint[4] == 1) active++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[] newPoint = {p[0], p[1], p[2], p[3], p[4]};
|
||||
|
||||
if (active == 3) newPoint[4] = 1;
|
||||
newPoints.add(newPoint);
|
||||
|
||||
}
|
||||
|
||||
return newPoints;
|
||||
|
||||
}
|
||||
|
||||
static int contains(int[] p, List<int[]> points) {
|
||||
for (int[] search : points) {
|
||||
if (search[0] == p[0] && search[1] == p[1] && search[2] == p[2]) {
|
||||
return points.indexOf(search);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int containsPart2(int[] p, List<int[]> points) {
|
||||
for (int[] search : points) {
|
||||
if (search[0] == p[0] && search[1] == p[1] && search[2] == p[2] && search[3] == p[3]) {
|
||||
return points.indexOf(search);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day18/day18.class
Normal file
BIN
AdventOfCode2020/day18/day18.class
Normal file
Binary file not shown.
167
AdventOfCode2020/day18/day18.java
Normal file
167
AdventOfCode2020/day18/day18.java
Normal file
@ -0,0 +1,167 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class day18 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File inputFile = new File("input.txt");
|
||||
Scanner in = new Scanner(inputFile);
|
||||
long total1 = 0;
|
||||
long total2 = 0;
|
||||
|
||||
while (in.hasNext()) {
|
||||
|
||||
String expression = in.nextLine();
|
||||
total1 += recursive(expression);
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Total: " + total1);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static long recursive(String expression) {
|
||||
|
||||
System.out.println(expression);
|
||||
|
||||
int openIndex = -1;
|
||||
int closeIndex = 0;
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < expression.length(); i++) {
|
||||
|
||||
char check = expression.charAt(i);
|
||||
if (check == '(' && count == 0) {
|
||||
count = 1;
|
||||
openIndex = i;
|
||||
} else if (check == '(' && count != 0) {
|
||||
count++;
|
||||
} else if (check == ')' && count > 1) {
|
||||
count--;
|
||||
} else if (check == ')' && count == 1) {
|
||||
closeIndex = i;
|
||||
count = 0;
|
||||
long solved = recursive(expression.substring(openIndex + 1, closeIndex));
|
||||
expression = expression.substring(0, openIndex) + solved + expression.substring(closeIndex + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (openIndex == -1) {
|
||||
//return solve(expression);
|
||||
//Part 2:
|
||||
return part2(expression);
|
||||
} else {
|
||||
return recursive(expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static long part2(String expression) {
|
||||
|
||||
expression = expression.replace("(", "");
|
||||
expression = expression.replace(")", "");
|
||||
expression = expression.replace(" ", "");
|
||||
|
||||
if (expression.contains("+") && expression.contains("*")) {
|
||||
|
||||
String[] split = expression.split("[*]");
|
||||
long total = 1;
|
||||
|
||||
for (String s : split) {
|
||||
total *= solve(s);
|
||||
}
|
||||
|
||||
return total;
|
||||
|
||||
} else {
|
||||
return solve(expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static long solve(String expression) {
|
||||
|
||||
expression = expression.replace("(", "");
|
||||
expression = expression.replace(")", "");
|
||||
expression = expression.replace(" ", "");
|
||||
|
||||
int loops = 0;
|
||||
//Looks bad but i think its faster than some REGEX or something,
|
||||
//plus its needed for iteration
|
||||
loops += expression.length() - expression.replace("+", "").length();
|
||||
loops += expression.length() - expression.replace("*", "").length();
|
||||
|
||||
if (loops == 0) return Long.parseLong(expression);
|
||||
|
||||
long total = 0;
|
||||
for (int i = 0; i < loops - 1; i++) {
|
||||
|
||||
int indexRest = 0;
|
||||
int currentIndex = 0;
|
||||
for (int j = 0; j < expression.length(); j++) {
|
||||
if (!Character.isDigit(expression.charAt(j))) {
|
||||
if (currentIndex == 0) {
|
||||
currentIndex = j;
|
||||
} else {
|
||||
indexRest = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String currentExpression = expression.substring(0, indexRest);
|
||||
String[] split = currentExpression.split("[+*/-]");
|
||||
long left = Long.parseLong(split[0]);
|
||||
long right = Long.parseLong(split[1]);
|
||||
|
||||
char operation = expression.charAt(currentIndex);
|
||||
|
||||
long currentTotal = 0;
|
||||
|
||||
if (operation == '+') {
|
||||
currentTotal = left + right;
|
||||
} else if (operation == '-') {
|
||||
currentTotal = left - right;
|
||||
} else if (operation == '*') {
|
||||
currentTotal = left * right;
|
||||
} else if (operation == '/') {
|
||||
currentTotal = left / right;
|
||||
}
|
||||
|
||||
expression = currentTotal + expression.substring(indexRest);
|
||||
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < expression.length(); i++) {
|
||||
if (!Character.isDigit(expression.charAt(i))) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String[] split = expression.split("[+*]");
|
||||
long left = Long.parseLong(split[0]);
|
||||
long right = Long.parseLong(split[1]);
|
||||
char operation = expression.charAt(index);
|
||||
|
||||
if (operation == '+') {
|
||||
total = left + right;
|
||||
} else if (operation == '*') {
|
||||
total = left * right;
|
||||
}
|
||||
|
||||
return total;
|
||||
|
||||
}
|
||||
|
||||
}
|
115
AdventOfCode2020/day19/day19.go
Normal file
115
AdventOfCode2020/day19/day19.go
Normal file
@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetRule(rules *map[string]string, r string) string {
|
||||
rule := (*rules)[r]
|
||||
|
||||
if strings.Contains(rule, `"`) {
|
||||
// Base case
|
||||
matchLetter := rule[1 : len(rule)-1]
|
||||
return matchLetter
|
||||
}
|
||||
|
||||
alternates := strings.Split(rule, " | ")
|
||||
|
||||
if len(alternates) == 1 {
|
||||
ruleNumbers := strings.Split(alternates[0], " ")
|
||||
str := ""
|
||||
for _, n := range ruleNumbers {
|
||||
str += GetRule(rules, n)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
if len(alternates) > 1 {
|
||||
ruleNumbers := strings.Split(alternates[0], " ")
|
||||
firstAlternate := ""
|
||||
for _, n := range ruleNumbers {
|
||||
firstAlternate += GetRule(rules, n)
|
||||
}
|
||||
|
||||
ruleNumbers = strings.Split(alternates[1], " ")
|
||||
secondAlternate := ""
|
||||
for _, n := range ruleNumbers {
|
||||
secondAlternate += GetRule(rules, n)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("(%s|%s)", firstAlternate, secondAlternate)
|
||||
}
|
||||
|
||||
panic("should never be here")
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
content, err := os.ReadFile("./input.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
splitInput := strings.Split(string(content), "\n\n")
|
||||
rules := strings.Split(splitInput[0], "\n")
|
||||
|
||||
ruleMap := make(map[string]string)
|
||||
|
||||
for _, rule := range rules {
|
||||
splitRule := strings.Split(rule, ": ")
|
||||
ruleNumber := splitRule[0]
|
||||
|
||||
ruleMap[ruleNumber] = splitRule[1]
|
||||
}
|
||||
|
||||
tests := splitInput[1]
|
||||
tests = tests[0 : len(tests)-1]
|
||||
|
||||
zeroRule := regexp.MustCompile("^" + GetRule(&ruleMap, "0") + "$")
|
||||
|
||||
matches := 0
|
||||
for _, t := range strings.Split(tests, "\n") {
|
||||
if zeroRule.Match([]byte(t)) {
|
||||
matches++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Part 1: %d\n", matches)
|
||||
|
||||
fRule := regexp.MustCompile(GetRule(&ruleMap, "42"))
|
||||
tRule := regexp.MustCompile(GetRule(&ruleMap, "31"))
|
||||
|
||||
matches = 0
|
||||
for _, t := range strings.Split(tests, "\n") {
|
||||
|
||||
// rule 0 = 8 11
|
||||
// 8 = 42+
|
||||
// 11 = 42{n} 31{n}
|
||||
// Therefore: 0 = 42 {n*2} 31{n}
|
||||
|
||||
fortyTwoMatch := fRule.FindStringIndex(t)
|
||||
fortyTwoCount := 0
|
||||
for fortyTwoMatch != nil && fortyTwoMatch[0] == 0 {
|
||||
t = t[fortyTwoMatch[1]:]
|
||||
fortyTwoMatch = fRule.FindStringIndex(t)
|
||||
fortyTwoCount++
|
||||
}
|
||||
|
||||
thirtyMatch := tRule.FindStringIndex(t)
|
||||
thirtyCount := 0
|
||||
for thirtyMatch != nil && thirtyMatch[0] == 0 {
|
||||
t = t[thirtyMatch[1]:]
|
||||
thirtyMatch = tRule.FindStringIndex(t)
|
||||
thirtyCount++
|
||||
}
|
||||
|
||||
if len(t) == 0 && thirtyCount > 0 && fortyTwoCount > thirtyCount {
|
||||
matches++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Part 2: %d\n", matches)
|
||||
}
|
253
AdventOfCode2020/day19/main.go
Normal file
253
AdventOfCode2020/day19/main.go
Normal file
@ -0,0 +1,253 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var THREE_SIMPLE_RULE = `
|
||||
func Rule%s(message string, index *int) error {
|
||||
err := Rule%s(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = Rule%s(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = Rule%s(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
var SIMPLE_RULE = `
|
||||
func Rule%s(message string, index *int) error {
|
||||
err := Rule%s(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = Rule%s(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
var ONE_SIMPLE_RULE = `
|
||||
func Rule%s(message string, index *int) error {
|
||||
err := Rule%s(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
var ALTERNATE_RULE = `
|
||||
func Rule%s(message string, index *int) error {
|
||||
indexCopy := *index
|
||||
err := Rule%sFirst(message, &indexCopy)
|
||||
|
||||
if err == nil {
|
||||
*index = indexCopy
|
||||
return nil
|
||||
}
|
||||
|
||||
err = Rule%sSecond(message, index)
|
||||
return err
|
||||
}
|
||||
%s
|
||||
%s
|
||||
`
|
||||
|
||||
var LITERAL_RULE = `
|
||||
func Rule%s(message string, index *int) error {
|
||||
if len(message) <= *index {
|
||||
return errors.New("out of bounds")
|
||||
}
|
||||
|
||||
if string(message[*index]) == "%c" {
|
||||
*index++
|
||||
return nil
|
||||
}
|
||||
return errors.New("Could not match")
|
||||
}
|
||||
`
|
||||
|
||||
func main() {
|
||||
content, err := os.ReadFile("./input.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
splitInput := strings.Split(string(content), "\n\n")
|
||||
|
||||
program := `
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
content, err := os.ReadFile("./input.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
splitInput := strings.Split(string(content), "\n\n")
|
||||
toTry := splitInput[1]
|
||||
counter := 0
|
||||
|
||||
toTrySplit := strings.Split(toTry, "\n")
|
||||
|
||||
for _, v := range toTrySplit[0: len(toTrySplit) - 1] {
|
||||
index := 0
|
||||
err := Rule0(v, &index)
|
||||
if err == nil && index == len(v) {
|
||||
counter++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(counter)
|
||||
}
|
||||
`
|
||||
|
||||
rules := strings.Split(splitInput[0], "\n")
|
||||
for _, v := range rules {
|
||||
|
||||
/*
|
||||
if v == "8: 42" {
|
||||
v = "8: 42 | 42 8"
|
||||
} else if v == "11: 42 31" {
|
||||
v = "11: 42 31 | 42 11 31"
|
||||
}
|
||||
*/
|
||||
|
||||
program += CreateRule(v)
|
||||
}
|
||||
|
||||
err = os.WriteFile("./parser.go", []byte(program), 0777)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateRule(rule string) (string) {
|
||||
splitRule := strings.Split(rule, ": ")
|
||||
ruleNumber := splitRule[0]
|
||||
|
||||
rules := strings.Split(splitRule[1], " | ")
|
||||
|
||||
if (len(rules) == 1) {
|
||||
return CreateSingleRule(ruleNumber, rules[0])
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ALTERNATE_RULE, ruleNumber, ruleNumber, ruleNumber, CreateSingleRule(ruleNumber + "First", rules[0]), CreateSingleRule(ruleNumber + "Second", rules[1]))
|
||||
}
|
||||
|
||||
// Single rule (4 5) or ("a")
|
||||
func CreateSingleRule(ruleNumber string, rule string) string {
|
||||
if string(rule[0]) == string('"') {
|
||||
return fmt.Sprintf(LITERAL_RULE, ruleNumber, rule[1])
|
||||
}
|
||||
|
||||
nums := strings.Split(rule, " ")
|
||||
|
||||
if len(nums) == 3 {
|
||||
return fmt.Sprintf(THREE_SIMPLE_RULE, ruleNumber, nums[0], nums[1], nums[2])
|
||||
} else if (len(nums) == 2) {
|
||||
return fmt.Sprintf(SIMPLE_RULE, ruleNumber, nums[0], nums[1])
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ONE_SIMPLE_RULE, ruleNumber, nums[0])
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
func Rule0(message string, index *int) error {
|
||||
err := Rule1(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := Rule2(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Rule2(message string, index *int) error {
|
||||
indexCopy := *index
|
||||
err := Rule2First(message, &indexCopy)
|
||||
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = Rule2Second(message, index)
|
||||
return err
|
||||
}
|
||||
|
||||
func Rule2First(message string, index *int) error {
|
||||
err := Rule1(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := Rule3(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Rule2Second(message string, index *int) error {
|
||||
err := Rule3(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := Rule1(message, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Rule3(message string, index *int) errro {
|
||||
if message[*index] == "b" {
|
||||
x := 5
|
||||
y := &x
|
||||
*y = *y + 1
|
||||
fmt.Println(x)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func Rule3(message string, index *int) error {
|
||||
if string(message[*index]) == "b" {
|
||||
*index++
|
||||
return nil
|
||||
}
|
||||
return errors.New("Could not match")
|
||||
}
|
||||
*/
|
1056
AdventOfCode2020/day19/parser.go
Executable file
1056
AdventOfCode2020/day19/parser.go
Executable file
File diff suppressed because it is too large
Load Diff
BIN
AdventOfCode2020/day2/Main.class
Normal file
BIN
AdventOfCode2020/day2/Main.class
Normal file
Binary file not shown.
51
AdventOfCode2020/day2/Main.java
Normal file
51
AdventOfCode2020/day2/Main.java
Normal file
@ -0,0 +1,51 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
Scanner in = new Scanner(myFile);
|
||||
|
||||
int valid = 0;
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
|
||||
String line = in.nextLine();
|
||||
|
||||
String[] firstSplit = line.split(" ");
|
||||
//0 - numbers
|
||||
//1 - letter
|
||||
//2 - Password
|
||||
|
||||
String[] boundsStr = firstSplit[0].split("-");
|
||||
int[] bounds = {Integer.parseInt(boundsStr[0]), Integer.parseInt(boundsStr[1])};
|
||||
char letter = firstSplit[1].charAt(0);
|
||||
String password = firstSplit[2];
|
||||
//int counter = 0;
|
||||
|
||||
//Part 1 code
|
||||
/*for (char c : password.toCharArray()) {
|
||||
if (c == letter) counter++;
|
||||
}
|
||||
|
||||
if (counter >= bounds[0] && counter <= bounds[1]) valid++;*/
|
||||
|
||||
//Second part code
|
||||
if ((password.charAt(bounds[0] - 1) == letter || password.charAt(bounds[1] - 1) == letter) && !(password.charAt(bounds[0] - 1) == letter && password.charAt(bounds[1] - 1) == letter)) valid++;
|
||||
|
||||
}
|
||||
|
||||
System.out.println(valid);
|
||||
in.close();
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
140
AdventOfCode2020/day21/day21.go
Normal file
140
AdventOfCode2020/day21/day21.go
Normal file
@ -0,0 +1,140 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func contains(arr []string, search string) bool {
|
||||
for _, val := range arr {
|
||||
if val == search {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func remove(arr []string, item string) []string {
|
||||
newThing := make([]string, 0)
|
||||
for _, val := range arr {
|
||||
if val != item {
|
||||
newThing = append(newThing, val)
|
||||
}
|
||||
}
|
||||
return newThing
|
||||
}
|
||||
|
||||
func mergeSets(set1 []string, set2 []string) []string {
|
||||
merged := make([]string, 0)
|
||||
for _, val := range set1 {
|
||||
if (contains(set2, val)) {
|
||||
merged = append(merged, val)
|
||||
}
|
||||
}
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
func isMapSingleValue(myMap map[string][]string) bool {
|
||||
for _, v := range myMap {
|
||||
if len(v) > 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func main() {
|
||||
content, err := os.ReadFile("./input.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_lines := strings.Split(string(content), "\n")
|
||||
lines := _lines[:len(_lines) - 1]
|
||||
|
||||
myMap := make(map[string][]string)
|
||||
|
||||
totalIngredients := make([]string, 0)
|
||||
|
||||
for _, line := range lines {
|
||||
split := strings.Split(line, " (contains ")
|
||||
if (len(split) == 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
ingredients := strings.Split(split[0], " ")
|
||||
for _, i := range ingredients {
|
||||
totalIngredients = append(totalIngredients, i)
|
||||
}
|
||||
|
||||
formatted := strings.Split(strings.TrimSuffix(split[1], ")"), ", ")
|
||||
for _, v := range formatted {
|
||||
val, exists := myMap[v]
|
||||
if !exists {
|
||||
myMap[v] = ingredients
|
||||
continue
|
||||
}
|
||||
|
||||
newSets := mergeSets(val, ingredients)
|
||||
myMap[v] = newSets
|
||||
|
||||
if (len(newSets) == 1) {
|
||||
found := newSets[0]
|
||||
for key, mapVal := range myMap {
|
||||
if key == v {
|
||||
continue
|
||||
}
|
||||
if (contains(mapVal, found)) {
|
||||
myMap[key] = remove(mapVal, found)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for !isMapSingleValue(myMap) {
|
||||
for firstK, v := range myMap {
|
||||
if len(v) == 1 {
|
||||
for k, i := range myMap {
|
||||
if k == firstK {
|
||||
continue
|
||||
}
|
||||
myMap[k] = remove(i, v[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allMapValues := make([]string, 0)
|
||||
for _, v := range myMap {
|
||||
for _, j := range v {
|
||||
if (!contains(allMapValues, j)) {
|
||||
allMapValues = append(allMapValues, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%+v\n", myMap)
|
||||
|
||||
for _, v := range allMapValues {
|
||||
totalIngredients = remove(totalIngredients, v)
|
||||
}
|
||||
|
||||
myIngredientList := make([]string, 0)
|
||||
for k := range myMap {
|
||||
myIngredientList = append(myIngredientList, k)
|
||||
}
|
||||
slices.Sort(myIngredientList)
|
||||
|
||||
part2 := ""
|
||||
for _, v := range myIngredientList {
|
||||
part2 += myMap[v][0] + ","
|
||||
}
|
||||
part2 = strings.TrimSuffix(part2, ",")
|
||||
|
||||
fmt.Println(len(totalIngredients))
|
||||
fmt.Println(part2)
|
||||
}
|
189
AdventOfCode2020/day22/day22.go
Normal file
189
AdventOfCode2020/day22/day22.go
Normal file
@ -0,0 +1,189 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Queue struct {
|
||||
arr []int
|
||||
head uint
|
||||
tail uint
|
||||
}
|
||||
|
||||
func (s *Queue) Dequeue() int {
|
||||
s.head++
|
||||
return s.arr[s.head - 1]
|
||||
}
|
||||
|
||||
func (s *Queue) Enqueue(num int) {
|
||||
if len(s.arr) <= int(s.tail) {
|
||||
s.arr = append(s.arr, num)
|
||||
} else {
|
||||
s.arr[s.tail] = num
|
||||
}
|
||||
s.tail++
|
||||
}
|
||||
|
||||
func (s *Queue) Print() string {
|
||||
str := ""
|
||||
for i := s.head; i < s.tail; i++ {
|
||||
str += strconv.Itoa(s.arr[i]) + ","
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func main() {
|
||||
content, err := os.ReadFile("./input.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
players := strings.Split(string(content), "\n\n")
|
||||
|
||||
player1 := strings.Split(players[0], "\n")[1:]
|
||||
player2 := strings.Split(players[1], "\n")[1:]
|
||||
|
||||
player1Cards := Queue{
|
||||
arr: make([]int, 0),
|
||||
head: 0,
|
||||
tail: 0,
|
||||
}
|
||||
player2Cards := Queue{
|
||||
arr: make([]int, 0),
|
||||
head: 0,
|
||||
tail: 0,
|
||||
}
|
||||
|
||||
for _, v := range player1 {
|
||||
n, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
player1Cards.Enqueue(n)
|
||||
}
|
||||
|
||||
for _, v := range player2 {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
n, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
player2Cards.Enqueue(n)
|
||||
}
|
||||
|
||||
/*
|
||||
rounds := 0
|
||||
for {
|
||||
if player1Cards.head == player1Cards.tail || player2Cards.head == player2Cards.tail {
|
||||
break
|
||||
}
|
||||
|
||||
player1Card := player1Cards.Dequeue()
|
||||
player2Card := player2Cards.Dequeue()
|
||||
if player1Card > player2Card {
|
||||
player1Cards.Enqueue(player1Card)
|
||||
player1Cards.Enqueue(player2Card)
|
||||
} else {
|
||||
player2Cards.Enqueue(player2Card)
|
||||
player2Cards.Enqueue(player1Card)
|
||||
}
|
||||
|
||||
rounds++
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
_, p1, p2 := PlayGame(player1Cards, player2Cards)
|
||||
|
||||
var winningScore uint = 0
|
||||
if p1.tail - p1.head < p2.tail - p2.head {
|
||||
for i := p2.head; i < p2.tail; i++ {
|
||||
winningScore += (p2.tail - i) * uint(p2.arr[i])
|
||||
}
|
||||
} else {
|
||||
for i := p1.head; i < p1.tail; i++ {
|
||||
winningScore += (p1.tail - i) * uint(p1.arr[i])
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(winningScore)
|
||||
}
|
||||
|
||||
// true = player1, false = player2
|
||||
func PlayGame(player1 Queue, player2 Queue) (bool, *Queue, *Queue) {
|
||||
cache1 := make(map[string]bool)
|
||||
cache2 := make(map[string]bool)
|
||||
for {
|
||||
if player1.head == player1.tail || player2.head == player2.tail {
|
||||
return player2.head == player2.tail, &player1, &player2
|
||||
}
|
||||
|
||||
// Before drawing, check.
|
||||
player1string := player1.Print()
|
||||
player2string := player2.Print()
|
||||
|
||||
_, exists := cache1[player1string]
|
||||
if exists {
|
||||
return true, &player1, &player2
|
||||
}
|
||||
|
||||
_, exists = cache2[player2string]
|
||||
if exists {
|
||||
return true, &player1, &player2
|
||||
}
|
||||
|
||||
cache1[player1string] = true
|
||||
cache2[player2string] = true
|
||||
|
||||
|
||||
player1Card := player1.Dequeue()
|
||||
player2Card := player2.Dequeue()
|
||||
|
||||
if int(player1.tail) - int(player1.head) >= player1Card && int(player2.tail) - int(player2.head) >= player2Card {
|
||||
// Recursive case!
|
||||
player1Copy := Queue{
|
||||
arr: slices.Clone(player1.arr),
|
||||
head: player1.head,
|
||||
tail: player1.head + uint(player1Card),
|
||||
}
|
||||
|
||||
player2Copy := Queue{
|
||||
arr: slices.Clone(player2.arr),
|
||||
head: player2.head,
|
||||
tail: player2.head + uint(player2Card),
|
||||
}
|
||||
|
||||
winner, _, _ := PlayGame(player1Copy, player2Copy)
|
||||
if winner {
|
||||
player1.Enqueue(player1Card)
|
||||
player1.Enqueue(player2Card)
|
||||
} else {
|
||||
player2.Enqueue(player2Card)
|
||||
player2.Enqueue(player1Card)
|
||||
}
|
||||
} else {
|
||||
if player1Card > player2Card {
|
||||
player1.Enqueue(player1Card)
|
||||
player1.Enqueue(player2Card)
|
||||
} else {
|
||||
player2.Enqueue(player2Card)
|
||||
player2.Enqueue(player1Card)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetString(arr []int) string {
|
||||
s := ""
|
||||
for _, v := range arr {
|
||||
s += "," + strconv.Itoa(v)
|
||||
}
|
||||
return s
|
||||
}
|
75
AdventOfCode2020/day23/LinkedList.go
Normal file
75
AdventOfCode2020/day23/LinkedList.go
Normal file
@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type CustomLinkedList struct {
|
||||
head *CustomListNode
|
||||
length int64
|
||||
}
|
||||
|
||||
type CustomListNode struct {
|
||||
payload int64
|
||||
next *CustomListNode
|
||||
}
|
||||
|
||||
func (l *CustomLinkedList) prepend(n *CustomListNode) {
|
||||
second := l.head
|
||||
l.head = n
|
||||
l.head.next = second
|
||||
l.length++
|
||||
}
|
||||
|
||||
func (l *CustomLinkedList) append(n *CustomListNode) {
|
||||
|
||||
if l.head == nil {
|
||||
l.head = n
|
||||
} else {
|
||||
node := l.head
|
||||
for node.next != nil {
|
||||
node = node.next
|
||||
}
|
||||
node.next = n
|
||||
}
|
||||
l.length++
|
||||
}
|
||||
|
||||
func (l *CustomLinkedList) appendNextTo(n *CustomListNode, pointer *CustomListNode) {
|
||||
node := l.head
|
||||
for node != nil {
|
||||
if node == pointer {
|
||||
next := node.next
|
||||
node.next = n
|
||||
n.next = next
|
||||
l.length++
|
||||
break
|
||||
}
|
||||
node = node.next
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
linkedList := CustomLinkedList{}
|
||||
linkedList.append(&CustomListNode{payload: 10})
|
||||
|
||||
node1 := &CustomListNode{payload: 1}
|
||||
node2 := &CustomListNode{payload: 2}
|
||||
node3 := &CustomListNode{payload: 3}
|
||||
|
||||
linkedList.append(node1)
|
||||
linkedList.append(node2)
|
||||
linkedList.append(node3)
|
||||
|
||||
linkedList.appendNextTo(&CustomListNode{payload: 69}, node2)
|
||||
|
||||
node := linkedList.head
|
||||
for node != nil {
|
||||
fmt.Println(node.payload)
|
||||
node = node.next
|
||||
}
|
||||
|
||||
fmt.Println("Length: ", linkedList.length)
|
||||
|
||||
}
|
0
AdventOfCode2020/day23/day23.go
Normal file
0
AdventOfCode2020/day23/day23.go
Normal file
3
AdventOfCode2020/day23/go.mod
Normal file
3
AdventOfCode2020/day23/go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module main
|
||||
|
||||
go 1.16
|
178
AdventOfCode2020/day24/day24.go
Normal file
178
AdventOfCode2020/day24/day24.go
Normal file
@ -0,0 +1,178 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Hex struct {
|
||||
q int
|
||||
r int
|
||||
s int
|
||||
}
|
||||
|
||||
func CreateHex(q int, r int, s int) Hex {
|
||||
return Hex{
|
||||
q: q,
|
||||
r: r,
|
||||
s: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hex) Print() string {
|
||||
return strconv.Itoa(h.q) + "," + strconv.Itoa(h.r) + "," + strconv.Itoa(h.s)
|
||||
}
|
||||
|
||||
func Count(arr []string, search string) int {
|
||||
counter := 0
|
||||
for i := 0; i < len(arr); i++ {
|
||||
if arr[i] == search {
|
||||
counter++
|
||||
}
|
||||
}
|
||||
return counter
|
||||
}
|
||||
|
||||
func AdjustValues(hexMap map[string]bool, key string, white *int, black *int) {
|
||||
v, exists := hexMap[key]
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
|
||||
if v {
|
||||
*white++
|
||||
} else {
|
||||
*black++
|
||||
}
|
||||
}
|
||||
|
||||
func AddIfMissing(hexMap map[string]bool, hex string) {
|
||||
_, exists := hexMap[hex]
|
||||
if !exists {
|
||||
hexMap[hex] = true
|
||||
}
|
||||
}
|
||||
|
||||
func AddAdjacents(hexMap map[string]bool, hex string) {
|
||||
split := strings.Split(hex, ",")
|
||||
q, _ := strconv.Atoi(split[0])
|
||||
r, _ := strconv.Atoi(split[1])
|
||||
s, _ := strconv.Atoi(split[2])
|
||||
|
||||
nw := strconv.Itoa(q) + "," + strconv.Itoa(r - 1) + "," + strconv.Itoa(s + 1)
|
||||
w := strconv.Itoa(q - 1) + "," + strconv.Itoa(r) + "," + strconv.Itoa(s + 1)
|
||||
sw := strconv.Itoa(q - 1) + "," + strconv.Itoa(r + 1) + "," + strconv.Itoa(s)
|
||||
se := strconv.Itoa(q) + "," + strconv.Itoa(r + 1) + "," + strconv.Itoa(s - 1)
|
||||
e := strconv.Itoa(q + 1) + "," + strconv.Itoa(r) + "," + strconv.Itoa(s - 1)
|
||||
ne := strconv.Itoa(q + 1) + "," + strconv.Itoa(r - 1) + "," + strconv.Itoa(s)
|
||||
|
||||
AddIfMissing(hexMap, nw)
|
||||
AddIfMissing(hexMap, w)
|
||||
AddIfMissing(hexMap, sw)
|
||||
AddIfMissing(hexMap, se)
|
||||
AddIfMissing(hexMap, e)
|
||||
AddIfMissing(hexMap, ne)
|
||||
}
|
||||
|
||||
func CountAdjacent(hexMap map[string]bool, hex string) (int, int) {
|
||||
white := 0
|
||||
black := 0
|
||||
|
||||
split := strings.Split(hex, ",")
|
||||
q, _ := strconv.Atoi(split[0])
|
||||
r, _ := strconv.Atoi(split[1])
|
||||
s, _ := strconv.Atoi(split[2])
|
||||
|
||||
nw := strconv.Itoa(q) + "," + strconv.Itoa(r - 1) + "," + strconv.Itoa(s + 1)
|
||||
w := strconv.Itoa(q - 1) + "," + strconv.Itoa(r) + "," + strconv.Itoa(s + 1)
|
||||
sw := strconv.Itoa(q - 1) + "," + strconv.Itoa(r + 1) + "," + strconv.Itoa(s)
|
||||
se := strconv.Itoa(q) + "," + strconv.Itoa(r + 1) + "," + strconv.Itoa(s - 1)
|
||||
e := strconv.Itoa(q + 1) + "," + strconv.Itoa(r) + "," + strconv.Itoa(s - 1)
|
||||
ne := strconv.Itoa(q + 1) + "," + strconv.Itoa(r - 1) + "," + strconv.Itoa(s)
|
||||
|
||||
AdjustValues(hexMap, nw, &white, &black)
|
||||
AdjustValues(hexMap, w, &white, &black)
|
||||
AdjustValues(hexMap, sw, &white, &black)
|
||||
AdjustValues(hexMap, se, &white, &black)
|
||||
AdjustValues(hexMap, e, &white, &black)
|
||||
AdjustValues(hexMap, ne, &white, &black)
|
||||
|
||||
return white, black
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("Day 24 Part 1")
|
||||
|
||||
file, err := os.ReadFile("input.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_content := strings.Split(string(file), "\n")
|
||||
content := _content[:len(_content) - 1]
|
||||
|
||||
directionRegex := regexp.MustCompile("e|se|sw|w|nw|ne")
|
||||
|
||||
// true = white, false = black
|
||||
cache := make(map[string]bool)
|
||||
|
||||
for _, line := range content {
|
||||
matches := directionRegex.FindAllString(line, -1)
|
||||
|
||||
nw := Count(matches, "nw")
|
||||
w := Count(matches, "w")
|
||||
sw := Count(matches, "sw")
|
||||
se := Count(matches, "se")
|
||||
e := Count(matches, "e")
|
||||
ne := Count(matches, "ne")
|
||||
|
||||
hex := CreateHex(ne + e - sw - w, se + sw - ne - nw, w + nw - se - e)
|
||||
|
||||
white, exists := cache[hex.Print()]
|
||||
if !exists {
|
||||
cache[hex.Print()] = false
|
||||
} else {
|
||||
cache[hex.Print()] = !white
|
||||
}
|
||||
}
|
||||
|
||||
blackTiles := 0
|
||||
for _, white := range cache {
|
||||
if !white {
|
||||
blackTiles++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Part 1: %d\n", blackTiles)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
|
||||
toFlip := make([]string, 0)
|
||||
for k := range cache {
|
||||
AddAdjacents(cache, k)
|
||||
}
|
||||
|
||||
for k, isWhite := range cache {
|
||||
_, black := CountAdjacent(cache, k)
|
||||
if isWhite && black == 2 {
|
||||
toFlip = append(toFlip, k)
|
||||
} else if !isWhite && (black == 0 || black > 2) {
|
||||
toFlip = append(toFlip, k)
|
||||
}
|
||||
}
|
||||
|
||||
for _, k := range toFlip {
|
||||
cache[k] = !cache[k]
|
||||
}
|
||||
|
||||
myTiles := 0
|
||||
for _, white := range cache {
|
||||
if !white {
|
||||
myTiles++
|
||||
}
|
||||
}
|
||||
fmt.Println(i, myTiles)
|
||||
}
|
||||
}
|
40
AdventOfCode2020/day25/day25.go
Normal file
40
AdventOfCode2020/day25/day25.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var dividerr int64 = 20201227
|
||||
// var cardPKey int64 = 5764801
|
||||
// var doorPKey int64 = 17807724
|
||||
|
||||
var cardPKey int64 = 16915772
|
||||
var doorPKey int64 = 18447943
|
||||
|
||||
var cardValue int64 = 1
|
||||
var cardLoopSize int64 = 0
|
||||
|
||||
for cardValue != cardPKey {
|
||||
cardValue *= 7 // Subject number
|
||||
cardValue = cardValue % dividerr
|
||||
cardLoopSize++
|
||||
}
|
||||
|
||||
var doorValue int64 = 1
|
||||
var doorLoopSize int64 = 0
|
||||
|
||||
for doorValue != doorPKey {
|
||||
doorValue *= 7 // Subject number
|
||||
doorValue = doorValue % dividerr
|
||||
doorLoopSize++
|
||||
}
|
||||
|
||||
var part1 int64 = 1
|
||||
var i int64 = 0
|
||||
|
||||
for i = 0; i < cardLoopSize; i++ {
|
||||
part1 *= doorPKey
|
||||
part1 = part1 % dividerr
|
||||
}
|
||||
|
||||
fmt.Printf("Part 1: %d %d %d\n", cardLoopSize, doorLoopSize, part1)
|
||||
}
|
BIN
AdventOfCode2020/day3/day3.class
Normal file
BIN
AdventOfCode2020/day3/day3.class
Normal file
Binary file not shown.
70
AdventOfCode2020/day3/day3.java
Normal file
70
AdventOfCode2020/day3/day3.java
Normal file
@ -0,0 +1,70 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
class day3 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
Scanner in = new Scanner(myFile);
|
||||
|
||||
String[] trees = new String[323];
|
||||
|
||||
int lineLength;
|
||||
|
||||
long multiple = 1;
|
||||
int numOfTrees = 0;
|
||||
|
||||
int x = 0;
|
||||
|
||||
for (int i = 0; i < 323; i++) {
|
||||
trees[i] = in.nextLine();
|
||||
}
|
||||
|
||||
lineLength = trees[0].length();
|
||||
|
||||
/*Part 1 code
|
||||
for (String line : trees) {
|
||||
|
||||
char current = line.charAt(x % lineLength);
|
||||
|
||||
if (current == '#') numOfTrees++;
|
||||
x = x + 3;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
for (int dy = 1; dy < 3; dy++) {
|
||||
for (int dx = 1; dx < 8; dx = dx + 2) {
|
||||
|
||||
if (!(dy == 2 && dx > 1)) {
|
||||
numOfTrees = 0;
|
||||
x = 0;
|
||||
for (int i = 0; i < 323; i = i + dy) {
|
||||
char current = trees[i].charAt(x % lineLength);
|
||||
|
||||
if (current == '#') numOfTrees++;
|
||||
x = x + dx;
|
||||
|
||||
}
|
||||
System.out.println(numOfTrees);
|
||||
multiple *= numOfTrees;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
System.out.println(multiple);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
BIN
AdventOfCode2020/day4/day4.class
Normal file
BIN
AdventOfCode2020/day4/day4.class
Normal file
Binary file not shown.
133
AdventOfCode2020/day4/day4.java
Normal file
133
AdventOfCode2020/day4/day4.java
Normal file
@ -0,0 +1,133 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
class day4 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
Scanner in = new Scanner(myFile);
|
||||
|
||||
ArrayList<String> passports = new ArrayList<String>();
|
||||
String line = "";
|
||||
String input = "";
|
||||
|
||||
while (in.hasNext()) {
|
||||
input = "";
|
||||
input = in.nextLine();
|
||||
if (input.length() == 0) {
|
||||
passports.add(line);
|
||||
line = "";
|
||||
} else {
|
||||
line += input;
|
||||
}
|
||||
}
|
||||
|
||||
passports.add(input);
|
||||
|
||||
int valid = 0;
|
||||
|
||||
for (String current : passports) {
|
||||
|
||||
String currentNoSpace = current.replaceAll("\\s","");
|
||||
|
||||
String[] fields = currentNoSpace.split(":");
|
||||
int counter = 0;
|
||||
|
||||
String currentField = "";
|
||||
|
||||
for (int i = 0; i < fields.length - 1; i++) {
|
||||
|
||||
currentField = fields[i].substring(fields[i].length() - 3);
|
||||
|
||||
System.out.println("Next value: " + fields[i + 1]);
|
||||
String value = "";
|
||||
try {
|
||||
value = fields[i + 1].substring(0, fields[i + 1].length() - 3);
|
||||
} catch (Exception e) {
|
||||
value = "";
|
||||
}
|
||||
if (i == fields.length - 2) {
|
||||
value = fields[i + 1];
|
||||
}
|
||||
|
||||
System.out.println(currentField);
|
||||
System.out.println(value);
|
||||
|
||||
if (currentField.equals("hcl")) {
|
||||
|
||||
String HEX_PATTERN = "^#([A-Fa-f0-9]{6})$";
|
||||
if(value.matches(HEX_PATTERN)) counter++;
|
||||
|
||||
} else if (currentField.equals("pid")) {
|
||||
|
||||
String DIGITS_PATTERN = "\\d+";
|
||||
if (value.matches(DIGITS_PATTERN) && value.length() == 9) counter++;
|
||||
|
||||
} else if (currentField.equals("ecl")) {
|
||||
|
||||
if (value.equals("amb") || value.equals("blu") || value.equals("brn") || value.equals("gry")
|
||||
|| value.equals("grn") || value.equals("hzl") || value.equals("oth")) counter++;
|
||||
|
||||
} else if (currentField.equals("eyr")) {
|
||||
|
||||
String DIGITS_PATTERN = "\\d+";
|
||||
if (value.matches(DIGITS_PATTERN)) {
|
||||
int year = Integer.parseInt(value);
|
||||
if (year >= 2020 && year <= 2030) counter++;
|
||||
}
|
||||
|
||||
} else if (currentField.equals("hgt")) {
|
||||
|
||||
String DIGITS_PATTERN = "\\d+";
|
||||
if (value.substring(0, value.length() - 2).matches(DIGITS_PATTERN)) {
|
||||
if (value.substring(value.length() - 2, value.length()).equals("in")) {
|
||||
|
||||
int num = Integer.parseInt(value.substring(0, value.length() - 2));
|
||||
if (num >= 59 && num <= 76) counter++;
|
||||
|
||||
} else if (value.substring(value.length() - 2, value.length()).equals("cm")) {
|
||||
int num = Integer.parseInt(value.substring(0, value.length() - 2));
|
||||
if (num >= 150 && num <= 193) counter++;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (currentField.equals("byr")) {
|
||||
|
||||
String DIGITS_PATTERN = "\\d+";
|
||||
if (value.matches(DIGITS_PATTERN)) {
|
||||
int year = Integer.parseInt(value);
|
||||
if (year >= 1920 && year <= 2002) counter++;
|
||||
}
|
||||
|
||||
} else if (currentField.equals("iyr")) {
|
||||
|
||||
String DIGITS_PATTERN = "\\d+";
|
||||
if (value.matches(DIGITS_PATTERN)) {
|
||||
int year = Integer.parseInt(value);
|
||||
if (year >= 2010 && year <= 2020) counter++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (counter == 7) valid++;
|
||||
counter = 0;
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Valid: " + valid);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
BIN
AdventOfCode2020/day5/day5.class
Normal file
BIN
AdventOfCode2020/day5/day5.class
Normal file
Binary file not shown.
63
AdventOfCode2020/day5/day5.java
Normal file
63
AdventOfCode2020/day5/day5.java
Normal file
@ -0,0 +1,63 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
class day5 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File inputs = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(inputs);
|
||||
String[] input = new String[884];
|
||||
|
||||
for (int i = 0; i < 884; i++) input[i] = in.nextLine();
|
||||
|
||||
int highest = 0;
|
||||
int lowest = 99999999;
|
||||
|
||||
ArrayList<Integer> seatIDs = new ArrayList<Integer>();
|
||||
|
||||
for (String line : input) {
|
||||
|
||||
int row = binaryConvertion(line.substring(0, line.length() - 3), 'B');
|
||||
int collumn = binaryConvertion(line.substring(line.length() - 3), 'R');
|
||||
|
||||
int calculation = row * 8 + collumn;
|
||||
if (calculation > highest) highest = calculation;
|
||||
else if (calculation < lowest) lowest = calculation;
|
||||
|
||||
seatIDs.add(calculation);
|
||||
|
||||
}
|
||||
|
||||
for (int i = lowest; i <= highest; i++) {
|
||||
|
||||
if (seatIDs.contains(i) == false) {
|
||||
System.out.println(i);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static int binaryConvertion(String givenInputs, char one) {
|
||||
int counter = 0;
|
||||
for (int i = givenInputs.length() - 1; i >= 0; i--) {
|
||||
if (givenInputs.charAt(i) == one) {
|
||||
counter += Math.pow(2, givenInputs.length() - i - 1);
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day6/day6.class
Normal file
BIN
AdventOfCode2020/day6/day6.class
Normal file
Binary file not shown.
64
AdventOfCode2020/day6/day6.java
Normal file
64
AdventOfCode2020/day6/day6.java
Normal file
@ -0,0 +1,64 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
class day6 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
ArrayList<String> inputs = new ArrayList<String>();
|
||||
String line = "";
|
||||
String input = "";
|
||||
|
||||
while (in.hasNext()) {
|
||||
input = "";
|
||||
input = in.nextLine();
|
||||
if (input.length() == 0) {
|
||||
inputs.add(line.substring(0, line.length() - 1));
|
||||
line = "";
|
||||
} else {
|
||||
line += input + ",";
|
||||
}
|
||||
}
|
||||
|
||||
inputs.add(line.substring(0, line.length() - 1));
|
||||
int sum = 0;
|
||||
|
||||
for (String current : inputs) {
|
||||
|
||||
HashMap<Character, Integer> map = new HashMap<>();
|
||||
String[] currentSplit = current.split(",");
|
||||
|
||||
for (String single : currentSplit) {
|
||||
for (char c : single.toCharArray()) {
|
||||
|
||||
if (map.get(c) == null) {
|
||||
map.put(c, 1);
|
||||
} else {
|
||||
map.put(c, map.get(c) + 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (char c : map.keySet()) {
|
||||
if (map.get(c) == currentSplit.length) sum++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
System.out.printf("Total sum %d", sum);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day7/BagInfo.class
Normal file
BIN
AdventOfCode2020/day7/BagInfo.class
Normal file
Binary file not shown.
BIN
AdventOfCode2020/day7/day7.class
Normal file
BIN
AdventOfCode2020/day7/day7.class
Normal file
Binary file not shown.
117
AdventOfCode2020/day7/day7.java
Normal file
117
AdventOfCode2020/day7/day7.java
Normal file
@ -0,0 +1,117 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.HashMap;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class day7 {
|
||||
|
||||
public static HashMap<String, ArrayList<BagInfo>> map = new HashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
String[] inputs = new String[594];
|
||||
|
||||
for (int i = 0; i < 594; i++) {
|
||||
inputs[i] = in.nextLine();
|
||||
}
|
||||
|
||||
for (String bag : inputs) {
|
||||
|
||||
String[] bags = bag.split(" bags contain ");
|
||||
String outerBag = bags[0];
|
||||
String innerBag = bags[1];
|
||||
|
||||
innerBag = innerBag.replace("bags", "").replace("bag", "");
|
||||
innerBag = innerBag.substring(0, innerBag.length() - 2);
|
||||
|
||||
if (innerBag.equals("no other")) {
|
||||
map.put(outerBag, new ArrayList<BagInfo>());
|
||||
} else {
|
||||
|
||||
String[] Innerbags = innerBag.split(" , ");
|
||||
ArrayList<BagInfo> innerBagList = new ArrayList<>();
|
||||
|
||||
for (String innerbag : Innerbags) {
|
||||
BagInfo current = new BagInfo();
|
||||
current.quantity = Integer.parseInt(innerbag.substring(0, 1));
|
||||
current.bag = innerbag.substring(2);
|
||||
|
||||
innerBagList.add(current);
|
||||
}
|
||||
map.put(outerBag, innerBagList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int sum = 0;
|
||||
//Part 1 solution
|
||||
/*for (String bag : map.keySet()) {
|
||||
if (isBagInside(bag, "shiny gold")) {
|
||||
sum++;
|
||||
};
|
||||
}*/
|
||||
|
||||
//Part 2 solution
|
||||
|
||||
//System.out.println(map);
|
||||
|
||||
System.out.println(howManyBags("shiny gold") - 1);
|
||||
//System.out.println(sum);
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static int howManyBags(String bagName) {
|
||||
|
||||
ArrayList<BagInfo> innerBags = map.get(bagName);
|
||||
if (innerBags.size() == 0)
|
||||
return 1;
|
||||
|
||||
int total = 1;
|
||||
for (BagInfo innerbag : innerBags) {
|
||||
total += (innerbag.quantity * howManyBags(innerbag.bag));
|
||||
}
|
||||
|
||||
return total;
|
||||
|
||||
}
|
||||
|
||||
public static boolean isBagInside(String bagName, String searchBag) {
|
||||
|
||||
ArrayList<BagInfo> innerBags = map.get(bagName);
|
||||
|
||||
if (innerBags.size() != 0) {
|
||||
|
||||
for (BagInfo innerbag : innerBags) {
|
||||
if (innerbag.bag.equals(searchBag)) return true;
|
||||
}
|
||||
|
||||
for (BagInfo innerbag : innerBags) {
|
||||
//Don't return to early, my god this took me ages.
|
||||
boolean idkwhattocallthis = isBagInside(innerbag.bag, searchBag);
|
||||
if (idkwhattocallthis) return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BagInfo {
|
||||
public int quantity;
|
||||
public String bag;
|
||||
public String toString() {
|
||||
return "Quantity: " + quantity + " | BagName: " + bag;
|
||||
}
|
||||
}
|
BIN
AdventOfCode2020/day8/Instruction.class
Normal file
BIN
AdventOfCode2020/day8/Instruction.class
Normal file
Binary file not shown.
BIN
AdventOfCode2020/day8/day8.class
Normal file
BIN
AdventOfCode2020/day8/day8.class
Normal file
Binary file not shown.
109
AdventOfCode2020/day8/day8.java
Normal file
109
AdventOfCode2020/day8/day8.java
Normal file
@ -0,0 +1,109 @@
|
||||
import java.util.Scanner;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class day8 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
ArrayList<Instruction> instructions = new ArrayList<>();
|
||||
|
||||
while (in.hasNext()) {
|
||||
String[] split = in.nextLine().split(" ");
|
||||
Instruction current = new Instruction(split[0], Integer.parseInt(split[1]), false);
|
||||
instructions.add(current);
|
||||
}
|
||||
|
||||
boolean done = false;
|
||||
int currentChangingInstruction = 0;
|
||||
ArrayList<Integer> checked = new ArrayList<>();
|
||||
|
||||
while (!done) {
|
||||
|
||||
while (instructions.get(currentChangingInstruction).instruction.equals("acc") || checked.contains(currentChangingInstruction)) {
|
||||
|
||||
currentChangingInstruction++;
|
||||
|
||||
}
|
||||
|
||||
checked.add(currentChangingInstruction);
|
||||
Instruction currentChange = instructions.get(currentChangingInstruction);
|
||||
|
||||
if (currentChange.instruction.equals("jmp")) currentChange.instruction = "nop";
|
||||
else currentChange.instruction = "jmp";
|
||||
instructions.set(currentChangingInstruction, currentChange);
|
||||
|
||||
for (Instruction i : instructions) System.out.println(i);
|
||||
|
||||
int acc = 0;
|
||||
int instructionIndex = 0;
|
||||
Instruction currentInstruction = instructions.get(instructionIndex);
|
||||
|
||||
while (currentInstruction.ran == false && done == false) {
|
||||
instructions.set(instructionIndex, new Instruction(currentInstruction.instruction, currentInstruction.arg, true));
|
||||
|
||||
if (currentInstruction.instruction.equals("acc")) {
|
||||
acc += currentInstruction.arg;
|
||||
instructionIndex++;
|
||||
} else if (currentInstruction.instruction.equals("jmp")) {
|
||||
|
||||
if (currentInstruction.arg + instructionIndex >= 0 && currentInstruction.arg + instructionIndex <= instructions.size()) {
|
||||
instructionIndex += currentInstruction.arg;
|
||||
} else {
|
||||
instructionIndex = instructions.size() % currentInstruction.arg;
|
||||
}
|
||||
|
||||
} else {
|
||||
instructionIndex++;
|
||||
}
|
||||
|
||||
if (instructionIndex == instructions.size()) {
|
||||
done = true;
|
||||
System.out.println("Acc: " + acc);
|
||||
} else {
|
||||
currentInstruction = instructions.get(instructionIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (currentChange.instruction.equals("jmp")) currentChange.instruction = "nop";
|
||||
else currentChange.instruction = "jmp";
|
||||
instructions.set(currentChangingInstruction, currentChange);
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
Instruction changeRan = instructions.get(i);
|
||||
changeRan.ran = false;
|
||||
instructions.set(i, changeRan);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Instruction {
|
||||
public String instruction;
|
||||
public int arg;
|
||||
public boolean ran;
|
||||
|
||||
public Instruction(String instruction, int arg, boolean ran) {
|
||||
this.instruction = instruction;
|
||||
this.arg = arg;
|
||||
this.ran = ran;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Instruction : " + this.instruction + " | Arg: " + this.arg + " | Ran: " + this.ran;
|
||||
}
|
||||
|
||||
}
|
BIN
AdventOfCode2020/day9/day8.class
Normal file
BIN
AdventOfCode2020/day9/day8.class
Normal file
Binary file not shown.
BIN
AdventOfCode2020/day9/day9.class
Normal file
BIN
AdventOfCode2020/day9/day9.class
Normal file
Binary file not shown.
101
AdventOfCode2020/day9/day9.java
Normal file
101
AdventOfCode2020/day9/day9.java
Normal file
@ -0,0 +1,101 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class day9 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File myFile = new File("input.txt");
|
||||
try {
|
||||
|
||||
Scanner in = new Scanner(myFile);
|
||||
ArrayList<Long> nums = new ArrayList<>();
|
||||
|
||||
while (in.hasNext()) {
|
||||
nums.add(Long.parseLong(in.nextLine()));
|
||||
}
|
||||
|
||||
//final int preamble = 25;
|
||||
//int lower = 0;
|
||||
|
||||
long target = 1309761972;
|
||||
|
||||
for (int i = 0; i < nums.size() - 1; i++) {
|
||||
|
||||
boolean over = false;
|
||||
long sum = 0;
|
||||
|
||||
|
||||
ArrayList<Long> currentSet = new ArrayList<>();
|
||||
|
||||
for (int j = i; j < nums.size() && over == false; j++) {
|
||||
|
||||
sum += nums.get(j);
|
||||
currentSet.add(nums.get(j));
|
||||
|
||||
if (sum == target) {
|
||||
|
||||
long highest = 0;
|
||||
long lowest = Long.MAX_VALUE;
|
||||
|
||||
for (int k = 0; k < currentSet.size(); k++) {
|
||||
long current = currentSet.get(k);
|
||||
if (current < lowest) lowest = current;
|
||||
if (current > highest) highest = current;
|
||||
}
|
||||
|
||||
over = true;
|
||||
|
||||
System.out.println("Lowest: " + lowest);
|
||||
System.out.println("highest: " + highest);
|
||||
|
||||
System.out.println(highest + lowest);
|
||||
break;
|
||||
|
||||
} else if (sum > target) {
|
||||
over = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Part 1, very inefficient code, had no time to do this one today
|
||||
//Made easier using a stack and an array to which the combination of numbers in the stack would add up to
|
||||
//Pop and remove from the stack and remove the last 25 items from array/list
|
||||
//And that would be the most efficient with an efficiency of O(n^2)? instead of O(n^3) - I think, not sure
|
||||
/*for (int currentNum = preamble; currentNum < nums.size(); currentNum++) {
|
||||
|
||||
boolean adds = false;
|
||||
|
||||
for (int i = currentNum - preamble; i < currentNum - 1; i++) {
|
||||
for (int j = i + 1; j < currentNum; j++) {
|
||||
|
||||
System.out.printf("Adding %d and %d, Current Num: %d \n", nums.get(i), nums.get(j), nums.get(currentNum));
|
||||
|
||||
if (nums.get(i) + nums.get(j) == nums.get(currentNum)) {
|
||||
adds = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(adds);
|
||||
|
||||
if (!adds) {
|
||||
System.out.println(nums.get(currentNum));
|
||||
break;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
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("---------------------------------------")
|
||||
}
|
3
AdventOfCode2022/README.md
Normal file
3
AdventOfCode2022/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Advent of Code 2022
|
||||
|
||||
This year I am sticking to Typescript, a language I use basically everyday. The only spicy thing I am doing this year is using Bun.js as a JavaScript runner, it has been making some headlines recently with its performance.
|
BIN
AdventOfCode2022/bun.lockb
Executable file
BIN
AdventOfCode2022/bun.lockb
Executable file
Binary file not shown.
6
AdventOfCode2022/nodemon.json
Normal file
6
AdventOfCode2022/nodemon.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"watch": ["src"],
|
||||
"ext": ".ts,.js",
|
||||
"ignore": [],
|
||||
"exec": "bun run start"
|
||||
}
|
16
AdventOfCode2022/package.json
Normal file
16
AdventOfCode2022/package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "AdventOfCode2022",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"start": "bun src/index.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bun-types": "^0.3.0",
|
||||
"nodemon": "^2.0.20"
|
||||
}
|
||||
}
|
18
AdventOfCode2022/src/days/Day1.ts
Normal file
18
AdventOfCode2022/src/days/Day1.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day1: DayFunc = (input) => {
|
||||
const elfFood: number[][] = input
|
||||
.split("\n\n")
|
||||
.map((i) => i.split("\n"))
|
||||
.map((i) => i.map((j) => parseInt(j)));
|
||||
|
||||
let highest = [0, 0, 0];
|
||||
elfFood.forEach((n) => {
|
||||
const h = n.reduce((prev, current) => (current += prev));
|
||||
const index = highest.findIndex(v => v < h);
|
||||
if (index !== -1) highest[index] = h;
|
||||
highest.sort();
|
||||
});
|
||||
|
||||
return [highest[0], highest.reduce((p, c) => c += p)];
|
||||
};
|
42
AdventOfCode2022/src/days/Day10.ts
Normal file
42
AdventOfCode2022/src/days/Day10.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day10: DayFunc = (input) => {
|
||||
const parsed = input.trim().split('\n').map(v => {
|
||||
const s = v.split(' ');
|
||||
if (s.length === 1) return [s[0]];
|
||||
return [s[0], parseInt(s[1])];
|
||||
});
|
||||
|
||||
let x = 1;
|
||||
let cycles: number[] = [x];
|
||||
|
||||
parsed.forEach(i => {
|
||||
if (i[0] === "noop") {
|
||||
cycles.push(x);
|
||||
} else {
|
||||
cycles.push(x);
|
||||
cycles.push(x);
|
||||
x += i[1] as number;
|
||||
}
|
||||
});
|
||||
|
||||
const part1 = cycles[20] * 20 + cycles[60] * 60 + cycles[100] * 100 + cycles[140] * 140 + cycles[180] * 180 + cycles[220] * 220;
|
||||
|
||||
let outStr = "";
|
||||
for (let i = 1; i < cycles.length; i++) {
|
||||
|
||||
if ((i - 1) % 40 === 0) {
|
||||
outStr += '\n';
|
||||
}
|
||||
|
||||
if (cycles[i] === (i - 1) % 40 || cycles[i] === (i - 2) % 40 || cycles[i] === i % 40) {
|
||||
outStr += '#';
|
||||
} else {
|
||||
outStr += '.';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
console.log(outStr);
|
||||
return [part1, 0];
|
||||
}
|
103
AdventOfCode2022/src/days/Day11.ts
Normal file
103
AdventOfCode2022/src/days/Day11.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
type MonkeyList = Record<
|
||||
number,
|
||||
{
|
||||
inspected: number;
|
||||
items: string[];
|
||||
operation: string;
|
||||
test: number;
|
||||
ifTrue: number;
|
||||
ifFalse: number;
|
||||
}
|
||||
>;
|
||||
|
||||
const Hcf = (a: number, b: number): number => {
|
||||
let larger = a > b ? a : b;
|
||||
let smaller = a > b ? b : a;
|
||||
|
||||
let r = -1;
|
||||
|
||||
while (true) {
|
||||
if (larger % smaller === 0) break;
|
||||
r = larger % smaller;
|
||||
larger = smaller;
|
||||
smaller = r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
export const Day11: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n\n")
|
||||
.map((v) => v.split("\n").map((i) => i.trim()));
|
||||
const list: MonkeyList = parsed.reduce((prev, next) => {
|
||||
const num = next[0].split(" ")[1].slice(0, -1);
|
||||
const items = next[1]
|
||||
.split(" ")
|
||||
.slice(2)
|
||||
.map((i) => i.replace(",", ""));
|
||||
const op = next[2].split("new = old ")[1];
|
||||
const test = parseInt(next[3].split(" ").pop());
|
||||
const ifTrue = parseInt(next[4].split(" ").pop());
|
||||
const ifFalse = parseInt(next[5].split(" ").pop());
|
||||
prev[num] = {
|
||||
items: items,
|
||||
operation: op,
|
||||
test: test,
|
||||
ifTrue: ifTrue,
|
||||
ifFalse: ifFalse,
|
||||
inspected: 0,
|
||||
};
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
const part1List: MonkeyList = JSON.parse(JSON.stringify(list));
|
||||
const part2List: MonkeyList = JSON.parse(JSON.stringify(list));
|
||||
|
||||
for (let round = 1; round <= 20; round++) {
|
||||
Object.values(part1List).forEach((v) => {
|
||||
v.items.forEach(old => {
|
||||
v.inspected++;
|
||||
let newVal = eval(`${old}${v.operation.replace('old', old.toString())}`);
|
||||
newVal = Math.floor(newVal / 3);
|
||||
if (newVal % v.test === 0) {
|
||||
part1List[v.ifTrue].items.push(newVal);
|
||||
} else {
|
||||
part1List[v.ifFalse].items.push(newVal);
|
||||
}
|
||||
});
|
||||
v.items = [];
|
||||
});
|
||||
}
|
||||
|
||||
const part1 = Object.values(part1List).map(v => v.inspected).sort((a, b) => b - a);
|
||||
const product = Object.values(part2List).reduce((p, v) => p * v.test, 1);
|
||||
|
||||
for (let round = 0; round < 10000; round++) {
|
||||
|
||||
Object.values(part2List).forEach((v) => {
|
||||
v.inspected += v.items.length;
|
||||
v.items.forEach(old => {
|
||||
let newVal = eval(`${old}${v.operation.replace('old', old.toString())}`);
|
||||
if (newVal > product) {
|
||||
newVal = newVal % product;
|
||||
}
|
||||
if (newVal % v.test === 0) {
|
||||
part2List[v.ifTrue].items.push(newVal);
|
||||
} else {
|
||||
part2List[v.ifFalse].items.push(newVal);
|
||||
}
|
||||
});
|
||||
v.items = [];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const part2 = Object.values(part2List).map(v => v.inspected).sort((a, b) => b - a);
|
||||
console.log(part2);
|
||||
|
||||
return [part1[0] * part1[1], part2[0] * part2[1]];
|
||||
};
|
132
AdventOfCode2022/src/days/Day12.ts
Normal file
132
AdventOfCode2022/src/days/Day12.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const FunnyCharCode = (input: string): number => {
|
||||
if (input === "S") return "a".charCodeAt(0);
|
||||
if (input === "E") return "z".charCodeAt(0);
|
||||
return input.charCodeAt(0);
|
||||
};
|
||||
|
||||
const IsOk = (
|
||||
input: string[][],
|
||||
edges: Record<string, string[]>,
|
||||
a: [number, number],
|
||||
b: [number, number]
|
||||
) => {
|
||||
if (!edges[`${a[0]},${a[1]}`]) {
|
||||
edges[`${a[0]},${a[1]}`] = [];
|
||||
}
|
||||
const c = edges[`${a[0]},${a[1]}`];
|
||||
if (FunnyCharCode(input[a[0]][a[1]]) - FunnyCharCode(input[b[0]][b[1]]) >= -1) {
|
||||
c.push(`${b[0]},${b[1]}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const Day12: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((i) => i.split(""));
|
||||
|
||||
const edges: Record<string, string[]> = {};
|
||||
const visited: { letter: string; node: string; visited: boolean }[] = [];
|
||||
|
||||
for (let i = 0; i < parsed.length; i++) {
|
||||
for (let j = 0; j < parsed[0].length; j++) {
|
||||
visited.push({
|
||||
letter: parsed[i][j],
|
||||
node: `${i},${j}`,
|
||||
visited: false,
|
||||
});
|
||||
if (i > 0 && j > 0 && i < parsed.length - 1 && j < parsed[0].length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (i > 0 && j > 0 && i < parsed.length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (i > 0 && j > 0 && j < parsed[0].length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (i === 0 && j > 0 && j < parsed[0].length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (j === 0 && i > 0 && i < parsed.length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IsOk(parsed, edges, [0, 0], [0, 1]);
|
||||
IsOk(parsed, edges, [0, 0], [1, 0]);
|
||||
|
||||
IsOk(
|
||||
parsed,
|
||||
edges,
|
||||
[parsed.length - 1, parsed[0].length - 1],
|
||||
[parsed.length - 1, parsed[0].length - 2]
|
||||
);
|
||||
IsOk(
|
||||
parsed,
|
||||
edges,
|
||||
[parsed.length - 1, parsed[0].length - 1],
|
||||
[parsed.length - 2, parsed[0].length - 1]
|
||||
);
|
||||
|
||||
IsOk(parsed, edges, [parsed.length - 1, 0], [parsed.length - 2, 0]);
|
||||
IsOk(parsed, edges, [parsed.length - 1, 0], [parsed.length - 1, 1]);
|
||||
|
||||
IsOk(parsed, edges, [0, parsed[0].length - 1], [0, parsed[0].length - 2]);
|
||||
IsOk(parsed, edges, [0, parsed[0].length - 1], [1, parsed[0].length - 1]);
|
||||
|
||||
const startNode = visited.find((v) => v.letter === "S");
|
||||
|
||||
const part1 = BFS(startNode.node, edges, visited);
|
||||
|
||||
const part2 = visited.filter(v => v.letter === 'a').map(n => BFS(n.node, edges, visited));
|
||||
|
||||
return [part1, Math.min(...part2)];
|
||||
};
|
||||
|
||||
const BFS = (
|
||||
currentNode: string,
|
||||
edges: Record<string, string[]>,
|
||||
visited: { letter: string; node: string; visited: boolean }[]
|
||||
): number => {
|
||||
const q: Array<{ letter: string; node: string; visited: boolean } | null> =
|
||||
[];
|
||||
|
||||
const marked = new Set();
|
||||
|
||||
const c = visited.find((v) => v.node === currentNode);
|
||||
q.push(c);
|
||||
|
||||
const depthQueue = [0];
|
||||
|
||||
marked.add(c.node);
|
||||
|
||||
while (q.length > 0) {
|
||||
const head = q.shift();
|
||||
const level = depthQueue.shift();
|
||||
|
||||
marked.add(head.node);
|
||||
|
||||
if (head.letter === "E") {
|
||||
return level;
|
||||
}
|
||||
|
||||
edges[head.node].filter(p => !marked.has(p)).forEach(v => {
|
||||
const n = visited.find(i => i.node === v);
|
||||
marked.add(n.node);
|
||||
q.push(n);
|
||||
depthQueue.push(level + 1);
|
||||
});
|
||||
}
|
||||
|
||||
return 10000000;
|
||||
};
|
56
AdventOfCode2022/src/days/Day13.ts
Normal file
56
AdventOfCode2022/src/days/Day13.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const Compare = (a: any, b: any): "left" | "right" | null => {
|
||||
if (typeof a === "number" && typeof b === "number") {
|
||||
if (a < b) {
|
||||
return "right";
|
||||
} else if (a > b) {
|
||||
return "left";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (typeof a === "object" && typeof b === "object") {
|
||||
if (a.length === 0 && b.length > 0) return "right";
|
||||
if (b.length === 0 && a.length > 0) return "left";
|
||||
if (a.length === 0 && b.length === 0) return null;
|
||||
const ans = Compare(a[0], b[0]);
|
||||
if (ans !== null) return ans;
|
||||
|
||||
a.shift();
|
||||
b.shift();
|
||||
return Compare(a, b);
|
||||
} else if (typeof a === "object") {
|
||||
return Compare(a, [b]);
|
||||
} else if (typeof b === "object") {
|
||||
return Compare([a], b);
|
||||
}
|
||||
};
|
||||
|
||||
export const Day13: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n\n")
|
||||
.map((v) => v.split("\n").map((w) => JSON.parse(w)));
|
||||
|
||||
const part2Parsed = input.trim().replaceAll('\n\n', '\n').split('\n').map(v => JSON.parse(v));
|
||||
part2Parsed.push([[2]]);
|
||||
part2Parsed.push([[6]]);
|
||||
|
||||
let part1 = 0;
|
||||
parsed.forEach(([a, b], i) => {
|
||||
const side = Compare(a, b);
|
||||
if (side === "right") {
|
||||
part1 += i + 1;
|
||||
}
|
||||
});
|
||||
|
||||
part2Parsed.sort((a, b) => {
|
||||
if (Compare(JSON.parse(JSON.stringify(a)), JSON.parse(JSON.stringify(b))) === "left") return 1
|
||||
return -1;
|
||||
});
|
||||
|
||||
const two = part2Parsed.findIndex(i => JSON.stringify(i) === JSON.stringify([[2]])) + 1;
|
||||
const six = part2Parsed.findIndex(i => JSON.stringify(i) === JSON.stringify([[6]])) + 1;
|
||||
|
||||
return [part1, two * six];
|
||||
};
|
178
AdventOfCode2022/src/days/Day14.ts
Normal file
178
AdventOfCode2022/src/days/Day14.ts
Normal file
@ -0,0 +1,178 @@
|
||||
import { DayFunc, UP } from "..";
|
||||
|
||||
const writer = Bun.stdout.writer();
|
||||
|
||||
const PrintGrid = async (g: string[][]) => {
|
||||
for (let i = 0; i < g.length; i++) {
|
||||
for (let j = 0; j < g[0].length; j++) {
|
||||
process.stdout.write(g[i][j]);
|
||||
}
|
||||
process.stdout.write('\n');
|
||||
}
|
||||
for (let i = 0; i < g.length; i++) {
|
||||
process.stdout.write(UP)
|
||||
}
|
||||
};
|
||||
|
||||
const EraseSand = ([x, y]: [number, number]) => {
|
||||
process.stdout.write(`\033[${y}B`);
|
||||
process.stdout.write(`\033[${x}C`);
|
||||
process.stdout.write('.');
|
||||
process.stdout.write(`\033[${y}A`);
|
||||
process.stdout.write(`\033[${x + 1}D`);
|
||||
}
|
||||
|
||||
const PrintSand = ([x, y]: [number, number]) => {
|
||||
process.stdout.write(`\033[${y}B`);
|
||||
process.stdout.write(`\033[${x}C`);
|
||||
process.stdout.write('+');
|
||||
process.stdout.write(`\033[${y}A`);
|
||||
process.stdout.write(`\033[${x + 1}D`);
|
||||
}
|
||||
|
||||
let minX = 0;
|
||||
let maxX = 0;
|
||||
let ySize = 0;
|
||||
|
||||
// Returns true if the sand has settled.
|
||||
const OneTick = (
|
||||
[y, x]: [number, number],
|
||||
grid: string[][]
|
||||
): [boolean, boolean, [number, number]] => {
|
||||
const next = grid[y + 1][x];
|
||||
|
||||
if (grid[y + 1][x] === undefined) {
|
||||
return [false, true, [0, 0]];
|
||||
}
|
||||
|
||||
if (next === ".") {
|
||||
grid[y][x] = ".";
|
||||
grid[y + 1][x] = "+";
|
||||
return [false, false, [y + 1, x]];
|
||||
} else {
|
||||
|
||||
if (grid[y + 1][x - 1] === ".") {
|
||||
grid[y][x] = ".";
|
||||
grid[y + 1][x - 1] = "+";
|
||||
return [false, false, [y + 1, x - 1]];
|
||||
} else if (grid[y + 1][x - 1] === undefined) {
|
||||
return [false, true, [0, 0]];
|
||||
} else if (grid[y + 1][x + 1] === ".") {
|
||||
grid[y][x] = ".";
|
||||
grid[y + 1][x + 1] = "+";
|
||||
return [false, false, [y + 1, x + 1]];
|
||||
} else if (grid[y + 1][x + 1] === undefined) {
|
||||
return [false, true, [0, 0]];
|
||||
} else {
|
||||
//Settled
|
||||
grid[y][x] = "o";
|
||||
return [true, false, [y, x]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const Day14: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((i) =>
|
||||
i.split(" -> ").map((v) => v.split(",").map((w) => parseInt(w)))
|
||||
);
|
||||
|
||||
const xs = parsed.flatMap((v) => v).map((v) => v[0]);
|
||||
const ys = parsed.flatMap((v) => v).map((v) => v[1]);
|
||||
minX = Math.min(...xs);
|
||||
maxX = Math.max(...xs);
|
||||
const xSize = maxX - minX;
|
||||
ySize = Math.max(...ys);
|
||||
|
||||
let sand: [number, number] = [0, 500 - minX];
|
||||
|
||||
const grid = Array.from({ length: ySize + 1 }, (_) =>
|
||||
new Array(xSize + 1).fill(".")
|
||||
);
|
||||
parsed.forEach((rocks) => {
|
||||
for (let i = 0; i < rocks.length - 1; i++) {
|
||||
const [x1, y1] = rocks[i];
|
||||
const [x2, y2] = rocks[i + 1];
|
||||
if (x1 === x2) {
|
||||
const startY = Math.min(y1, y2);
|
||||
const endY = Math.max(y1, y2);
|
||||
for (let j = startY; j <= endY; j++) {
|
||||
grid[j][x1 - minX] = "#";
|
||||
}
|
||||
} else {
|
||||
const startX = Math.min(x1, x2) - minX;
|
||||
const endX = Math.max(x1, x2) - minX;
|
||||
for (let j = startX; j <= endX; j++) {
|
||||
grid[y1][j] = "#";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
PrintGrid(grid);
|
||||
grid[sand[0]][sand[1]] = "+";
|
||||
|
||||
const increaseSize = 200;
|
||||
const part2Grid: string[][] = JSON.parse(JSON.stringify(grid));
|
||||
for (let i = 0; i < part2Grid.length; i++) {
|
||||
part2Grid[i] = [...Array(increaseSize).fill("."), ...part2Grid[i], ...Array(increaseSize).fill(".")];
|
||||
}
|
||||
|
||||
part2Grid.push(Array(xSize + increaseSize * 2 + 1).fill("."));
|
||||
part2Grid.push(Array(xSize + increaseSize * 2 + 1).fill("#"));
|
||||
|
||||
while (true) {
|
||||
Bun.sleepSync(0.01);
|
||||
const [settled, gameOver, newSand] = OneTick(sand, grid);
|
||||
EraseSand([sand[1], sand[0]]);
|
||||
|
||||
if (gameOver) {
|
||||
grid[sand[0]][sand[1]] = ".";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!settled) {
|
||||
sand = newSand;
|
||||
} else {
|
||||
sand = [0, 500 - minX];
|
||||
grid[sand[0]][sand[1]] = "+";
|
||||
}
|
||||
PrintSand([sand[1], sand[0]]);
|
||||
}
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
process.stdout.write('\n');
|
||||
}
|
||||
|
||||
const part1 = grid.reduce((p, n) => p + n.filter((i) => i === "o").length, 0);
|
||||
|
||||
minX = minX - increaseSize;
|
||||
ySize = ySize + 2;
|
||||
sand = [0, 500 - minX];
|
||||
while (true) {
|
||||
// Bun.sleepSync(0.001);
|
||||
// PrintGrid(part2Grid);
|
||||
const [settled, gameOver, newSand] = OneTick(sand, part2Grid);
|
||||
if (gameOver) {
|
||||
part2Grid[sand[0]][sand[1]] = ".";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!settled) {
|
||||
sand = newSand;
|
||||
} else {
|
||||
if (newSand[0] === 0 && newSand[1] === 500 - minX) {
|
||||
part2Grid[0][500 - minX] = 'o';
|
||||
break;
|
||||
}
|
||||
sand = [0, 500 - minX];
|
||||
part2Grid[sand[0]][sand[1]] = "+";
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
writer.write('\n');
|
||||
}
|
||||
const part2 = part2Grid.reduce((p, n) => p + n.filter((i) => i === "o").length, 0);
|
||||
|
||||
return [part1, part2];
|
||||
};
|
69
AdventOfCode2022/src/days/Day15.ts
Normal file
69
AdventOfCode2022/src/days/Day15.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
type Pos = { x: number; y: number };
|
||||
|
||||
export const Day15: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((v) => v.split(" at "))
|
||||
.map((v) => [v[1].slice(0, v[1].indexOf(":")), v[2]])
|
||||
.map((v) => v.map((i) => i.replaceAll(/[a-z]=/g, "").replaceAll(" ", "")))
|
||||
.map((v) => {
|
||||
const oneSplit = v[0].split(",");
|
||||
const twoSplit = v[1].split(",");
|
||||
return [
|
||||
[parseInt(oneSplit[0]), parseInt(oneSplit[1])],
|
||||
[parseInt(twoSplit[0]), parseInt(twoSplit[1])],
|
||||
];
|
||||
});
|
||||
const grid: Array<{ sensor: Pos; beacon: Pos; distance: number }> = [];
|
||||
|
||||
let smallestX = 10000;
|
||||
let largestX = 0;
|
||||
parsed.forEach((i) => {
|
||||
const dist = Math.abs(i[0][0] - i[1][0]) + Math.abs(i[0][1] - i[1][1]);
|
||||
if (i[0][0] < smallestX) smallestX = i[0][0];
|
||||
if (i[1][0] < smallestX) smallestX = i[1][0];
|
||||
|
||||
if (i[0][0] > largestX) largestX = i[0][0];
|
||||
if (i[1][0] > largestX) largestX = i[1][0];
|
||||
|
||||
grid.push({
|
||||
sensor: {
|
||||
x: i[0][0],
|
||||
y: i[0][1],
|
||||
},
|
||||
beacon: {
|
||||
x: i[1][0],
|
||||
y: i[1][1],
|
||||
},
|
||||
distance: dist,
|
||||
});
|
||||
});
|
||||
|
||||
const y = 10;
|
||||
let part1 = 0;
|
||||
console.log(smallestX);
|
||||
console.log(largestX);
|
||||
for (let i = smallestX - 10000000; i <= largestX + 10000000; i++) {
|
||||
const testPos: Pos = {
|
||||
x: i,
|
||||
y: y,
|
||||
};
|
||||
|
||||
const beaconHere = grid.find(p => p.beacon.x === testPos.x && p.beacon.y === testPos.y);
|
||||
if (beaconHere) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const testPoint = grid.find(p => Math.abs(p.sensor.x - testPos.x) + Math.abs(p.sensor.y - testPos.y) <= p.distance);
|
||||
|
||||
|
||||
if (testPoint) {
|
||||
part1++;
|
||||
}
|
||||
}
|
||||
|
||||
return [part1, 0];
|
||||
};
|
218
AdventOfCode2022/src/days/Day17.ts
Normal file
218
AdventOfCode2022/src/days/Day17.ts
Normal file
@ -0,0 +1,218 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const blocks = [
|
||||
[["@", "@", "@", "@"]],
|
||||
[
|
||||
[".", "@", "."],
|
||||
["@", "@", "@"],
|
||||
[".", "@", "."],
|
||||
],
|
||||
[
|
||||
[".", ".", "@"],
|
||||
[".", ".", "@"],
|
||||
["@", "@", "@"],
|
||||
],
|
||||
[["@"], ["@"], ["@"], ["@"]],
|
||||
[
|
||||
["@", "@"],
|
||||
["@", "@"],
|
||||
],
|
||||
];
|
||||
|
||||
function PrintGrid(grid: string[][]) {
|
||||
for (let i = grid.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
process.stdout.write(grid[i][j]);
|
||||
}
|
||||
process.stdout.write("\n");
|
||||
}
|
||||
process.stdout.write("++++++++++++++++++++++++++++\n");
|
||||
}
|
||||
|
||||
function MoveDown(
|
||||
grid: string[][],
|
||||
block: string[][],
|
||||
[x, y]: [number, number]
|
||||
): boolean {
|
||||
// Moving through the floor.
|
||||
if (y - block.length + 1 === 0) return false;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@" && grid[y - i - 1][j + x] === "#") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No collision. Clear block.
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
y--;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = "@";
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function MoveSides(
|
||||
grid: string[][],
|
||||
block: string[][],
|
||||
[x, y]: [number, number],
|
||||
unit: -1 | 1
|
||||
): boolean {
|
||||
// Goes off the sides
|
||||
if (x + unit < 0 || x + block[0].length + unit > grid[0].length) return false;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@" && grid[y - i][j + x + unit] === "#") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No collision. Clear block.
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
x += unit;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = "@";
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function SettleBlock(
|
||||
grid: string[][],
|
||||
block: string[][],
|
||||
[x, y]: [number, number]
|
||||
) {
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = "#";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* BlockGen(start = 0, end = Infinity, step = 1) {
|
||||
for (let i = start; i < end; i += step) {
|
||||
yield { block: blocks[i % blocks.length]!, index: i % blocks.length };
|
||||
}
|
||||
}
|
||||
|
||||
function CalcHeight(grid: string[][]) {
|
||||
let e = 0;
|
||||
for (let i = grid.length - 1; i >= 0; i--) {
|
||||
if (grid[i].some((j) => j === "#")) {
|
||||
break;
|
||||
}
|
||||
e++;
|
||||
}
|
||||
return grid.length - e;
|
||||
}
|
||||
|
||||
export const Day17: DayFunc = (input) => {
|
||||
const parsed = input.trim().split("");
|
||||
const gen = BlockGen();
|
||||
|
||||
const grid: string[][] = [];
|
||||
let jet = 0;
|
||||
let part1: number;
|
||||
let addedOnHeight = 0;
|
||||
|
||||
const depthMap: Record<string, {height: number; index: number}> = {};
|
||||
|
||||
for (let i = 0; i < 1e12; i++) {
|
||||
if (i === 2022) {
|
||||
part1 = CalcHeight(grid);
|
||||
}
|
||||
|
||||
const g = gen.next().value;
|
||||
if (!g) return;
|
||||
const block = g.block;
|
||||
|
||||
// Not right, not necessarily the top row.
|
||||
let emptyRows = 0;
|
||||
let rock = -1;
|
||||
for (let c = grid.length - 1; c >= 0; c--) {
|
||||
if (grid[c].some((i) => i === "#")) {
|
||||
rock = c;
|
||||
break;
|
||||
}
|
||||
emptyRows++;
|
||||
}
|
||||
if (emptyRows < 3 + block.length) {
|
||||
for (let c = 0; c <= 2 + block.length - emptyRows; c++) {
|
||||
grid.push([".", ".", ".", ".", ".", ".", "."]);
|
||||
}
|
||||
}
|
||||
const topLeft: [number, number] = [2, rock + 3 + block.length];
|
||||
|
||||
for (let j = block.length - 1; j >= 0; j--) {
|
||||
const newRow = [".", ".", ...block[j]];
|
||||
for (let k = 0; k < 5 - block[j].length; k++) {
|
||||
newRow.push(".");
|
||||
}
|
||||
grid[rock === -1 ? 3 - j : block.length - j + rock + 3] = newRow;
|
||||
}
|
||||
|
||||
let movedDown = true;
|
||||
do {
|
||||
if (parsed[jet % parsed.length] === "<") {
|
||||
const moved = MoveSides(grid, block, topLeft, -1);
|
||||
if (moved) topLeft[0]--;
|
||||
} else {
|
||||
const moved = MoveSides(grid, block, topLeft, 1);
|
||||
if (moved) topLeft[0]++;
|
||||
}
|
||||
jet++;
|
||||
movedDown = MoveDown(grid, block, topLeft);
|
||||
if (movedDown) {
|
||||
topLeft[1]--;
|
||||
}
|
||||
} while (movedDown);
|
||||
SettleBlock(grid, block, topLeft);
|
||||
|
||||
const depth = [0, 0, 0, 0, 0, 0, 0];
|
||||
for (let x = 0; x < 7; x++) {
|
||||
for (let y = grid.length - 1; y >= 0; y--) {
|
||||
if (grid[y][x] === '#') {
|
||||
depth[x] = grid.length - y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const key = `${g.index},${jet % parsed.length},${JSON.stringify(depth)}`;
|
||||
if (key in depthMap) {
|
||||
const height = CalcHeight(grid);
|
||||
const mapEntry = depthMap[key];
|
||||
const diff = height - mapEntry.height;
|
||||
const cycleNum = Math.floor((1e12 - i) / (i - mapEntry.index));
|
||||
i += cycleNum * (i - mapEntry.index);
|
||||
addedOnHeight += diff * cycleNum;
|
||||
} else {
|
||||
depthMap[key] = { height: CalcHeight(grid), index: i };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [part1, CalcHeight(grid) + addedOnHeight];
|
||||
};
|
31
AdventOfCode2022/src/days/Day18.ts
Normal file
31
AdventOfCode2022/src/days/Day18.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
function CalcDist(
|
||||
[x1, y1, z1]: [number, number, number],
|
||||
[x2, y2, z2]: [number, number, number]
|
||||
): number {
|
||||
return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2);
|
||||
}
|
||||
|
||||
export const Day18: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((i) => i.split(",").map((j) => parseInt(j)));
|
||||
|
||||
let part1 = parsed.length * 6;
|
||||
for (let i = 0; i < parsed.length; i++) {
|
||||
const a = parsed[i];
|
||||
for (let j = 0; j < parsed.length; j++) {
|
||||
if (i === j) continue;
|
||||
const b = parsed[j];
|
||||
// @ts-ignore
|
||||
const dist = CalcDist(a, b);
|
||||
if (dist === 1) {
|
||||
part1--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [part1, 0];
|
||||
};
|
70
AdventOfCode2022/src/days/Day2.ts
Normal file
70
AdventOfCode2022/src/days/Day2.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
// A = Rock, B = Paper, C = Scissors
|
||||
// X = Rock, Y = Paper, Z = Scissors
|
||||
// 1 = Rock, 2 = Paper, 3 = Scissors
|
||||
// 0 = Lose, 3 = Draw, 6 = Win
|
||||
type Options = 'r' | 'p' | 's';
|
||||
|
||||
const mapping: {[key: string]: Options} = {
|
||||
A: 'r',
|
||||
B: 'p',
|
||||
C: 's',
|
||||
X: 'r',
|
||||
Y: 'p',
|
||||
Z: 's',
|
||||
}
|
||||
|
||||
const scores: Record<
|
||||
Options,
|
||||
{
|
||||
score: number;
|
||||
beats: Options;
|
||||
loses: Options;
|
||||
}
|
||||
> = {
|
||||
'r': {
|
||||
score: 1,
|
||||
beats: "s",
|
||||
loses: "p",
|
||||
},
|
||||
'p': {
|
||||
score: 2,
|
||||
beats: "r",
|
||||
loses: "s",
|
||||
},
|
||||
's': {
|
||||
score: 3,
|
||||
beats: "p",
|
||||
loses: "r",
|
||||
},
|
||||
};
|
||||
|
||||
export const Day2: DayFunc = (input) => {
|
||||
const plays: string[][] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((line) => line.split(" "));
|
||||
|
||||
let part1 = 0;
|
||||
let part2 = 0;
|
||||
|
||||
plays.forEach(([opp, you]) => {
|
||||
part1 += scores[mapping[you]].score;
|
||||
if (mapping[you] === mapping[opp]) {
|
||||
part1 += 3;
|
||||
} else if (scores[mapping[you]].beats === mapping[opp]) {
|
||||
part1 += 6;
|
||||
}
|
||||
|
||||
if (you === 'X') {
|
||||
part2 += scores[scores[mapping[opp]].beats].score;
|
||||
} else if (you === 'Y') {
|
||||
part2 += 3 + scores[mapping[opp]].score;
|
||||
} else {
|
||||
part2 += 6 + scores[scores[mapping[opp]].loses].score;
|
||||
}
|
||||
});
|
||||
|
||||
return [part1, part2];
|
||||
};
|
35
AdventOfCode2022/src/days/Day3.ts
Normal file
35
AdventOfCode2022/src/days/Day3.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const getCode = (x: Set<string>): number => {
|
||||
const code = x.values().next().value.charCodeAt(0);
|
||||
return code + (code <= 90 ? -38 : -96);
|
||||
};
|
||||
|
||||
export const Day3: DayFunc = (input) => {
|
||||
const bags: string[] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
|
||||
const part1Bags = bags.map((i) => [i.slice(0, i.length / 2), i.slice(i.length / 2)]);
|
||||
const part2Bags = []
|
||||
for (let i = 0; i < bags.length; i += 3) {
|
||||
part2Bags.push(bags.slice(i, i + 3));
|
||||
}
|
||||
|
||||
const part1 = part1Bags.reduce((prev, [c1, c2]) => {
|
||||
const set1 = new Set(c1);
|
||||
const set2 = new Set(c2);
|
||||
const n = new Set([...set1].filter((x) => set2.has(x)));
|
||||
return prev + getCode(n);
|
||||
}, 0);
|
||||
|
||||
const part2 = part2Bags.reduce((prev, [c1, c2, c3]) => {
|
||||
const set1 = new Set(c1);
|
||||
const set2 = new Set(c2);
|
||||
const set3 = new Set(c3);
|
||||
const n = new Set([...set1].filter((x) => set2.has(x)).filter(x => set3.has(x)));
|
||||
return prev + getCode(n as Set<string>);
|
||||
}, 0)
|
||||
|
||||
return [part1, part2];
|
||||
};
|
29
AdventOfCode2022/src/days/Day4.ts
Normal file
29
AdventOfCode2022/src/days/Day4.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day4: DayFunc = (input) => {
|
||||
const pairs: number[][][] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((l) => l.split(",").map((p) => p.split("-").map((v) => parseInt(v))));
|
||||
|
||||
const [part1, part2] = pairs.reduce(
|
||||
([part1, part2], next) => {
|
||||
if (
|
||||
(next[0][0] <= next[1][0] && next[0][1] >= next[1][1]) ||
|
||||
(next[1][0] <= next[0][0] && next[1][1] >= next[0][1])
|
||||
) {
|
||||
part1++;
|
||||
part2++;
|
||||
} else if (
|
||||
(next[0][0] <= next[1][0] && next[1][0] <= next[0][1]) ||
|
||||
(next[1][0] <= next[0][0] && next[0][0] <= next[1][1])
|
||||
) {
|
||||
part2++;
|
||||
}
|
||||
return [part1, part2];
|
||||
},
|
||||
[0, 0]
|
||||
);
|
||||
|
||||
return [part1, part2];
|
||||
};
|
45
AdventOfCode2022/src/days/Day5.ts
Normal file
45
AdventOfCode2022/src/days/Day5.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day5: DayFunc = (input) => {
|
||||
let [inStacks, instructions] = input
|
||||
.split("\n\n")
|
||||
|
||||
const stacks = inStacks.split('\n')
|
||||
stacks.pop();
|
||||
|
||||
const numOfStacks = (stacks[0].length + 1) / 4;
|
||||
let realStacks = [...Array(numOfStacks)].map(() => []);
|
||||
|
||||
for (let i = 0; i < stacks.length; i++) {
|
||||
for (let j = 1; j < stacks[i].length; j += 4) {
|
||||
const c = stacks[i].charAt(j);
|
||||
const stackNum = (j - 1) / 4;
|
||||
if (c !== " ") {
|
||||
realStacks[stackNum].push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
realStacks.map(s => s.reverse());
|
||||
const realStacks2 = [...realStacks].map(i => [...i]);
|
||||
|
||||
const rules = instructions.split('\n').map((i) => {
|
||||
const is = i.split(" ");
|
||||
return [parseInt(is[1]), parseInt(is[3]) - 1, parseInt(is[5]) - 1];
|
||||
});
|
||||
rules.pop();
|
||||
|
||||
rules.forEach(r => {
|
||||
for (let i = 0; i < r[0]; i++) {
|
||||
const popped = realStacks[r[1]].pop();
|
||||
realStacks[r[2]].push(popped);
|
||||
}
|
||||
|
||||
const crates = realStacks2[r[1]].splice(-r[0]);
|
||||
realStacks2[r[2]].push(...crates);
|
||||
});
|
||||
|
||||
const part1 = realStacks.reduce((prev, next) => prev + next[next.length - 1], "");
|
||||
const part2 = realStacks2.reduce((prev, next) => prev + next[next.length - 1], "");
|
||||
|
||||
return [part1, part2];
|
||||
};
|
21
AdventOfCode2022/src/days/Day6.ts
Normal file
21
AdventOfCode2022/src/days/Day6.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const FindRepeated = (input: string, gap: number): number => {
|
||||
for (let i = 0; i < input.length - gap; i++) {
|
||||
const sub = input.substring(i, i + gap);
|
||||
let changed = false;
|
||||
for (const c of sub) {
|
||||
if (sub.split(c).length > 2) {
|
||||
i += sub.indexOf(c);
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!changed) return i + gap;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
export const Day6: DayFunc = (input) => {
|
||||
return [FindRepeated(input, 4), FindRepeated(input, 14)];
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user