Pouring sand
Kind of cool because running the code you can visualize dripping sand across an obstacle course.
package problems
import (
"fmt"
"strings"
"github.com/sooflee/advent/internal"
)
type day14 struct {
lines []string
}
func Day14(part int, file string) int {
in := day14{
lines: internal.Read(file),
}
switch part {
case 1:
return in.part_one()
case 2:
return in.part_two()
default:
return 0
}
}
func create_cavern(lines []string, part2 bool) ([][]string, int, int) {
sequences := [][]coordinate{}
max_x := 0
max_y := 0
for _, line := range lines {
sequence := []coordinate{}
for _, coordinate_str := range strings.Split(line, "->") {
coordinates := strings.Split(coordinate_str, ",")
x := internal.StrToInt(coordinates[0])
y := internal.StrToInt(coordinates[1])
sequence = append(sequence, coordinate{x, y})
if x > max_x {
max_x = x
}
if y > max_y {
max_y = y
}
}
sequences = append(sequences, sequence)
}
if part2 {
max_y = max_y + 2
max_x = max_x + max_x
}
cavern := make([][]string, max_y+1)
for i := range cavern {
cavern_row := make([]string, max_x+1)
for j := range cavern_row {
cavern_row[j] = "."
}
cavern[i] = cavern_row
}
if part2 {
cavern_row := make([]string, max_x+1)
for j := range cavern_row {
cavern_row[j] = "#"
}
cavern[max_y] = cavern_row
}
for _, sequence := range sequences {
last_c := coordinate{}
for i, c := range sequence {
cavern[c.y][c.x] = "#"
if i != 0 {
if last_c.x < c.x {
for x := last_c.x; x <= c.x; x++ {
cavern[c.y][x] = "#"
}
} else if last_c.x > c.x {
for x := last_c.x; x >= c.x; x-- {
cavern[c.y][x] = "#"
}
} else if last_c.y < c.y {
for y := last_c.y; y <= c.y; y++ {
cavern[y][c.x] = "#"
}
} else if last_c.y > c.y {
for y := last_c.y; y >= c.y; y-- {
cavern[y][c.x] = "#"
}
}
}
last_c = coordinate{c.x, c.y}
}
}
return cavern, max_x, max_y
}
func draw_cavern(cavern [][]string) {
for i, cavern_row := range cavern {
fmt.Println(i, cavern_row)
}
}
func (input day14) part_one() int {
cavern, max_x, max_y := create_cavern(input.lines, false)
sand_count := 0
for {
sand_count++
sand_x := 500
sand_y := 0
for {
if sand_y == max_y || sand_x == max_x {
break
}
if cavern[sand_y+1][sand_x] == "." {
sand_y++
} else if cavern[sand_y+1][sand_x-1] == "." {
sand_x--
sand_y++
} else if cavern[sand_y+1][sand_x+1] == "." {
sand_x++
sand_y++
} else {
break
}
}
if sand_y >= max_y || sand_x >= max_x {
break
}
draw_cavern(cavern)
if sand_y >= max_y {
break
}
cavern[sand_y][sand_x] = "o"
}
return sand_count - 1
}
func (input day14) part_two() int {
cavern, max_x, max_y := create_cavern(input.lines, true)
sand_count := 0
for {
sand_count++
sand_x := 500
sand_y := 0
not_move := true
for {
if sand_y == max_y || sand_x == max_x {
break
}
if cavern[sand_y+1][sand_x] == "." {
sand_y++
not_move = false
} else if cavern[sand_y+1][sand_x-1] == "." {
sand_x--
sand_y++
not_move = false
} else if cavern[sand_y+1][sand_x+1] == "." {
sand_x++
sand_y++
not_move = false
} else {
break
}
}
// if sand_count%50 == 0 {
// draw_cavern(cavern)
// }
if not_move {
break
}
if sand_y >= max_y {
break
}
cavern[sand_y][sand_x] = "o"
}
return sand_count
}