Advent of Code 2021 https://adventofcode.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
3.8 KiB

  1. #lang racket
  2. ; util
  3. (define (split-on lst x) ; like splitOn in haskell. couldn't find this in the std lib..
  4. (foldr (λ (element next)
  5. (if (equal? element x)
  6. (cons empty next)
  7. (cons (cons element (first next)) (rest next))))
  8. (list empty) lst))
  9. (define (map-map f lst) ; why tf can't i do (compose map map)
  10. (map (λ (x) (map (λ (y) (f y)) x)) lst))
  11. (define (map-map-map f lst) ; (map . map . map)
  12. (map (λ (x) (map-map f x)) lst))
  13. (define (transpose xss)
  14. (apply map list xss))
  15. (define (all? f list)
  16. (not (findf (λ (x) (not (f x))) list)))
  17. ; IO and setup
  18. (define lines
  19. (file->lines "day4.txt"))
  20. (define numbers ; grab first line of file, split into a list on ,
  21. (map string->number (string-split (first lines) ",")))
  22. (define boards
  23. (let* ([str-lists (split-on (drop lines 2) "")] ; split on empty lines
  24. [split-up (map-map string-split str-lists)] ; convert '("1 2 3") to '("1" "2" "3")
  25. [num-lists (map-map-map string->number split-up)]) ; convert '("1" "2" "3") to '(1 2 3)
  26. (map-map-map (λ (x) (cons x #f)) num-lists))); change each cell to (<number>, <picked>)
  27. ; part 1
  28. (define (mark-board board number) ; mark up a board with #t or #f based on the number
  29. (map-map (λ (cell)
  30. (match cell
  31. [(cons num on) (cons num (or on (= num number)))]))
  32. board))
  33. (define (mark-boards boards number) ; mark all boards based on the number
  34. (map (λ (board) (mark-board board number)) boards))
  35. (define (all-winners? lst) ; check if all pairs in the list are #t
  36. (all? cdr lst))
  37. (define (is-winner? board) ; check if any row or column in the board is a winner
  38. (let ([cols (transpose board)])
  39. (or
  40. (findf all-winners? board)
  41. (findf all-winners? cols))))
  42. (define (mark-all-until-win boards numbers)
  43. (foldl (λ (number acc)
  44. (match acc
  45. ([cons boards last-number]
  46. (if (findf is-winner? boards) ; if we have any winners
  47. (cons boards last-number) ; just return the boards
  48. (cons (mark-boards boards number) number))))) ; otherwise keep marking
  49. (cons boards 0) numbers))
  50. (define (sum-unmarked board)
  51. (let* ([cells (apply append board)] ; flatten it
  52. [unmarked (filter (λ (x) (not (cdr x))) cells)] ; filter out marked cells
  53. [nums (map car unmarked)])
  54. (foldl + 0 nums)))
  55. (define part1
  56. (let* ([marked-up (mark-all-until-win boards numbers)] ; get (the final board state . last number)
  57. [marked-boards (car marked-up)] ; car out the boards
  58. [last-number (cdr marked-up)] ; cdr out the last number
  59. [winning-board (findf is-winner? marked-boards)] ; find the winning board
  60. [unmarked-sum (sum-unmarked winning-board)]) ; sum up the unmarked cells
  61. (* unmarked-sum last-number)))
  62. part1
  63. ; part 2
  64. (define (mark-all-until-one boards numbers)
  65. (foldl (λ (number acc)
  66. (match acc
  67. ([cons boards last-number]
  68. (if (= (length boards) 1) ; if we have only have 1 board left
  69. (cons boards last-number) ; just return it
  70. (let ([filtered-boards (filter (λ (x) (not (is-winner? x))) boards)]) ; otherwise filter out the winners
  71. (cons (mark-boards filtered-boards number) number)))))) ; and then keep marking
  72. (cons boards 0) numbers))
  73. (define part2
  74. (let* ([marked-up (mark-all-until-one boards numbers)] ; get (the final board state . last number)
  75. [marked-boards (car marked-up)] ; car out the boards
  76. [last-number (cdr marked-up)] ; cdr out the last number
  77. [winning-board (findf is-winner? marked-boards)] ; find the winning board
  78. [unmarked-sum (sum-unmarked winning-board)]) ; sum up the unmarked cells
  79. (* unmarked-sum last-number)))
  80. part2