#!/usr/bin/env -S sbcl --script ;; Copyright (C) 2022 ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . (require 'asdf) (require 'uiop) (require 'str) (require 'iterate) (defpackage :advent-of-code-day-8 (:use :cl :iterate)) (in-package :advent-of-code-day-8) (defclass tree () ((x :initarg :x :reader x) (y :initarg :y :reader y))) (defmacro make-tree (x y) `(make-instance 'tree :x ,x :y ,y)) (defun scan-right? (trees position) (iter (with width = (- (array-dimension trees 1) 1)) (with tree-height = (aref trees (y position) (x position))) (for i from (+ (x position) 1) to width) (for tree = (aref trees (y position) i)) (counting t into view-count) (unless (< tree tree-height) (return (cons :not-visible view-count))) (finally (return (cons :visible view-count))))) (defun scan-left? (trees position) (iter (with tree-height = (aref trees (y position) (x position))) (for i from (- (x position) 1) downto 0) (for tree = (aref trees (y position) i)) (counting t into view-count) (unless (< tree tree-height) (return (cons :not-visible view-count))) (finally (return (cons :visible view-count))))) (defun scan-down? (trees position) (iter (with height = (- (array-dimension trees 0) 1)) (with tree-height = (aref trees (y position) (x position))) (for i from (+ (y position) 1) to height) (for tree = (aref trees i (x position))) (counting t into view-count) (unless (< tree tree-height) (return (cons :not-visible view-count))) (finally (return (cons :visible view-count))))) (defun scan-up? (trees position) (iter (with tree-height = (aref trees (y position) (x position))) (for i from (- (y position) 1) downto 0) (for tree = (aref trees i (x position))) (counting t into view-count) (unless (< tree tree-height) (return (cons :not-visible view-count))) (finally (return (cons :visible view-count))))) (defun tree-visible? (trees position) (or (equal (car (scan-right? trees position)) :visible) (equal (car (scan-left? trees position)) :visible) (equal (car (scan-down? trees position)) :visible) (equal (car (scan-up? trees position)) :visible))) (defun scenic-score (trees tree) (* (cdr (scan-right? trees tree)) (cdr (scan-left? trees tree)) (cdr (scan-down? trees tree)) (cdr (scan-up? trees tree)))) (defun trees-from-file-lines (lines) (let* ((split-lines-into-digits (mapcar (lambda (line) (str:split "" line :omit-nulls t)) lines)) (numbers (mapcar (lambda (row) (mapcar 'parse-integer row)) split-lines-into-digits)) (x (length (nth 0 numbers))) (y (length numbers))) (make-array (list x y) :initial-contents numbers))) (defun solution-part-1 (trees) (iter (with width = (- (array-dimension trees 1) 1)) (with height = (- (array-dimension trees 0) 1)) (for y from 1 to (- height 1)) (sum (iter (for x from 1 to (- width 1)) (for tree = (make-instance 'tree :x x :y y)) (counting (tree-visible? trees tree))) into visible-interior-trees) (finally (return (+ visible-interior-trees (* width 2) (* height 2)))))) (defun solution-part-2 (trees) (iter (with width = (- (array-dimension trees 1) 1)) (with height = (- (array-dimension trees 0) 1)) (for y from 1 to (- height 1)) (appending (iter (for x from 1 to (- width 1)) (for tree = (make-instance 'tree :x x :y y)) (collect (scenic-score trees tree))) into scores) (finally (return (let* ((sorted-scores (sort scores '>))) (car sorted-scores)))))) (let ((trees (trees-from-file-lines (uiop:read-file-lines "example.txt")))) (assert (= 21 (solution-part-1 trees)))) (let ((trees (trees-from-file-lines (uiop:read-file-lines "input.txt")))) (assert (= 1736 (solution-part-1 trees)))) (let ((trees (trees-from-file-lines (uiop:read-file-lines "example.txt")))) (assert (= 8 (solution-part-2 trees)))) (let ((trees (trees-from-file-lines (uiop:read-file-lines "input.txt")))) (assert (= 268800 (solution-part-2 trees)))) ;; Local Variables: ;; mode: lisp ;; End: