Go
package main
import (
"aoc/utils"
"fmt"
)
type rollMap [][]bool
func (rm *rollMap) addRow(line string) {
runes := []rune(line)
row := make([]bool, len(runes))
for idx, r := range runes {
row[idx] = r == '@'
}
*rm = append(*rm, row)
}
func (rm rollMap) getAdjacentContents(row, col int) []bool {
contents := []bool{}
lenrow := len(rm[0])
lenrm := len(rm)
for _, i := range []int{-1, 0, 1} {
for _, j := range []int{-1, 0, 1} {
if i == 0 && j == 0 {
continue
}
r := row + i
c := col + j
if r >= 0 && r < lenrm && c >= 0 && c < lenrow {
contents = append(contents, rm[r][c])
}
}
}
return contents
}
func countTrue(array []bool) int {
count := 0
for _, val := range array {
if val {
count++
}
}
return count
}
func createMap(input chan string) rollMap {
rm := rollMap{}
for line := range input {
rm.addRow(line)
}
return rm
}
func stepOne(input chan string) (int, error) {
rm := createMap(input)
lenrow := len(rm[0])
accessibleRolls := 0
for row := range rm {
for col := range lenrow {
if rm[row][col] {
adj := rm.getAdjacentContents(row, col)
numRolls := countTrue(adj)
if numRolls < 4 {
accessibleRolls++
}
}
}
}
return accessibleRolls, nil
}
type position struct {
row, col int
}
func stepTwo(input chan string) (int, error) {
rm := createMap(input)
lenrow := len(rm[0])
accessibleRolls := 0
for true {
accessedRolls := []position{}
for row := range rm {
for col := range lenrow {
if rm[row][col] {
adj := rm.getAdjacentContents(row, col)
numRolls := countTrue(adj)
if numRolls < 4 {
accessibleRolls++
accessedRolls = append(accessedRolls, position{
row: row,
col: col,
})
}
}
}
}
if len(accessedRolls) == 0 {
break
} else {
for _, pos := range accessedRolls {
rm[pos.row][pos.col] = false
}
}
}
return accessibleRolls, nil
}
func main() {
input := utils.FilePath("day04.txt")
ch1, err1 := input.GetLineChannel()
if err1 != nil {
fmt.Errorf("step one error: %s\n", err1)
return
}
val1, errStep1 := stepOne(ch1)
if errStep1 != nil {
fmt.Errorf("step one error: %s\n", errStep1)
return
}
fmt.Printf("Step one result: %d\n", val1)
ch2, err2 := input.GetLineChannel()
if err2 != nil {
fmt.Errorf("step two error: %s\n", err2)
return
}
val2, errStep2 := stepTwo(ch2)
if errStep2 != nil {
fmt.Errorf("step two error: %s\n", errStep2)
return
}
fmt.Printf("Step two result: %d\n", val2)
}