diff --git a/day8-input.txt b/day8-input.txt new file mode 100644 index 0000000..ffdd5b1 --- /dev/null +++ b/day8-input.txt @@ -0,0 +1,99 @@ +011201001000123232122300403211332202122424332111151523152310403222120311202224013311113203311122001 +102201211220103202323002411123324024134251423232343141424431144431022143443131141222323122010012220 +002022232232102013311311301321044421352134513235443522243113311323213013301030440423203311103101020 +002212021110130112400112141310424411421435324412235335534245212325313312413434430114302030310200000 +202000312203303110042324124431114212153432535412115323131323541522511253002131401212012131031321110 +120203002030304244102444143021314124552253521343321513511124144454343454102412220143321013220111212 +012133330030200444414333325255125142322121412245551424242135123513411533153323130432231002121211210 +012300220003100211444401144353345522135453435223464636451554321531323513234331131114224102232333310 +000201310302031301344341134512444312432566266533252332656654251123535525135213300040211242011230031 +121002133124022203240512452433331223524622643252532325346635555552514352434233454024134201432001111 +112213110140442401434531255323512525265655352543623565556265545555235551143135124203142220020302000 +033001202421424143555311243322416262636322654432542644633525453666655354514351121150231101002002310 +133303044321221102531154151541224245536464535622566355532543644552554644312231415325142303020031312 +112333344411024045335422225146442243536464622553556234523445362524655623435243115242532313102020021 +123023422310204444121415255225254435644446326664473564435422565325224635623542352154120001224144312 +102303024142131515433355242322223363453633455657436436574636544336652564626641215232314243234004001 +021344140434455245134415553542352643537665534644574553367446664254532523624521243554252411433032112 +100140101131444142414254644644434663647646555637737475474473636562243265243536422253531252202124322 +111043301134142345422324342454235374733474673456744577746755765343355535622342432251442244140231224 +232120141224122324244532255543256467566454337465647735433663734756446566663442525425254525142212311 +102310340244433433553362546534535757453376643763344566566557634664535744445254533545223521213213014 +330111232252114431226334564636467643777466445537346735563633337744734474466254662225321443542401243 +344311321253412213666443354643647347656735478884748547564466577774737677363226422622515344334010341 +222340105234132533423442424376674757757675647476557547564445666676437755355626455436313331225343402 +334241221121414455435265324646757456774784864846746867457546648735456677555624445353555434433340341 +333430021343121666326363537633737767788775478777445558858444854755434544735362564626265444342330020 +332224425333452333556456745375454657668644877658744844547774765844454475434765533256545152435214410 +411322431421116436336347456774356844455867864644844878664785864444475567664473365652253123453220003 +130345455115155526426437663665665668576686587847778476557678655576775553535745643522532344433523042 +241333521455132466523664543556384776587787745658797755565556576546847447434775733626365325451531301 +202135433134452323646546565545646885747548679876767658578565476458486465755545465664435422532454541 +344025243154435524235475655536845545775797795959686975588855546544875685664377465455353661444452422 +120511445324333353265334766654858656857755669695597899959957757545465687447345336332322634434414522 +041425252513666643357433333888555778459755889566967799659865567757457567576463765323236366123221323 +142343534134652443554434768544658774587669979986775985989879787975445856456554364645323653454511323 +443155144123223566654765746758688875856899955996667659755976778586644774777456744653322566354532232 +013242522162435447764573774877757879868788876799896979576555597985885468586473474464455426633333452 +101431333345553353553337548577478656967866886877887889699999856979976485874455544477534422463331314 +422325541533664573334736464857446675995799977868697688998787757585668584775766563477536636621514142 +313315332565562573637376866486547776557979868979996867779966955885566785455767644565336236452541411 +231122455364326235655644685888786685587796897688777698977986787596655865857448333576665523356143332 +314415154446535337443754887576795586569678967879977696896667866768856785586774365336636426455324541 +251324556334435537567468544665859588888869687767876697967887867856679658788866355353346553442543353 +134353225423362456734666455757877769577678987866887877799886886885859796767664444665534363236114533 +251241346545626367667578575687955957988796678987999979977897978877579787844755554533763646262143315 +353543555544353753474346565789555799696999667888997899777669899867697878476845756644734243432245123 +221521465632632737777766744748678869769669668898887888987898666789869785645678734643552655525624335 +351552456455622567337644647486678857766866879798779999878779869885869788874885873744772665326352324 +153242153665224557353455465857685566797887699998988788877767696668668675666664465757646436665554315 +321113152666424547657348876876678597898779877779998999978978777885976658558676664444674243656333212 +421511245364456777655754476646885699898678788797778788778778999795687589454774563737333365434325525 +213532265252653474345766566877669898969767779777879797899977669868595997784466766655547455234435452 +125232235356525353764645486577668857868788699799787978898988669878688867586564457353673236664223343 +441242562562223643773466848558599657669669968987979987787969676777796877655876456745562442232541525 +135122156635652746574578664849659556998698797778797889988788869797687977855447474475546334662522444 +144315413442434666777478887855885568968799966889978797797867786966685589646488554737453225335213325 +511213234443636433646678657654587788667696879878989799867699988765895758788675765445656425425334544 +052145146243336363474565857687976889776768867898889967686967668565998666768575534675445244546424155 +235513424332444756467574556745997958679678999799789777998968876679956958746554677637762355253554335 +331155256654246447545776676487485655676699678967897779688898989999768655488874564764434223445132152 +152152253254255234473347878744485766678897879689897888667968795675655864748584644653323363464154251 +245154344235223346354765457746867586969968687876867899766986679689585778787473555663424264553541344 +235253541263666477544377746867785766579566868896689699876766695956667455774677646576554255521144355 +033522343456423455634354575764856898657669957896677776766596688857787474488436433455326554242331222 +321532413246333226435563556578864759978657759897896799958558598588975755858856537673332523244522141 +101422552442534324467345475684574877989759655788785857697957976679848768474665346435664653421242444 +103425135453353666736674677847548667967885667765576995797857589796866646565443377775564436443333543 +041131245522253556554636537878457787468577768876778599999689667978487755747676763666266652435545351 +424232344536333364556466767555646468677996965895798968676966868665587584664535544755645232211324114 +334034423343366322247357747635787857555667756956768657779596877655676555367754633345545442422145333 +424344345121532564223643563774744574746844686888885779565686455664565643634566756543362551431252401 +232123114442152332546734767375678475664877645798695799654765488755876545334345452455463633534433233 +414423121145222454332477456654436757485685646546884446667744645744675377357654436554353221451345404 +234130223314353235262655676637577858558554556467788664555466588778677546456334642623666524333250443 +414001252524152463224524734765775677644765886656877578666575855788653533364773455446565352432424320 +024323134311552535243564667476365737764685474446876486685546667685363735646643655435355533243440034 +331141044111451522226436327536773637654887585478885586588745847444466365767232265352211455413531431 +241321311312323233252665352455436545735388846445565487667644555744667753556266645332452431541341044 +234030032312154414563442653244476576544654676884777445766434443476675746365245632242515342521301442 +202112004552434344564624422526757574735736566643654737673776743354737744242533546523434111443034202 +323422334452422412134566522262537334374446646774476534347655656336555632626663364214333341322443300 +031243421344143515452456444553266345437737337675574563437533573575456463665443432215213541123241240 +002114441013421154331235436253442576764555535635775735635377573353666526333623554524421352131443020 +111342301013125124521245222663363363467436357434736773473777464564655622533254352444544553311114233 +222323000331131531351433363334345533653474663466435557365553376535246564324662454422135233103003200 +002103300342403311123432563445263435443255635353333564444573456633466424623313351545133022013122320 +300304042333200223123432352234525626625234236453763536563235242224645265643515312312520000242200000 +210121244033001141551213125554433445222532265463624234562324443435344362451243522525243002401410013 +303323342040431313415255233251226626334264553655346266323665655652522363324341123235410333230402230 +300112203021311400115231251543524354554262365526643622264625434236554412121342322522123434120120203 +011001023222004142422445443143212526654365444643442536365453622222634154551441553400220414300301332 +230032020342121242113341435444543253355352433246243543645634456552525315313143243431133302112320020 +232132202131312144424224413332214322543242664652323324456222615212244414145113442320023403200012111 +112222030320432400004224215552515412325221525356363643351335211141344255554442403013303120331312202 +110321230332323212301432002424211134155124241552254334221154111545254253122214132321141212032221001 +021020121321302320401011302153145251455114411155452245422422135453412153112033343412340101230302010 +122203012232330222213342133012334131225335225325343355122151154444535354414423434423220001330003020 +221120213213221333210131242440001425551432522221141211124544343151315104244333311124033221102312011 +202201033331203122413021242022211002455531321354252412214332215513311231404032244320020330332301120 diff --git a/day8-test-input.txt b/day8-test-input.txt new file mode 100644 index 0000000..16d6fbd --- /dev/null +++ b/day8-test-input.txt @@ -0,0 +1,5 @@ +30373 +25512 +65332 +33549 +35390 diff --git a/day8-tree-heights.lisp b/day8-tree-heights.lisp new file mode 100644 index 0000000..9fe92fc --- /dev/null +++ b/day8-tree-heights.lisp @@ -0,0 +1,372 @@ +;;; https://www.youtube.com/watch?v=aGedUxTAfBk + +;; tree is visible if from one of 4 directions there are only trees that are "strictly lower" +;; the computation reuse - if we checked the tree on the top before, and it's visible from top and lower - then currnt is visible +;; but if it's not visible from top, then we need to know which tree covered it up, to calculate whether current tree is taller than that. +;; +;; so. i'd want to i think this time actually use classes. to store visibility from the directions. +;; or rather for each tree store the highest tree towards the enge in the direction. +;; and would be possible to calculate visibility into a direction then +;; +;; so. have a class with hash-table of DIRECTION -> tallest-in-that-direction +;; i suppose can be done without storing this data. just go through the line against the checking direction, and store last tallest tree in var +;; could store visibility in the shared 2d array + +(loop + :for i :across (vector 1 2 3 4) + :do (print (* 5 i))) + +(coerce (list 1 2 3 4) 'vector) + +(require 'cl-ppcre) +(cl-ppcre:split "" "hello") + +(coerce (mapcar #'parse-integer (cl-ppcre:split "" "30373" )) 'vector) + +;; (defparameter *file-name* "day8-test-input.txt") +(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)))) + +*trees-2d-vector* +;; (aref *trees-2d-vector* 3 0) ; error +(let ((arr (make-array '(2 3)))) + (setf (aref arr 1 1) "hello") + arr) ; but can't access row at a time. + ; ugh. + +;; now. i'd want visibility matrix. with true on edges and false inside + +;; then loop over lines / rows against the direction +;; store previous max height, if current is bigger - store it as previous max visible and +;; put visible into the shared matrix +;; +;; then do iteration against all directions, only updating table to true +(ql:quickload "iterate") +(use-package 'iterate) + +(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)) + (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)))) + ;; cool + + ;; (loop + ;; for rownum from 0 to (1- rows-count) + ;; for colnum from 0 to (1- cols-count) + ;; when (or (= rownum 0) + ;; (= rownum (1- rows-count)) + ;; (= colnum 0) + ;; (= colnum (1- cols-count))) + ;; do (progn + ;; (setf (aref visibility-matrix rownum colnum) "hello") + ;; )) + + ;; (setf (aref visibility-matrix 1 1) "hello") + visibility-matrix)) + +;; now for i j if +(loop + for rownum from 0 to 3 + for colnum from 0 to 4 + ;; when (or (= rownum 0) + ;; (= rownum (1- rows-count)) + ;; (= colnum 0) + ;; (= colnum (1- cols-count))) + collect rownum) + +(iterate:iter (for i from 1 to 5) + (print i)) +(iterate:iter (for i from 5 downto 1) + (print i)) +(iterate:iter (for item in '(1 2 3)) + (print item)) + +;; so. now i have visibility matrix wihch is 2d, +;; to store which trees are "visible" +;; and also i have Vector(Vectors) for tree sizes, for iteration. +;; +;; now ideally I'd be able to code these iterations in a compact way. +;; but i'm just ugh + +;; no, just no. let's of iterations which i'm not sure how to generalize +;; and need to share state, upleasant +;; (defun nextPoint (row col direction) +;; (case direction +;; ('UP (list row (1- col))) +;; ('DOWN (list row (1+ col))) +;; ('LEFT (list (1- row) col)) +;; ('RIGHT (list (1+ row) col)))) +;; (nextpoint 1 1 'up) +;; (nextpoint 1 1 'left) +;; (nextpoint 1 1 'right) +;; (nextpoint 1 1 'down) +;; (apply #'nextpoint '(1 1 down)) +;; (apply #'+ '(1 2 3)) + +(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))))) + +(gen-line-coords 0 0 4 5 'down) +(gen-line-coords 0 0 4 5 'right) +(gen-line-coords 3 4 4 5 'up) +(gen-line-coords 2 4 4 5 'left) +(apply #'gen-line-coords '(0 0 4 5 down)) + +;; well, looks like this works +;; and then generic iteration on these coordinates? +;; store previous max tree. +;; if current is bigger than previous max - store it as previous max and put T into vix.matrix +;; i really dislike this task so far. + +(defparameter *test-line-coords* (gen-line-coords 1 0 4 5 'right)) +(let ((biggest-tree-so-far -1)) + (loop + for coords in *test-line-coords* + 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)))))) + +*test-line-coords* +*trees-2d-vector* +*tree-vis-matr* +(aref *tree-vis-matr* 1 1) + +;; well it kinda worked. +;; now i need to get all possible line-coords, with desired directions +;; and then run for each of these +;; and then - count amount of T in the resulting matr + +;; getting all possible direction line-coords +;; +(progn + (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)) + +;;; wow, 1835 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 +;; for each tree take tail of coord line into each direction +;; and count how long to the first tree of at least same height. + +*trees-2d-vector* + +(defparameter *test-tree-coords* '(2 2)) +(defparameter *test-line-coords* (gen-line-coords 3 3 4 5 'right)) +(cdr *test-line-coords*) +(eval `(gen-line-coords ,@*test-tree-coords* *trees-rownum* *trees-colnum* 'right)) +(defparameter *test-tree-direction-cols* + (mapcar #'cdr + (mapcar #'eval + (mapcar + (lambda (direction) + `(gen-line-coords ,@*test-tree-coords* *trees-rownum* *trees-colnum* ,direction) + ) + '('right 'down 'left 'up))))) + +(defun tree-size-by-coords (coords) + (aref (aref *trees-2d-vector* (first coords)) (second coords))) +(tree-size-by-coords '(1 1) ) + +(print (mapcar (lambda (coord-line) + (mapcar #'tree-size-by-coords coord-line)) *test-tree-direction-cols*)) + +(defun take-while (list pred) + (loop for elt in list while (funcall pred elt) collect elt)) +(take-while '(1 2 3 3 3 4 5 6) (lambda (n) (>= 3 n))) + +;; it's not it. ugh. why it's so hard. +;; how can i find index of first inclusion of element in list. +;; i guess i could do strict less than and add 1? no. + +(take-while '(1 2 3 3 3 4 5 6) (lambda (n) (> 3 n))) +;; and then if list i got not equal to initial list - add 1 because we dropped something? +;; UGH! +;; should be a better way. +(do* + ((start-tree-size (tree-size-by-coords '(3 3))) + (coords-direction (car *test-tree-direction-cols*) (cdr coords-direction)) + (coord (car coords-direction) (car coords-direction)) + (coord-tree-size (tree-size-by-coords coord) (tree-size-by-coords coord)) + (count 0 (1+ count))) + ((or (not coords-direction) + (> coord-tree-size start-tree-size)) + (if ((= coord-tree-size start-tree-size) + (1+ count) + count)))) +;; i'm incredibly frustrated +;; more that an hour on trying to get initial part of list until first inclusion of target element. +;; horrible + +;; ok. this monstrocity +(let ((self 3) + (found-self nil)) + (loop for elt in '(1 2 2 3 1 5 1) + while (and (not found-self) + (>= self elt)) collect elt + if (= elt self) do (setq found-self 't))) + +(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)))) +(my-get-prefix '(3 3 1 5 1 2) 4) +(my-get-prefix '() 6) +;; ok. let's map that on top of other shit + +(print (mapcar (lambda (height-list) + (length (my-get-prefix height-list 3))) + (mapcar (lambda (coord-line) + (mapcar #'tree-size-by-coords coord-line)) *test-tree-direction-cols*))) + +;; and this was all inconsequential because for 3 seeing 3 and seing 5 is same end +;; so i could have used take-while with strict condition. +;; in any way would have needed to add 1? + +;; will modify my ugly function, making it uglier, cool +;; +;; now need to multiply them and call that with correct coords for all inner trees. +;; this is pain. + +;;; returning to calculating the directions from each tree +*trees-2d-vector* + +(defparameter *test-tree-coords* '(4 2)) +(defparameter *test-line-coords* (gen-line-coords 3 3 4 5 'right)) +(defparameter *test-tree-direction-cols* + (mapcar #'cdr + (mapcar #'eval + (mapcar + (lambda (direction) + `(gen-line-coords ,@*test-tree-coords* *trees-rownum* *trees-colnum* ,direction) + ) + '('right 'down 'left 'up))))) + +(defun get-tree-direction-cols (tree-coords) + (mapcar #'cdr + (mapcar #'eval + (mapcar + (lambda (direction) + `(gen-line-coords ,@tree-coords *trees-rownum* *trees-colnum* ,direction) + ) + '('right 'down 'left 'up)))) + ) + +(defun tree-size-by-coords (coords) + (aref (aref *trees-2d-vector* (first coords)) (second coords))) +(tree-size-by-coords '(1 1) ) + +(print (mapcar (lambda (coord-line) + (mapcar #'tree-size-by-coords coord-line)) *test-tree-direction-cols*)) + +(print (mapcar (lambda (height-list) + (length (my-get-prefix height-list 3))) + (mapcar (lambda (coord-line) + (mapcar #'tree-size-by-coords coord-line)) *test-tree-direction-cols*))) +(apply #'* '(1 2 2 0)) + +(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) + +;; wow. i got an aswer 8 +;; now try to recalculate this horrible thing with actual input.