Created
December 5, 2024 09:04
-
-
Save YannickFricke/b1544e31d679810d15d9157c9c803bf7 to your computer and use it in GitHub Desktop.
AoC 2024 Day 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"math" | |
"os" | |
"slices" | |
"strconv" | |
"strings" | |
) | |
type Rule struct { | |
Lhs int | |
Rhs int | |
} | |
func parseRule(rawRule string) Rule { | |
parts := strings.Split(rawRule, "|") | |
lhs := parts[0] | |
rhs := parts[1] | |
parsedLhs, _ := strconv.Atoi(lhs) | |
parsedRhs, _ := strconv.Atoi(rhs) | |
return Rule{ | |
Lhs: parsedLhs, | |
Rhs: parsedRhs, | |
} | |
} | |
func parseUpdateLine(line string) []int { | |
parts := strings.Split(line, ",") | |
result := make([]int, 0) | |
for _, part := range parts { | |
parsedPart, _ := strconv.Atoi(part) | |
result = append(result, parsedPart) | |
} | |
return result | |
} | |
func getRulesForLine(updateLine []int, allRules []Rule) []Rule { | |
result := make([]Rule, 0) | |
for _, rule := range allRules { | |
if slices.Contains(updateLine, rule.Lhs) == false { | |
continue | |
} | |
if slices.Contains(updateLine, rule.Rhs) == false { | |
continue | |
} | |
result = append(result, rule) | |
} | |
return result | |
} | |
func getRulesForNumber(rules []Rule, number int) []Rule { | |
result := make([]Rule, 0) | |
for _, rule := range rules { | |
if rule.Rhs != number { | |
continue | |
} | |
result = append(result, rule) | |
} | |
return result | |
} | |
func areNumbersInSlice(slice []int, numbers []int) bool { | |
for _, number := range numbers { | |
if slices.Contains(slice, number) { | |
continue | |
} | |
return false | |
} | |
return true | |
} | |
func isInCorrectOrder(updateLine []int, lineRules []Rule) bool { | |
for index, number := range updateLine { | |
currentSlice := updateLine[0:index] | |
rulesForNumber := getRulesForNumber(lineRules, number) | |
requiredNumbers := make([]int, 0) | |
for _, rule := range rulesForNumber { | |
requiredNumbers = append(requiredNumbers, rule.Lhs) | |
} | |
if areNumbersInSlice(currentSlice, requiredNumbers) == false { | |
return false | |
} | |
} | |
return true | |
} | |
func getMiddlePageNumber(line []int) int { | |
index := math.Round(float64(len(line) / 2)) | |
return line[int(index)] | |
} | |
func addNumber(rowResult []int, lineRules []Rule, numberToAdd int) []int { | |
if slices.Contains(rowResult, numberToAdd) { | |
return rowResult | |
} | |
rulesForNumber := getRulesForNumber(lineRules, numberToAdd) | |
tempResult := rowResult | |
for _, rule := range rulesForNumber { | |
tempResult = addNumber(tempResult, lineRules, rule.Lhs) | |
} | |
return append(tempResult, numberToAdd) | |
} | |
func calculateResult(lines [][]int) int { | |
var result = 0 | |
for _, correctLine := range lines { | |
middlePageNumber := getMiddlePageNumber(correctLine) | |
result += middlePageNumber | |
} | |
return result | |
} | |
func part1(fileContents string) ([]Rule, [][]int) { | |
splittedContents := strings.Split(fileContents, "\n\n") | |
rawRules := strings.Split(splittedContents[0], "\n") | |
rawUpdates := strings.Split(splittedContents[1], "\n") | |
parsedRules := make([]Rule, 0) | |
parsedUpdates := make([][]int, 0) | |
for _, rule := range rawRules { | |
parsedRules = append(parsedRules, parseRule(rule)) | |
} | |
for _, updateLine := range rawUpdates { | |
parsedUpdates = append(parsedUpdates, parseUpdateLine(updateLine)) | |
} | |
correctLines := make([][]int, 0) | |
incorrectLines := make([][]int, 0) | |
for _, updateLine := range parsedUpdates { | |
rulesForLine := getRulesForLine(updateLine, parsedRules) | |
if isInCorrectOrder(updateLine, rulesForLine) == false { | |
incorrectLines = append(incorrectLines, updateLine) | |
continue | |
} | |
correctLines = append(correctLines, updateLine) | |
} | |
var result = calculateResult(correctLines) | |
fmt.Println("Result part 1:", result) | |
return parsedRules, incorrectLines | |
} | |
func part2(allRules []Rule, incorrectLines [][]int) { | |
fixedLines := make([][]int, 0) | |
for _, line := range incorrectLines { | |
rulesForLine := getRulesForLine(line, allRules) | |
rowResult := make([]int, 0) | |
for _, number := range line { | |
rowResult = addNumber(rowResult, rulesForLine, number) | |
} | |
fixedLines = append(fixedLines, rowResult) | |
} | |
result := calculateResult(fixedLines) | |
fmt.Println("Result part 2:", result) | |
} | |
func main() { | |
inputFile := "input.txt" | |
fileContentsAsBytes, err := os.ReadFile(inputFile) | |
if err != nil { | |
fmt.Println("Could not read input file", err) | |
return | |
} | |
fileContents := string(fileContentsAsBytes) | |
allRules, incorrectLines := part1(fileContents) | |
part2(allRules, incorrectLines) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment