#!/usr/local/bin/chicken-csi -ss (import (chicken string) (chicken io)) (define (char->digit c) (- (char->integer c) 48)) (define (lines->grid lines) (let* ((vecs (map (lambda (l) (list->vector (map char->digit l))) (map string->list lines)))) (list->vector vecs))) (define (grid-get grid r c) (vector-ref (vector-ref grid r) c)) (define (neg? x) (< x 0)) (define (max-in-dir? grid r c dr dc) (let ((tree (grid-get grid r c)) (n (vector-length grid))) (let loop ((r r) (c c)) (let ((nr (+ r dr)) (nc (+ c dc))) (if (or (neg? nr) (neg? nc) (>= nr n) (>= nc n)) #t ; made it off the map (and (> tree (grid-get grid nr nc)) (loop nr nc))))))) (define (is-visible? grid r c) ; (print "visiting " r " " c) (let ((n (sub1 (vector-length grid)))) (if (or (equal? r 0) (equal? c 0) (equal? r n) (equal? c n)) #t (or (max-in-dir? grid r c 0 1) (max-in-dir? grid r c 1 0) (max-in-dir? grid r c -1 0) (max-in-dir? grid r c 0 -1))))) (define (num-in-dir grid r c dr dc) (let ((tree (grid-get grid r c)) (n (vector-length grid))) (let loop ((r r) (c c) (count 0)) (let ((nr (+ r dr)) (nc (+ c dc))) (if (or (neg? nr) (neg? nc) (>= nr n) (>= nc n)) count ; made it off the map (if (<= tree (grid-get grid nr nc)) (add1 count) (loop nr nc (add1 count)))))))) (define (score grid r c) ; (print "visiting " r " " c) (apply * (filter (lambda (x) (> x 0)) (list (num-in-dir grid r c 0 1) (num-in-dir grid r c 1 0) (num-in-dir grid r c -1 0) (num-in-dir grid r c 0 -1))))) (define (range n) (if (equal? n 0) '(0) (append (range (sub1 n)) (list n)))) (define (filter pred lst) (if (null? lst) '() (if (pred (car lst)) (cons (car lst) (filter pred (cdr lst))) (filter pred (cdr lst))))) (define (count-visible grid) (let ((n (sub1 (vector-length grid)))) (let rloop ((r 0) (count 0)) (if (> r n) count (rloop (add1 r) (+ count (length (filter (lambda (c) (is-visible? grid r c)) (range n))))))))) (define (best-view grid) (let ((n (sub1 (vector-length grid)))) (apply max (map (lambda (r) (apply max (map (lambda (c) (score grid r c)) (range n)))) (range n))))) (define (main args) (let* ((lines (read-lines)) (grid (lines->grid lines))) (print (count-visible grid)) (print (best-view grid)))) ;; for repl exploration (define gd '#(#(3 0 3 7 3) #(2 5 5 1 2) #(6 5 3 3 2) #(3 3 5 4 9) #(3 5 3 9 0)))