diff --git a/AdventOfCode2015/README.md b/AdventOfCode2015/README.md new file mode 100644 index 0000000..b0de8a7 --- /dev/null +++ b/AdventOfCode2015/README.md @@ -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. diff --git a/AdventOfCode2015/day1/day1.go b/AdventOfCode2015/day1/day1.go new file mode 100644 index 0000000..b8b7a74 --- /dev/null +++ b/AdventOfCode2015/day1/day1.go @@ -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) + +} diff --git a/AdventOfCode2015/day10/day10.go b/AdventOfCode2015/day10/day10.go new file mode 100644 index 0000000..03bbbd3 --- /dev/null +++ b/AdventOfCode2015/day10/day10.go @@ -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) + +} diff --git a/AdventOfCode2015/day12/day12.go b/AdventOfCode2015/day12/day12.go new file mode 100644 index 0000000..76ef06b --- /dev/null +++ b/AdventOfCode2015/day12/day12.go @@ -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 +} diff --git a/AdventOfCode2015/day12/day12.js b/AdventOfCode2015/day12/day12.js new file mode 100644 index 0000000..347add3 --- /dev/null +++ b/AdventOfCode2015/day12/day12.js @@ -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; + } +} \ No newline at end of file diff --git a/AdventOfCode2015/day13/day13.go b/AdventOfCode2015/day13/day13.go new file mode 100644 index 0000000..e3deb9b --- /dev/null +++ b/AdventOfCode2015/day13/day13.go @@ -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 +} diff --git a/AdventOfCode2015/day14/day14.go b/AdventOfCode2015/day14/day14.go new file mode 100644 index 0000000..de5e34e --- /dev/null +++ b/AdventOfCode2015/day14/day14.go @@ -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) + +} diff --git a/AdventOfCode2015/day15/day15.go b/AdventOfCode2015/day15/day15.go new file mode 100644 index 0000000..2eac9f8 --- /dev/null +++ b/AdventOfCode2015/day15/day15.go @@ -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 + } + +} diff --git a/AdventOfCode2015/day16/Aunt.class b/AdventOfCode2015/day16/Aunt.class new file mode 100644 index 0000000..7fa412f Binary files /dev/null and b/AdventOfCode2015/day16/Aunt.class differ diff --git a/AdventOfCode2015/day16/Main.class b/AdventOfCode2015/day16/Main.class new file mode 100644 index 0000000..ffaf365 Binary files /dev/null and b/AdventOfCode2015/day16/Main.class differ diff --git a/AdventOfCode2015/day16/Main.java b/AdventOfCode2015/day16/Main.java new file mode 100644 index 0000000..c1ea5c0 --- /dev/null +++ b/AdventOfCode2015/day16/Main.java @@ -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 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(); + + } + +} \ No newline at end of file diff --git a/AdventOfCode2015/day2/day2.go b/AdventOfCode2015/day2/day2.go new file mode 100644 index 0000000..dca5d62 --- /dev/null +++ b/AdventOfCode2015/day2/day2.go @@ -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 +} diff --git a/AdventOfCode2015/day3/day3.go b/AdventOfCode2015/day3/day3.go new file mode 100644 index 0000000..768f7df --- /dev/null +++ b/AdventOfCode2015/day3/day3.go @@ -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]++ + } +} diff --git a/AdventOfCode2015/day4/day4.go b/AdventOfCode2015/day4/day4.go new file mode 100644 index 0000000..5699bcc --- /dev/null +++ b/AdventOfCode2015/day4/day4.go @@ -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) + +} diff --git a/AdventOfCode2015/day5/day5.go b/AdventOfCode2015/day5/day5.go new file mode 100644 index 0000000..b152109 --- /dev/null +++ b/AdventOfCode2015/day5/day5.go @@ -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 +} diff --git a/AdventOfCode2015/day6/day6.go b/AdventOfCode2015/day6/day6.go new file mode 100644 index 0000000..cf19f48 --- /dev/null +++ b/AdventOfCode2015/day6/day6.go @@ -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 +} diff --git a/AdventOfCode2015/day7/day7.zig b/AdventOfCode2015/day7/day7.zig new file mode 100644 index 0000000..ef59b1d --- /dev/null +++ b/AdventOfCode2015/day7/day7.zig @@ -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}); +} diff --git a/AdventOfCode2015/day7/utils.zig b/AdventOfCode2015/day7/utils.zig new file mode 120000 index 0000000..059db98 --- /dev/null +++ b/AdventOfCode2015/day7/utils.zig @@ -0,0 +1 @@ +../../zig/utils.zig \ No newline at end of file diff --git a/AdventOfCode2015/day8/day8.go b/AdventOfCode2015/day8/day8.go new file mode 100644 index 0000000..f96d526 --- /dev/null +++ b/AdventOfCode2015/day8/day8.go @@ -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 +} diff --git a/AdventOfCode2020/README.md b/AdventOfCode2020/README.md new file mode 100644 index 0000000..e1a999e --- /dev/null +++ b/AdventOfCode2020/README.md @@ -0,0 +1,3 @@ +# Advent of Code 2020 + +These are my solutions, currently all in Java. diff --git a/AdventOfCode2020/day1/day1.class b/AdventOfCode2020/day1/day1.class new file mode 100644 index 0000000..3cb1b51 Binary files /dev/null and b/AdventOfCode2020/day1/day1.class differ diff --git a/AdventOfCode2020/day1/day1.java b/AdventOfCode2020/day1/day1.java new file mode 100644 index 0000000..12e66e1 --- /dev/null +++ b/AdventOfCode2020/day1/day1.java @@ -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); + } + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day10/day10.class b/AdventOfCode2020/day10/day10.class new file mode 100644 index 0000000..d55ffd6 Binary files /dev/null and b/AdventOfCode2020/day10/day10.class differ diff --git a/AdventOfCode2020/day10/day10.java b/AdventOfCode2020/day10/day10.java new file mode 100644 index 0000000..5547773 --- /dev/null +++ b/AdventOfCode2020/day10/day10.java @@ -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, Long> cache = new HashMap<>(); + + public static void main(String[] args) { + + File myFile = new File("input.txt"); + try { + + Scanner in = new Scanner(myFile); + ArrayList 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 nums) { + + long sum = 0; + if (nums.size() == 1) { + //System.out.println("Size 1"); + return 1; + } + + ArrayList 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 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; + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day11/day11.class b/AdventOfCode2020/day11/day11.class new file mode 100644 index 0000000..467e77e Binary files /dev/null and b/AdventOfCode2020/day11/day11.class differ diff --git a/AdventOfCode2020/day11/day11.java b/AdventOfCode2020/day11/day11.java new file mode 100644 index 0000000..c58822d --- /dev/null +++ b/AdventOfCode2020/day11/day11.java @@ -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; + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day13/day13.class b/AdventOfCode2020/day13/day13.class new file mode 100644 index 0000000..1d54e76 Binary files /dev/null and b/AdventOfCode2020/day13/day13.class differ diff --git a/AdventOfCode2020/day13/day13.java b/AdventOfCode2020/day13/day13.java new file mode 100644 index 0000000..18b9681 --- /dev/null +++ b/AdventOfCode2020/day13/day13.java @@ -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 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(); + } + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day14/day14.class b/AdventOfCode2020/day14/day14.class new file mode 100644 index 0000000..823b13f Binary files /dev/null and b/AdventOfCode2020/day14/day14.class differ diff --git a/AdventOfCode2020/day14/day14.java b/AdventOfCode2020/day14/day14.java new file mode 100644 index 0000000..de7741d --- /dev/null +++ b/AdventOfCode2020/day14/day14.java @@ -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 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 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; + } + +} diff --git a/AdventOfCode2020/day15/NumberTurns.class b/AdventOfCode2020/day15/NumberTurns.class new file mode 100644 index 0000000..91ea7aa Binary files /dev/null and b/AdventOfCode2020/day15/NumberTurns.class differ diff --git a/AdventOfCode2020/day15/day15.class b/AdventOfCode2020/day15/day15.class new file mode 100644 index 0000000..ae1ecf1 Binary files /dev/null and b/AdventOfCode2020/day15/day15.class differ diff --git a/AdventOfCode2020/day15/day15.java b/AdventOfCode2020/day15/day15.java new file mode 100644 index 0000000..3889a96 --- /dev/null +++ b/AdventOfCode2020/day15/day15.java @@ -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 spokenNums = new ArrayList<>(); + HashMap 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)); + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day16/Field.class b/AdventOfCode2020/day16/Field.class new file mode 100644 index 0000000..0f841b5 Binary files /dev/null and b/AdventOfCode2020/day16/Field.class differ diff --git a/AdventOfCode2020/day16/day16.class b/AdventOfCode2020/day16/day16.class new file mode 100644 index 0000000..d28addf Binary files /dev/null and b/AdventOfCode2020/day16/day16.class differ diff --git a/AdventOfCode2020/day16/day16.java b/AdventOfCode2020/day16/day16.java new file mode 100644 index 0000000..e8cb3e6 --- /dev/null +++ b/AdventOfCode2020/day16/day16.java @@ -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 input = new ArrayList<>(); + + while (in.hasNext()) input.add(in.nextLine()); + + List fields = input.subList(0, input.indexOf("your ticket:") - 1); + String ticket = input.get(input.indexOf("your ticket:") + 1); + List otherTickets = input.subList(input.indexOf("nearby tickets:") + 1, input.size()); + + HashMap ranges = new HashMap<>(); + + List 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 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 newOtherTickets = new ArrayList<>(); + for (int i = 0; i < otherTickets.size(); i++) { + if (!toRemove.contains(i)) newOtherTickets.add(otherTickets.get(i)); + } + + HashMap> 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 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 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]; + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day17/day17.class b/AdventOfCode2020/day17/day17.class new file mode 100644 index 0000000..9ce066b Binary files /dev/null and b/AdventOfCode2020/day17/day17.class differ diff --git a/AdventOfCode2020/day17/day17.java b/AdventOfCode2020/day17/day17.java new file mode 100644 index 0000000..fb4a09b --- /dev/null +++ b/AdventOfCode2020/day17/day17.java @@ -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 points = new ArrayList<>(); + List 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 step(List points) { + + List newPoints = new ArrayList<>(); + List 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 stepPart2(List points) { + + System.out.println(points.size()); + + List newPoints = new ArrayList<>(); + List 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 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 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; + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day18/day18.class b/AdventOfCode2020/day18/day18.class new file mode 100644 index 0000000..7cccfa2 Binary files /dev/null and b/AdventOfCode2020/day18/day18.class differ diff --git a/AdventOfCode2020/day18/day18.java b/AdventOfCode2020/day18/day18.java new file mode 100644 index 0000000..53b2f11 --- /dev/null +++ b/AdventOfCode2020/day18/day18.java @@ -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; + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day19/day19.go b/AdventOfCode2020/day19/day19.go new file mode 100644 index 0000000..244bc27 --- /dev/null +++ b/AdventOfCode2020/day19/day19.go @@ -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) +} diff --git a/AdventOfCode2020/day19/main.go b/AdventOfCode2020/day19/main.go new file mode 100644 index 0000000..8753604 --- /dev/null +++ b/AdventOfCode2020/day19/main.go @@ -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") +} +*/ diff --git a/AdventOfCode2020/day19/parser.go b/AdventOfCode2020/day19/parser.go new file mode 100755 index 0000000..4f4f390 --- /dev/null +++ b/AdventOfCode2020/day19/parser.go @@ -0,0 +1,1056 @@ + + 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) + } + +func Rule42(message string, index *int) error { + indexCopy := *index + err := Rule42First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule42Second(message, index) + return err +} + +func Rule42First(message string, index *int) error { + err := Rule9(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule42Second(message string, index *int) error { + err := Rule10(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule9(message string, index *int) error { + indexCopy := *index + err := Rule9First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule9Second(message, index) + return err +} + +func Rule9First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule27(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule9Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule26(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule10(message string, index *int) error { + indexCopy := *index + err := Rule10First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule10Second(message, index) + return err +} + +func Rule10First(message string, index *int) error { + err := Rule23(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule10Second(message string, index *int) error { + err := Rule28(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule1(message string, index *int) error { + if len(message) <= *index { + return errors.New("out of bounds") + } + + if string(message[*index]) == "a" { + *index++ + return nil + } + return errors.New("Could not match") +} + +func Rule11(message string, index *int) error { + err := Rule42(message, index) + if err != nil { + return err + } + + err = Rule31(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule5(message string, index *int) error { + indexCopy := *index + err := Rule5First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule5Second(message, index) + return err +} + +func Rule5First(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule5Second(message string, index *int) error { + err := Rule15(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule19(message string, index *int) error { + indexCopy := *index + err := Rule19First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule19Second(message, index) + return err +} + +func Rule19First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule19Second(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule12(message string, index *int) error { + indexCopy := *index + err := Rule12First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule12Second(message, index) + return err +} + +func Rule12First(message string, index *int) error { + err := Rule24(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule12Second(message string, index *int) error { + err := Rule19(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule16(message string, index *int) error { + indexCopy := *index + err := Rule16First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule16Second(message, index) + return err +} + +func Rule16First(message string, index *int) error { + err := Rule15(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule16Second(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule31(message string, index *int) error { + indexCopy := *index + err := Rule31First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule31Second(message, index) + return err +} + +func Rule31First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule17(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule31Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule13(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule6(message string, index *int) error { + indexCopy := *index + err := Rule6First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule6Second(message, index) + return err +} + +func Rule6First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule6Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule14(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 { + *index = indexCopy + 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 = Rule24(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule2Second(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule4(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule0(message string, index *int) error { + err := Rule8(message, index) + if err != nil { + return err + } + + err = Rule11(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule13(message string, index *int) error { + indexCopy := *index + err := Rule13First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule13Second(message, index) + return err +} + +func Rule13First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule3(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule13Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule12(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule15(message string, index *int) error { + indexCopy := *index + err := Rule15First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule15Second(message, index) + return err +} + +func Rule15First(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule15Second(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule17(message string, index *int) error { + indexCopy := *index + err := Rule17First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule17Second(message, index) + return err +} + +func Rule17First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule2(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule17Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule7(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule23(message string, index *int) error { + indexCopy := *index + err := Rule23First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule23Second(message, index) + return err +} + +func Rule23First(message string, index *int) error { + err := Rule25(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule23Second(message string, index *int) error { + err := Rule22(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule28(message string, index *int) error { + err := Rule16(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule4(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule20(message string, index *int) error { + indexCopy := *index + err := Rule20First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule20Second(message, index) + return err +} + +func Rule20First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule20Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule15(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule3(message string, index *int) error { + indexCopy := *index + err := Rule3First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule3Second(message, index) + return err +} + +func Rule3First(message string, index *int) error { + err := Rule5(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule3Second(message string, index *int) error { + err := Rule16(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule27(message string, index *int) error { + indexCopy := *index + err := Rule27First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule27Second(message, index) + return err +} + +func Rule27First(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule6(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule27Second(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule18(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule14(message string, index *int) error { + if len(message) <= *index { + return errors.New("out of bounds") + } + + if string(message[*index]) == "b" { + *index++ + return nil + } + return errors.New("Could not match") +} + +func Rule21(message string, index *int) error { + indexCopy := *index + err := Rule21First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule21Second(message, index) + return err +} + +func Rule21First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule21Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule25(message string, index *int) error { + indexCopy := *index + err := Rule25First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule25Second(message, index) + return err +} + +func Rule25First(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule25Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule22(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule14(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule8(message string, index *int) error { + err := Rule42(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule26(message string, index *int) error { + indexCopy := *index + err := Rule26First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule26Second(message, index) + return err +} + +func Rule26First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule22(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule26Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule20(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule18(message string, index *int) error { + err := Rule15(message, index) + if err != nil { + return err + } + + err = Rule15(message, index) + if err != nil { + return err + } + + return nil +} + +func Rule7(message string, index *int) error { + indexCopy := *index + err := Rule7First(message, &indexCopy) + + if err == nil { + *index = indexCopy + return nil + } + + err = Rule7Second(message, index) + return err +} + +func Rule7First(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule5(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule7Second(message string, index *int) error { + err := Rule1(message, index) + if err != nil { + return err + } + + err = Rule21(message, index) + if err != nil { + return err + } + + return nil +} + + +func Rule24(message string, index *int) error { + err := Rule14(message, index) + if err != nil { + return err + } + + err = Rule1(message, index) + if err != nil { + return err + } + + return nil +} diff --git a/AdventOfCode2020/day2/Main.class b/AdventOfCode2020/day2/Main.class new file mode 100644 index 0000000..a1e3e6c Binary files /dev/null and b/AdventOfCode2020/day2/Main.class differ diff --git a/AdventOfCode2020/day2/Main.java b/AdventOfCode2020/day2/Main.java new file mode 100644 index 0000000..a93338d --- /dev/null +++ b/AdventOfCode2020/day2/Main.java @@ -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); + } + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day21/day21.go b/AdventOfCode2020/day21/day21.go new file mode 100644 index 0000000..c9b3cfd --- /dev/null +++ b/AdventOfCode2020/day21/day21.go @@ -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) +} diff --git a/AdventOfCode2020/day22/day22.go b/AdventOfCode2020/day22/day22.go new file mode 100644 index 0000000..8456c70 --- /dev/null +++ b/AdventOfCode2020/day22/day22.go @@ -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 +} diff --git a/AdventOfCode2020/day23/LinkedList.go b/AdventOfCode2020/day23/LinkedList.go new file mode 100644 index 0000000..028608e --- /dev/null +++ b/AdventOfCode2020/day23/LinkedList.go @@ -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) + +} diff --git a/AdventOfCode2020/day23/day23.go b/AdventOfCode2020/day23/day23.go new file mode 100644 index 0000000..e69de29 diff --git a/AdventOfCode2020/day23/go.mod b/AdventOfCode2020/day23/go.mod new file mode 100644 index 0000000..b48dafc --- /dev/null +++ b/AdventOfCode2020/day23/go.mod @@ -0,0 +1,3 @@ +module main + +go 1.16 diff --git a/AdventOfCode2020/day24/day24.go b/AdventOfCode2020/day24/day24.go new file mode 100644 index 0000000..c0781e7 --- /dev/null +++ b/AdventOfCode2020/day24/day24.go @@ -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) + } +} diff --git a/AdventOfCode2020/day25/day25.go b/AdventOfCode2020/day25/day25.go new file mode 100644 index 0000000..7929a86 --- /dev/null +++ b/AdventOfCode2020/day25/day25.go @@ -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) +} diff --git a/AdventOfCode2020/day3/day3.class b/AdventOfCode2020/day3/day3.class new file mode 100644 index 0000000..ba68a5a Binary files /dev/null and b/AdventOfCode2020/day3/day3.class differ diff --git a/AdventOfCode2020/day3/day3.java b/AdventOfCode2020/day3/day3.java new file mode 100644 index 0000000..861fb72 --- /dev/null +++ b/AdventOfCode2020/day3/day3.java @@ -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); + } + + } + +} + diff --git a/AdventOfCode2020/day4/day4.class b/AdventOfCode2020/day4/day4.class new file mode 100644 index 0000000..c527166 Binary files /dev/null and b/AdventOfCode2020/day4/day4.class differ diff --git a/AdventOfCode2020/day4/day4.java b/AdventOfCode2020/day4/day4.java new file mode 100644 index 0000000..ea2b736 --- /dev/null +++ b/AdventOfCode2020/day4/day4.java @@ -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 passports = new ArrayList(); + 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); + } + + } + +} + diff --git a/AdventOfCode2020/day5/day5.class b/AdventOfCode2020/day5/day5.class new file mode 100644 index 0000000..5b5fa8d Binary files /dev/null and b/AdventOfCode2020/day5/day5.class differ diff --git a/AdventOfCode2020/day5/day5.java b/AdventOfCode2020/day5/day5.java new file mode 100644 index 0000000..c802756 --- /dev/null +++ b/AdventOfCode2020/day5/day5.java @@ -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 seatIDs = new ArrayList(); + + 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; + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day6/day6.class b/AdventOfCode2020/day6/day6.class new file mode 100644 index 0000000..e9954d4 Binary files /dev/null and b/AdventOfCode2020/day6/day6.class differ diff --git a/AdventOfCode2020/day6/day6.java b/AdventOfCode2020/day6/day6.java new file mode 100644 index 0000000..70e33fd --- /dev/null +++ b/AdventOfCode2020/day6/day6.java @@ -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 inputs = new ArrayList(); + 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 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(); + } + + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day7/BagInfo.class b/AdventOfCode2020/day7/BagInfo.class new file mode 100644 index 0000000..ef6927b Binary files /dev/null and b/AdventOfCode2020/day7/BagInfo.class differ diff --git a/AdventOfCode2020/day7/day7.class b/AdventOfCode2020/day7/day7.class new file mode 100644 index 0000000..298440c Binary files /dev/null and b/AdventOfCode2020/day7/day7.class differ diff --git a/AdventOfCode2020/day7/day7.java b/AdventOfCode2020/day7/day7.java new file mode 100644 index 0000000..93b54de --- /dev/null +++ b/AdventOfCode2020/day7/day7.java @@ -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> 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()); + } else { + + String[] Innerbags = innerBag.split(" , "); + ArrayList 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 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 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; + } +} diff --git a/AdventOfCode2020/day8/Instruction.class b/AdventOfCode2020/day8/Instruction.class new file mode 100644 index 0000000..19dd99d Binary files /dev/null and b/AdventOfCode2020/day8/Instruction.class differ diff --git a/AdventOfCode2020/day8/day8.class b/AdventOfCode2020/day8/day8.class new file mode 100644 index 0000000..e729f97 Binary files /dev/null and b/AdventOfCode2020/day8/day8.class differ diff --git a/AdventOfCode2020/day8/day8.java b/AdventOfCode2020/day8/day8.java new file mode 100644 index 0000000..1f14cab --- /dev/null +++ b/AdventOfCode2020/day8/day8.java @@ -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 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 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; + } + +} \ No newline at end of file diff --git a/AdventOfCode2020/day9/day8.class b/AdventOfCode2020/day9/day8.class new file mode 100644 index 0000000..3442bf5 Binary files /dev/null and b/AdventOfCode2020/day9/day8.class differ diff --git a/AdventOfCode2020/day9/day9.class b/AdventOfCode2020/day9/day9.class new file mode 100644 index 0000000..dc6d234 Binary files /dev/null and b/AdventOfCode2020/day9/day9.class differ diff --git a/AdventOfCode2020/day9/day9.java b/AdventOfCode2020/day9/day9.java new file mode 100644 index 0000000..301c901 --- /dev/null +++ b/AdventOfCode2020/day9/day9.java @@ -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 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 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(); + } + + } + +} \ No newline at end of file diff --git a/AdventOfCode2021/README.md b/AdventOfCode2021/README.md new file mode 100644 index 0000000..5c9861a --- /dev/null +++ b/AdventOfCode2021/README.md @@ -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. diff --git a/AdventOfCode2021/day1/day1.go b/AdventOfCode2021/day1/day1.go new file mode 100644 index 0000000..59840e5 --- /dev/null +++ b/AdventOfCode2021/day1/day1.go @@ -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 + +} diff --git a/AdventOfCode2021/day13/day13.go b/AdventOfCode2021/day13/day13.go new file mode 100644 index 0000000..d7124d6 --- /dev/null +++ b/AdventOfCode2021/day13/day13.go @@ -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 +} \ No newline at end of file diff --git a/AdventOfCode2021/day14/day14.go b/AdventOfCode2021/day14/day14.go new file mode 100644 index 0000000..f1600b3 --- /dev/null +++ b/AdventOfCode2021/day14/day14.go @@ -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 +} diff --git a/AdventOfCode2021/day2/day2.go b/AdventOfCode2021/day2/day2.go new file mode 100644 index 0000000..55cc4a7 --- /dev/null +++ b/AdventOfCode2021/day2/day2.go @@ -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 + +} diff --git a/AdventOfCode2021/day3/day3.go b/AdventOfCode2021/day3/day3.go new file mode 100644 index 0000000..cd90d54 --- /dev/null +++ b/AdventOfCode2021/day3/day3.go @@ -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 +} diff --git a/AdventOfCode2021/day4/day4.go b/AdventOfCode2021/day4/day4.go new file mode 100644 index 0000000..42f9102 --- /dev/null +++ b/AdventOfCode2021/day4/day4.go @@ -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 + +} \ No newline at end of file diff --git a/AdventOfCode2021/day5/day5.go b/AdventOfCode2021/day5/day5.go new file mode 100644 index 0000000..f4d02db --- /dev/null +++ b/AdventOfCode2021/day5/day5.go @@ -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 + +} \ No newline at end of file diff --git a/AdventOfCode2021/day6/day6.go b/AdventOfCode2021/day6/day6.go new file mode 100644 index 0000000..cf04829 --- /dev/null +++ b/AdventOfCode2021/day6/day6.go @@ -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 + +} \ No newline at end of file diff --git a/AdventOfCode2021/day7/day7.go b/AdventOfCode2021/day7/day7.go new file mode 100644 index 0000000..b363e31 --- /dev/null +++ b/AdventOfCode2021/day7/day7.go @@ -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 + +} \ No newline at end of file diff --git a/AdventOfCode2021/day8/day8.go b/AdventOfCode2021/day8/day8.go new file mode 100644 index 0000000..f58cb9e --- /dev/null +++ b/AdventOfCode2021/day8/day8.go @@ -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 +} \ No newline at end of file diff --git a/AdventOfCode2021/go.mod b/AdventOfCode2021/go.mod new file mode 100644 index 0000000..54eeb44 --- /dev/null +++ b/AdventOfCode2021/go.mod @@ -0,0 +1,3 @@ +module johncosta.tech/AdventOfCode2021 + +go 1.17 diff --git a/AdventOfCode2021/main.go b/AdventOfCode2021/main.go new file mode 100644 index 0000000..d252d11 --- /dev/null +++ b/AdventOfCode2021/main.go @@ -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("---------------------------------------") +} diff --git a/AdventOfCode2022/README.md b/AdventOfCode2022/README.md new file mode 100644 index 0000000..5b289cf --- /dev/null +++ b/AdventOfCode2022/README.md @@ -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. diff --git a/AdventOfCode2022/bun.lockb b/AdventOfCode2022/bun.lockb new file mode 100755 index 0000000..d05205d Binary files /dev/null and b/AdventOfCode2022/bun.lockb differ diff --git a/AdventOfCode2022/nodemon.json b/AdventOfCode2022/nodemon.json new file mode 100644 index 0000000..f2fb416 --- /dev/null +++ b/AdventOfCode2022/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["src"], + "ext": ".ts,.js", + "ignore": [], + "exec": "bun run start" +} diff --git a/AdventOfCode2022/package.json b/AdventOfCode2022/package.json new file mode 100644 index 0000000..6ea5436 --- /dev/null +++ b/AdventOfCode2022/package.json @@ -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" + } +} diff --git a/AdventOfCode2022/src/days/Day1.ts b/AdventOfCode2022/src/days/Day1.ts new file mode 100644 index 0000000..2b3d572 --- /dev/null +++ b/AdventOfCode2022/src/days/Day1.ts @@ -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)]; +}; diff --git a/AdventOfCode2022/src/days/Day10.ts b/AdventOfCode2022/src/days/Day10.ts new file mode 100644 index 0000000..13d5f70 --- /dev/null +++ b/AdventOfCode2022/src/days/Day10.ts @@ -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]; +} diff --git a/AdventOfCode2022/src/days/Day11.ts b/AdventOfCode2022/src/days/Day11.ts new file mode 100644 index 0000000..1e906ee --- /dev/null +++ b/AdventOfCode2022/src/days/Day11.ts @@ -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]]; +}; diff --git a/AdventOfCode2022/src/days/Day12.ts b/AdventOfCode2022/src/days/Day12.ts new file mode 100644 index 0000000..b3ea72d --- /dev/null +++ b/AdventOfCode2022/src/days/Day12.ts @@ -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, + 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 = {}; + 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, + 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; +}; diff --git a/AdventOfCode2022/src/days/Day13.ts b/AdventOfCode2022/src/days/Day13.ts new file mode 100644 index 0000000..76ff9be --- /dev/null +++ b/AdventOfCode2022/src/days/Day13.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day14.ts b/AdventOfCode2022/src/days/Day14.ts new file mode 100644 index 0000000..dc1598f --- /dev/null +++ b/AdventOfCode2022/src/days/Day14.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day15.ts b/AdventOfCode2022/src/days/Day15.ts new file mode 100644 index 0000000..e2a3229 --- /dev/null +++ b/AdventOfCode2022/src/days/Day15.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day17.ts b/AdventOfCode2022/src/days/Day17.ts new file mode 100644 index 0000000..b4d72bd --- /dev/null +++ b/AdventOfCode2022/src/days/Day17.ts @@ -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 = {}; + + 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]; +}; diff --git a/AdventOfCode2022/src/days/Day18.ts b/AdventOfCode2022/src/days/Day18.ts new file mode 100644 index 0000000..95f52d0 --- /dev/null +++ b/AdventOfCode2022/src/days/Day18.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day2.ts b/AdventOfCode2022/src/days/Day2.ts new file mode 100644 index 0000000..a8fe509 --- /dev/null +++ b/AdventOfCode2022/src/days/Day2.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day3.ts b/AdventOfCode2022/src/days/Day3.ts new file mode 100644 index 0000000..2066558 --- /dev/null +++ b/AdventOfCode2022/src/days/Day3.ts @@ -0,0 +1,35 @@ +import { DayFunc } from ".."; + +const getCode = (x: Set): 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); + }, 0) + + return [part1, part2]; +}; diff --git a/AdventOfCode2022/src/days/Day4.ts b/AdventOfCode2022/src/days/Day4.ts new file mode 100644 index 0000000..992fdc6 --- /dev/null +++ b/AdventOfCode2022/src/days/Day4.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day5.ts b/AdventOfCode2022/src/days/Day5.ts new file mode 100644 index 0000000..4384211 --- /dev/null +++ b/AdventOfCode2022/src/days/Day5.ts @@ -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]; +}; diff --git a/AdventOfCode2022/src/days/Day6.ts b/AdventOfCode2022/src/days/Day6.ts new file mode 100644 index 0000000..4c617b9 --- /dev/null +++ b/AdventOfCode2022/src/days/Day6.ts @@ -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)]; +} diff --git a/AdventOfCode2022/src/days/Day7.ts b/AdventOfCode2022/src/days/Day7.ts new file mode 100644 index 0000000..d45d9d7 --- /dev/null +++ b/AdventOfCode2022/src/days/Day7.ts @@ -0,0 +1,92 @@ +import { DayFunc } from ".."; + +type Node = { + name: string; + type: "file" | "dir"; + size: number; +}; + +type Files = { + [key: string]: { size: number; children: Node[] }; +}; + +const totalItems: Files = {}; + +const CalcSize = (dirName: string): number => { + const dir = totalItems[dirName]; + let size = 0; + for (const c of dir.children) { + if (c.type === "file") { + size += c.size; + } else { + size += CalcSize(c.name); + } + } + dir.size = size; + return size; +}; + +export const Day7: DayFunc = (input) => { + const parsed = input + .trim() + .split("\n") + .filter((i) => i !== "$ ls").slice(1); + + let path: string[] = []; + let items: Node[] = []; + + parsed.forEach((i) => { + let pathReduced = "/"; + for (const c of path) { + pathReduced += c + "/"; + } + if (i === "$ cd ..") { + if (!(pathReduced in totalItems)) { + totalItems[pathReduced] = { size: 0, children: [...items] }; + items = []; + } + path.pop(); + } else if (i.charAt(0) === "$") { + if (!(pathReduced in totalItems)) { + totalItems[pathReduced] = { size: 0, children: [...items] }; + items = []; + } + path.push(i.split(" ")[2]); + } else { + const s = i.split(" "); + items.push({ + type: s[0] === "dir" ? "dir" : "file", + size: s[0] === "dir" ? 0 : parseInt(s[0]), + name: s[0] === "dir" ? pathReduced + s[1] + "/" : s[1], + }); + } + }); + + let pathReduced = "/"; + for (const c of path) { + pathReduced += c + "/"; + } + if (!(pathReduced in totalItems)) { + totalItems[pathReduced] = { size: -1, children: [...items] }; + items = []; + } + + CalcSize("/"); + const part1 = Object.values(totalItems).reduce((p, n) => { + if (n.size <= 100000) { + return p + n.size; + } + return p; + }, 0); + + const usedSize = totalItems["/"].size; + const toFree = 30000000 - (70000000 - usedSize); + + const part2 = Object.entries(totalItems).map(v => { + if (v[1].size > toFree) { + return v[1].size; + } + }).filter(v => v).sort()[0]; + + return [part1, part2]; +}; diff --git a/AdventOfCode2022/src/days/Day8.ts b/AdventOfCode2022/src/days/Day8.ts new file mode 100644 index 0000000..53d0918 --- /dev/null +++ b/AdventOfCode2022/src/days/Day8.ts @@ -0,0 +1,57 @@ +import { DayFunc } from ".."; + +const GetSmaller = (arr: number[], target: number): number => { + let i = 0; + for (; i < arr.length && arr[i] < target; i++) {} + return i; +}; + +const Part2 = (arr: number[], target: number): number => { + const i = arr.findIndex(i => i >= target); + if (i === -1) { + return arr.length; + } + return i + 1; +} + +export const Day8: DayFunc = (input) => { + const parsed: number[][] = input + .trim() + .split("\n") + .map((v) => v.split("").map((i) => parseInt(i))); + const transposed = parsed[0].map((_, colIndex) => + parsed.map((row) => row[colIndex]) + ); + + let part1 = parsed.length * 2 + parsed[0].length * 2 - 4; + let part2 = 0; + + for (let i = 1; i < parsed.length - 1; i++) { + for (let j = 1; j < parsed[0].length - 1; j++) { + const c = parsed[i][j]; + const row = parsed[i]; + const col = transposed[j]; + + const left = row.slice(0, j).reverse(); + const right = row.slice(j + 1); + const top = col.slice(0, i).reverse(); + const bottom = col.slice(i + 1); + + if ( + GetSmaller(left, c) === left.length || + GetSmaller(right, c) === right.length || + GetSmaller(top, c) === top.length || + GetSmaller(bottom, c) === bottom.length + ) { + part1++; + } + + const view = Part2(left, c) * Part2(right, c) * Part2(top, c) * Part2(bottom, c); + if (view > part2) { + part2 = view; + } + } + } + + return [part1, part2]; +}; diff --git a/AdventOfCode2022/src/days/Day9.ts b/AdventOfCode2022/src/days/Day9.ts new file mode 100644 index 0000000..0ec9d26 --- /dev/null +++ b/AdventOfCode2022/src/days/Day9.ts @@ -0,0 +1,71 @@ +import { DayFunc } from ".."; + +type Pos = { x: number; y: number }; + +// Returns the non square rooted distance +const CalcDist = (a: Pos, b: Pos) => { + return (a.x - b.x) ** 2 + (a.y - b.y) ** 2; +}; + +const CalcVisited = (snake: Pos[], parsed: [string, number][]): Record => { + + const visited: Record = {}; + visited[JSON.stringify(snake[1])] = 1; + + parsed.forEach(([direction, num]) => { + for (let i = 0; i < num; i++) { + if (direction === "R") snake[0].x++; + else if (direction === "L") snake[0].x--; + else if (direction === "U") snake[0].y++; + else if (direction === "D") snake[0].y--; + + for (let j = 1; j < snake.length; j++) { + const t = snake[j]; + const h = snake[j - 1] + const dist = CalcDist(h, t); + if (dist === 4) { + if (t.x === h.x) { + t.y += (h.y < t.y) ? -1 : 1; + } else if (t.y === h.y) { + t.x += (h.x < t.x) ? -1 : 1; + } + } else if (dist === 5 || dist === 8) { + t.x += (h.x > t.x) ? 1 : -1; + t.y += (h.y > t.y) ? 1 : -1; + } + } + + const tailString = JSON.stringify(snake[snake.length - 1]); + if (tailString in visited) { + visited[tailString] = visited[tailString] + 1; + } else { + visited[tailString] = 1; + } + } + }); + + return visited; +} + +export const Day9: DayFunc = (input) => { + const parsed: [string, number][] = input + .trim() + .split("\n") + .map((v) => v.split(" ")) + .map(([a, b]) => [a, parseInt(b)]); + + // 0th index is the head; + const part1Snake: Pos[] = [ + { x: 0, y: 0 }, + { x: 0, y: 0 }, + ]; + const part2Snake: Pos[] = []; + for (let i = 0; i < 10; i++) { + part2Snake.push({x: 0, y: 0}); + } + + const part1 = CalcVisited(part1Snake, parsed) + const part2 = CalcVisited(part2Snake, parsed) + + return [Object.keys(part1).length, Object.keys(part2).length]; +}; diff --git a/AdventOfCode2022/src/days/index.ts b/AdventOfCode2022/src/days/index.ts new file mode 100644 index 0000000..a6d075a --- /dev/null +++ b/AdventOfCode2022/src/days/index.ts @@ -0,0 +1,17 @@ +export * from './Day1'; +export * from './Day2'; +export * from './Day3'; +export * from './Day4'; +export * from './Day5'; +export * from './Day6'; +export * from './Day7'; +export * from './Day8'; +export * from './Day9'; +export * from './Day10'; +export * from './Day11'; +export * from './Day12'; +export * from './Day13'; +export * from './Day14'; +export * from './Day15'; +export * from './Day17'; +export * from './Day18'; diff --git a/AdventOfCode2022/src/index.ts b/AdventOfCode2022/src/index.ts new file mode 100644 index 0000000..2601111 --- /dev/null +++ b/AdventOfCode2022/src/index.ts @@ -0,0 +1,63 @@ +import { file } from "bun"; +import { + Day1, + Day2, + Day3, + Day4, + Day5, + Day6, + Day7, + Day8, + Day9, + Day10, + Day11, + Day12, + Day13, + Day14, + Day17, + Day15, + Day18, +} from "./days"; + +export type DayFunc = (input: string) => [any, any]; +export const UP = "\033[F"; + +const RunDay = async ( + dayFunc: (input: string) => [number, number], + dayPath: string +) => { + console.time("Time Taken"); + const dayInput = await file(`./inputs/${dayPath}.txt`).text(); + const [part1, part2] = dayFunc(dayInput); + + console.log( + `------------------Day ${dayPath.charAt( + dayPath.length - 1 + )}--------------------` + ); + console.log("Part 1:", part1); + console.log("Part 2:", part2); + console.timeEnd("Time Taken"); + console.log("------------------------------------------"); +}; + +console.log("Advent Of Code - 2022"); +console.time("total"); + +// await RunDay(Day1, 'day1'); +// await RunDay(Day2, 'day2'); +// await RunDay(Day3, 'day3'); +// await RunDay(Day4, 'day4'); +// await RunDay(Day5, 'day5'); +// await RunDay(Day6, 'day6'); +// await RunDay(Day7, 'day7'); +// await RunDay(Day8, 'day8'); +// await RunDay(Day9, 'day9'); +// await RunDay(Day10, 'day10'); +// await RunDay(Day11, 'day11'); +// await RunDay(Day12, 'day12'); +// await RunDay(Day13, 'day13'); +// await RunDay(Day14, "day14"); +// await RunDay(Day17, "day17"); +await RunDay(Day18, 'day18'); +console.timeEnd("total"); diff --git a/AdventOfCode2022/tsconfig.json b/AdventOfCode2022/tsconfig.json new file mode 100644 index 0000000..26e7df4 --- /dev/null +++ b/AdventOfCode2022/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "lib": ["ESNext"], + "module": "esnext", + "moduleResolution": "node", + "target": "esnext", + "types": ["bun-types"] + } +}