advent_of_code_2022

My (attempted) solutions to the 2022 Advent of Code
git clone https://git.eamoncaddigan.net/advent_of_code_2022.git
Log | Files | Refs | README

day_8.jl (2217B)


      1 #!/usr/bin/env julia
      2 # https://adventofcode.com/2022/day/8
      3 using AdventOfCode
      4 
      5 example = readlines(IOBuffer("""
      6     30373
      7     25512
      8     65332
      9     33549
     10     35390"""))
     11 input = readlines("data/day_8.txt")
     12 
     13 # Just a helper to turn an array of strings to a 2D int matrix
     14 function parse_input(input)
     15     parse.(Int, hcat(split.(input, "")...))
     16 end
     17 
     18 # Returns an array of the same length as x that's true for every element in x
     19 # that's greater than the elements visited so far. Sad I couldn't figure out
     20 # how to do this cleanly with accumulate()
     21 function cumismax(x)
     22     currmax = -1
     23     result = similar(x, Bool)
     24     for (i, v) = enumerate(x)
     25         if v > currmax
     26             currmax = v
     27             result[i] = true
     28         else
     29             result[i] = false
     30         end
     31     end
     32     result
     33 end
     34 
     35 # Return the tallest trees when viewed from one direction
     36 function visible_here(trees, dims, doreverse)
     37     doreverse && (trees = reverse(trees, dims = dims))
     38     istallest =  mapslices(cumismax, trees, dims = dims)
     39     doreverse ? reverse(istallest, dims = dims) : istallest
     40 end
     41 
     42 # Return the trees visible from any direction
     43 function visible_anywhere(trees)
     44     mapreduce(
     45         (x)->visible_here(trees, x[1], x[2]),
     46         (x, y)->x .| y,
     47         Iterators.product((1, 2), (false, true))
     48     )
     49 end
     50 
     51 function part_1(input)
     52     sum(visible_anywhere(parse_input(input)))
     53 end
     54 @assert part_1(example) == 21
     55 @info part_1(input)
     56 
     57 # Find the component of a scenic score looking along one direction
     58 function score_component(treeheight::Int, neighbortrees::Vector{Int})::Int
     59     trees_seen = findfirst(x->x>=treeheight, neighbortrees)
     60     trees_seen == nothing ? length(neighbortrees) : trees_seen
     61 end
     62 
     63 function part_2(input)
     64     trees = parse_input(input)
     65     mapheight, mapwidth = size(trees)
     66     scenicscore = zeros(Int, mapheight, mapwidth)
     67 
     68     for row = 2:mapheight-1, col = 2:mapwidth-1
     69         scenicscore[row, col] = mapreduce(
     70             Base.Fix1(score_component, trees[row, col]),
     71             *,
     72             (trees[row, col-1:-1:1], trees[row, col+1:end],
     73              trees[row-1:-1:1, col], trees[row+1:end, col])
     74         )
     75     end
     76 
     77     maximum(scenicscore)
     78 end
     79 @assert part_2(example) == 8
     80 @info part_2(input)