(defn calc-scenic-scores [[rows cols]]
(let [init-heights (partial map (comp vector second))
cons-heights (fn [xs acc-heights]
(map (fn [[_ n] heights] (cons n heights))
xs acc-heights))
calc-score (fn [self-height heights-in-dir]
(reduce (fn [sum height] (if (< height self-height)
(inc sum)
(reduced (inc sum))))
0 heights-in-dir))
[min max] [0 (dec (count rows))]]
(loop [[lhts l & lr] (cons (init-heights (first cols)) (rest cols))
[rhts r & rr] (cons (init-heights (last cols)) (rest (reverse cols)))
[thts t & tr] (cons (init-heights (first rows)) (rest rows))
[bhts b & br] (cons (init-heights (last rows)) (rest (reverse rows)))
coord->score {}]
(let [scores (map (fn [xs xhts]
(into {} (map (fn [[[x y :as coords] n] heights]
(when (and (> x min) (> y min)
(< x max) (< y max))
[coords (calc-score n heights)]))
xs xhts)))
[l r t b] [lhts rhts thts bhts])
coord->score (apply merge-with * coord->score scores)]
(if (< (count lr) 2)
coord->score
(recur (cons (cons-heights l lhts) lr)
(cons (cons-heights r rhts) rr)
(cons (cons-heights t thts) tr)
(cons (cons-heights b bhts) br)
coord->score))))))