Skip to content

Instantly share code, notes, and snippets.

@YannickFricke
Created December 5, 2024 09:04
Show Gist options
  • Save YannickFricke/b1544e31d679810d15d9157c9c803bf7 to your computer and use it in GitHub Desktop.
Save YannickFricke/b1544e31d679810d15d9157c9c803bf7 to your computer and use it in GitHub Desktop.
AoC 2024 Day 5
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