adventOfCode/internal/2023/day_03/in.go

201 lines
4.6 KiB
Go
Raw Normal View History

2023-12-01 12:12:28 +00:00
package day_03
2022-12-06 21:10:52 +00:00
2023-12-03 08:49:00 +00:00
import (
"fmt"
"strings"
"git.rpjosh.de/RPJosh/go-logger"
"rpjosh.de/adventOfCode/pkg/utils"
)
type Day struct {
engine []string
currentRow int
currentLine int
}
2022-12-06 21:10:52 +00:00
func (d *Day) Part1(in string) string {
2023-12-03 08:49:00 +00:00
// Initialize variables
sum := 0
d.currentLine = -1
d.engine = strings.Split(in, "\n")
for _, val := range d.engine {
if val == "" {
continue
}
// Initialize variables
strVal := ""
isSymbolNear := false
d.currentRow = 0
d.currentLine++
// Loop through all characters and find ints
for _, str := range val {
if utils.IsInt(string(str)) {
strVal += string(str)
if !isSymbolNear {
// Check if a symbol is near
isSymbolNear = d.isSymbolNear()
}
} else {
// It's a '.' or a symbole
if strVal != "" && isSymbolNear {
logger.Debug("Found value %q", strVal)
sum += utils.ToInt(strVal)
}
// Reset variables
strVal = ""
isSymbolNear = false
}
d.currentRow += 1
}
// End of line
if strVal != "" && isSymbolNear {
logger.Debug("Found value %q", strVal)
sum += utils.ToInt(strVal)
}
}
return fmt.Sprintf("%d", sum)
}
func (d *Day) isSymbolNear() bool {
// Left and right
if d.isSymbole(d.currentRow-1, d.currentLine, ' ') || d.isSymbole(d.currentRow+1, d.currentLine, ' ') {
return true
}
// Top and bottom
if d.isSymbole(d.currentRow, d.currentLine-1, ' ') || d.isSymbole(d.currentRow, d.currentLine+1, ' ') {
return true
}
// Diagonale
if d.isSymbole(d.currentRow-1, d.currentLine-1, ' ') || d.isSymbole(d.currentRow-1, d.currentLine+1, ' ') {
return true
}
if d.isSymbole(d.currentRow+1, d.currentLine-1, ' ') || d.isSymbole(d.currentRow+1, d.currentLine+1, ' ') {
return true
}
return false
}
// isGearNear returns weather a * is near and the index of that gear
// (row,line)
func (d *Day) isGearNear() (bool, string) {
// Left and right
if d.isSymbole(d.currentRow-1, d.currentLine, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow-1, d.currentLine)
}
if d.isSymbole(d.currentRow+1, d.currentLine, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow+1, d.currentLine)
}
// Top and bottom
if d.isSymbole(d.currentRow, d.currentLine-1, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow, d.currentLine-1)
}
if d.isSymbole(d.currentRow, d.currentLine+1, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow, d.currentLine+1)
}
// Diagonale
if d.isSymbole(d.currentRow-1, d.currentLine-1, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow-1, d.currentLine-1)
}
if d.isSymbole(d.currentRow-1, d.currentLine+1, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow-1, d.currentLine+1)
}
if d.isSymbole(d.currentRow+1, d.currentLine-1, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow+1, d.currentLine-1)
}
if d.isSymbole(d.currentRow+1, d.currentLine+1, '*') {
return true, fmt.Sprintf("%d,%d", d.currentRow+1, d.currentLine+1)
}
return false, ""
}
// isSymbole checks if the characters at the given position is a rune.
// If an invalid line or row is provided, this function returns false
func (d *Day) isSymbole(row, line int, symbole rune) bool {
// Check out of bounds
if row < 0 || line < 0 || line >= len(d.engine) || row >= len(d.engine[line]) {
return false
}
val := d.engine[line][row]
return val != '.' && !utils.IsInt(string(val)) && (symbole == ' ' || symbole == rune(val))
2022-12-06 21:10:52 +00:00
}
func (d *Day) Part2(in string) string {
2023-12-03 08:49:00 +00:00
// Initialize variables
d.currentLine = -1
d.engine = strings.Split(in, "\n")
gears := make(map[string][]int, 0)
for _, val := range d.engine {
if val == "" {
continue
}
// Initialize variables
strVal := ""
isGearNear := false
isGearNearPos := ""
d.currentRow = 0
d.currentLine++
// Loop through all characters and find ints
for _, str := range val {
if utils.IsInt(string(str)) {
strVal += string(str)
// Check if a symbol is near
if isNear, pos := d.isGearNear(); isNear {
isGearNear = true
isGearNearPos = pos
}
} else {
// It's a '.' or a symbole
if strVal != "" && isGearNear {
logger.Debug("Found pos %q with value %q", isGearNearPos, strVal)
gears[isGearNearPos] = append(gears[isGearNearPos], utils.ToInt(strVal))
}
// Reset variables
strVal = ""
isGearNear = false
isGearNearPos = ""
}
d.currentRow += 1
}
// End of line
// Check if a symbol is near
if isGearNear {
logger.Debug("Found pos %q with value %q", isGearNearPos, strVal)
gears[isGearNearPos] = append(gears[isGearNearPos], utils.ToInt(strVal))
}
}
sum := 0
for _, values := range gears {
if len(values) == 2 {
sum += values[0] * values[1]
}
}
return fmt.Sprintf("%d", sum)
2022-12-06 21:10:52 +00:00
}