package day14 import ( "fmt" "os" "strings" ) func Run() int { fmt.Println("hello day 14") field := ReadPlatform("day14/example") fmt.Println(field.String()) // fmt.Printf("> lines for field %+v\n", field.UpIndices()) field.MoveUp(field.Height()) fmt.Println(field.String()) // north rock load return field.NorthLoad() } const Rock rune = 'O' const Wall rune = '#' const Space rune = '.' type Platform struct { Rocks [][]rune } func (p *Platform)Height() int { return len(p.Rocks) } func (p *Platform)Width() int { return len(p.Rocks[0]) } func ReadPlatform(filename string) Platform { bytes, err := os.ReadFile(filename) if err != nil { panic(fmt.Sprint("cannot read file: ", filename)) } text := string(bytes) text = strings.TrimSpace(text) lines := strings.Split(text, "\n") rocks := make([][]rune, len(lines)) for i, line := range lines { rocks[i] = []rune(line) } return Platform{ Rocks: rocks, } } func (p *Platform) String() string { text := "\n" for _, row := range p.Rocks { text += string(row) text += "\n" } return text } type Coord struct { Row, Col int } func (p *Platform) UpIndices() [][]Coord { lines := make([][]Coord,0) for col := 0; col < p.Width(); col++ { line := make([]Coord, 0) for row := 0; row < p.Height(); row++ { line = append(line, Coord{Row: row, Col: col}) } lines = append(lines, line) } return lines } func (p *Platform) DownIndices() [][]Coord { lines := make([][]Coord,0) for col := 0; col < p.Width(); col++ { line := make([]Coord, 0) for row := p.Height() - 1; row >= 0; row-- { line = append(line, Coord{Row: row, Col: col}) } lines = append(lines, line) } return lines } func (p *Platform)SymbAt(coord Coord) rune { return p.Rocks[coord.Row][coord.Col] } func (p *Platform)SetSymbAt(coord Coord, symb rune) { p.Rocks[coord.Row][coord.Col] = symb } func (p *Platform) MoveUp(n int) { lines := p.UpIndices() for _, line := range lines { moveSize := 0 for i, coord := range line { symb := p.SymbAt(coord) switch symb { case Space: moveSize += 1 if moveSize > n { moveSize = n } case Wall: moveSize = 0 case Rock: if moveSize == 0 { continue } // get coord for moveSize back. and set that to 'o' // and set current to '.' // panic if that place is not '.' i guess moveTo := line[i - moveSize] symbAtTarget := p.SymbAt(moveTo) if symbAtTarget != Space { panic(fmt.Sprintf("attempting to move %+v to %+v, target symbol is %s, not '.'", coord, moveTo, string(symbAtTarget))) } p.SetSymbAt(moveTo, Rock) p.SetSymbAt(coord, Space) } } } } func (p *Platform)NorthLoad() int { total := 0 height := p.Height() for i, row := range p.Rocks { for _, symb := range row { if symb == Rock { total += (height - i) } } } return total }