123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- package main
- import (
- "bufio"
- "fmt"
- "log"
- "os"
- )
- func readInput(file *os.File) [][]byte {
- scanner := bufio.NewScanner(file)
- var trees [][]byte
- for scanner.Scan() {
- line := scanner.Text()
- if line == "" {
- continue
- }
- trees = append(trees, []byte(line))
- }
- return trees
- }
- func visibleFromLeft(x int, y int, trees [][]byte) bool {
- visible := true
- for i := 0; i < x; i++ {
- if trees[y][i] >= trees[y][x] {
- visible = false
- break
- }
- }
- return visible
- }
- func visibleFromRight(x int, y int, trees [][]byte, limit int) bool {
- visible := true
- for i := x + 1; i < limit; i++ {
- if trees[y][i] >= trees[y][x] {
- visible = false
- break
- }
- }
- return visible
- }
- func visibleFromTop(x int, y int, trees [][]byte) bool {
- visible := true
- for i := 0; i < y; i++ {
- if trees[i][x] >= trees[y][x] {
- visible = false
- break
- }
- }
- return visible
- }
- func visibleFromBottom(x int, y int, trees [][]byte, limit int) bool {
- visible := true
- for i := y + 1; i < limit; i++ {
- if trees[i][x] >= trees[y][x] {
- visible = false
- break
- }
- }
- return visible
- }
- func isVisible(x int, y int, trees [][]byte, width int, height int) bool {
- if visibleFromLeft(x, y, trees) {
- return true
- }
- if visibleFromRight(x, y, trees, width) {
- return true
- }
- if visibleFromTop(x, y, trees) {
- return true
- }
- if visibleFromBottom(x, y, trees, height) {
- return true
- }
- return false
- }
- func part1(trees [][]byte) int {
- width := len(trees[0])
- height := len(trees)
- visible := 2*height + (width-2)*2
- for y := 1; y < height-1; y++ {
- for x := 1; x < width-1; x++ {
- if isVisible(x, y, trees, width, height) {
- visible++
- }
- }
- }
- return visible
- }
- func numberFromLeft(x int, y int, trees [][]byte) int {
- count := 0
- for i := x - 1; i >= 0; i-- {
- count++
- if trees[y][i] >= trees[y][x] {
- break
- }
- }
- return count
- }
- func numberFromRight(x int, y int, trees [][]byte, limit int) int {
- count := 0
- for i := x + 1; i < limit; i++ {
- count++
- if trees[y][i] >= trees[y][x] {
- break
- }
- }
- return count
- }
- func numberFromTop(x int, y int, trees [][]byte) int {
- count := 0
- for i := y - 1; i >= 0; i-- {
- count++
- if trees[i][x] >= trees[y][x] {
- break
- }
- }
- return count
- }
- func numberFromBottom(x int, y int, trees [][]byte, limit int) int {
- count := 0
- for i := y + 1; i < limit; i++ {
- count++
- if trees[i][x] >= trees[y][x] {
- break
- }
- }
- return count
- }
- func numberVisible(x int, y int, trees [][]byte, width int, height int) int {
- count := 1
- count *= numberFromLeft(x, y, trees)
- count *= numberFromRight(x, y, trees, width)
- count *= numberFromTop(x, y, trees)
- count *= numberFromBottom(x, y, trees, height)
- return count
- }
- func part2(trees [][]byte) int {
- width := len(trees[0])
- height := len(trees)
- max := 0
- for y := 0; y < height; y++ {
- for x := 0; x < width; x++ {
- count := numberVisible(x, y, trees, width, height)
- if count > max {
- max = count
- }
- }
- }
- return max
- }
- func main() {
- if len(os.Args) < 2 {
- log.Fatal("You need to specify a file!")
- }
- filePath := os.Args[1]
- file, err := os.Open(filePath)
- if err != nil {
- log.Fatalf("Failed to open %s!\n", filePath)
- }
- trees := readInput(file)
- fmt.Println("Part1:", part1(trees))
- fmt.Println("Part2:", part2(trees))
- }
|