Files
advent-of-code/internal/2025/DaySix/code.go

175 lines
3.9 KiB
Go

package daysix
import (
"os"
"strconv"
"strings"
"advent-of-code/internal/registry"
)
func init() {
registry.Register("2025D6", ParseInput, PartOne, PartTwo)
}
func ParseInput(filepath string) []string {
content, _ := os.ReadFile(filepath)
return strings.Split(strings.TrimRight(string(content), "\n"), "\n")
}
func transpose(lines []string) []string {
maxWidth := 0
for _, line := range lines {
if len(line) > maxWidth {
maxWidth = len(line)
}
}
transposed := make([]string, maxWidth)
for column := 0; column < maxWidth; column++ {
var builder strings.Builder
for _, line := range lines {
if column < len(line) {
builder.WriteByte(line[column])
} else {
builder.WriteByte(' ')
}
}
transposed[column] = builder.String()
}
return transposed
}
func isSpaceColumn(column string) bool {
return strings.TrimSpace(column) == ""
}
func extractRowFromColumns(transposed []string, row, startColumn, endColumn int) string {
var builder strings.Builder
for column := startColumn; column <= endColumn && column < len(transposed); column++ {
if row < len(transposed[column]) {
builder.WriteByte(transposed[column][row])
} else {
builder.WriteByte(' ')
}
}
return builder.String()
}
func extractNumbers(transposed []string, startColumn, endColumn, operationRow int) []int {
numbers := make([]int, 0)
for row := range operationRow {
rowStr := extractRowFromColumns(transposed, row, startColumn, endColumn)
trimmed := strings.TrimSpace(rowStr)
fields := strings.FieldsSeq(trimmed)
for field := range fields {
if number, err := strconv.Atoi(field); err == nil {
numbers = append(numbers, number)
}
}
}
return numbers
}
func extractNumberFromColumn(column string, operationRow int) (int, bool) {
numberStr := strings.Map(func(r rune) rune {
if r >= '0' && r <= '9' {
return r
}
return -1
}, column[:min(operationRow, len(column))])
number, _ := strconv.Atoi(numberStr)
return number, true
}
func extractOperation(segment string) byte {
if idx := strings.IndexAny(segment, "+*"); idx != -1 {
return segment[idx]
}
return 0
}
func applyOperation(numbers []int, operation byte) int {
result := numbers[0]
if operation == '+' {
for idx := 1; idx < len(numbers); idx++ {
result += numbers[idx]
}
} else {
for idx := 1; idx < len(numbers); idx++ {
result *= numbers[idx]
}
}
return result
}
func PartOne(data []string) int {
operationRow := len(data) - 1
transposed := transpose(data)
total := 0
column := 0
for column < len(transposed) {
if isSpaceColumn(transposed[column]) {
column++
continue
}
startColumn := column
for column < len(transposed) && !isSpaceColumn(transposed[column]) {
column++
}
endColumn := column - 1
numbers := extractNumbers(transposed, startColumn, endColumn, operationRow)
operationRowStr := extractRowFromColumns(transposed, operationRow, startColumn, endColumn)
operation := extractOperation(operationRowStr)
if len(numbers) > 0 && operation != 0 {
result := applyOperation(numbers, operation)
total += result
}
}
return total
}
func PartTwo(data []string) int {
operationRow := len(data) - 1
transposed := transpose(data)
total := 0
column := len(transposed) - 1
for column >= 0 {
if isSpaceColumn(transposed[column]) {
column--
continue
}
endColumn := column
for column >= 0 && !isSpaceColumn(transposed[column]) {
column--
}
startColumn := column + 1
numbers := make([]int, 0)
for column := startColumn; column <= endColumn && column < len(transposed); column++ {
if number, ok := extractNumberFromColumn(transposed[column], operationRow); ok {
numbers = append(numbers, number)
}
}
operationRowStr := extractRowFromColumns(transposed, operationRow, startColumn, endColumn)
operation := extractOperation(operationRowStr)
if len(numbers) > 0 && operation != 0 {
result := applyOperation(numbers, operation)
total += result
}
}
return total
}