136 lines
2.6 KiB
Go
136 lines
2.6 KiB
Go
package day3
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
func Run() int {
|
|
filename := "day3/example"
|
|
bytes, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
panic(fmt.Sprint(err, filename))
|
|
}
|
|
|
|
text := string(bytes)
|
|
matrix := ReadMatrix(text)
|
|
|
|
fmt.Println(matrix.String())
|
|
|
|
numbers := ReadNumbers(&matrix)
|
|
fmt.Println(numbers)
|
|
|
|
partNumbersSum := 0
|
|
for _, num := range numbers {
|
|
if len(num.Specials) > 0 {
|
|
partNumbersSum += num.Num
|
|
}
|
|
}
|
|
|
|
return partNumbersSum
|
|
}
|
|
|
|
type Matrix [][]rune
|
|
|
|
func ReadMatrix(text string) Matrix {
|
|
text = strings.TrimSpace(text)
|
|
lines := strings.Split(text, "\n")
|
|
matrix := make([][]rune, len(lines))
|
|
|
|
for i, lineStr := range strings.Split(text, "\n") {
|
|
for _, r := range lineStr {
|
|
matrix[i] = append(matrix[i], r)
|
|
}
|
|
}
|
|
|
|
return matrix
|
|
}
|
|
|
|
func (m *Matrix)String() string {
|
|
res := make([]string, len(*m))
|
|
for _, row := range *m {
|
|
res = append(res, string(row) + "\n")
|
|
}
|
|
|
|
return strings.Join(res, "")
|
|
}
|
|
|
|
// and now from matrix, i want to scan top-down, left-right
|
|
// when encountering digit - start new number, read it in
|
|
// and when finished reading : scan around for the special symbols
|
|
|
|
type SpecialSymbol struct {
|
|
Symb rune
|
|
X, Y int
|
|
}
|
|
func (s SpecialSymbol) String() string {
|
|
return fmt.Sprintf("('%s' at x:%d,y:%d)", string(s.Symb), s.X, s.Y)
|
|
}
|
|
func (s SpecialSymbol) Equal() bool {
|
|
return false
|
|
}
|
|
|
|
type MatrixNumber struct {
|
|
Num int
|
|
Specials map[SpecialSymbol]any
|
|
}
|
|
|
|
func ReadNumbers(m *Matrix) []MatrixNumber {
|
|
res := make([]MatrixNumber, 0)
|
|
|
|
var curNum *MatrixNumber
|
|
for x, row := range *m {
|
|
for y, symb := range row {
|
|
if unicode.IsDigit(symb) {
|
|
digit := int(symb - '0')
|
|
// seing digit
|
|
if curNum == nil {
|
|
curNum = &MatrixNumber{
|
|
Num: digit,
|
|
Specials: make(map[SpecialSymbol]any),
|
|
}
|
|
} else {
|
|
curNum.Num = curNum.Num*10 + digit
|
|
}
|
|
|
|
// on each digit - scan around for special symbols
|
|
for i := x-1; i <= x+1; i++ {
|
|
for j := y-1; j <= y+1; j++ {
|
|
if isValidCoord(i, j, m) {
|
|
checkingForSpecial := (*m)[i][j]
|
|
if checkingForSpecial != '.' && !unicode.IsDigit(checkingForSpecial) {
|
|
special := SpecialSymbol{
|
|
Symb: checkingForSpecial,
|
|
X: i,
|
|
Y: j,
|
|
}
|
|
curNum.Specials[special] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// now let's check for special symbols around and save them
|
|
}
|
|
if symb == '.' {
|
|
if curNum != nil {
|
|
res = append(res, *curNum)
|
|
curNum = nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
// x is row, y is column. from top-left to bottom-right
|
|
func isValidCoord(x, y int, m *Matrix) bool {
|
|
if x < 0 || y < 0 || x >= len(*m) || y >= len((*m)[x]) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|