Compare commits

..
50 Commits
Author SHA1 Message Date
ryan 8ec58edd08 solve day 18!
it was kinda ez
2024-02-13 23:03:04 -08:00
ryan 1904239ca7 reorganize day 17 code a bit 2024-01-11 10:48:11 -08:00
ryan 46d49dc3fe add pretty printed tower test in day 17 2024-01-11 10:19:39 -08:00
ryan 950f2860df fix day 12 performance regerssion
caused by a change to Grid.at_e that would eagerly format an exception
string even if the function never throws an exception.
2024-01-08 12:48:55 -08:00
ryan d203c9a520 finish day 17 part 2 2024-01-08 12:36:14 -08:00
ryan 8b54ae782c finish day 17 part 1 2024-01-05 11:33:26 -08:00
ryan 9f1499a1d3 implement day 17 rock falling logic 2024-01-04 00:38:09 -08:00
ryan 490696c63d make Grid.draw more flexible
- printer callback includes Vec2.t in the arguments now
- added optional rev_x and rev_y params
2024-01-03 09:18:57 -08:00
ryan a7c039197b fix .ocamlinit ?? 2024-01-03 09:18:27 -08:00
ryan 94f4badcc4 30x speedup on 16.2 from using bitmasks as a set!! 2023-12-04 23:28:54 -08:00
rmanseau 4e57ad4072 clean up 15.1 implementation a bit 2023-11-27 13:45:32 -08:00
ryan f2f3e497d6 get rid of old day 16 solution 2023-11-23 21:35:32 -08:00
ryan 2a515a5323 day 16.1 down to 1.5 seconds !! 2023-11-23 12:22:17 -08:00
ryan 5c0d7867a4 speed up 16.2 by 10x but its still 10 seconds >:( 2023-11-23 11:17:41 -08:00
ryan 1df5532c24 finally solved day 16 part 2 (in 100 seconds :P) 2023-11-22 22:58:22 -08:00
ryan 8db68c9baf use djikstra to get min dist between all valves
now i should be able to rewrite traverse in a way that doesn't suck
2023-11-22 18:27:42 -08:00
ryan 360be1a368 modify djikstra to work without a goal
if you give None as a goal, then it traverses the entire grid and finds
the shortest path to every node. the distances can then be queried via the
get_info that is passed in as an argument
2023-11-22 16:10:47 -08:00
ryan ae2acb87fa refactor generalized djikstra out of day 12 2023-11-22 16:10:47 -08:00
ryan c7eae53378 doesnt work for 16.2 :( 2023-11-21 23:22:43 -08:00
ryan b9a36a476a brute force day 16.1 with incorrect algorithm lol
it gets the right answer for the input but not for the example input
2023-11-21 18:17:35 -08:00
ryan 8270ee7aa8 never touching day 15 ever again 2023-11-21 16:50:51 -08:00
ryan 894e83fe12 fix day 15 for example inputs
part 1 didn't work for the example input :(
2023-11-21 16:48:03 -08:00
ryan 11546bff5f fix ocamlformat
apparently `version = x` simply refuses to format if you dont have the
specified version. doesn't seem very useful for a repo like this.
2023-11-21 16:47:17 -08:00
ryan d1e69ba66e cosmetic refactoring for day 15 2023-11-20 18:57:00 -08:00
ryan 2887274ad9 update the comment in day 15.1 2023-11-20 18:34:44 -08:00
ryan 6758130700 speed up day 15.1 with intersections
also update the vec module to use Iter in some places
2023-11-20 18:26:55 -08:00
ryan ff4bb0ae89 simplify day 15 parsing with regex 2023-11-20 14:26:01 -08:00
ryan b69f867423 update opam file 2023-11-20 14:25:38 -08:00
ryan a652ec69da add memo wrapper for recursive functions 2023-11-20 14:11:04 -08:00
rmanseau 421616a282 add dev env packages to depends 2023-11-20 13:36:40 -08:00
rmanseau f775ed645b fix opam file and add install steps to README 2023-11-20 12:24:23 -08:00
ryan 705c9e9a7c faster 15.2 solution with line intersections :/ 2023-11-10 18:24:41 -08:00
ryan 8d97e7601c very slow solution to day 15 part 2 :)
could be sped up by doing math to find intesections points of the
borders but that sounds boring
2023-11-09 14:23:41 -08:00
ryan b89e9c05ef refac day 14 to use new Vec2.bounds function 2023-11-08 10:37:44 -08:00
ryan b90478cd03 solve day 15 part 1 ! 2023-11-08 10:37:31 -08:00
ryan 383c6c0fca add Vec2.iter_region 2023-11-08 10:36:33 -08:00
ryan 19a763b73f manually implement show & pp for Vec2
so that it prints as if it were a tuple
2023-11-08 09:14:22 -08:00
ryan dcb1338aa3 parse day 15 2023-11-08 09:14:00 -08:00
ryan 724576d120 refactor day 14 a bit 2023-11-01 14:40:16 -07:00
ryan ceaebf895d solve day 14! 2023-11-01 14:14:46 -07:00
ryan ceb0f04a78 implement sand dropping logic & pretty visuals 2023-11-01 12:10:15 -07:00
ryan c5c9b584c0 update Grid.%() operator to return option 2023-11-01 12:09:53 -07:00
ryan 80f29ae00e swap Vec2 up/down
going down on the grid increases the int for y
2023-11-01 12:08:43 -07:00
ryan 2418d2ff0d normalize points in input
this way i can print the full input in as small a space as possible!
2023-10-31 18:06:12 -07:00
ryan 1ca2a95e1d make Grid.set_e throw out of bounds errors 2023-10-31 18:05:10 -07:00
ryan 61e3520ede parse day 14 grid
haven't implemented the falling sand yet, but theres a cool expect test
that draws the grid
2023-10-31 17:04:20 -07:00
ryan 98f47654f8 change Vec2 implementation to a record type 2023-10-31 15:57:13 -07:00
ryan 88acb381f1 move Grid into its own file 2023-10-31 15:57:11 -07:00
ryan 1d60878428 add init_grid func 2023-10-31 14:43:12 -07:00
ryan 63bad67c1b create angstrom wrapper in Utils for int parser
and other common parsers for the future
2023-10-31 14:40:22 -07:00
27 changed files with 3502 additions and 125 deletions

No files matched your search

+1 -1
View File
@@ -1 +1 @@
eval $(opam config env)
eval $(opam env --switch=.)
+1
View File
@@ -1,2 +1,3 @@
.DS_Store
_build/
_opam/
-1
View File
@@ -1,2 +1 @@
profile = janestreet
version = 0.26.0
+1 -1
View File
@@ -1,2 +1,2 @@
#install_printer Aoc.Vec2.pp;;
#install_printer Aoc.Vec2.pp_grid;;
#install_printer Aoc.Grid.pp;;
+6
View File
@@ -0,0 +1,6 @@
## 2022 AOC problems in Ocaml
```sh
$ opam switch create . --deps-only -y
$ dune build
```
+13
View File
@@ -10,8 +10,21 @@ homepage: "https://github.com/username/reponame"
doc: "https://url/to/documentation"
bug-reports: "https://github.com/username/reponame/issues"
depends: [
"utop"
"ocaml-lsp-server"
"ocamlformat"
"ocaml"
"dune" {>= "3.10"}
"re"
"containers"
"iter"
"dune-site"
"angstrom"
"ppx_deriving"
"ppx_deriving_hash"
"ppx_regexp"
"ppx_expect"
"ppx_inline_test"
"odoc" {with-doc}
]
build: [
+22 -1
View File
@@ -21,7 +21,28 @@
(name aoc)
(synopsis "A short synopsis")
(description "A longer description")
(depends ocaml dune)
(depends
;; development env
utop
ocaml-lsp-server
ocamlformat
;; deps
ocaml
dune
re
containers
iter
dune-site
angstrom
;; ppx
ppx_deriving
ppx_deriving_hash
ppx_regexp
ppx_expect
ppx_inline_test
)
(sites (lib inputs))
(tags
(topics "to describe" your project)))
+148
View File
@@ -0,0 +1,148 @@
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
502,32 -> 507,32
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
516,32 -> 521,32
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
512,30 -> 517,30
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
506,34 -> 511,34
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
512,173 -> 517,173
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
545,94 -> 550,94
539,100 -> 544,100
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
553,100 -> 558,100
501,170 -> 506,170
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
546,100 -> 551,100
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
542,97 -> 547,97
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
535,97 -> 540,97
533,108 -> 533,109 -> 538,109 -> 538,108
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
509,32 -> 514,32
513,34 -> 518,34
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
507,164 -> 512,164
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
557,103 -> 562,103
538,94 -> 543,94
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
501,28 -> 506,28
505,173 -> 510,173
531,87 -> 531,88 -> 543,88
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
524,126 -> 524,127 -> 528,127 -> 528,126
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
508,28 -> 513,28
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
511,167 -> 516,167
549,97 -> 554,97
541,91 -> 546,91
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
520,34 -> 525,34
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
505,30 -> 510,30
543,103 -> 548,103
510,146 -> 515,146
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
498,173 -> 503,173
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
498,13 -> 498,15 -> 492,15 -> 492,23 -> 506,23 -> 506,15 -> 501,15 -> 501,13
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
533,108 -> 533,109 -> 538,109 -> 538,108
517,146 -> 522,146
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
513,144 -> 518,144
515,170 -> 520,170
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
519,173 -> 524,173
532,100 -> 537,100
524,126 -> 524,127 -> 528,127 -> 528,126
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
521,148 -> 526,148
504,167 -> 509,167
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
520,130 -> 520,133 -> 515,133 -> 515,138 -> 533,138 -> 533,133 -> 525,133 -> 525,130
514,148 -> 519,148
510,141 -> 515,141
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
533,108 -> 533,109 -> 538,109 -> 538,108
524,126 -> 524,127 -> 528,127 -> 528,126
550,103 -> 555,103
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
529,103 -> 534,103
504,26 -> 509,26
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
508,170 -> 513,170
523,63 -> 523,66 -> 515,66 -> 515,71 -> 529,71 -> 529,66 -> 528,66 -> 528,63
499,34 -> 504,34
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
495,32 -> 500,32
507,148 -> 512,148
515,60 -> 515,52 -> 515,60 -> 517,60 -> 517,55 -> 517,60 -> 519,60 -> 519,50 -> 519,60 -> 521,60 -> 521,56 -> 521,60 -> 523,60 -> 523,53 -> 523,60 -> 525,60 -> 525,53 -> 525,60
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
531,87 -> 531,88 -> 543,88
536,103 -> 541,103
501,161 -> 501,152 -> 501,161 -> 503,161 -> 503,157 -> 503,161 -> 505,161 -> 505,155 -> 505,161 -> 507,161 -> 507,154 -> 507,161 -> 509,161 -> 509,155 -> 509,161
522,84 -> 522,76 -> 522,84 -> 524,84 -> 524,75 -> 524,84 -> 526,84 -> 526,81 -> 526,84 -> 528,84 -> 528,74 -> 528,84 -> 530,84 -> 530,79 -> 530,84 -> 532,84 -> 532,77 -> 532,84 -> 534,84 -> 534,78 -> 534,84 -> 536,84 -> 536,80 -> 536,84
522,47 -> 522,43 -> 522,47 -> 524,47 -> 524,41 -> 524,47 -> 526,47 -> 526,39 -> 526,47 -> 528,47 -> 528,39 -> 528,47
498,30 -> 503,30
492,34 -> 497,34
529,112 -> 529,116 -> 526,116 -> 526,122 -> 541,122 -> 541,116 -> 535,116 -> 535,112
+36
View File
@@ -0,0 +1,36 @@
Sensor at x=13820, y=3995710: closest beacon is at x=1532002, y=3577287
Sensor at x=3286002, y=2959504: closest beacon is at x=3931431, y=2926694
Sensor at x=3654160, y=2649422: closest beacon is at x=3702627, y=2598480
Sensor at x=3702414, y=2602790: closest beacon is at x=3702627, y=2598480
Sensor at x=375280, y=2377181: closest beacon is at x=2120140, y=2591883
Sensor at x=3875726, y=2708666: closest beacon is at x=3931431, y=2926694
Sensor at x=3786107, y=2547075: closest beacon is at x=3702627, y=2598480
Sensor at x=2334266, y=3754737: closest beacon is at x=2707879, y=3424224
Sensor at x=1613400, y=1057722: closest beacon is at x=1686376, y=-104303
Sensor at x=3305964, y=2380628: closest beacon is at x=3702627, y=2598480
Sensor at x=1744420, y=3927424: closest beacon is at x=1532002, y=3577287
Sensor at x=3696849, y=2604845: closest beacon is at x=3702627, y=2598480
Sensor at x=2357787, y=401688: closest beacon is at x=1686376, y=-104303
Sensor at x=2127900, y=1984887: closest beacon is at x=2332340, y=2000000
Sensor at x=3705551, y=2604421: closest beacon is at x=3702627, y=2598480
Sensor at x=1783014, y=2978242: closest beacon is at x=2120140, y=2591883
Sensor at x=2536648, y=2910642: closest beacon is at x=2707879, y=3424224
Sensor at x=3999189, y=2989409: closest beacon is at x=3931431, y=2926694
Sensor at x=3939169, y=2382534: closest beacon is at x=3702627, y=2598480
Sensor at x=2792378, y=2002602: closest beacon is at x=2332340, y=2000000
Sensor at x=3520934, y=3617637: closest beacon is at x=2707879, y=3424224
Sensor at x=2614525, y=1628105: closest beacon is at x=2332340, y=2000000
Sensor at x=2828931, y=3996545: closest beacon is at x=2707879, y=3424224
Sensor at x=2184699, y=2161391: closest beacon is at x=2332340, y=2000000
Sensor at x=2272873, y=1816621: closest beacon is at x=2332340, y=2000000
Sensor at x=1630899, y=3675405: closest beacon is at x=1532002, y=3577287
Sensor at x=3683190, y=2619409: closest beacon is at x=3702627, y=2598480
Sensor at x=180960, y=185390: closest beacon is at x=187063, y=-1440697
Sensor at x=1528472, y=3321640: closest beacon is at x=1532002, y=3577287
Sensor at x=3993470, y=2905566: closest beacon is at x=3931431, y=2926694
Sensor at x=1684313, y=20931: closest beacon is at x=1686376, y=-104303
Sensor at x=2547761, y=2464195: closest beacon is at x=2120140, y=2591883
Sensor at x=3711518, y=845968: closest beacon is at x=3702627, y=2598480
Sensor at x=3925049, y=2897039: closest beacon is at x=3931431, y=2926694
Sensor at x=1590740, y=3586256: closest beacon is at x=1532002, y=3577287
Sensor at x=1033496, y=3762565: closest beacon is at x=1532002, y=3577287
+60
View File
@@ -0,0 +1,60 @@
Valve XB has flow rate=0; tunnels lead to valves WZ, LE
Valve BM has flow rate=0; tunnels lead to valves PL, RI
Valve GC has flow rate=0; tunnels lead to valves HN, IT
Valve RM has flow rate=0; tunnels lead to valves ZQ, YL
Valve ZM has flow rate=5; tunnels lead to valves SN, KE, UW, MY, GW
Valve UH has flow rate=0; tunnels lead to valves HM, HN
Valve GW has flow rate=0; tunnels lead to valves LE, ZM
Valve HN has flow rate=19; tunnels lead to valves UW, UH, GL, WZ, GC
Valve VT has flow rate=0; tunnels lead to valves ZD, PE
Valve VI has flow rate=0; tunnels lead to valves JS, AA
Valve YL has flow rate=12; tunnels lead to valves PM, MH, RM, CM
Valve LA has flow rate=0; tunnels lead to valves SN, IY
Valve CM has flow rate=0; tunnels lead to valves YL, UL
Valve JI has flow rate=24; tunnels lead to valves UV, WH, XW, OJ
Valve ZD has flow rate=25; tunnels lead to valves VB, XW, VT
Valve VB has flow rate=0; tunnels lead to valves QX, ZD
Valve FO has flow rate=0; tunnels lead to valves WH, PE
Valve JS has flow rate=0; tunnels lead to valves VI, IY
Valve RI has flow rate=0; tunnels lead to valves PE, BM
Valve XD has flow rate=14; tunnel leads to valve CP
Valve ES has flow rate=11; tunnels lead to valves GU, WU
Valve WZ has flow rate=0; tunnels lead to valves XB, HN
Valve HW has flow rate=0; tunnels lead to valves QY, LE
Valve KE has flow rate=0; tunnels lead to valves AA, ZM
Valve IY has flow rate=22; tunnels lead to valves JS, AB, LA, IT
Valve XW has flow rate=0; tunnels lead to valves ZD, JI
Valve BE has flow rate=0; tunnels lead to valves AB, LE
Valve QY has flow rate=23; tunnels lead to valves AM, HW, MY
Valve MH has flow rate=0; tunnels lead to valves YL, AM
Valve IT has flow rate=0; tunnels lead to valves GC, IY
Valve DA has flow rate=0; tunnels lead to valves QR, CP
Valve PM has flow rate=0; tunnels lead to valves LE, YL
Valve WU has flow rate=0; tunnels lead to valves SM, ES
Valve UL has flow rate=0; tunnels lead to valves CM, QR
Valve SM has flow rate=13; tunnel leads to valve WU
Valve XC has flow rate=0; tunnels lead to valves ZJ, AA
Valve OJ has flow rate=0; tunnels lead to valves GI, JI
Valve SN has flow rate=0; tunnels lead to valves LA, ZM
Valve WH has flow rate=0; tunnels lead to valves JI, FO
Valve UW has flow rate=0; tunnels lead to valves HN, ZM
Valve HM has flow rate=0; tunnels lead to valves UH, PE
Valve AB has flow rate=0; tunnels lead to valves BE, IY
Valve QR has flow rate=8; tunnels lead to valves WW, UL, DA
Valve UV has flow rate=0; tunnels lead to valves JI, FF
Valve ZQ has flow rate=20; tunnel leads to valve RM
Valve ZJ has flow rate=0; tunnels lead to valves PE, XC
Valve GL has flow rate=0; tunnels lead to valves HN, PL
Valve CP has flow rate=0; tunnels lead to valves DA, XD
Valve AM has flow rate=0; tunnels lead to valves QY, MH
Valve PL has flow rate=17; tunnels lead to valves GL, YE, BM, FF, QX
Valve YE has flow rate=0; tunnels lead to valves PL, AA
Valve PE has flow rate=4; tunnels lead to valves FO, RI, ZJ, VT, HM
Valve MY has flow rate=0; tunnels lead to valves QY, ZM
Valve QX has flow rate=0; tunnels lead to valves VB, PL
Valve GI has flow rate=0; tunnels lead to valves OJ, AA
Valve WW has flow rate=0; tunnels lead to valves GU, QR
Valve FF has flow rate=0; tunnels lead to valves UV, PL
Valve LE has flow rate=6; tunnels lead to valves HW, GW, XB, BE, PM
Valve GU has flow rate=0; tunnels lead to valves ES, WW
Valve AA has flow rate=0; tunnels lead to valves KE, GI, VI, YE, XC
+1
View File
@@ -0,0 +1 @@
><<<<>>>><>>><<><<<<>>>><<>>><>>><<<<>>>><<>>>><<<>>>><<<>>>><<<>>><<<<>><>><<<<>>><><<<><><>>>><<<<><<<<>><<<>>>><<>><><>>>><<<>>><<<>>><<>>>><>>>><>><>>><<>><><<<<><>><<<>>>><<<>>><<<>><>><<<>>><<<<>>>><><<<>>><<<>>><<<<><<<<>>><<<<>>><<<>>><<<<>>><<>>><<><<<>><<<>>><<<<><<<<>>><<<><<>>>><<<>><>>><<>>><<<><<<<>>><<><<<<>>>><<>>>><<>>>><<<<>>><><<<<><>><<<>>>><<<<>><>>>><>><>><>><<<>><<<>>>><<<>><<>><<<<><<<<><<>>>><<<<><<<>>><>><<<>>><<<><<<><<<<><<><<<>>><<<<>>>><<<<><<>><<<<>>><>>><<<<><<<>>>><<><>><<<<>><<<<>>>><<<><<<<><<<<>>><<<><<>>><>>><<<<>>><<>><<<<>>><<<><<<>><<<<>>>><<<<><<><<<<>>>><>>>><<<<>>>><<<>>>><<<><<>>><>>><<<<>><<<<>>><><>><<<>>>><<<<>><<<>><<>><<<>>><<<>>>><<<<>>>><<>>>><<>>>><><<<<>><<<<>>>><<<<>>><<<<>><>><<<>>><>>>><><<>><<>>><<<>>>><>>><<>><<<>><>>><>>><><>><>><<<><<<>>>><>><<<><<<>>><<<<><<>>>><<<><<<>>>><>><<<>>>><<<>>>><>>><><>>>><>><<><<<>>>><<>>>><<<>>><<<<>>><<<>><>>>><<<<>>>><>><<>>><<<<>>>><<<<><>>>><<>><<>>>><>><<<<>>>><<<<>><<<>>>><<>><><>><<<<>><<<>>>><<<>>><<>><><<<>>>><<>><>><<>><>><<<<>><<<>>><<<<>>><<>>>><<>>><<<<>>><>><<><<<>><>>><<<>><<<<>>>><<<>>><<>>><<<>>><<<<>>>><<<<>>><<<>>><<>>>><<>>><<<>>><<><<>>>><<>>>><<><<>>><<><<<>>>><<<<><<<<>><<<>>>><>>><<<<>>><<<<>>>><<>><<<<>>>><<<><<<><<>>>><<<>>>><<<>>>><<<>><<>>><>>><<<<>>><<<<>><<<>>><<<>><<<<>>><<<<><<><>>><<<<>>><<<<>>>><>><<<<>><<<<>>>><<<<><<<>>>><>><<<<><<<<>>>><>><<><<<>>><<>>><<<<>><<<><<<><>><<>>>><<<><<<<><<<>>>><<<<>><<>><<<<>>>><><<<><<<>>>><<>>>><<>><<<<>>>><><><<<<><><<>>><<><<>>><>>><<>><><<><<>>>><<<<><<<>>>><<>><><<>>>><<<<><><<<>>>><<>>><<<><<<>>>><>><<<<>>>><>>><<><>>>><>>>><<<><>>><>>>><<<>><<<>>><<<<>>>><<>>>><<<<>>>><<><>><<<<>><<<<>>><<>>><>>>><<><<>>><>>>><<><<><<><><<<>><>><<<<>>><<<>>>><<<><<<<>><>><>>><<<<><<<>>>><<<>>><><<<<>>><<<<><<<<>>>><>><>>><<<><<>><<<><>>><<<<>><><<<<><>><<>><<>><>><<<<><<<>><>>>><<>><<<<>>><><<<>><<>><<>><>>><>>>><<><>><<<<>>><>>><<>>><<>>>><<>><<<<>>><>><<<>>><<<>>><<<<>>>><<<><<<<>><<><<<><<<>>><<><<>><>><>>><<<>>><<>><<>>><<>><<>><>><<<<>>>><<<<>>><<<>>>><<<<>>><<<>><<<>><<<<>>>><<>><<<<><<<<>><<>>><><<><<<<>>>><><>>>><<<<>>>><<<<>>>><<>><<<<>>>><<<><>><<>>>><<>>>><<<<>>>><<<>>><>><<>>>><<<>>>><<<<>>><<<<>><<<<>>>><<>>><<>>>><>>><>>>><><>><<<<>>>><<<>>>><<<>><<>>><<<<>>><>>>><<>>>><<<><>>><><<>>>><<>>>><<<>>>><<<<><<<<>>>><>>>><>><<<>>><<<>>>><<<>><<<>>><>><<>>><<><><<><<>>>><>>><<<<>><><>><>>><<<<><>>><<<>>><<<><<<<>>><<<>><<<>>><<>>><<<<><<<<><>><><<<<>>><<<>><<>><<<>><<<<>><>><>>>><<>>><<<>><<<>><<<<>><><<<<>>><<<>>>><<<<>>><<>><>><<>>><><<>>><<<>>><<<>><<>>>><<<<>><<<<>>>><<<><<><<<<>><<<<>><<<>>>><>><<<><>>>><<>>>><<><<<>>>><<<<>><<<>>>><<>>><>><<<<>>>><<<<>>><>>>><<<<><<><<>><>><>>><<<><<<<><<<<>><<<>>><<<<>><<><<<<>>>><<<>>>><<<>>>><<<<>>><<><<>><<><<<<>>>><<<><<<<>>>><<>>><<<<>><>>>><<<<>><<<>>>><<><<<<>>>><<<>><>>>><><<<>><<<><<<>>><>>>><>>><<<<><<<<>>><<>>><<<>>><<<<><<<<>>>><<>>><<<>><<>>><><<<>>>><<><>>><<>><<<>>>><<<><>><<<>>><<>>>><<<>>>><>><<><>><<>>>><<<>>>><<<<>>>><<<>>><<<>><<<<><<<<>><><<><<<>><>>><<<<>>><<<<>><<<>>><<>><<<<><<<><<<><<<>>><<<<>>><<<<>><<>>><<>><<<<>>>><<>>>><<>>>><<>><>>><>>>><<>>>><<<>>><<<<>>><>>><>>>><<<>><<>>><<>>>><<>>>><<<>>><<>>><<<><<<>><>>>><<<>><>>><<<>>><>>>><>><<>>><<<<>>><<<<>><>>><<<<>>><<<<><<<>>><><>>><<<>>><>><>>>><<>>>><<<>><<>>><<>><<<<>><<<<><>>><<>><<<<>>><<<>>><<>>>><>>>><<<><>>>><<><><>>><<>>>><<<>>>><><>><<<<>><<<>>>><<<<><<<<>>>><<<<>><>>>><<<>>>><<><<>>>><<<<>>>><<<<>>><>><>>>><>>>><>><<>>>><>>>><<>>><<<<>>>><<>>><><<>>>><<>><<<<><<><>>>><<<<>><<><<><<>><<<><<<>><<<<>>><<<<>><<>><>>><<<<>>>><<<<>>>><<<<>>><><<<<><<<<><><<<<><<<<>>>><<<<>>>><><>>><<<<><<<<><<<><><<<<>><><<<><<<<>><>>><><><<<><>>><<><<>><<<>><<<>>>><<<<>>><<>><<<<><>>><>>><<>>>><<<<>>><<<>>>><<<>>>><<<>><<<>><<<<>>><<<<>><>>><<<<><>>>><<<>><>>><<>>><<<<>><<><<<>><>>><<<>><<<<>>><<<>>>><>>><><<<><<<>>>><<>>><<><>>>><>>>><<<<>>><><><>>>><<<<>><<<<>>><<>>><<<><<<>>>><<><<<>><<<>>>><<<<>>>><>>><<<>>><><<<>><<<<>><<<>>>><>><<><><<>><<<>><<<>>><<<<>>>><<<><<<<>><<<<>>>><<<<>>>><<><<<<>>><<<<>><<<<>><<<>><<<<>>><<>>>><<>>><>><<>>>><>>><>>><<<><>>>><<<>>><<<<><<<<>>><<><><>>>><<>>>><<>>>><<<<>>>><<><<><<<>>><<<>>>><<><<<><<>>><<<><<<>>>><<<<>>><<>>>><<>><><<<><<>><<>>><<<<>><>><<<>><<<<>><<<<><<>>><<><<<<>>>><<<>><<<<>><<>>>><>>>><>>><>>>><<<>>><<<>>>><<>>>><>><>><<<>><<<>>><<>>><<<<>>><<<<>>><<>>>><>>><>><<<<>>>><<>>>><<>>>><<<<>>>><>>>><><>>><<>>>><<<<><<>>>><<<<>><<<<>>>><<>><<<<><<<<>>><<<<>><<>>>><<<>>>><<<><>><<<><<>>><<<<>><<<>>><><<<<>><<<<>><>>><<<<>>><<<<>>>><>>>><<>>>><<>>><>>>><<<<>>><<>><<<><<><<<>>>><<<>>>><<<<><<>>><>><<<<><<<>>><>><><<<><<>>>><>>>><>><<>>><<>>>><<>>>><<<<>><<>><><<>>><<>><<>><<>>><>><<<<>>>><<>>>><<<<>>><<>><><<<><>><<<>><>>><>><<>>><><>>><<>>>><<<>>><<<<>>><<<>><<>><<<<>>><<<><<<>><<<<><<>><>><<<<>><<>>>><<<>><<<>>>><<<<>>>><<<<>><<>>><<<>>><<<>>>><<<<>>><<<<>>>><>><<<<>>>><<>>><><<>>>><<<<>>>><<<<>>>><>><<>><<<<><<<<>>><><>>><<<<>>><<><>>>><<<<><<<>>>><>>>><<<>>>><<<>>>><<>>><<>>><<<<><<<>><>>><<<><<<>>><Line truncated
+2025
View File
File diff suppressed because it is too large. Load diff
+64 -46
View File
@@ -1,7 +1,5 @@
open Containers
let infinity = 1000000000
type node =
{ char : char
; mutable visited : bool
@@ -10,25 +8,20 @@ type node =
[@@deriving show]
let parse_grid start_anywhere =
let s = ref @@ Vec2.origin in
let e = ref @@ Vec2.origin in
let unvisited = ref [] in
let start_nodes = ref [] in
let end_node = ref @@ Vec2.origin in
let grid =
Utils.lines_of_input 12
|> Vec2.parse_grid (fun char -> { char; visited = false; distance = infinity })
|> Grid.of_lines (fun char -> { char; visited = false; distance = Int.max_int })
in
Vec2.iter_grid grid (fun pos ->
let n = Vec2.at_e grid pos in
match n.char with
| 'E' -> e := pos
| 'S' ->
n.distance <- 0;
s := pos
| 'a' when start_anywhere ->
n.distance <- 0;
unvisited := pos :: !unvisited
Grid.iter grid (fun pos ->
let node = Grid.at_e grid pos in
match node.char with
| 'E' -> end_node := pos
| 'S' -> start_nodes := pos :: !start_nodes
| 'a' when start_anywhere -> start_nodes := pos :: !start_nodes
| _ -> ());
grid, !e, !s, !unvisited
grid, !end_node, !start_nodes
;;
let reachable f t =
@@ -41,42 +34,67 @@ let reachable f t =
Char.compare (height f) (height t) >= -1
;;
let rec path grid goal current unvisited =
let current_node = Vec2.at_e grid current in
let get_neighbors grid node_pos =
let node = Grid.at_e grid node_pos in
Vec2.directions
|> List.map (fun dir -> Vec2.(current + dir))
|> List.iter (fun neighbor ->
match Vec2.at grid neighbor with
| Some node when (not node.visited) && reachable current_node.char node.char ->
let new_distance = current_node.distance + 1 in
if new_distance < node.distance then node.distance <- new_distance;
if Option.is_none @@ List.find_opt (fun x -> Vec2.(x = neighbor)) !unvisited
then unvisited := neighbor :: !unvisited
| _ -> ());
current_node.visited <- true;
unvisited
:= List.sort
(fun a b ->
let a = Vec2.at_e grid a in
let b = Vec2.at_e grid b in
a.distance - b.distance)
!unvisited;
match !unvisited with
| shortest :: _ when Vec2.(shortest = goal) -> Vec2.at grid shortest
| shortest :: rest -> path grid goal shortest @@ ref rest
| [] -> None
|> Iter.of_list
|> Iter.filter_map (fun dir ->
let neighbor_pos = Vec2.(node_pos + dir) in
match Grid.at grid neighbor_pos with
| Some neighbor when reachable node.char neighbor.char -> Some neighbor_pos
| _ -> None)
;;
let path_distance grid goal start_nodes =
let set_info position (dist, visited) =
let node = Grid.at_e grid position in
node.distance <- dist;
node.visited <- visited
in
let get_info position =
let { char = _; distance; visited } = Grid.at_e grid position in
distance, visited
in
Utils.djikstra
~set_info
~get_info
~eq:Vec2.( = )
~get_weight:(fun _ _ -> 1)
~get_neighbors:(get_neighbors grid)
~goal
~start_nodes
|> Option.get_exn_or "couldn't find"
;;
let%expect_test "Day 12.1" =
let grid, e, s, unvisited = parse_grid false in
let solution = Option.get_exn_or "coulnd't find" @@ path grid e s @@ ref unvisited in
Printf.printf "%d" solution.distance;
let grid, goal, start_nodes = parse_grid false in
Printf.printf "%i" @@ path_distance grid (Some goal) start_nodes;
[%expect {| 497 |}]
;;
let%expect_test "Day 12.2" =
let grid, e, s, unvisited = parse_grid true in
let solution = Option.get_exn_or "coulnd't find" @@ path grid e s @@ ref unvisited in
Printf.printf "%d" solution.distance;
let grid, goal, start_nodes = parse_grid true in
Printf.printf "%i" @@ path_distance grid (Some goal) start_nodes;
[%expect {| 492 |}]
;;
let%expect_test "Day 12 test" =
let grid, goal, start_nodes = parse_grid false in
let _ = path_distance grid None start_nodes in
let print_dist_to pos =
let node = Option.get_exn_or "invalid pos!" grid.Grid.%(pos) in
Printf.printf "%s %c %i\n" (Vec2.show pos) node.char node.distance
in
print_dist_to goal;
print_dist_to Vec2.(goal + right);
print_dist_to Vec2.(goal + down);
print_dist_to Vec2.(of_tuple (121, 23));
print_dist_to Vec2.(origin + right);
[%expect
{|
(149, 20) E 497
(150, 20) z 498
(149, 21) y 496
(121, 23) a 138
(1, 0) b 21 |}]
;;
+2 -7
View File
@@ -7,13 +7,8 @@ module Packet = struct
[@@deriving show { with_path = false }]
let of_str line =
let open Angstrom in
let int =
take_while1 (function
| '0' .. '9' -> true
| _ -> false)
>>= fun s -> return @@ I (int_of_string s) <?> "int"
in
let open Utils.Parse in
let int = int >>= fun i -> return @@ I i in
let packet =
fix (fun packet ->
let lb, delimited, rb = char '[', sep_by (char ','), char ']' in
+190
View File
@@ -0,0 +1,190 @@
open Containers
type tile =
| Empty
| Rock
| Sand
| Start
| Path_D
| Path_L
| Path_R
let char_of_tile _ = function
| Empty -> '-'
| Rock -> '#'
| Sand -> 'o'
| Start -> 'v'
| Path_D -> '|'
| Path_L -> '/'
| Path_R -> '\\'
;;
let is_sand = function
| Sand -> true
| _ -> false
;;
let parse_line line =
let open Utils.Parse in
let vec = Vec2.of_tuple <$> both int (char ',' *> int) in
let vec_list = sep_by (string " -> ") vec in
Result.get_or_failwith @@ parse_string ~consume:All vec_list line
;;
let draw_rocks grid points =
let open Grid in
let _ =
points
|> List.reduce (fun a b ->
iter_region grid a b (fun pos -> grid.%(pos) <- Rock);
b)
in
()
;;
let parse_grid lines start =
let points = Iter.map Fun.(parse_line %> Iter.of_list) lines in
let Vec2.{ x = lx; y = ly }, Vec2.{ x = hx; y = hy } =
points |> Iter.flatten |> Iter.cons start |> Vec2.find_bounds 0
in
let pad_floor = 1 in
let pad_x = 2 in
let height = 1 + hy - ly + pad_floor in
let lx = min lx (start.x - height) in
let hx = max hx (start.x + height) in
let width = 1 + hx - lx + (pad_x * 2) in
let extra = Vec2.of_tuple (lx - pad_x, ly) in
let start = Vec2.(start - extra) in
let open Grid in
let grid = init ~width ~height (fun _ -> Empty) in
grid.%(start) <- Start;
Iter.iter
Fun.(Iter.map (fun point -> Vec2.(point - extra)) %> Iter.to_list %> draw_rocks grid)
points;
grid, start
;;
type is_done =
| Continue
| Done
let rec drop_sand_abyss draw_path grid start =
let d = Vec2.(start + down) in
let l = Vec2.(d + left) in
let r = Vec2.(d + right) in
let open Grid in
match grid.%(l), grid.%(d), grid.%(r) with
| _, None, _ -> Done
| _, Some Empty, _ ->
if draw_path then grid.%(d) <- Path_D;
drop_sand_abyss draw_path grid d
| Some Empty, _, _ ->
if draw_path then grid.%(l) <- Path_L;
drop_sand_abyss draw_path grid l
| _, _, Some Empty ->
if draw_path then grid.%(r) <- Path_R;
drop_sand_abyss draw_path grid r
| _, _, _ ->
(match grid.%(start) with
| Some Empty ->
grid.%(start) <- Sand;
Continue
| _ -> failwith "oh no!")
;;
let rec drop_sand_floor grid start =
let d = Vec2.(start + down) in
let l = Vec2.(d + left) in
let r = Vec2.(d + right) in
let open Grid in
match grid.%(l), grid.%(d), grid.%(r) with
| _, Some Empty, _ -> drop_sand_floor grid d
| Some Empty, _, _ -> drop_sand_floor grid l
| _, _, Some Empty -> drop_sand_floor grid r
| _, _, _ ->
(match grid.%(start) with
| Some Empty ->
grid.%(start) <- Sand;
Continue
| Some Start ->
grid.%(start) <- Sand;
Done
| _ -> failwith "oh no!")
;;
let rec drop_all_sand drop grid start =
match drop grid start with
| Continue -> drop_all_sand drop grid start
| Done -> ()
;;
let%expect_test "Day 14.1 example" =
let lines =
Iter.of_list [ "498,4 -> 498,6 -> 496,6"; "503,4 -> 502,4 -> 502,9 -> 494,9" ]
in
let start = Vec2.of_tuple (500, 0) in
let grid, start = parse_grid lines start in
drop_all_sand (drop_sand_abyss false) grid start;
let _ = drop_sand_abyss true grid start in
let count = Grid.count grid is_sand in
Printf.printf "%i grains\n%s" count @@ Grid.draw grid char_of_tile;
[%expect
{|
24 grains
-------------v-------------
-------------|-------------
------------/o-------------
-----------/ooo------------
----------/#ooo##----------
---------/o#ooo#-----------
--------/###ooo#-----------
--------|--oooo#-----------
-------/o-ooooo#-----------
------/#########-----------
------|-------------------- |}]
;;
let%expect_test "Day 14.2 example" =
let lines =
Iter.of_list [ "498,4 -> 498,6 -> 496,6"; "503,4 -> 502,4 -> 502,9 -> 494,9" ]
in
let start = Vec2.of_tuple (500, 0) in
let grid, start = parse_grid lines start in
drop_all_sand drop_sand_floor grid start;
let count = Grid.count grid is_sand in
Printf.printf "%i grains\n%s" count @@ Grid.draw grid char_of_tile;
[%expect
{|
93 grains
-------------o-------------
------------ooo------------
-----------ooooo-----------
----------ooooooo----------
---------oo#ooo##o---------
--------ooo#ooo#ooo--------
-------oo###ooo#oooo-------
------oooo-oooo#ooooo------
-----oooooooooo#oooooo-----
----ooo#########ooooooo----
---ooooo-------ooooooooo--- |}]
;;
let%expect_test "Day 14.1" =
let lines = Iter.of_list @@ Utils.lines_of_input 14 in
let start = Vec2.of_tuple (500, 0) in
let grid, start = parse_grid lines start in
drop_all_sand (drop_sand_abyss false) grid start;
let count = Grid.count grid is_sand in
Printf.printf "%i" count;
[%expect {| 683 |}]
;;
let%expect_test "Day 14.2" =
let lines = Iter.of_list @@ Utils.lines_of_input 14 in
let start = Vec2.of_tuple (500, 0) in
let grid, start = parse_grid lines start in
drop_all_sand drop_sand_floor grid start;
let count = Grid.count grid is_sand in
Printf.printf "%i" count;
[%expect {| 28821 |}]
;;
+167
View File
@@ -0,0 +1,167 @@
open Containers
let example_lines =
[ "Sensor at x=2, y=18: closest beacon is at x=-2, y=15"
; "Sensor at x=9, y=16: closest beacon is at x=10, y=16"
; "Sensor at x=13, y=2: closest beacon is at x=15, y=3"
; "Sensor at x=12, y=14: closest beacon is at x=10, y=16"
; "Sensor at x=10, y=20: closest beacon is at x=10, y=16"
; "Sensor at x=14, y=17: closest beacon is at x=10, y=16"
; "Sensor at x=8, y=7: closest beacon is at x=2, y=10"
; "Sensor at x=2, y=0: closest beacon is at x=2, y=10"
; "Sensor at x=0, y=11: closest beacon is at x=2, y=10"
; "Sensor at x=20, y=14: closest beacon is at x=25, y=17"
; "Sensor at x=17, y=20: closest beacon is at x=21, y=22"
; "Sensor at x=16, y=7: closest beacon is at x=15, y=3"
; "Sensor at x=14, y=3: closest beacon is at x=15, y=3"
; "Sensor at x=20, y=1: closest beacon is at x=15, y=3"
]
;;
type sensor =
{ pos : Vec2.t
; beacon : Vec2.t
; dist : int
}
[@@deriving show { with_path = false }]
let taxicab_dist a b =
let x, y = Vec2.(abs (a - b) |> to_tuple) in
x + y
;;
let parse_sensor line =
match List.map int_of_string Re.(matches (Pcre.regexp {|-?\d+|}) line) with
| [ sx; sy; bx; by ] ->
let pos, beacon = Vec2.(of_tuple (sx, sy), of_tuple (bx, by)) in
{ pos; beacon; dist = taxicab_dist pos beacon }
| _ -> failwith "parse error"
;;
let could_be_beacon sensors ignore_known pos =
sensors
|> Iter.fold_while
(fun _ s ->
let d = taxicab_dist pos s.pos in
if d <= s.dist && (ignore_known || not Vec2.(pos = s.beacon))
then false, `Stop
else true, `Continue)
true
;;
(*{[
equation for line
y = m*x + c
beacon range boundaries are made up of four lines:
slope 1 passing thru bx + dist + 1, by
slope 1 passing thru bx - dist - 1, by
slope -1 passing thru bx + dist + 1, by
slope -1 passing thru bx - dist - 1, by
to find the constant given a slope, plug a point into
c = y - m*x
constants are stored separately for boundaries with positive and negative
slope so that they can be handled separately
p1 = y - bx - dist - 1
p2 = y - bx + dist + 1
n1 = y + bx + dist + 1
n2 = y + bx - dist - 1
]}*)
let get_consts sensors extra =
sensors
|> Iter.fold
(fun (p_slope_consts, n_slope_consts) { pos; beacon = _; dist } ->
let p1 = pos.y - pos.x + dist + extra in
let p2 = pos.y - pos.x - dist - extra in
let n1 = pos.y + pos.x + dist + extra in
let n2 = pos.y + pos.x - dist - extra in
Iter.(
( append p_slope_consts (of_list [ p1; p2 ])
, append n_slope_consts (of_list [ n1; n2 ]) )))
(Iter.empty, Iter.empty)
;;
let solve_part_1 lines scan_y =
let sensors = lines |> Iter.of_list |> Iter.map parse_sensor in
let p_slope_consts, n_slope_consts = get_consts sensors 0 in
(*{[
for a known y to intersect with a positive slope boundary:
y = x + p
x = y - p
and for a negative slope boundary:
y = -x + n
x = n - y
]}*)
let intersection_xs =
Iter.append
(Iter.map (fun p -> scan_y - p) p_slope_consts)
(Iter.map (fun n -> n - scan_y) n_slope_consts)
|> Iter.sort_uniq ~cmp:Int.compare
in
let check x = could_be_beacon sensors false @@ Vec2.of_tuple (x, scan_y) in
let rec count_not_beacons count xs =
match xs with
| x :: next :: rest ->
(* if there is a region [x+1, next), the value of check
is the same for each point within it. intersection points
must be checked separately from the regions between them *)
let intersection = if check x then 0 else 1 in
let region = if x + 1 < next && check (x + 1) then 0 else next - (x + 1) in
count_not_beacons (count + intersection + region) (next :: rest)
| _ -> count
in
count_not_beacons 0 @@ Iter.to_list intersection_xs
;;
let%expect_test "Day 15.1 example" =
Printf.printf "%i\n" @@ solve_part_1 example_lines 10;
[%expect {| 26 |}]
;;
let%expect_test "Day 15.1" =
Printf.printf "%i\n" @@ solve_part_1 (Utils.lines_of_input 15) 2000000;
[%expect {| 5525990 |}]
;;
let solve_part_2 lines range mult =
let sensors = lines |> Iter.of_list |> Iter.map parse_sensor in
let in_bounds = Vec2.(in_bounds origin @@ of_tuple (range, range)) in
let p_slope_consts, n_slope_consts = get_consts sensors 1 in
(*{[
boundaries only itersect if they have opposite slope.
to find the intersection, set equations to be equal and solve.
y = x + p
y = -x + n // set equal
x + p = -x + n // add x and subtract p
2x = n - p // divide 2
-> x = (n - p)/2 // substitute x into original
y = (n - p)/2 + p // multiply 2
2y = n + p // div 2
-> y = (n + p)/2
]}*)
let point =
Iter.product p_slope_consts n_slope_consts
|> Iter.fold_while
(fun _ (p, n) ->
let i = Vec2.of_tuple ((n - p) / 2, (n + p) / 2) in
if in_bounds i && could_be_beacon sensors true i
then Some i, `Stop
else None, `Continue)
None
|> Option.get_exn_or "no distress beacon found :("
in
(mult * point.x) + point.y
;;
let%expect_test "Day 15.2 example" =
Printf.printf "%i\n" @@ solve_part_2 example_lines 20 4000000;
[%expect {| 56000011 |}]
;;
let%expect_test "Day 15.2" =
Printf.printf "%i\n" @@ solve_part_2 (Utils.lines_of_input 15) 4000000 4000000;
[%expect {| 11756174628223 |}]
;;
+141
View File
@@ -0,0 +1,141 @@
open Containers
let example_lines =
String.lines
{|Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
Valve BB has flow rate=13; tunnels lead to valves CC, AA
Valve CC has flow rate=2; tunnels lead to valves DD, BB
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
Valve EE has flow rate=3; tunnels lead to valves FF, DD
Valve FF has flow rate=0; tunnels lead to valves EE, GG
Valve GG has flow rate=0; tunnels lead to valves FF, HH
Valve HH has flow rate=22; tunnel leads to valve GG
Valve II has flow rate=0; tunnels lead to valves AA, JJ
Valve JJ has flow rate=21; tunnel leads to valve II
|}
;;
type valve =
{ flow : int
; mask : int
}
let parse_valves lines =
let rooms = Hashtbl.create 100 in
lines
|> List.iter (fun line ->
let int_matches = List.map int_of_string Re.(matches (Pcre.regexp {|\d+|}) line) in
let valve_matches = Re.(matches (Pcre.regexp {|[A-Z]{2}|}) line) in
match int_matches, valve_matches with
| [ flow ], name :: tunnels -> Hashtbl.add rooms name (flow, tunnels)
| _ -> failwith "parse error");
let valves =
Hashtbl.to_list rooms
|> List.filter (fun (_, (flow, _)) -> flow > 0)
|> List.mapi (fun i (name, (flow, _)) ->
let mask = Int.(1 lsl i) in
name, { flow; mask })
in
let distances = Hashtbl.create 100 in
valves
|> List.map (fun (valve, _) -> valve)
|> List.cons "AA"
|> List.iter (fun from ->
let dist_of =
Fun.(
Utils.djikstra_hash
~get_weight:(fun _ _ -> 1)
~get_neighbors:(fun room ->
match Hashtbl.get rooms room with
| Some (_, tunnels) -> Iter.of_list tunnels
| None -> failwith "sad")
~start_nodes:[ from ]
()
%> Option.get_exn_or "big sad")
in
valves
|> List.remove_assoc ~eq:String.equal from
|> List.iter (fun (valve, _) ->
Hashtbl.replace distances (from, valve) (dist_of valve)));
let get_dist f t =
match Hashtbl.get distances (f, t) with
| Some dist -> dist
| None -> failwith @@ Printf.sprintf "cant find distance %s -> %s" f t
in
valves, get_dist
;;
let traverse
get_dist
(valves : (string * valve) list)
?(current = "AA")
?(released = 0)
?(opened = 0)
time
=
let states = Hashtbl.create 1000 in
let rec traverse' current time released opened =
Hashtbl.update
states
~f:(fun _ current ->
match current with
| Some r when r >= released -> Some r
| _ -> Some released)
~k:opened;
valves
|> List.iter (fun (name, { flow; mask }) ->
if Int.(mask land opened) = 0
then (
let dist = get_dist current name in
let time' = time - (dist + 1) in
if time' > 0
then (
let released' = released + (flow * time') in
let opened' = Int.(mask lor opened) in
traverse' name time' released' opened')))
in
traverse' current time released opened;
states
|> Iter.of_hashtbl
|> Iter.sort ~cmp:(fun (_, a_score) (_, b_score) -> b_score - a_score)
;;
let solve_part_1 lines =
let valves, get_dist = parse_valves lines in
let states = traverse get_dist valves 30 in
match states |> Iter.take 1 |> Iter.to_list with
| [ (_, score) ] -> score
| _ -> failwith "no traversals ?"
;;
let%expect_test "Day 16.1 example" =
Printf.printf "%i\n" @@ solve_part_1 example_lines;
[%expect {| 1651 |}]
;;
let%expect_test "Day 16.1" =
Printf.printf "%i\n" @@ solve_part_1 @@ Utils.lines_of_input 16;
[%expect {| 2265 |}]
;;
let solve_part_2 lines =
let valves, get_dist = parse_valves @@ lines in
let states = traverse get_dist valves 26 in
states
|> Iter.filter_map (fun (a_set, a_score) ->
match Iter.find_pred (fun (b_set, _) -> Int.(a_set land b_set) = 0) states with
| Some (_, b_score) -> Some (a_score + b_score)
| None -> None)
|> Iter.fold Int.max 0
;;
let%expect_test "Day 16.2 example" =
Printf.printf "%i\n" @@ solve_part_2 example_lines;
[%expect {| 1707 |}]
;;
(* god damn bitmasks are fast, 30x speedup from StrSet! down to 50ms now *)
let%expect_test "Day 16.2" =
Printf.printf "%i\n" @@ solve_part_2 @@ Utils.lines_of_input 16;
[%expect {| 2811 |}]
;;
+201
View File
@@ -0,0 +1,201 @@
open Containers
let cave_width = 7
let example_lines = [ ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>" ]
let dir_of_char = function
| '<' -> Vec2.left
| '>' -> Vec2.right
| _ -> failwith "oof"
;;
let next_stream_idx stream idx = (idx + 1) mod Array.length stream
(*[{
#
# # #
### # # ##
#### # ### # ##
row plus angle col square
}]*)
type shape =
| Row
| Plus
| Angle
| Col
| Square
let get_shape idx = [| Row; Plus; Angle; Col; Square |].(idx mod 5)
let shape_points shape pos =
let points =
match shape with
| Row -> [ 0, 0; 1, 0; 2, 0; 3, 0 ]
| Plus -> [ 0, 1; 1, 0; 1, 1; 1, 2; 2, 1 ]
| Angle -> [ 0, 0; 1, 0; 2, 0; 2, 1; 2, 2 ]
| Col -> [ 0, 0; 0, 1; 0, 2; 0, 3 ]
| Square -> [ 0, 0; 1, 0; 0, 1; 1, 1 ]
in
points |> List.map (fun point -> Vec2.(pos + of_tuple point))
;;
type loop_key =
{ rock : shape
; stream_idx : int
; normalized_topo : int array
}
type loop =
{ rock_idx : int
; height : int
}
type cave =
{ grid : char Grid.t
; mutable grid_topo : int array
; mutable grid_height : int
; total_rocks : int
; mutable rocks : int
; mutable stream_idx : int
; loop_cache : (loop_key, loop) Hashtbl.t
; mutable height : int
}
let init_cave max_height total_rocks =
let grid = Grid.init ~width:7 ~height:max_height (Fun.const '.') in
{ grid
; height = -1
; grid_height = -1
; rocks = 0
; stream_idx = 0
; grid_topo = Array.init cave_width (Fun.const 0)
; loop_cache = Hashtbl.create max_height
; total_rocks
}
;;
let draw_cave cave = Grid.draw cave.grid ~rev_y:true (fun _ contents -> contents)
let place_shape cave shape pos =
shape_points shape pos
|> List.iter (fun point ->
let delta = point.Vec2.y - cave.grid_height in
if delta > 0
then (
cave.height <- cave.height + delta;
cave.grid_height <- cave.grid_height + delta);
cave.grid_topo.(point.x) <- max point.y cave.grid_topo.(point.x);
Grid.set_e cave.grid point '#')
;;
let can_place_shape cave shape pos =
shape_points shape pos
|> List.fold_while
(fun _ point ->
match cave.grid.Grid.%(point) with
| Some '.' -> true, `Continue
| _ -> false, `Stop)
false
;;
let drop_shape cave stream =
let shape = get_shape cave.rocks in
let rec drop pos =
let stream_pos = Vec2.(pos + stream.(cave.stream_idx)) in
cave.stream_idx <- next_stream_idx stream cave.stream_idx;
let pos = if can_place_shape cave shape stream_pos then stream_pos else pos in
let drop_pos = Vec2.(pos + Vec2.up) in
if can_place_shape cave shape drop_pos
then drop drop_pos
else place_shape cave shape pos
in
cave.rocks <- cave.rocks + 1;
drop Vec2.{ x = 2; y = Int.(cave.grid_height + 4) }
;;
let normalize_topo topo =
let min = Array.min_exn Int.compare topo in
Array.map (fun x -> x - min) topo
;;
let rec drop_shapes cave stream =
let loop_key =
{ rock = get_shape cave.rocks
; stream_idx = cave.stream_idx
; normalized_topo = normalize_topo cave.grid_topo
}
in
let remaining_rocks cave = cave.total_rocks - cave.rocks in
let loop_rocks loop = cave.rocks - loop.rock_idx in
let loop_fits loop = loop_rocks loop < remaining_rocks cave in
match Hashtbl.get cave.loop_cache loop_key with
| Some loop when loop_fits loop ->
let loop_height = cave.height - loop.height in
cave.height <- cave.height + loop_height;
cave.rocks <- cave.rocks + loop_rocks loop;
drop_shapes cave stream
| _ when remaining_rocks cave > 0 ->
let loop = { height = cave.height; rock_idx = cave.rocks } in
Hashtbl.add cave.loop_cache loop_key loop;
drop_shape cave stream;
drop_shapes cave stream
| _ -> ()
;;
let solve remaining_rocks lines =
let stream = lines |> List.hd |> Iter.of_str |> Iter.map dir_of_char |> Iter.to_array in
let cave = init_cave 100_000 remaining_rocks in
drop_shapes cave stream;
cave.height + 1
;;
let%expect_test "Day 17.1 Example" =
Printf.printf "height: %i\n" @@ solve 2022 example_lines;
[%expect {| height: 3068 |}]
;;
let%expect_test "Day 17.1" =
Printf.printf "height: %i\n" @@ solve 2022 (Utils.lines_of_input 17);
[%expect {| height: 3227 |}]
;;
let%expect_test "Day 17.2 Example" =
Printf.printf "height: %i\n" @@ solve 1_000_000_000_000 example_lines;
[%expect {| height: 1514285714288 |}]
;;
let%expect_test "Day 17.2" =
Printf.printf "height: %i\n" @@ solve 1_000_000_000_000 (Utils.lines_of_input 17);
[%expect {| height: 1597714285698 |}]
;;
let%expect_test "Smol tower" =
let stream =
example_lines |> List.hd |> Iter.of_str |> Iter.map dir_of_char |> Iter.to_array
in
let cave = init_cave 18 8 in
drop_shapes cave stream;
Printf.printf "%s" @@ draw_cave cave;
[%expect
{|
.......
.......
.......
.....#.
.....#.
..####.
.###...
..#....
.####..
....##.
....##.
....#..
..#.#..
..#.#..
#####..
..###..
...#...
..####. |}]
;;
+121
View File
@@ -0,0 +1,121 @@
open Containers
let example_lines =
String.lines
{|2,2,2
1,2,2
3,2,2
2,1,2
2,3,2
2,2,1
2,2,3
2,2,4
2,2,6
1,2,5
3,2,5
2,1,5
2,3,5|}
;;
module Vec3 = struct
type t = int * int * int [@@deriving show, eq, ord, hash]
let directions = [ 1, 0, 0; -1, 0, 0; 0, 1, 0; 0, -1, 0; 0, 0, 1; 0, 0, -1 ]
let ( + ) (x1, y1, z1) (x2, y2, z2) = x1 + x2, y1 + y2, z1 + z2
let ( - ) (x1, y1, z1) (x2, y2, z2) = x1 - x2, y1 - y2, z1 - z2
let ( = ) = equal
let iter_region (ax, ay, az) (bx, by, bz) callback =
for z = az to bz do
for y = ay to by do
for x = ax to bx do
let p = x, y, z in
callback p
done
done
done
;;
let in_bounds (lx, ly, lz) (hx, hy, hz) (x, y, z) =
not (x < lx || x > hx || y < ly || y > hy || z < lz || z > hz)
;;
let find_bounds points =
let first = Iter.head_exn points in
let padding = 1, 1, 1 in
let min, max =
points
|> Iter.drop 1
|> Iter.fold
(fun ((lx, ly, lz), (hx, hy, hz)) (x, y, z) ->
(min lx x, min ly y, min lz z), (max hx x, max hy y, max hz z))
(first, first)
in
min - padding, max + padding
;;
end
module Vec3Set = Set.Make (Vec3)
let parse_points lines =
lines
|> List.map (fun line ->
match List.map Int.of_string_exn Re.(matches (Pcre.regexp {|\d+|}) line) with
| [ x; y; z ] -> x, y, z
| _ -> failwith "oopzi doopers")
|> Vec3Set.of_list
;;
let solve_part_1 lines =
let points = parse_points lines in
let min, max = Vec3.find_bounds @@ Vec3Set.to_iter points in
let surface_area = ref 0 in
Vec3.iter_region min max (fun point ->
if not @@ Vec3Set.mem point points
then
Vec3.directions
|> List.iter (fun dir ->
let n = Vec3.(point + dir) in
if Vec3Set.mem n points then incr surface_area));
!surface_area
;;
let%expect_test "Day 18.1 example" =
Format.printf "%i" @@ solve_part_1 example_lines;
[%expect {| 64 |}]
;;
let%expect_test "Day 18.1" =
Format.printf "%i" @@ solve_part_1 @@ Utils.lines_of_input 18;
[%expect {| 3662 |}]
;;
let solve_part_2 lines =
let points = parse_points lines in
let min, max = Vec3.find_bounds @@ Vec3Set.to_iter points in
let in_bounds = Vec3.in_bounds min max in
let surface_area = ref 0 in
let directions_iter = Iter.of_list Vec3.directions in
let get_neighbors point =
directions_iter
|> Iter.map Vec3.(fun dir -> point + dir)
|> Iter.filter (fun neighbor ->
let in_droplet = Vec3Set.mem neighbor points in
if in_droplet then incr surface_area;
(not in_droplet) && in_bounds neighbor)
in
let _ignore =
Utils.djikstra_hash ~get_weight:(fun _ _ -> 1) ~get_neighbors ~start_nodes:[ min ] ()
in
!surface_area
;;
let%expect_test "Day 18.2 example" =
Format.printf "%i" @@ solve_part_2 example_lines;
[%expect {| 58 |}]
;;
let%expect_test "Day 18.2" =
Format.printf "%i" @@ solve_part_2 @@ Utils.lines_of_input 18;
[%expect {| 2060 |}]
;;
+7 -7
View File
@@ -1,17 +1,17 @@
open Containers
let parse_grid () =
Vec2.parse_grid Fun.(Char.to_string %> int_of_string) @@ Utils.lines_of_input 8
Grid.of_lines Fun.(Char.to_string %> int_of_string) @@ Utils.lines_of_input 8
;;
let part1 () =
let grid = parse_grid () in
let num_visible = ref 0 in
Vec2.iter_grid grid (fun start ->
let start_height = Option.get_exn_or "unreachable" @@ Vec2.at grid start in
Grid.iter grid (fun start ->
let start_height = Option.get_exn_or "unreachable" @@ Grid.at grid start in
let rec walk_shorter_trees start step =
let next = Vec2.(start + step) in
match Vec2.at grid next with
match Grid.at grid next with
| Some height when height < start_height -> walk_shorter_trees next step
| opt -> opt
in
@@ -28,11 +28,11 @@ let part1 () =
let part2 () =
let grid = parse_grid () in
let best_score = ref 0 in
Vec2.iter_grid grid (fun start ->
let start_height = Option.get_exn_or "unreachable" @@ Vec2.at grid start in
Grid.iter grid (fun start ->
let start_height = Option.get_exn_or "unreachable" @@ Grid.at grid start in
let rec trees_in_view start in_view step =
let next = Vec2.(start + step) in
match Vec2.at grid next with
match Grid.at grid next with
| Some height when height < start_height -> trees_in_view next (in_view + 1) step
| Some _ -> in_view + 1
| None -> in_view
+1 -1
View File
@@ -24,7 +24,7 @@ let next_pos head tail =
then tail
else (
let x_dir = if dx > 0 then Vec2.right else Vec2.left in
let y_dir = if dy > 0 then Vec2.up else Vec2.down in
let y_dir = if dy > 0 then Vec2.down else Vec2.up in
let dir =
if abs dx = abs dy
then Vec2.(x_dir + y_dir)
+4 -1
View File
@@ -1,10 +1,13 @@
(library
(name aoc)
(libraries re containers dune-site angstrom)
(libraries re containers iter dune-site angstrom)
(inline_tests)
(preprocess (pps
ppx_regexp
ppx_deriving.show
ppx_deriving.eq
ppx_deriving.ord
ppx_deriving_hash
ppx_expect
ppx_inline_test)))
+99
View File
@@ -0,0 +1,99 @@
open Containers
type 'a t =
{ width : int
; height : int
; items : 'a array
}
[@@deriving show]
let vec2_of_idx ~width ~idx =
let y = idx / width in
let x = idx mod width in
Vec2.of_tuple (x, y)
;;
let idx_of_vec2 width vec = Vec2.(Int.((width * vec.y) + vec.x))
let in_bounds grid point =
let x, y = Vec2.to_tuple point in
x >= 0 && x < grid.width && y >= 0 && y < grid.height
;;
let at grid point =
if in_bounds grid point
then Array.get_safe grid.items @@ idx_of_vec2 grid.width point
else None
;;
let at_e (grid : 'a t) (point : Vec2.t) =
match at grid point with
| Some point -> point
| None -> failwith @@ Format.sprintf "point %a out of bounds!" Vec2.pp point
;;
let set_e grid point item =
if in_bounds grid point
then Array.set grid.items (idx_of_vec2 grid.width point) item
else failwith (Format.sprintf "point %a out of bounds!" Vec2.pp point)
;;
let ( .%() ) = at
let ( .%()<- ) = set_e
let find (grid : 'a t) pred =
let open Option.Infix in
let* idx, item = Array.find_idx pred grid.items in
Some (vec2_of_idx ~width:grid.width ~idx, item)
;;
let count grid pred =
Array.fold (fun count item -> if pred item then count + 1 else count) 0 grid.items
;;
let init ~width ~height init =
{ width
; height
; items = Array.init (width * height) (fun idx -> init @@ vec2_of_idx ~width ~idx)
}
;;
let of_lines parse_char lines : 'a t =
match lines with
| first_line :: _ ->
let width = String.length first_line in
let height = List.length lines in
let yeet =
lines
|> List.map String.to_list
|> List.flatten
|> List.map parse_char
|> Array.of_list
in
{ width; height; items = yeet }
| _ -> failwith "somethin fucd up"
;;
let iter_region grid a b callback =
Vec2.iter_region a b (fun pos -> if in_bounds grid pos then callback pos)
;;
let iter grid callback =
let a = Vec2.of_tuple (0, 0) in
let b = Vec2.of_tuple (grid.width - 1, grid.height - 1) in
iter_region grid a b callback
;;
let draw grid ?(rev_y = false) ?(rev_x = false) printer =
let line = ref [] in
let lines = ref [] in
iter grid (fun point ->
let item = grid.%(point) in
let char = printer point (Option.get_exn_or "iter is broken" item) in
line := if rev_x then char :: !line else !line @ [ char ];
if List.length !line = grid.width
then (
lines := !lines @ [ String.of_list !line ];
line := []));
String.concat "\n" (if rev_y then List.rev !lines else !lines)
;;
+14
View File
@@ -0,0 +1,14 @@
type 'a t [@@deriving show]
val at : 'a t -> Vec2.t -> 'a option
val at_e : 'a t -> Vec2.t -> 'a
val set_e : 'a t -> Vec2.t -> 'a -> unit
val ( .%() ) : 'a t -> Vec2.t -> 'a option
val ( .%()<- ) : 'a t -> Vec2.t -> 'a -> unit
val init : width:int -> height:int -> (Vec2.t -> 'a) -> 'a t
val of_lines : (char -> 'a) -> string list -> 'a t
val find : 'a t -> ('a -> bool) -> (Vec2.t * 'a) option
val count : 'a t -> ('a -> bool) -> int
val iter_region : 'a t -> Vec2.t -> Vec2.t -> (Vec2.t -> unit) -> unit
val iter : 'a t -> (Vec2.t -> unit) -> unit
val draw : 'a t -> ?rev_y:bool -> ?rev_x:bool -> (Vec2.t -> 'a -> char) -> string
+121
View File
@@ -9,3 +9,124 @@ let lines_of_input day =
let path = Printf.sprintf "%s/day%d.tt" base_path day in
IO.(with_in path read_lines_l)
;;
(** [f] in [memo f] should be a function that makes recursive calls
via the memoized function passed as its first argument. ie:
{[
let fib_m =
memo (fun self x ->
match x with
| 0 | 1 -> 1
| x -> self (x - 1) + self (x - 2))
;;
]} *)
let memo f =
let open Hashtbl in
let cache = create 100000 in
let rec f_mem k =
try find cache k with
| Not_found ->
let v = f f_mem k in
add cache k v;
v
in
f_mem
;;
let%expect_test "fib memoized" =
let fib_m =
memo (fun fib_m x ->
match x with
| 0 | 1 -> 1
| x -> fib_m (x - 1) + fib_m (x - 2))
in
Printf.printf "%i\n" @@ fib_m 100;
[%expect {| 1298777728820984005 |}]
;;
let djikstra ~eq ~get_info ~set_info ~get_weight ~get_neighbors ~goal ~start_nodes =
let seen = ref [] in
let rec djikstra' c_node =
let c_dist, _ = get_info c_node in
set_info c_node (c_dist, true);
get_neighbors c_node
|> Iter.iter (fun neighbor ->
let n_dist, n_visited = get_info neighbor in
if not n_visited
then (
let new_dist = c_dist + get_weight c_node neighbor in
if new_dist < n_dist then set_info neighbor (new_dist, n_visited);
seen := List.add_nodup ~eq neighbor !seen));
seen
:= List.fast_sort
(fun a b ->
let a_dist, _ = get_info a in
let b_dist, _ = get_info b in
Int.compare a_dist b_dist)
!seen;
match goal, !seen with
| Some goal_node, next :: _ when eq goal_node next ->
let dist, _ = get_info next in
Some dist
| None, [] -> Some 0
| _, next :: rest ->
seen := rest;
djikstra' next
| Some _, [] -> None
in
List.iter (fun node -> set_info node (0, false)) start_nodes;
match start_nodes with
| first :: rest ->
seen := rest;
djikstra' first
| _ -> failwith "start_nodes cannot be empty"
;;
let djikstra_hash
(type k)
?(hash = Hashtbl.hash)
?(eq = Stdlib.( = ))
?(slots = 100)
~get_weight
~get_neighbors
~start_nodes
()
=
let module Tbl =
CCHashtbl.Make (struct
type t = k
let equal = eq
let hash = hash
end)
in
let table = Tbl.create slots in
let get_info node = Tbl.get_or ~default:(Int.max_int, false) table node in
let set_info node info = Tbl.replace table node info in
let dist_of node = Option.(Tbl.get table node >|= fun (dist, _) -> dist) in
let _ =
djikstra ~eq ~get_info ~set_info ~get_weight ~get_neighbors ~goal:None ~start_nodes
in
dist_of
;;
module Parse = struct
include Angstrom
let sign = option 1 (char '-' >>= fun _ -> return (-1))
let digits =
take_while1 (function
| '0' .. '9' -> true
| _ -> false)
>>| int_of_string
;;
let int = map2 sign digits ~f:( * )
let not_int =
skip_while (function
| '0' .. '9' | '-' -> false
| _ -> true)
;;
end
+44 -52
View File
@@ -1,65 +1,57 @@
open Containers
type t = int * int [@@deriving show]
type 'a grid =
{ width : int
; height : int
; items : 'a array
type t =
{ x : int
; y : int
}
[@@deriving show]
[@@deriving eq, ord, hash]
let origin = 0, 0
let up = 0, 1
let down = 0, -1
let left = -1, 0
let right = 1, 0
let pp (fmt : Format.formatter) v = Format.fprintf fmt "(%i, %i)" v.x v.y
let show v = Format.asprintf "%a" pp v
let origin = { x = 0; y = 0 }
let up = { x = 0; y = -1 }
let down = { x = 0; y = 1 }
let right = { x = 1; y = 0 }
let left = { x = -1; y = 0 }
let directions = [ up; down; left; right ]
let of_tuple x = x
let to_tuple x = x
let ( + ) a b = Pair.map_same2 ( + ) a b
let ( - ) a b = Pair.map_same2 ( - ) a b
let ( = ) a b = Pair.equal ( = ) ( = ) a b
let of_tuple (x, y) = { x; y }
let to_tuple { x; y } = x, y
let ( + ) a b = { x = a.x + b.x; y = a.y + b.y }
let ( - ) a b = { x = a.x - b.x; y = a.y - b.y }
let ( = ) = equal
let abs a = Int.{ x = abs a.x; y = abs a.y }
let at (grid : 'a grid) (point : t) =
let x, y = point in
if x >= 0 && x < grid.width && y >= 0 && y < grid.height
then Array.get_safe grid.items @@ Int.((grid.width * y) + x)
else None
let iter_region a b callback =
for y = min a.y b.y to max a.y b.y do
for x = min a.x b.x to max a.x b.x do
callback { x; y }
done
done
;;
let at_e (grid : 'a grid) (point : t) =
Option.get_exn_or "out of bounds!" @@ at grid point
let fold_region a b callback init =
let acc = ref init in
iter_region a b (fun pos -> acc := callback !acc pos);
!acc
;;
let find (grid : 'a grid) pred =
let open Option.Infix in
let* idx, item = Array.find_idx pred grid.items in
let y = idx / grid.width in
let x = idx mod grid.width in
Some ((x, y), item)
;;
let parse_grid parse_char lines : 'a grid =
match lines with
| first_line :: _ ->
let width = String.length first_line in
let height = List.length lines in
let yeet =
lines
|> List.map String.to_list
|> List.flatten
|> List.map parse_char
|> Array.of_list
let find_bounds padding points =
let lx, hx, ly, hy =
points
|> Iter.fold
(fun (lx, hx, ly, hy) { x; y } ->
let lx = min lx x in
let hx = max hx x in
let ly = min ly y in
let hy = max hy y in
lx, hx, ly, hy)
(Int.max_int, 0, Int.max_int, 0)
in
{ width; height; items = yeet }
| _ -> failwith "somethin fucd up"
let lx = Int.(lx - padding) in
let hx = Int.(hx + padding) in
let ly = Int.(ly - padding) in
let hy = Int.(hy + padding) in
of_tuple (lx, ly), of_tuple (hx, hy)
;;
let iter_grid (grid : 'a grid) callback =
for y = 0 to Int.(grid.height - 1) do
for x = 0 to Int.(grid.width - 1) do
callback (x, y)
done
done
;;
let in_bounds l h p = p.x >= l.x && p.x <= h.x && p.y >= l.y && p.y <= h.y
+12 -7
View File
@@ -1,6 +1,11 @@
type t [@@deriving show]
type 'a grid [@@deriving show]
type t =
{ x : int
; y : int
}
[@@deriving eq, ord, hash]
val show : t -> string
val pp : Format.formatter -> t -> unit
val origin : t
val up : t
val down : t
@@ -12,8 +17,8 @@ val to_tuple : t -> int * int
val ( + ) : t -> t -> t
val ( - ) : t -> t -> t
val ( = ) : t -> t -> bool
val at : 'a grid -> t -> 'a option
val at_e : 'a grid -> t -> 'a
val parse_grid : (char -> 'a) -> string list -> 'a grid
val find : 'a grid -> ('a -> bool) -> (t * 'a) option
val iter_grid : 'a grid -> (t -> unit) -> unit
val abs : t -> t
val iter_region : t -> t -> (t -> unit) -> unit
val fold_region : t -> t -> ('a -> t -> 'a) -> 'a -> 'a
val find_bounds : int -> t Iter.t -> t * t
val in_bounds : t -> t -> t -> bool