package main
import (
"bufio"
"log"
"os"
"strings"
)
type coord [2]int
type ocean struct {
easts []coord
souths []coord
grid [][]byte
}
func (o ocean) String() string {
ret := strings.Builder{}
ret.WriteByte('\n')
for _, line := range o.grid {
for _, elem := range line {
ret.WriteByte(elem)
}
ret.WriteByte('\n')
}
return ret.String()
}
func main() {
if err := myMain(); err != nil {
log.Println(err)
}
}
func myMain() error {
m, err := parseInput("input.txt")
if err != nil {
return err
}
log.Println(solveFirst(m))
return nil
}
func solveFirst(o ocean) int {
var steps int
for ; ; steps++ {
e := o.moveEast()
s := o.moveSouth()
if e == false && s == false {
break
}
}
return steps + 1
}
func (o ocean) moveSouth() bool {
toDot := []coord{}
toV := []coord{}
for sIter, sCoord := range o.souths {
down := (sCoord[0] + 1) % len(o.grid)
if o.grid[down][sCoord[1]] == '.' {
o.souths[sIter] = [2]int{down, sCoord[1]}
toDot = append(toDot, coord{sCoord[0], sCoord[1]})
toV = append(toV, coord{down, sCoord[1]})
}
}
if len(toDot) == 0 && len(toV) == 0 {
return false
}
for _, d := range toDot {
o.grid[d[0]][d[1]] = '.'
}
for _, v := range toV {
o.grid[v[0]][v[1]] = 'v'
}
return true
}
func (o ocean) moveEast() bool {
toDot := []coord{}
toR := []coord{}
for eIter, eCoord := range o.easts {
right := (eCoord[1] + 1) % len(o.grid[0])
if o.grid[eCoord[0]][right] == '.' {
o.easts[eIter] = [2]int{eCoord[0], right}
toDot = append(toDot, coord{eCoord[0], eCoord[1]})
toR = append(toR, coord{eCoord[0], right})
}
}
if len(toDot) == 0 && len(toR) == 0 {
return false
}
for _, d := range toDot {
o.grid[d[0]][d[1]] = '.'
}
for _, v := range toR {
o.grid[v[0]][v[1]] = '>'
}
return true
}
func parseInput(fileName string) (ocean, error) {
ret := ocean{}
fd, err := os.Open(fileName)
if err != nil {
return ret, err
}
defer fd.Close()
buf := bufio.NewScanner(fd)
for line := 0; buf.Scan(); line++ {
l := make([]byte, len(buf.Text()))
for col, elem := range buf.Text() {
l[col] = byte(elem)
if elem == '>' {
ret.easts = append(ret.easts, coord{line, col})
}
if elem == 'v' {
ret.souths = append(ret.souths, coord{line, col})
}
}
ret.grid = append(ret.grid, l)
}
return ret, nil
}