From 3105b97f1de34eac47a28f7ad5e8900c912978bc Mon Sep 17 00:00:00 2001 From: efim Date: Thu, 8 Dec 2022 12:17:31 +0000 Subject: [PATCH] day 8 cleaning up code --- day8-tree-heights.lisp | 137 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/day8-tree-heights.lisp b/day8-tree-heights.lisp index 9fe92fc..453b61d 100644 --- a/day8-tree-heights.lisp +++ b/day8-tree-heights.lisp @@ -227,7 +227,7 @@ (incf running-sum 1)))) running-sum)) -;;; wow, 1835 was the right answer. urrgh +;;; wow, 1845 was the right answer. urrgh ;;; now to the second part ;; and that's totally different thing now. ;; i guess i could use my "col-line" to get coords to check from the tree @@ -367,6 +367,141 @@ (if (> cur-tree-score cur-max) (setq cur-max cur-tree-score))))) cur-max) +;; 230112 is the correct answer ;; wow. i got an aswer 8 ;; now try to recalculate this horrible thing with actual input. + +;;; let's CLEAN UP THE CODE, at least set it all together +;;; PART 1: Count visible trees + +(defparameter *file-name* "day8-input.txt") +(progn + (defparameter *trees-2d-vector* + (let ((rows-accumulation ())) + (with-open-file (in *file-name*) + (loop + for line = (read-line in nil nil) + while line + do (push + (coerce (mapcar #'parse-integer (cl-ppcre:split "" line)) 'vector) + rows-accumulation) + ) + (coerce (reverse rows-accumulation) 'vector)))) + (defparameter *trees-rownum* (length *trees-2d-vector*)) + (defparameter *trees-colnum* (length (aref *trees-2d-vector* 0)))) + +;; generate Visibility matrix for trees +(defparameter *tree-vis-matr* + (let* ((rows-count (length *trees-2d-vector*)) + (cols-count (length (aref *trees-2d-vector* 0))) + (visibility-matrix (make-array (list rows-count cols-count) :initial-element nil))) + + (iterate:iter (for rownum from 0 to (1- rows-count)) ; trying iter to avoid nested LOOP + (iterate:iter (for colnum from 0 to (1- cols-count)) + (if (or (= rownum 0) + (= rownum (1- rows-count)) + (= colnum 0) + (= colnum (1- cols-count))) + (setf (aref visibility-matrix rownum colnum) 'T)))) + visibility-matrix)) + +;; get list of coordinates towards DIRECTION, starting from startRow & startCol +;; for generalizing LOOP'ing into different directions +(defun gen-line-coords (startRow startCol rowNum colNum direction) + (flet ((row-col-valid (row col) + (and (>= row 0) (>= col 0) (< row rowNum) (< col colNum))) + (nextPoint (row col) + (case direction + ('LEFT (list row (1- col))) + ('RIGHT (list row (1+ col))) + ('UP (list (1- row) col)) + ('DOWN (list (1+ row) col))))) + (let ((coords-collected ())) + (do + ((coords (list startRow startCol) (apply #'nextpoint coords))) + ((not (apply #'row-col-valid coords)) (reverse coords-collected)) + (push coords coords-collected))))) + + +(progn + ;; this is with unfortunate amount of manual tinkering + (defparameter *trees-right-line-coords* + (loop + for startRow from 0 below *trees-rownum* + collect (gen-line-coords startRow 0 *trees-rownum* *trees-colnum* 'right))) + + (defparameter *trees-left-line-coords* + (loop + for startRow from 0 below *trees-rownum* + collect (gen-line-coords startRow (1- *trees-colnum*) *trees-rownum* *trees-colnum* 'left))) + + (defparameter *trees-right-down-coords* + (loop + for startCol from 0 below *trees-colnum* + collect (gen-line-coords 0 startCol *trees-rownum* *trees-colnum* 'down))) + + (defparameter *trees-right-up-coords* + (loop + for startCol from 0 below *trees-colnum* + collect (gen-line-coords (1- *trees-rownum*) startCol *trees-rownum* *trees-colnum* 'up))) + + (defparameter *trees-all-line-coords* + (concatenate 'list + *trees-right-line-coords* + *trees-left-line-coords* + *trees-right-down-coords* + *trees-right-up-coords*)) + +;;; iterate over all col-lines + (loop + for coord-line in *trees-all-line-coords* + do (let ((biggest-tree-so-far -1)) + (loop + for coords in coord-line + do (let* ((rownum (first coords)) + (colnum (second coords)) + (row (aref *trees-2d-vector* rownum)) + (tree-size (aref row colnum))) + (if (< biggest-tree-so-far tree-size) + (progn (setq biggest-tree-so-far tree-size) + (setf (aref *tree-vis-matr* rownum colnum) 't))))))) + + *tree-vis-matr* + + ;; counting amount of 'T in the visibility matrix + (let ((running-sum 0)) + (iterate:iter (for rownum from 0 to (1- *trees-rownum*)) + (iterate:iter (for colnum from 0 to (1- *trees-colnum*)) + (if (aref *tree-vis-matr* rownum colnum) + (incf running-sum 1)))) + running-sum)) + + +;;; PART 2. find tree with highest view-score +;; from list of tree-heights take trees that lover than current, until first tree of same height or higher +(defun my-get-prefix (trees-heights self-height) + (let ((self self-height) + (found-self nil)) + (loop for elt in trees-heights + while (not found-self) collect elt + if (>= elt self) do (setq found-self 't)))) + +;; use same trees 2d array. O(n^2) - for each tree construct lines into 4 directions, +;; get prefix of these lines for trees that of not exceeding height, calculate score +;; instead of CUR-MAX could possibly use MAXIMIZING of LOOP, or something +(let ((cur-max -1)) + (iterate:iter (for row from 1 to (1- *trees-rownum*)) + (iterate:iter (for col from 1 to (1- *trees-colnum*)) + (let* ((cur-tree-height (tree-size-by-coords (list row col))) + (cur-tree-lines (get-tree-direction-cols (list row col))) + (cur-tree-lines-tree-heights + (mapcar (lambda (coord-line) + (mapcar #'tree-size-by-coords coord-line)) cur-tree-lines)) + (cur-tree-visibilities + (mapcar (lambda (height-list) + (length (my-get-prefix height-list cur-tree-height))) cur-tree-lines-tree-heights)) + (cur-tree-score (apply #'* cur-tree-visibilities))) + (if (> cur-tree-score cur-max) + (setq cur-max cur-tree-score))))) + cur-max)