170 lines
3.1 KiB
Go
170 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
|
)
|
|
|
|
func main() {
|
|
inp := h.StdinToCoordMap()
|
|
part1(inp)
|
|
fmt.Println("")
|
|
part2(inp)
|
|
}
|
|
|
|
func part1(inp h.CoordByteMap) {
|
|
var count int
|
|
for x := inp.TLX; x <= inp.BRX; x++ {
|
|
for y := inp.TLY; y <= inp.BRY; y++ {
|
|
tree := h.Coordinate{X: x, Y: y}
|
|
if treeIsVisibleFromOutside(inp, tree) {
|
|
count++
|
|
}
|
|
}
|
|
}
|
|
fmt.Println("# Part 1")
|
|
fmt.Println("Visible tree from the outside:", count)
|
|
}
|
|
|
|
func part2(inp h.CoordByteMap) {
|
|
var bestScore int
|
|
var bestTree h.Coordinate
|
|
for x := inp.TLX; x <= inp.BRX; x++ {
|
|
for y := inp.TLY; y <= inp.BRY; y++ {
|
|
tree := h.Coordinate{X: x, Y: y}
|
|
ss := scenicScore(inp, tree)
|
|
if ss > bestScore {
|
|
bestScore = ss
|
|
bestTree = tree
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println("# Part 2")
|
|
fmt.Println("Best Score:", bestScore, "@", bestTree)
|
|
}
|
|
|
|
func treeIsVisibleFromOutside(inp h.CoordByteMap, pos h.Coordinate) bool {
|
|
if pos.X == inp.TLX || pos.X == inp.BRX || pos.Y == inp.TLY || pos.Y == inp.BRY {
|
|
return true
|
|
}
|
|
treeHeight := inp.Get(pos)
|
|
n, e, s, w := true, true, true, true
|
|
// Check North
|
|
for y := inp.TLY; y < pos.Y; y++ {
|
|
if inp.Get(h.Coordinate{X: pos.X, Y: y}) >= treeHeight {
|
|
n = false
|
|
break
|
|
}
|
|
}
|
|
if n {
|
|
return true
|
|
}
|
|
// Check East
|
|
for x := inp.BRX; x > pos.X; x-- {
|
|
if inp.Get(h.Coordinate{X: x, Y: pos.Y}) >= treeHeight {
|
|
e = false
|
|
break
|
|
}
|
|
}
|
|
if e {
|
|
return true
|
|
}
|
|
// Check South
|
|
for y := inp.BRY; y > pos.Y; y-- {
|
|
if inp.Get(h.Coordinate{X: pos.X, Y: y}) >= treeHeight {
|
|
s = false
|
|
break
|
|
}
|
|
}
|
|
if s {
|
|
return true
|
|
}
|
|
// Check West
|
|
for x := inp.TLX; x < pos.X; x++ {
|
|
if inp.Get(h.Coordinate{X: x, Y: pos.Y}) >= treeHeight {
|
|
w = false
|
|
break
|
|
}
|
|
}
|
|
if w {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func scenicScore(inp h.CoordByteMap, pos h.Coordinate) int {
|
|
var n, e, s, w int
|
|
treeHeight := inp.Get(pos)
|
|
// Find how many trees we can see to the North
|
|
if pos.Y == inp.TLY {
|
|
return 0
|
|
} else {
|
|
for y := pos.Y - 1; y >= inp.TLY; y-- {
|
|
tst := inp.Get(h.Coordinate{X: pos.X, Y: y})
|
|
if tst < treeHeight {
|
|
n++
|
|
} else if tst >= treeHeight {
|
|
n++
|
|
break
|
|
}
|
|
}
|
|
if n == 0 {
|
|
return 0
|
|
}
|
|
}
|
|
// Find how many trees we can see to the East
|
|
if pos.X == inp.BRX {
|
|
return 0
|
|
} else {
|
|
for x := pos.X + 1; x <= inp.BRX; x++ {
|
|
tst := inp.Get(h.Coordinate{X: x, Y: pos.Y})
|
|
if tst < treeHeight {
|
|
e++
|
|
} else if tst >= treeHeight {
|
|
e++
|
|
break
|
|
}
|
|
}
|
|
if e == 0 {
|
|
return 0
|
|
}
|
|
}
|
|
// Find how many trees we can see to the South
|
|
if pos.Y == inp.BRY {
|
|
return 0
|
|
} else {
|
|
for y := pos.Y + 1; y <= inp.BRY; y++ {
|
|
tst := inp.Get(h.Coordinate{X: pos.X, Y: y})
|
|
if tst < treeHeight {
|
|
s++
|
|
} else if tst >= treeHeight {
|
|
s++
|
|
break
|
|
}
|
|
}
|
|
if s == 0 {
|
|
return 0
|
|
}
|
|
}
|
|
// Find how many trees we can see to the West
|
|
if pos.X == inp.TLX {
|
|
return 0
|
|
} else {
|
|
for x := pos.X - 1; x >= inp.TLX; x-- {
|
|
tst := inp.Get(h.Coordinate{X: x, Y: pos.Y})
|
|
if tst < treeHeight {
|
|
w++
|
|
} else if tst >= treeHeight {
|
|
w++
|
|
break
|
|
}
|
|
}
|
|
if w == 0 {
|
|
return 0
|
|
}
|
|
}
|
|
return n * e * s * w
|
|
}
|