AOC-2024/03/main.go
2024-12-03 18:20:13 +01:00

249 lines
4.4 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const FILE_PATH = "./input.txt"
//const FILE_PATH = "./sample.txt"
func LoadInput(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
}
type structuredInput = string
func TransformInput(lines []string) structuredInput {
return strings.Join(lines, "")
}
const PRE_FIX = "mul("
func IsNummeric(input byte) bool {
return input >= '0' && input <= '9'
}
func ExtractNumber(input string, start_index int) (int, int, bool) {
var end_index = start_index
if !IsNummeric(input[start_index]) {
return -1, -1, false
}
for i := start_index; i < len(input); i++ {
if !IsNummeric(input[i]) {
break
}
end_index = i
}
result, error := strconv.Atoi(input[start_index : end_index+1])
if error != nil {
return -1, -1, false
}
return result, end_index - start_index + 1, true
}
func CalculateLinePart1(input string) int {
var error = -1
var success = false
var num1 = 0
var num2 = 0
var num_length = 0
var index = 0
var result = 0
for i := 0; i < len(input); i++ {
error = -1
for j := 0; j < len(PRE_FIX) && i+j < len(input); j++ {
if PRE_FIX[j] != input[i+j] {
error = i + j
break
}
}
index = i + len(PRE_FIX)
if error != -1 {
i = error
continue
}
num1 = 0
num2 = 0
num1, num_length, success = ExtractNumber(input, index)
if !success {
continue
}
index += num_length
if input[index] != ',' {
continue
}
index++
num2, num_length, success = ExtractNumber(input, index)
if !success {
continue
}
index += num_length
if input[index] != ')' {
continue
}
result += num1 * num2
i = index
}
return result
}
func Part1(input structuredInput) int {
return CalculateLinePart1(input)
}
type Method struct {
method string
num1 int
num2 int
}
var METHODS = map[string]func(paramters string) (bool, Method){
"mul": func(paramters string) (bool, Method) {
var num_length1 = 0
var num_length2 = 0
var success = false
var num1 = 0
var num2 = 0
num1, num_length1, success = ExtractNumber(paramters, 0)
if !success {
return false, Method{}
}
if len(paramters) <= num_length1 || paramters[num_length1] != ',' {
return false, Method{}
}
num2, num_length2, success = ExtractNumber(paramters, num_length1+1)
if !success {
return false, Method{}
}
if len(paramters) > num_length1+num_length2+1 {
return false, Method{}
}
return true, Method{"mul", num1, num2}
},
"do": func(paramters string) (bool, Method) {
return len(paramters) == 0, Method{"do", -1, -1}
},
"don't": func(paramters string) (bool, Method) {
return len(paramters) == 0, Method{"don't", -1, -1}
},
}
func IsMethod(line string, method_name string, start_index int) bool {
if start_index+len(method_name) >= len(line) {
return false
}
for i := 0; i < len(method_name); i++ {
if line[start_index+i] != method_name[i] {
return false
}
}
return true
}
func CalculateLinePart2(line string) int {
var result = 0
var para_start = 0
var para_end = 0
var success = false
var code = make([]Method, 0)
var temp Method
for i := 0; i < len(line); i++ {
for method := range METHODS {
if !IsMethod(line, method, i) {
continue
}
para_start = i + len(method)
if line[para_start] != '(' {
continue
}
para_end = para_start
for para_end < len(line) && line[para_end] != ')' {
para_end++
}
if line[para_end] != ')' {
continue
}
success, temp = METHODS[method](line[para_start+1 : para_end])
if success {
code = append(code, temp)
break
}
}
}
var enabled = true
for _, method := range code {
switch method.method {
case "do":
enabled = true
case "don't":
enabled = false
case "mul":
if enabled {
result += method.num1 * method.num2
}
}
}
return result
}
func Part2(input structuredInput) int {
return CalculateLinePart2(input)
}
func main() {
input, err := LoadInput(FILE_PATH)
if err != nil {
fmt.Println("Error loading input:", err)
return
}
structuredInput := TransformInput(input)
fmt.Println("Structured Input:", structuredInput)
fmt.Println("Solution Part 1: ", Part1(structuredInput))
fmt.Println("Solution Part 2: ", Part2(structuredInput))
}