Big update: Adding all advent of codes to same repo

This commit is contained in:
2024-12-06 00:14:09 +00:00
parent 5116bd4696
commit 233dda4fe9
106 changed files with 7790 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
# Advent Of Code 2015
I started doing AoC puzzles in 2020. I have a few more days to finish in 2020, but I wanted to start on 2015 as a way to learn more about Golang.
A language which I want to properly learn, and this is a brilliant way of doing just that.
## Day 6
Brute forced solution, it would be good to get a real solution which takes less than a few milliseconds.
## Day 7
Partial solution, misread the instructions, need to rethink it entirely. I actually wrote an emulator for the second set of example instructions
## Day 8
Just started it, not finished as I have to do something else right now.
- Finished it, solution takes less than 1ms to complete. Could have finished it much quicker if I didn't forget to add regular characters onto the end result.

View File

@@ -0,0 +1,39 @@
package main
import (
"fmt"
"io/ioutil"
"time"
)
func main() {
fmt.Println("Day 1")
start := time.Now()
dat, err := ioutil.ReadFile("day1.txt")
if err != nil {
panic(err)
}
var floor int64 = 0
basement := -1
for i, value := range dat {
if basement == -1 && floor == -1 {
basement = i
}
if value == 40 {
floor++
} else if value == 41 {
floor--
}
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", floor, elapsed)
fmt.Printf("Part 2: %v %v", basement, elapsed)
}

View File

@@ -0,0 +1,49 @@
package main
import (
"fmt"
"strconv"
"time"
)
func main() {
fmt.Println("Day 9")
start := time.Now()
inputString := "1113122113"
input := []int64{}
for _, c := range inputString {
stringChar, _ := strconv.Atoi(string(c))
input = append(input, int64(stringChar))
}
//Change 40 to 50 for part 2
for rounds := 0; rounds < 40; rounds++ {
lastNum := input[0]
var counter int64 = 1
newNumbers := []int64{}
for i := 1; i < len(input); i++ {
if input[i] != lastNum {
newNumbers = append(newNumbers, counter)
newNumbers = append(newNumbers, lastNum)
counter = 1
lastNum = input[i]
} else {
counter++
}
}
newNumbers = append(newNumbers, counter)
newNumbers = append(newNumbers, lastNum)
input = newNumbers
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", len(input), elapsed)
fmt.Printf("Part 2: %v %v \n", len(input), elapsed)
}

View File

@@ -0,0 +1,64 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"time"
)
func main() {
fmt.Println("Day 12")
start := time.Now()
dat, err := ioutil.ReadFile("day12.json")
if err != nil {
panic(err)
}
var result map[string]interface{}
json.Unmarshal(dat, &result)
fmt.Printf("Input: %v | %T \n", result, result)
var count float64 = solver(result)
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", count, elapsed)
}
func solver(json map[string]interface{}) float64 {
var counter float64
for _, value := range json {
switch valueType := value.(type) {
case bool:
case float64:
counter += valueType
case string:
case []interface{}:
counter += interfaceArraySolver(valueType)
case map[string]interface{}:
counter += solver(valueType)
}
}
return counter
}
func interfaceArraySolver(json []interface{}) float64 {
var counter float64
for _, value := range json {
switch valueType := value.(type) {
case bool:
case float64:
counter += valueType
case string:
case []interface{}:
counter += interfaceArraySolver(valueType)
case map[string]interface{}:
counter += solver(valueType)
}
}
return counter
}

View File

@@ -0,0 +1,55 @@
const fs = require('fs');
const obj = JSON.parse(fs.readFileSync('day12.json', 'utf8'));
console.log("Part 1: " + solver(obj));
console.log("Part 2: ", + solverPart2(obj));
function solver(json) {
let counter = 0;
for (let value in json) {
if (typeof json[value] == 'number') {
counter += json[value]
} else if (typeof json[value] == 'boolean') {
} else if (typeof json[value] == 'string') {
} else if (typeof json[value] == 'object') {
counter += solver(json[value]);
}
}
return counter;
}
function solverPart2(json) {
let counter = 0;
let redFound = false;
let toSolver = [];
for (let value in json) {
if (typeof json[value] == 'number') {
counter += json[value]
} else if (typeof json[value] == 'boolean') {
} else if (typeof json[value] == 'string') {
if (json[value] == 'red' && !Array.isArray(json)) {
redFound = true;
break;
}
} else if (typeof json[value] == 'object') {
toSolver.push(json[value]);
}
}
if (redFound) {
return 0;
} else {
for (let e of toSolver) {
counter += solverPart2(e);
}
return counter;
}
}

View File

@@ -0,0 +1,143 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"strconv"
"strings"
"time"
)
type Combination struct {
subject string
nextTo string
}
type Average struct {
person1 string
person2 string
average int
}
func main() {
fmt.Println("Day 13")
start := time.Now()
dat, err := ioutil.ReadFile("day13.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
combinationMap := make(map[Combination]int)
people := make([]string, 0)
for _, line := range lines {
stringLine := string(line)
stringLine = stringLine[:len(stringLine)-1]
lineWordArray := strings.Split(string(stringLine), " ")
gained, _ := strconv.Atoi(lineWordArray[3])
if !contains(people, lineWordArray[0]) {
people = append(people, lineWordArray[0])
}
if lineWordArray[2] == "lose" {
gained = -gained
}
combinationMap[Combination{subject: lineWordArray[0], nextTo: lineWordArray[10]}] = gained
}
averageCombinations := make([]Average, 0)
for _, person := range people {
for i := 0; i < len(people); i++ {
nextPerson := people[i]
if nextPerson != person {
average := combinationMap[Combination{subject: person, nextTo: nextPerson}] + combinationMap[Combination{subject: nextPerson, nextTo: person}]
averageCombinations = append(averageCombinations, Average{person1: person, person2: nextPerson, average: average})
}
}
}
startingPerson := people[0]
remaining := make([]string, 0)
for _, value := range people {
if value != startingPerson {
remaining = append(remaining, value)
}
}
part1 := travellingSalesMan(averageCombinations, startingPerson, startingPerson, remaining)
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
start = time.Now()
for _, person := range people {
averageCombinations = append(averageCombinations, Average{person1: "me", person2: person, average: 0})
averageCombinations = append(averageCombinations, Average{person1: person, person2: "me", average: 0})
}
people = append(people, "me")
startingPerson = people[0]
remaining = make([]string, 0)
for _, value := range people {
if value != startingPerson {
remaining = append(remaining, value)
}
}
part2 := travellingSalesMan(averageCombinations, startingPerson, startingPerson, remaining)
elapsed = time.Since(start)
fmt.Printf("Part 2: %v %v \n", part2, elapsed)
}
func travellingSalesMan(averages []Average, startingPerson string, currentPerson string, remainingPeople []string) int {
//*Needs to return to the beginning
if len(remainingPeople) == 0 {
return getAverage(averages, startingPerson, currentPerson)
} else {
distances := make([]int, 0)
for _, person := range remainingPeople {
newRemaining := make([]string, 0)
for _, p := range remainingPeople {
if p != person {
newRemaining = append(newRemaining, p)
}
}
distances = append(distances, getAverage(averages, currentPerson, person)+travellingSalesMan(averages, startingPerson, person, newRemaining))
}
max := 0
for _, value := range distances {
if value > max {
max = value
}
}
return max
}
}
func contains(array []string, person string) bool {
for _, v := range array {
if v == person {
return true
}
}
return false
}
func getAverage(array []Average, person1 string, person2 string) int {
for _, p := range array {
if p.person1 == person1 && p.person2 == person2 {
return p.average
}
}
return 0
}

View File

@@ -0,0 +1,89 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"strconv"
"strings"
"time"
)
func main() {
fmt.Println("Day 13")
start := time.Now()
dat, err := ioutil.ReadFile("day14.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
part1 := 0
total := 2503
for _, line := range lines {
stringLine := string(line)
splitLine := strings.Split(stringLine, " ")
v, _ := strconv.Atoi(splitLine[3])
s, _ := strconv.Atoi(splitLine[6])
r, _ := strconv.Atoi(splitLine[13])
currentDistance := (total / (s + r)) * v * s
remaining := total % (s + r)
if remaining >= s {
currentDistance += v * s
} else {
currentDistance += v * remaining
}
if currentDistance > part1 {
part1 = currentDistance
}
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
start = time.Now()
horses := make(map[int]int)
for i := 1; i <= total; i++ {
longest := 0
fastestHorse := 0
for index, line := range lines {
stringLine := string(line)
splitLine := strings.Split(stringLine, " ")
v, _ := strconv.Atoi(splitLine[3])
s, _ := strconv.Atoi(splitLine[6])
r, _ := strconv.Atoi(splitLine[13])
currentDistance := (i / (s + r)) * v * s
remaining := i % (s + r)
if remaining >= s {
currentDistance += v * s
} else {
currentDistance += v * remaining
}
if currentDistance > longest {
longest = currentDistance
fastestHorse = index
}
}
horses[fastestHorse] = horses[fastestHorse] + 1
}
fastest := 0
for _, value := range horses {
if value > fastest {
fastest = value
}
}
elapsed = time.Since(start)
fmt.Printf("Part 2: %v %v \n", fastest, elapsed)
}

View File

@@ -0,0 +1,93 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"strconv"
"strings"
)
func main() {
fmt.Println("Day 15")
dat, err := ioutil.ReadFile("day15.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
ingredients := make([][]int, 4)
for i := range ingredients {
ingredients[i] = make([]int, 5)
}
for index, line := range lines {
stringLine := string(line)
splitString := strings.Split(stringLine, " ")
ingredients[index][0], _ = strconv.Atoi(strings.TrimRight(splitString[2], ","))
ingredients[index][1], _ = strconv.Atoi(strings.TrimRight(splitString[4], ","))
ingredients[index][2], _ = strconv.Atoi(strings.TrimRight(splitString[6], ","))
ingredients[index][3], _ = strconv.Atoi(strings.TrimRight(splitString[8], ","))
ingredients[index][4], _ = strconv.Atoi(splitString[10])
}
best := 0
part2 := 0
for a := 0; a <= 100; a++ {
for b := 0; b <= 100-a; b++ {
for c := 0; c <= 100-a-b; c++ {
for d := 0; d <= 100-a-b-c; d++ {
calculation := calc_cookie(ingredients, a, b, c, d)
totalCalories := a*ingredients[0][4] + b*ingredients[1][4] + c*ingredients[2][4] + d*ingredients[3][4]
if calculation > best {
best = calculation
}
if totalCalories == 500 && calculation > part2 {
part2 = calculation
}
}
}
}
}
fmt.Println(best)
fmt.Println(part2)
}
func calc_cookie(ingredients [][]int, sprinkles int, peanut int, frosting int, sugar int) int {
capacity := sprinkles*ingredients[0][0] +
peanut*ingredients[1][0] +
frosting*ingredients[2][0] +
sugar*ingredients[3][0]
durability := sprinkles*ingredients[0][1] +
peanut*ingredients[1][1] +
frosting*ingredients[2][1] +
sugar*ingredients[3][1]
flavor := sprinkles*ingredients[0][2] +
peanut*ingredients[1][2] +
frosting*ingredients[2][2] +
sugar*ingredients[3][2]
texture := sprinkles*ingredients[0][3] +
peanut*ingredients[1][3] +
frosting*ingredients[2][3] +
sugar*ingredients[3][3]
if capacity <= 0 || durability <= 0 || flavor <= 0 || texture <= 0 {
return 0
} else {
return capacity * durability * flavor * texture
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,118 @@
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
File myFile = new File("day16.txt");
Scanner in = new Scanner(myFile);
int index = 1;
while (in.hasNext()) {
String[] input = in.nextLine().replaceAll("\\s+", "").split(":");
Map<String, Integer> currentAunt = new HashMap<>();
String[] secondLineSplit = input[2].split(",");
String[] thirdLineSplit = input[3].split(",");
currentAunt.put(input[1], Integer.parseInt(secondLineSplit[0]));
currentAunt.put(secondLineSplit[1], Integer.parseInt(thirdLineSplit[0]));
currentAunt.put(thirdLineSplit[1], Integer.parseInt(input[4]));
int counter = 0;
int part2counter = 0;
for (String key : currentAunt.keySet()) {
switch (key) {
case "children":
if (currentAunt.get(key) == 3) {
counter++;
part2counter++;
}
break;
case "cats":
if (currentAunt.get(key) == 7) {
counter++;
}
if (currentAunt.get(key) > 7) {
part2counter++;
}
break;
case "samoyeds":
if (currentAunt.get(key) == 2) {
counter++;
part2counter++;
}
break;
case "pomeranians":
if (currentAunt.get(key) == 3) {
counter++;
}
if (currentAunt.get(key) < 3) {
part2counter++;
}
break;
case "akitas":
if (currentAunt.get(key) == 0) {
counter++;
part2counter++;
}
break;
case "vizslas":
if (currentAunt.get(key) == 0) {
counter++;
part2counter++;
}
break;
case "goldfish":
if (currentAunt.get(key) == 5) {
counter++;
}
if (currentAunt.get(key) < 5) {
part2counter++;
}
break;
case "trees":
if (currentAunt.get(key) == 3) {
counter++;
}
if (currentAunt.get(key) > 3) {
part2counter++;
}
break;
case "cars":
if (currentAunt.get(key) == 2) {
counter++;
part2counter++;
}
break;
case "perfumes":
if (currentAunt.get(key) == 1) {
counter++;
part2counter++;
}
break;
}
}
if (counter == 3) {
System.out.printf("Part 1: %d \n", index);
} else if (part2counter == 3) {
System.out.printf("Part 2: %d \n", index);
}
index++;
}
in.close();
}
}

View File

@@ -0,0 +1,53 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"strconv"
"time"
)
func main() {
fmt.Println("Day 2")
start := time.Now()
dat, err := ioutil.ReadFile("day2.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
total := 0
totalPart2 := 0
for _, value := range lines {
splitLine := bytes.Split(value, []byte("x"))
l, _ := strconv.Atoi(string(splitLine[0]))
w, _ := strconv.Atoi(string(splitLine[1]))
h, _ := strconv.Atoi(string(splitLine[2]))
total += 2*l*w + 2*l*h + 2*w*h + MinOf(l*w, w*h, h*l)
totalPart2 += MinOf(l*2+w*2, w*2+h*2, h*2+l*2) + l*w*h
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", total, elapsed)
fmt.Printf("Part 2: %v %v", totalPart2, elapsed)
}
func MinOf(vars ...int) int {
min := vars[0]
for _, i := range vars {
if min > i {
min = i
}
}
return min
}

View File

@@ -0,0 +1,69 @@
package main
import (
"fmt"
"io/ioutil"
"time"
)
type Coords struct {
x int
y int
}
func main() {
fmt.Println("Day 3")
start := time.Now()
dat, err := ioutil.ReadFile("day3.txt")
if err != nil {
panic(err)
}
position := Coords{x: 0, y: 0}
visited := make(map[Coords]int)
visited[position] = 1
for _, value := range dat {
solve(visited, &position, value)
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", len(visited), elapsed)
start = time.Now()
position = Coords{x: 0, y: 0}
visited = make(map[Coords]int)
visited[position] = 1
for i := 0; i < len(dat); i = i + 2 {
solve(visited, &position, dat[i])
}
position.x = 0
position.y = 0
for i := 1; i < len(dat); i = i + 2 {
solve(visited, &position, dat[i])
}
fmt.Printf("Part 2: %v %v", len(visited), elapsed)
}
func solve(visited map[Coords]int, position *Coords, value byte) {
if value == []byte("<")[0] {
position.x--
visited[*position]++
} else if value == []byte(">")[0] {
position.x++
visited[*position]++
} else if value == []byte("^")[0] {
position.y++
visited[*position]++
} else if value == []byte("v")[0] {
position.y--
visited[*position]++
}
}

View File

@@ -0,0 +1,53 @@
package main
import (
"crypto/md5"
"fmt"
"io/ioutil"
"strconv"
"time"
)
type Coords struct {
x int
y int
}
func main() {
fmt.Println("Day 3")
start := time.Now()
dat, err := ioutil.ReadFile("day4.txt")
if err != nil {
panic(err)
}
input := string(dat)
part1 := ""
var hash [16]byte
for i := 1; part1 == ""; i++ {
hashString := input + strconv.Itoa(i)
hash = md5.Sum([]byte(hashString))
if hash[0] == 0x00 && hash[1] == 0x00 && hash[2] <= 0x0f {
part1 = hashString
}
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
start = time.Now()
part2 := ""
for i := 1; part2 == ""; i++ {
hashString := input + strconv.Itoa(i)
hash = md5.Sum([]byte(hashString))
if hash[0] == 0x00 && hash[1] == 0x00 && hash[2] == 0x00 {
part2 = hashString
}
}
elapsed = time.Since(start)
fmt.Printf("Part 2: %v %v", part2, elapsed)
}

View File

@@ -0,0 +1,107 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"time"
)
func main() {
fmt.Println("Day 5")
start := time.Now()
dat, err := ioutil.ReadFile("day5.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
part1 := 0
part2 := 0
for _, value := range lines {
vowels := 0
twiceInARow := false
forbiddenPhrases := false
for i := 0; i < len(value); i++ {
current := value[i]
if current == []byte("a")[0] || current == []byte("e")[0] || current == []byte("i")[0] || current == []byte("o")[0] || current == []byte("u")[0] {
vowels++
}
if i != 0 {
if value[i-1] == value[i] {
twiceInARow = true
}
last2 := []byte{value[i-1], value[i]}
if compare(last2, []byte("ab")) || compare(last2, []byte("cd")) || compare(last2, []byte("pq")) || compare(last2, []byte("xy")) {
forbiddenPhrases = true
break
}
}
}
if !forbiddenPhrases {
if twiceInARow && vowels >= 3 {
part1++
}
}
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
start = time.Now()
for _, value := range lines {
repeatedPair := false
repeatedLetterWithGap := false
var pairs [][]byte
for i := 0; i < len(value)-1; i++ {
pairs = append(pairs, value[i:i+2])
}
for i := 0; i < len(pairs)-1; i++ {
for j := i + 2; j < len(pairs); j++ {
if compare(pairs[i], pairs[j]) {
repeatedPair = true
break
}
}
}
for i := 0; i < len(value)-2; i++ {
if value[i] == value[i+2] {
repeatedLetterWithGap = true
break
}
}
if repeatedLetterWithGap && repeatedPair {
part2++
}
}
elapsed = time.Since(start)
fmt.Printf("Part 2: %v %v", part2, elapsed)
}
func compare(slice1 []byte, slice2 []byte) bool {
for i := 0; i < len(slice1) && i < len(slice2); i++ {
if slice1[i] != slice2[i] {
return false
}
}
return true
}

View File

@@ -0,0 +1,130 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"strconv"
"time"
)
type Square struct {
x int64
y int64
}
func main() {
fmt.Println("Day 6")
start := time.Now()
dat, err := ioutil.ReadFile("day6.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
lights := make(map[Square]bool)
lights2 := make(map[Square]int64)
SwitchTheLights(lights, false, false, 0, 0, 1000, 1000)
part1 := 0
var part2 int64 = 0
for _, value := range lines {
words := bytes.Split(value, []byte(" "))
if len(words) == 4 {
start := bytes.Split(words[1], []byte(","))
end := bytes.Split(words[3], []byte(","))
startX, _ := strconv.Atoi(string(start[0]))
startY, _ := strconv.Atoi(string(start[1]))
endX, _ := strconv.Atoi(string(end[0]))
endY, _ := strconv.Atoi(string(end[1]))
SwitchTheLights(lights, false, true, int64(startX), int64(startY), int64(endX), int64(endY))
SwitchTheLights2(lights2, false, true, int64(startX), int64(startY), int64(endX), int64(endY))
} else {
start := bytes.Split(words[2], []byte(","))
end := bytes.Split(words[4], []byte(","))
startX, _ := strconv.Atoi(string(start[0]))
startY, _ := strconv.Atoi(string(start[1]))
endX, _ := strconv.Atoi(string(end[0]))
endY, _ := strconv.Atoi(string(end[1]))
SwitchTheLights(lights, compare(words[1], []byte("on")), false, int64(startX), int64(startY), int64(endX), int64(endY))
SwitchTheLights2(lights2, compare(words[1], []byte("on")), false, int64(startX), int64(startY), int64(endX), int64(endY))
}
}
for _, v := range lights {
if v {
part1++
}
}
for _, v := range lights2 {
part2 += v
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", part1, elapsed)
fmt.Printf("Part 2: %v %v \n", part2, elapsed)
}
func SwitchTheLights(lights map[Square]bool, state bool, toggle bool, startX int64, startY int64, endX int64, endY int64) {
for i := startX; i <= endX; i++ {
for j := startY; j <= endY; j++ {
if toggle {
lights[Square{x: i, y: j}] = !lights[Square{x: i, y: j}]
} else {
lights[Square{x: i, y: j}] = state
}
}
}
}
func SwitchTheLights2(lights map[Square]int64, state bool, toggle bool, startX int64, startY int64, endX int64, endY int64) {
for i := startX; i <= endX; i++ {
for j := startY; j <= endY; j++ {
var brighness int64 = lights[Square{x: i, y: j}]
if toggle {
lights[Square{x: i, y: j}] = brighness + 2
} else {
if state {
lights[Square{x: i, y: j}] = brighness + 1
} else {
lights[Square{x: i, y: j}] = brighness - 1
if lights[Square{x: i, y: j}] < 0 {
lights[Square{x: i, y: j}] = 0
}
}
}
}
}
}
func compare(slice1 []byte, slice2 []byte) bool {
for i := 0; i < len(slice1) && i < len(slice2); i++ {
if slice1[i] != slice2[i] {
return false
}
}
return true
}

View File

@@ -0,0 +1,155 @@
const std = @import("std");
const utils = @import("./utils.zig");
const InstructionType = enum { LITERAL, REASSIGN, NOT, AND, HACKY_AND, OR, LSHIFT, RSHIFT };
const Instruction = struct {
type: InstructionType,
// To be used with LITERAL
num: ?u16,
firstLetter: ?[]const u8,
secondLetter: ?[]const u8,
};
fn getOp(op: []const u8) InstructionType {
if (std.mem.eql(u8, op, "AND")) {
return InstructionType.AND;
}
if (std.mem.eql(u8, op, "OR")) {
return InstructionType.OR;
}
if (std.mem.eql(u8, op, "LSHIFT")) {
return InstructionType.LSHIFT;
}
if (std.mem.eql(u8, op, "RSHIFT")) {
return InstructionType.RSHIFT;
}
unreachable;
}
fn getLetter(map: std.StringHashMap(Instruction), cache: *std.StringHashMap(u16), letter: []const u8) !u16 {
if (cache.contains(letter)) {
return cache.*.get(letter).?;
}
var op = map.get(letter).?;
if (op.type == InstructionType.LITERAL) {
try cache.*.put(letter, op.num.?);
return op.num.?;
}
if (op.type == InstructionType.NOT) {
var notRes = ~(try getLetter(map, cache, op.firstLetter.?));
try cache.*.put(letter, notRes);
return notRes;
}
if (op.type == InstructionType.REASSIGN) {
var reassignRes = try getLetter(map, cache, op.firstLetter.?);
try cache.*.put(letter, reassignRes);
return reassignRes;
}
var first = try getLetter(map, cache, op.firstLetter.?);
if (op.type == InstructionType.HACKY_AND) {
try cache.*.put(letter, op.num.? & first);
return op.num.? & first;
}
if (op.type == InstructionType.AND or op.type == InstructionType.OR) {
var second = try getLetter(map, cache, op.secondLetter.?);
if (op.type == InstructionType.AND) {
try cache.*.put(letter, first & second);
return first & second;
}
try cache.*.put(letter, first | second);
return first | second;
}
if (op.type == InstructionType.LSHIFT) {
var shortNum: u4 = @truncate(op.num.?);
try cache.*.put(letter, first << shortNum);
return first << shortNum;
}
var shortNum: u4 = @truncate(op.num.?);
try cache.*.put(letter, first >> shortNum);
return first >> shortNum;
}
pub fn main() !void {
var allocator = std.heap.page_allocator;
var lines = try utils.splitLines("input.txt", allocator);
defer lines.deinit();
var wireMap = std.StringHashMap(Instruction).init(allocator);
defer wireMap.deinit();
var resultCache = std.StringHashMap(u16).init(allocator);
defer resultCache.deinit();
for (lines.items) |line| {
var instructionAndOutput = std.mem.tokenizeSequence(u8, line, " -> ");
var op = instructionAndOutput.next().?;
var output = instructionAndOutput.next().?;
var instructionParts = std.mem.tokenizeSequence(u8, op, " ");
var first = instructionParts.next().?;
if (std.mem.eql(u8, first, "NOT")) {
var notOp = Instruction{ .type = InstructionType.NOT, .firstLetter = instructionParts.next().?, .num = undefined, .secondLetter = undefined };
try wireMap.put(output, notOp);
continue;
}
var firstNumber = std.fmt.parseInt(u16, first, 10) catch {
// Must be a regular double operation (a AND b)
if (instructionParts.next()) |rawOperator| {
var operator = getOp(rawOperator);
var second = instructionParts.next().?;
var myOp = switch (operator) {
InstructionType.AND, InstructionType.OR => Instruction{ .type = operator, .firstLetter = first, .secondLetter = second, .num = undefined },
InstructionType.LSHIFT, InstructionType.RSHIFT => Instruction{ .type = operator, .firstLetter = first, .secondLetter = undefined, .num = try std.fmt.parseInt(u4, second, 10) },
else => unreachable,
};
try wireMap.put(output, myOp);
continue;
}
// x -> y
var reassign = Instruction{ .type = InstructionType.REASSIGN, .firstLetter = first, .secondLetter = undefined, .num = undefined };
try wireMap.put(output, reassign);
continue;
};
// Edge case. and gates can have numbers too (seems to be limited to first argument).
if (instructionParts.next()) |_| {
// an and operation with a 1 in front.
var second = instructionParts.next().?;
var hackyAnd = Instruction{ .type = InstructionType.HACKY_AND, .firstLetter = second, .secondLetter = undefined, .num = firstNumber };
try wireMap.put(output, hackyAnd);
continue;
}
var literalOp = Instruction{ .type = InstructionType.LITERAL, .num = firstNumber, .firstLetter = undefined, .secondLetter = undefined };
try wireMap.put(output, literalOp);
}
var part1 = try getLetter(wireMap, &resultCache, "a");
std.debug.print("Part 1: {}\n", .{part1});
var resetResultCache = std.StringHashMap(u16).init(allocator);
defer resetResultCache.deinit();
try resetResultCache.put("b", part1);
var part2 = try getLetter(wireMap, &resetResultCache, "a");
std.debug.print("Part 2: {}\n", .{part2});
}

View File

@@ -0,0 +1 @@
../../zig/utils.zig

View File

@@ -0,0 +1,83 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"time"
)
type Square struct {
x int64
y int64
}
func main() {
fmt.Println("Day 8")
start := time.Now()
dat, err := ioutil.ReadFile("day8.txt")
if err != nil {
panic(err)
}
lines := bytes.Split(dat, []byte("\n"))
part2 := 0
totalCharacters := 0
realCharacters := 0
for _, value := range lines {
line := string(value)
totalCharacters += len(line)
newLine := line[1 : len(line)-1]
currentReal := 0
for i := 0; i < len(newLine); i++ {
char := string(newLine[i])
if char == `\` {
nextChar := string(newLine[i+1])
if nextChar == "x" {
i = i + 2
} else if nextChar == `"` || nextChar == `\` {
i++
currentReal++
}
} else {
currentReal++
}
}
realCharacters += currentReal
currentPart2 := 0
for i := 0; i < len(line); i++ {
char := string(line[i])
if char == `"` || char == `\` {
currentPart2 += 2
} else {
currentPart2++
}
}
//Double quotes around the string
currentPart2 += 2
part2 += currentPart2
}
elapsed := time.Since(start)
fmt.Printf("Part 1: %v %v \n", totalCharacters-realCharacters, elapsed)
fmt.Printf("Part 2: %v %v \n", part2-totalCharacters, elapsed)
}
func compare(slice1 []byte, slice2 []byte) bool {
for i := 0; i < len(slice1) && i < len(slice2); i++ {
if slice1[i] != slice2[i] {
return false
}
}
return true
}