summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ O'Leary <dijitol@proton.me>2026-06-27 04:28:48 +0200
committerDJ O'Leary <dijitol@proton.me>2026-06-27 04:28:48 +0200
commitbc8b9edc0860f4804dfd0ea868ee7beaa564e62a (patch)
treee1123d11627b4829586da3b097015b1dbb3d0285
parent976048a85403fbb0751c34fa42703a3c47f6e918 (diff)
test: fix ocaml tests 2024 {WIP}HEADmain
-rw-r--r--2024/ocaml/.envrc1
-rw-r--r--2024/ocaml/.gitignore29
-rw-r--r--2024/ocaml/.ocamlformat2
-rw-r--r--2024/ocaml/AoC_2024.opam32
-rw-r--r--2024/ocaml/README.md21
-rw-r--r--2024/ocaml/Taskfile.yml56
-rw-r--r--2024/ocaml/bin/dune5
-rw-r--r--2024/ocaml/bin/main.ml46
-rw-r--r--2024/ocaml/dune-project28
-rw-r--r--2024/ocaml/flake.lock27
-rw-r--r--2024/ocaml/flake.nix44
-rw-r--r--2024/ocaml/lib/file/read_input.ml11
-rw-r--r--2024/ocaml/lib/grid/cell.ml18
-rw-r--r--2024/ocaml/lib/grid/cell.mli18
-rw-r--r--2024/ocaml/lib/grid/grid.ml14
-rw-r--r--2024/ocaml/lib/grid/grid.mli6
-rw-r--r--2024/ocaml/test/day_01_part_01.ml27
-rw-r--r--2024/ocaml/test/day_01_part_02.ml17
-rw-r--r--2024/ocaml/test/day_02_part_01.ml38
-rw-r--r--2024/ocaml/test/day_03_part_01.ml29
-rw-r--r--2024/ocaml/test/day_04_part_01.ml151
-rw-r--r--2024/ocaml/test/day_05_part_01.ml4
-rw-r--r--2024/ocaml/test/dune10
-rw-r--r--2024/ocaml/test/grid.ml5
-rw-r--r--ocaml/README.md20
-rw-r--r--ocaml/flake.nix3
-rw-r--r--ocaml/lib/year2024/day01/part01.ml (renamed from 2024/ocaml/lib/day_01/part_01.ml)0
-rw-r--r--ocaml/lib/year2024/day01/part02.ml (renamed from 2024/ocaml/lib/day_01/part_02.ml)0
-rw-r--r--ocaml/lib/year2024/day02/part01.ml (renamed from 2024/ocaml/lib/day_02/part_01.ml)0
-rw-r--r--ocaml/lib/year2024/day03/part01.ml (renamed from 2024/ocaml/lib/day_03/part_01.ml)0
-rw-r--r--ocaml/lib/year2024/day04/part01.ml (renamed from 2024/ocaml/lib/day_04/part_01.ml)0
-rw-r--r--ocaml/lib/year2024/day05/part01.ml (renamed from 2024/ocaml/lib/day_05/part_01.ml)54
-rw-r--r--ocaml/lib/year2024/dune (renamed from 2024/ocaml/lib/dune)6
-rw-r--r--ocaml/test/year2024/day01/dune11
-rw-r--r--ocaml/test/year2024/day01/test_part01.ml30
-rw-r--r--ocaml/test/year2024/day01/test_part02.ml16
-rw-r--r--ocaml/test/year2024/day02/dune10
-rw-r--r--ocaml/test/year2024/day02/test_part01.ml41
-rw-r--r--ocaml/test/year2024/day03/dune10
-rw-r--r--ocaml/test/year2024/day03/test_part01.ml29
-rw-r--r--ocaml/test/year2024/day04/dune10
-rw-r--r--ocaml/test/year2024/day04/test_part01.ml141
42 files changed, 351 insertions, 669 deletions
diff --git a/2024/ocaml/.envrc b/2024/ocaml/.envrc
deleted file mode 100644
index 3550a30..0000000
--- a/2024/ocaml/.envrc
+++ /dev/null
@@ -1 +0,0 @@
-use flake
diff --git a/2024/ocaml/.gitignore b/2024/ocaml/.gitignore
deleted file mode 100644
index a18e084..0000000
--- a/2024/ocaml/.gitignore
+++ /dev/null
@@ -1,29 +0,0 @@
-*.annot
-*.cmo
-*.cma
-*.cmi
-*.a
-*.o
-*.cmx
-*.cmxs
-*.cmxa
-
-# ocamlbuild working directory
-_build/
-
-# ocamlbuild targets
-*.byte
-*.native
-
-# oasis generated files
-setup.data
-setup.log
-
-# Merlin configuring file for Vim and Emacs
-.merlin
-
-# Dune generated files
-*.install
-
-# Local OPAM switch
-_opam/
diff --git a/2024/ocaml/.ocamlformat b/2024/ocaml/.ocamlformat
deleted file mode 100644
index 912bea4..0000000
--- a/2024/ocaml/.ocamlformat
+++ /dev/null
@@ -1,2 +0,0 @@
-profile = default
-version = 0.27.0
diff --git a/2024/ocaml/AoC_2024.opam b/2024/ocaml/AoC_2024.opam
deleted file mode 100644
index 6be14e1..0000000
--- a/2024/ocaml/AoC_2024.opam
+++ /dev/null
@@ -1,32 +0,0 @@
-# This file is generated by dune, edit dune-project instead
-opam-version: "2.0"
-synopsis: "Advent of Code 2024"
-description: "Solutions to the Advent of Code puzzles for 2024"
-maintainer: ["D.J. O'Leary"]
-authors: ["D.J. O'Leary"]
-license: "Unlicense"
-tags: ["aoc2024" "Advent of Code 2024"]
-homepage: "https://github.com/DJOLEARY/Advent_of_Code"
-doc:
- "https://github.com/DJOLEARY/Advent_of_Code/blob/main/2024/OCaml/README.md"
-bug-reports: "https://github.com/DJOLEARY/Advent_of_Code/issues"
-depends: [
- "ocaml"
- "dune" {>= "3.16"}
- "odoc" {with-doc}
-]
-build: [
- ["dune" "subst"] {dev}
- [
- "dune"
- "build"
- "-p"
- name
- "-j"
- jobs
- "@install"
- "@runtest" {with-test}
- "@doc" {with-doc}
- ]
-]
-dev-repo: "git+https://github.com/DJOLEARY/Advent_of_Code.git"
diff --git a/2024/ocaml/README.md b/2024/ocaml/README.md
deleted file mode 100644
index caa88fe..0000000
--- a/2024/ocaml/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# OCaml 2024
-
-## Getting Started
-
-### How to Build
-
-```sh
-task build
-```
-
-### How to Run
-
-```sh
-task run
-```
-
-### How to Test
-
-```sh
-task test
-```
diff --git a/2024/ocaml/Taskfile.yml b/2024/ocaml/Taskfile.yml
deleted file mode 100644
index 1d8a89e..0000000
--- a/2024/ocaml/Taskfile.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-# https://taskfile.dev
-
-version: "3"
-vars:
- PROJECT_NAME: AoC_2024
-tasks:
- default:
- desc: Prints this message
- cmds:
- - cmd: task --list-all
- build:doc:
- desc: Builds documentation using ocamldoc
- preconditions:
- - which ocamldoc
- cmds:
- - cmd: ocamldoc -html -d docs bin/main.ml
- silent: true
- build:
- desc: Builds the project
- preconditions:
- - which dune
- cmds:
- - cmd: dune build
- test:
- desc: Runs the tests in the 'tests' directory
- ignore_error: true
- env:
- OUNIT_CI: true
- preconditions:
- - which dune
- deps:
- - task: build
- cmds:
- - cmd: dune test {{.CLI_ARGS}}
- test:watch:
- desc: Continuously runs the tests in the 'tests' directory
- ignore_error: true
- sources:
- - lib/**/*.ml
- - test/**/*.ml
- env:
- OUNIT_CI: true
- preconditions:
- - which dune
- deps:
- - task: build
- cmds:
- - cmd: dune test --watch {{.CLI_ARGS}}
- run:
- desc: Runs the project
- preconditions:
- - which dune
- deps:
- - task: build
- cmds:
- - cmd: dune exec {{.PROJECT_NAME}}
diff --git a/2024/ocaml/bin/dune b/2024/ocaml/bin/dune
deleted file mode 100644
index ee36b46..0000000
--- a/2024/ocaml/bin/dune
+++ /dev/null
@@ -1,5 +0,0 @@
-(executable
- (public_name AoC_2024)
- (name main)
- (modes byte exe)
- (libraries AoC_2024))
diff --git a/2024/ocaml/bin/main.ml b/2024/ocaml/bin/main.ml
deleted file mode 100644
index a76e046..0000000
--- a/2024/ocaml/bin/main.ml
+++ /dev/null
@@ -1,46 +0,0 @@
-open AoC_2024
-
-let day_to_path day =
- let string_day = string_of_int day in
- let formatted_day = if day < 10 then "0" ^ string_day else string_day in
- "../_input/day_" ^ formatted_day ^ ".txt"
-
-let print_solution day_num part_num answer =
- print_string "D";
- print_int day_num;
- print_string ":P";
- print_int part_num;
- print_string " -> ";
- print_int answer;
- print_newline ()
-
-let day_1 =
- let lines = File.Read_input.lines_from_file (day_to_path 1) in
- let left, right = Day_01.Part_01.lines_to_lists lines in
- let part_01 = Day_01.Part_01.solve left right in
- print_solution 1 1 part_01;
- let part_02 = Day_01.Part_02.solve left right in
- print_solution 1 2 part_02
-
-let day_2 =
- let lines = File.Read_input.lines_from_file (day_to_path 2) in
- let reports = Day_02.Part_01.lines_to_reports lines in
- let part_01 = Day_02.Part_01.solve reports in
- print_solution 2 1 part_01
-
-let day_3 =
- let lines = File.Read_input.lines_from_file (day_to_path 3) in
- let line = List.fold_left (fun acc line -> acc ^ line) "" lines in
- let part_01 = Day_03.Part_01.solve line in
- print_solution 3 1 part_01
-
-let day_4 =
- let lines = File.Read_input.lines_from_file (day_to_path 4) in
- let part_01 = Day_04.Part_01.solve lines in
- print_solution 4 1 part_01
-
-let _ =
- day_1;
- day_2;
- day_3;
- day_4
diff --git a/2024/ocaml/dune-project b/2024/ocaml/dune-project
deleted file mode 100644
index 3f3a7bc..0000000
--- a/2024/ocaml/dune-project
+++ /dev/null
@@ -1,28 +0,0 @@
-(lang dune 3.16)
-
-(name AoC_2024)
-
-(generate_opam_files true)
-
-(source
- (github DJOLEARY/Advent_of_Code))
-
-(authors "D.J. O'Leary")
-
-(maintainers "D.J. O'Leary")
-
-(license Unlicense)
-
-(documentation https://github.com/DJOLEARY/Advent_of_Code/blob/main/2024/OCaml/README.md)
-
-(map_workspace_root false)
-
-(package
- (name AoC_2024)
- (synopsis "Advent of Code 2024")
- (description "Solutions to the Advent of Code puzzles for 2024")
- (depends ocaml dune)
- (tags
- (aoc2024 "Advent of Code 2024")))
-
-; See the complete stanza docs at https://dune.readthedocs.io/en/stable/reference/dune-project/index.html
diff --git a/2024/ocaml/flake.lock b/2024/ocaml/flake.lock
deleted file mode 100644
index b7695d9..0000000
--- a/2024/ocaml/flake.lock
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "nodes": {
- "nixpkgs": {
- "locked": {
- "lastModified": 1741010256,
- "narHash": "sha256-WZNlK/KX7Sni0RyqLSqLPbK8k08Kq7H7RijPJbq9KHM=",
- "owner": "nixos",
- "repo": "nixpkgs",
- "rev": "ba487dbc9d04e0634c64e3b1f0d25839a0a68246",
- "type": "github"
- },
- "original": {
- "owner": "nixos",
- "ref": "nixos-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "root": {
- "inputs": {
- "nixpkgs": "nixpkgs"
- }
- }
- },
- "root": "root",
- "version": 7
-}
diff --git a/2024/ocaml/flake.nix b/2024/ocaml/flake.nix
deleted file mode 100644
index 74a5dc6..0000000
--- a/2024/ocaml/flake.nix
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- description = "Advent of Code 2024: OCaml";
-
- inputs = {
- nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
- };
-
- outputs =
- { nixpkgs, ... }:
- let
- pkgs = nixpkgs.legacyPackages.x86_64-linux;
- in
- {
- devShells.x86_64-linux.default =
- let
- ocamlPackages = pkgs.ocaml-ng.ocamlPackages_5_2;
- in
- pkgs.mkShell {
- # build tools
- nativeBuildInputs = with ocamlPackages; [
- pkgs.opam
- ocaml
- findlib
- dune_3
- ];
- # dependencies
- buildInputs = with ocamlPackages; [
- bisect_ppx
- findlib
- menhir
- ocaml-lsp
- earlybird
- ocamlformat
- ocamlgraph
- odoc
- ounit2
- re2
- utop
-
- pkgs.gh # GitHub CLI
- ];
- };
- };
-}
diff --git a/2024/ocaml/lib/file/read_input.ml b/2024/ocaml/lib/file/read_input.ml
deleted file mode 100644
index 0f7470b..0000000
--- a/2024/ocaml/lib/file/read_input.ml
+++ /dev/null
@@ -1,11 +0,0 @@
-let rec lines_from_channel ic =
- try
- let line = input_line ic in
- line :: lines_from_channel ic
- with End_of_file -> []
-
-let lines_from_file filename =
- let channel = open_in filename in
- let lines = lines_from_channel channel in
- close_in channel;
- lines
diff --git a/2024/ocaml/lib/grid/cell.ml b/2024/ocaml/lib/grid/cell.ml
deleted file mode 100644
index 186e451..0000000
--- a/2024/ocaml/lib/grid/cell.ml
+++ /dev/null
@@ -1,18 +0,0 @@
-type t = {
- value : string;
- up : t option;
- down : t option;
- left : t option;
- right : t option;
-}
-
-let create value = { value; up = None; down = None; left = None; right = None }
-let with_up up c = { c with up = Some up }
-let with_down down c = { c with down = Some down }
-let with_left left c = { c with left = Some left }
-let with_right right c = { c with right = Some right }
-let move_up co = match co with Some c -> c.up | None -> None
-let move_down co = match co with Some c -> c.down | None -> None
-let move_left co = match co with Some c -> c.left | None -> None
-let move_right co = match co with Some c -> c.right | None -> None
-let ( = ) c1 c2 = c1.value = c2.value
diff --git a/2024/ocaml/lib/grid/cell.mli b/2024/ocaml/lib/grid/cell.mli
deleted file mode 100644
index e61e34a..0000000
--- a/2024/ocaml/lib/grid/cell.mli
+++ /dev/null
@@ -1,18 +0,0 @@
-type t = {
- value : string;
- up : t option;
- down : t option;
- left : t option;
- right : t option;
-}
-
-val create : string -> t
-val with_up : t -> t -> t
-val with_down : t -> t -> t
-val with_left : t -> t -> t
-val with_right : t -> t -> t
-val move_up : t option -> t option
-val move_down : t option -> t option
-val move_left : t option -> t option
-val move_right : t option -> t option
-val ( = ) : t -> t -> bool
diff --git a/2024/ocaml/lib/grid/grid.ml b/2024/ocaml/lib/grid/grid.ml
deleted file mode 100644
index 0d6bc4c..0000000
--- a/2024/ocaml/lib/grid/grid.ml
+++ /dev/null
@@ -1,14 +0,0 @@
-let rec to_grid_aux tokens max_width acc =
- match tokens with
- | [] -> acc
- | h :: t ->
- let new_cell = Cell.create h |> Cell.with_left acc in
- let new_acc = acc |> Cell.with_right new_cell in
- to_grid_aux t max_width new_acc
-
-let to_grid tokens max_width : Cell.t option =
- match tokens with
- | [] -> None
- | h :: t ->
- let first_cell = Cell.create h in
- Some (to_grid_aux t max_width first_cell)
diff --git a/2024/ocaml/lib/grid/grid.mli b/2024/ocaml/lib/grid/grid.mli
deleted file mode 100644
index a69fcfe..0000000
--- a/2024/ocaml/lib/grid/grid.mli
+++ /dev/null
@@ -1,6 +0,0 @@
-val to_grid : string list -> int -> Cell.t option
-(** The cell in the top left corner of the grid is returned where each element
- of [tokens] is converted into rows with [width]. An empty list of [tokens]
- returns None. Requires: [width] is greater than 0 **)
-
-(* val print : Cell.t -> () *)
diff --git a/2024/ocaml/test/day_01_part_01.ml b/2024/ocaml/test/day_01_part_01.ml
deleted file mode 100644
index 824c95b..0000000
--- a/2024/ocaml/test/day_01_part_01.ml
+++ /dev/null
@@ -1,27 +0,0 @@
-open OUnit2
-open AoC_2024.Day_01.Part_01
-
-let tests =
- "test suite for day 01 part 01"
- >::: [
- ("empty list is 0" >:: fun _ -> assert_equal 0 (solve [] []));
- ( "distance between 0 and 1 is 1" >:: fun _ ->
- assert_equal 1 (solve [ 0 ] [ 1 ]) );
- ( "distance between 1 and 0 is 1" >:: fun _ ->
- assert_equal 1 (solve [ 1 ] [ 0 ]) );
- ( "smallest are paired, then next smallest, ..." >:: fun _ ->
- assert_equal 0 (solve [ 1; 2; 3 ] [ 3; 2; 1 ]) );
- (* See https://adventofcode.com/2024/day/1 *)
- ( "solves example correctly" >:: fun _ ->
- assert_equal 11 (solve [ 3; 4; 2; 1; 3; 3 ] [ 4; 3; 5; 3; 9; 3 ]) );
- ( "same number is 0 distance apart" >:: fun _ ->
- assert_equal 0 (calculate_distance 0 0) );
- ( "same number is 0 distance apart" >:: fun _ ->
- assert_equal 0 (calculate_distance 1 1) );
- ( "distance is equal to abs(x - y)" >:: fun _ ->
- assert_equal 1 (calculate_distance 0 1) );
- ( "order of inputs doesn't matter" >:: fun _ ->
- assert_equal 1 (calculate_distance 1 0) );
- ]
-
-let _ = run_test_tt_main tests
diff --git a/2024/ocaml/test/day_01_part_02.ml b/2024/ocaml/test/day_01_part_02.ml
deleted file mode 100644
index f7340df..0000000
--- a/2024/ocaml/test/day_01_part_02.ml
+++ /dev/null
@@ -1,17 +0,0 @@
-open OUnit2
-open AoC_2024.Day_01.Part_02
-
-let test_solve =
- "test suite for day 01 part 02"
- >::: [
- ("empty list is 0" >:: fun _ -> assert_equal 0 (solve [] []));
- ( "ten x zero occurrances of ten" >:: fun _ ->
- assert_equal 0 (solve [ 10 ] [ 1; 2; 3 ]) );
- ( "two x three occurrances of two" >:: fun _ ->
- assert_equal 6 (solve [ 2 ] [ 2; 2; 2 ]) );
- (* See https://adventofcode.com/2024/day/1#part2 *)
- ( "solves example correctly" >:: fun _ ->
- assert_equal 31 (solve [ 3; 4; 2; 1; 3; 3 ] [ 4; 3; 5; 3; 9; 3 ]) );
- ]
-
-let _ = run_test_tt_main test_solve
diff --git a/2024/ocaml/test/day_02_part_01.ml b/2024/ocaml/test/day_02_part_01.ml
deleted file mode 100644
index 36af248..0000000
--- a/2024/ocaml/test/day_02_part_01.ml
+++ /dev/null
@@ -1,38 +0,0 @@
-open OUnit2
-open AoC_2024.Day_02.Part_01
-
-let tests =
- "test suite for day 2 part 1"
- >::: [
- ( "empty list should have no valid reports" >:: fun _ ->
- assert_equal 0 (solve []) );
- ( "valid report should count as one" >:: fun _ ->
- assert_equal 1 (solve [ [ 7; 6; 4; 2; 1 ] ]) );
- ( "example correct" >:: fun _ ->
- assert_equal 2
- (solve
- [
- [ 7; 6; 4; 2; 1 ];
- [ 1; 2; 7; 8; 9 ];
- [ 9; 7; 6; 2; 1 ];
- [ 1; 3; 2; 4; 5 ];
- [ 8; 6; 4; 4; 1 ];
- [ 1; 3; 6; 7; 9 ];
- ]) );
- ( "all increasing" >:: fun _ ->
- assert_equal true (check_report_safety [ 1; 2; 3 ]) );
- ( "all decreasing" >:: fun _ ->
- assert_equal true (check_report_safety [ 3; 2; 1 ]) );
- ( "increasing and decreasing" >:: fun _ ->
- assert_equal false (check_report_safety [ 1; 3; 2 ]) );
- ( "change of at least one" >:: fun _ ->
- assert_equal true (check_report_safety [ 1; 2; 3 ]) );
- ( "no change" >:: fun _ ->
- assert_equal false (check_report_safety [ 1; 1; 2 ]) );
- ( "change of at most three" >:: fun _ ->
- assert_equal true (check_report_safety [ 1; 2; 4; 7 ]) );
- ( "change of at more than three" >:: fun _ ->
- assert_equal false (check_report_safety [ 1; 5 ]) );
- ]
-
-let _ = run_test_tt_main tests
diff --git a/2024/ocaml/test/day_03_part_01.ml b/2024/ocaml/test/day_03_part_01.ml
deleted file mode 100644
index 0db039a..0000000
--- a/2024/ocaml/test/day_03_part_01.ml
+++ /dev/null
@@ -1,29 +0,0 @@
-open OUnit2
-open AoC_2024.Day_03.Part_01
-
-let example_input =
- "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
-
-let test_find_mul _ =
- assert_equal
- [ "mul(2,4)"; "mul(5,5)"; "mul(11,8)"; "mul(8,5)" ]
- (let result = find_mul example_input in
- List.map (fun x -> Re2.Match.get_exn x ~sub:(`Index 0)) result)
-
-let test_extract_pairs _ =
- assert_equal
- [ (2, 4); (5, 5); (11, 8); (8, 5) ]
- (let matches = find_mul example_input in
- extract_pairs matches)
-
-let test_solve _ = assert_equal ~printer:string_of_int 161 (solve example_input)
-
-let tests =
- "test suite for day 3 part 1"
- >::: [
- "muls extracted from example correctly" >:: test_find_mul;
- "pairs extracted from matches" >:: test_extract_pairs;
- "example correctly solved" >:: test_solve;
- ]
-
-let _ = run_test_tt_main tests
diff --git a/2024/ocaml/test/day_04_part_01.ml b/2024/ocaml/test/day_04_part_01.ml
deleted file mode 100644
index 9550e5b..0000000
--- a/2024/ocaml/test/day_04_part_01.ml
+++ /dev/null
@@ -1,151 +0,0 @@
-open OUnit2
-open AoC_2024.Day_04.Part_01
-
-let example_input =
- [
- "MMMSXXMASM";
- "MSAMXMSMSA";
- "AMXSXMAAMM";
- "MSAMASMSMX";
- "XMASAMXAMM";
- "XXAMMXXAMA";
- "SMSMSASXSS";
- "SAXAMASAAA";
- "MAMMMXMMMM";
- "MXMXAXMASX";
- ]
-
-let is_in_bounds_tests =
- let test_is_in_bounds expected length index _ =
- let actual = is_in_bounds length index in
- assert_equal ~printer:string_of_bool expected actual
- in
- [
- "not in bounds if below 0" >:: test_is_in_bounds false 1 (-1);
- "in bounds if gte 0 and lt length" >:: test_is_in_bounds true 1 0;
- "not in bounds if eq length" >:: test_is_in_bounds false 1 1;
- "not in bounds if gt length" >:: test_is_in_bounds false 1 2;
- ]
-
-let calculate_num_of_matches_tests =
- let test_calculate_num_of_matches expected line row_offset character _ =
- let actual = calculate_num_of_matches line row_offset character in
- assert_equal ~printer:string_of_int expected actual
- in
- [
- "is 0 when no matches present"
- >:: test_calculate_num_of_matches 0 "SMMX" 1 { index = 3; character = 'X' };
- "is 1 when only one match present - top to bottom"
- >::
- (*
- |.|X|.|
- |.|M|.|
- |.|A|.|
- |.|S|.|
- *)
- test_calculate_num_of_matches 1 ".X..M..A..S." 3
- { index = 1; character = 'X' };
- "is 1 when only one match present - top to bottom edge"
- >::
- (*
- |X|.|.|
- |M|.|.|
- |A|.|.|
- |S|.|.|
- *)
- test_calculate_num_of_matches 1 "X..M..A..S.." 3
- { index = 0; character = 'X' };
- "is 1 when only one match present - bottom to top"
- >::
- (*
- |.|S|.|
- |.|A|.|
- |.|M|.|
- |.|X|.|
- *)
- test_calculate_num_of_matches 1 ".S..A..M..X." 3
- { index = 10; character = 'X' };
- "is 1 when only one match present - left to right"
- >::
- (*
- |X|M|A|S|
- *)
- test_calculate_num_of_matches 1 "XMAS" 4 { index = 0; character = 'X' };
- "is 1 when only one match present - right to left"
- >::
- (*
- |S|A|M|X|
- *)
- test_calculate_num_of_matches 1 "SAMX" 4 { index = 3; character = 'X' };
- "is 1 when only one match present - bottom right to top left"
- >::
- (*
- |S|.|.|.|
- |.|A|.|.|
- |.|.|M|.|
- |.|.|.|X|
- *)
- test_calculate_num_of_matches 1 "S....A....M....X" 4
- { index = 15; character = 'X' };
- "is 1 when only one match present - top left to bottom right"
- >::
- (*
- |X|.|.|.|
- |.|M|.|.|
- |.|.|A|.|
- |.|.|.|S|
- *)
- test_calculate_num_of_matches 1 "X....M....A....S" 4
- { index = 0; character = 'X' };
- "is 1 when only one match present - bottom left to top right"
- >::
- (*
- |.|.|.|S|
- |.|.|A|.|
- |.|M|.|.|
- |X|.|.|.|
- *)
- test_calculate_num_of_matches 1 "...S..A..M..X..." 4
- { index = 12; character = 'X' };
- "is 1 when only one match present - top right to bottom left"
- >::
- (*
- |.|.|.|X|
- |.|.|M|.|
- |.|A|.|.|
- |S|.|.|.|
- *)
- test_calculate_num_of_matches 1 "...X..M..A..S..." 4
- { index = 3; character = 'X' };
- "is 8 when matches present in all possible directions"
- >::
- (*
- |S|.|.|S|.|.|S|
- |.|A|.|A|.|A|.|
- |.|.|M|M|M|.|.|
- |S|A|M|X|M|A|S|
- |.|.|M|M|M|.|.|
- |.|A|.|A|.|A|.|
- |S|.|.|S|.|.|S|
- *)
- test_calculate_num_of_matches 8
- "S..S..S.A.A.A...MMM..SAMXMAS..MMM...A.A.A.S..S..S" 7
- { index = 24; character = 'X' };
- ]
-
-let solve_tests =
- let test_solve expected lines _ =
- let actual = solve lines in
- assert_equal ~printer:string_of_int expected actual
- in
- [
- "example is solved correctly" >:: test_solve 18 example_input;
- "minimal example is solved correctly"
- >:: test_solve 4 [ "..X..."; ".SAMX."; ".A..A."; "XMAS.S"; ".X...." ];
- ]
-
-let tests =
- "test suite for day 4 part 1"
- >::: is_in_bounds_tests @ calculate_num_of_matches_tests @ solve_tests
-
-let _ = run_test_tt_main tests
diff --git a/2024/ocaml/test/day_05_part_01.ml b/2024/ocaml/test/day_05_part_01.ml
deleted file mode 100644
index 0f50476..0000000
--- a/2024/ocaml/test/day_05_part_01.ml
+++ /dev/null
@@ -1,4 +0,0 @@
-open OUnit2
-
-let tests = "test suite for day n part 1" >::: []
-let _ = run_test_tt_main tests
diff --git a/2024/ocaml/test/dune b/2024/ocaml/test/dune
deleted file mode 100644
index e19cbe9..0000000
--- a/2024/ocaml/test/dune
+++ /dev/null
@@ -1,10 +0,0 @@
-(tests
- (names
- day_01_part_01
- day_01_part_02
- day_02_part_01
- day_03_part_01
- day_04_part_01
- grid)
- (modes byte exe)
- (libraries AoC_2024 ounit2))
diff --git a/2024/ocaml/test/grid.ml b/2024/ocaml/test/grid.ml
deleted file mode 100644
index bd384cd..0000000
--- a/2024/ocaml/test/grid.ml
+++ /dev/null
@@ -1,5 +0,0 @@
-open OUnit2
-open AoC_2024.Grid
-
-let tests = "" >::: []
-let _ = run_test_tt_main tests
diff --git a/ocaml/README.md b/ocaml/README.md
index 7d64eb8..a2a6b4f 100644
--- a/ocaml/README.md
+++ b/ocaml/README.md
@@ -1 +1,21 @@
# Advent of Code: OCaml
+
+## Getting Started
+
+### How to Build
+
+```sh
+task build
+```
+
+### How to Run
+
+```sh
+task run
+```
+
+### How to Test
+
+```sh
+task test
+```
diff --git a/ocaml/flake.nix b/ocaml/flake.nix
index 0176014..7b267a1 100644
--- a/ocaml/flake.nix
+++ b/ocaml/flake.nix
@@ -39,6 +39,7 @@
cmdliner # command line library
ppx_deriving # derivers
logs # logging library
+ menhir # parsing library
];
sysTools = with pkgs; [
go-task
@@ -48,4 +49,4 @@
buildInputs = ocamlPackages ++ sysTools;
};
};
-}
+} \ No newline at end of file
diff --git a/2024/ocaml/lib/day_01/part_01.ml b/ocaml/lib/year2024/day01/part01.ml
index 100b12a..100b12a 100644
--- a/2024/ocaml/lib/day_01/part_01.ml
+++ b/ocaml/lib/year2024/day01/part01.ml
diff --git a/2024/ocaml/lib/day_01/part_02.ml b/ocaml/lib/year2024/day01/part02.ml
index 25c8b7d..25c8b7d 100644
--- a/2024/ocaml/lib/day_01/part_02.ml
+++ b/ocaml/lib/year2024/day01/part02.ml
diff --git a/2024/ocaml/lib/day_02/part_01.ml b/ocaml/lib/year2024/day02/part01.ml
index 32d7ab8..32d7ab8 100644
--- a/2024/ocaml/lib/day_02/part_01.ml
+++ b/ocaml/lib/year2024/day02/part01.ml
diff --git a/2024/ocaml/lib/day_03/part_01.ml b/ocaml/lib/year2024/day03/part01.ml
index c12b68a..c12b68a 100644
--- a/2024/ocaml/lib/day_03/part_01.ml
+++ b/ocaml/lib/year2024/day03/part01.ml
diff --git a/2024/ocaml/lib/day_04/part_01.ml b/ocaml/lib/year2024/day04/part01.ml
index acb3e3b..acb3e3b 100644
--- a/2024/ocaml/lib/day_04/part_01.ml
+++ b/ocaml/lib/year2024/day04/part01.ml
diff --git a/2024/ocaml/lib/day_05/part_01.ml b/ocaml/lib/year2024/day05/part01.ml
index f32bef1..96ff486 100644
--- a/2024/ocaml/lib/day_05/part_01.ml
+++ b/ocaml/lib/year2024/day05/part01.ml
@@ -3,14 +3,16 @@
module StringMap = Map.Make (String)
let inverse_page_rule page_rule =
- String.split_on_char '|' page_rule |> fun lst ->
+ String.split_on_char '|' page_rule
+ |> fun lst ->
match lst with [] -> "" | _ :: _ -> String.concat "|" (List.rev lst)
(** [parse_aux acc page_rules] is a map of all invalid transitions as defined by
[page_rules] *)
let rec get_invalid_transitions_aux acc page_rules : unit StringMap.t =
match page_rules with
- | [] -> acc
+ | [] ->
+ acc
| h :: t ->
get_invalid_transitions_aux
(acc |> StringMap.add (inverse_page_rule h) ())
@@ -31,32 +33,32 @@ let get_invalid_transitions page_rules =
- if yes, then it is an illegal transition
- if no, then add the list to a list for further processing *)
let solve page_rules _ =
- let invalid_transitions = get_invalid_transitions page_rules in
+ let[@warning "-26"] invalid_transitions =
+ get_invalid_transitions page_rules
+ in
()
let _ =
solve
- [
- "47|53";
- "97|13";
- "97|61";
- "97|47";
- "75|29";
- "61|13";
- "75|53";
- "29|13";
- "97|29";
- "53|29";
- "61|53";
- "97|53";
- "61|29";
- "47|13";
- "75|47";
- "97|75";
- "47|61";
- "75|61";
- "47|29";
- "75|13";
- "53|13";
- ]
+ [ "47|53"
+ ; "97|13"
+ ; "97|61"
+ ; "97|47"
+ ; "75|29"
+ ; "61|13"
+ ; "75|53"
+ ; "29|13"
+ ; "97|29"
+ ; "53|29"
+ ; "61|53"
+ ; "97|53"
+ ; "61|29"
+ ; "47|13"
+ ; "75|47"
+ ; "97|75"
+ ; "47|61"
+ ; "75|61"
+ ; "47|29"
+ ; "75|13"
+ ; "53|13" ]
[]
diff --git a/2024/ocaml/lib/dune b/ocaml/lib/year2024/dune
index 84e62ca..63bf2a1 100644
--- a/2024/ocaml/lib/dune
+++ b/ocaml/lib/year2024/dune
@@ -1,5 +1,5 @@
+(include_subdirs qualified)
+
(library
- (name AoC_2024)
+ (name year2024)
(libraries re2))
-
-(include_subdirs qualified)
diff --git a/ocaml/test/year2024/day01/dune b/ocaml/test/year2024/day01/dune
new file mode 100644
index 0000000..8891ccf
--- /dev/null
+++ b/ocaml/test/year2024/day01/dune
@@ -0,0 +1,11 @@
+(tests
+ (names
+ test_part01
+ test_part02)
+ (libraries
+ year2024
+ alcotest
+ qcheck-core
+ qcheck-alcotest)
+ (action (run %{test} -e))
+ (modes byte exe))
diff --git a/ocaml/test/year2024/day01/test_part01.ml b/ocaml/test/year2024/day01/test_part01.ml
new file mode 100644
index 0000000..706284d
--- /dev/null
+++ b/ocaml/test/year2024/day01/test_part01.ml
@@ -0,0 +1,30 @@
+open Year2024.Day01.Part01
+
+let test_solve haveLeft haveRight want () =
+ Alcotest.(check int) "incorrect solution" want @@ solve haveLeft haveRight
+
+let test_distance_calculation haveX haveY want () =
+ Alcotest.(check int) "incorrect solution" want
+ @@ calculate_distance haveX haveY
+
+let () =
+ let open Alcotest in
+ run "test suite for day 01 part 01"
+ [ ( "test solutions"
+ , [ test_case "empty list is 0" `Quick @@ (test_solve [] []) 0
+ ; test_case "distance between 0 and 1 is 1" `Quick
+ @@ (test_solve [0] [1]) 1
+ ; test_case "distance between 1 and 0 is 1" `Quick
+ @@ (test_solve [1] [0]) 1
+ ; test_case "smallest are paired, then next smallest, ..." `Quick
+ @@ (test_solve [1; 2; 3] [3; 2; 1]) 0
+ ; test_case "solves example correctly" `Quick
+ @@ (test_solve [3; 4; 2; 1; 3; 3] [4; 3; 5; 3; 9; 3]) 11
+ ; test_case "same number is 0 distance apart" `Quick
+ @@ (test_distance_calculation 0 0) 0
+ ; test_case "same number is 0 distance apart" `Quick
+ @@ (test_distance_calculation 1 1) 0
+ ; test_case "distance is equal to abs(x - y)" `Quick
+ @@ (test_distance_calculation 0 1) 1
+ ; test_case "order of inputs doesn't matter" `Quick
+ @@ (test_distance_calculation 1 0) 1 ] ) ]
diff --git a/ocaml/test/year2024/day01/test_part02.ml b/ocaml/test/year2024/day01/test_part02.ml
new file mode 100644
index 0000000..142add6
--- /dev/null
+++ b/ocaml/test/year2024/day01/test_part02.ml
@@ -0,0 +1,16 @@
+open Year2024.Day01.Part02
+
+let test_solve haveLeft haveRight want () =
+ Alcotest.(check int) "incorrect solution" want @@ solve haveLeft haveRight
+
+let () =
+ let open Alcotest in
+ run "test suite for day 01 part 02"
+ [ ( "test solutions"
+ , [ test_case "empty list is 0" `Quick @@ (test_solve [] []) 0
+ ; test_case "ten x zero occurrances of ten" `Quick
+ @@ (test_solve [10] [1; 2; 3]) 0
+ ; test_case "two x three occurrances of two" `Quick
+ @@ (test_solve [2] [2; 2; 2]) 6
+ ; test_case "solves example correctly" `Quick
+ @@ (test_solve [3; 4; 2; 1; 3; 3] [4; 3; 5; 3; 9; 3]) 31 ] ) ]
diff --git a/ocaml/test/year2024/day02/dune b/ocaml/test/year2024/day02/dune
new file mode 100644
index 0000000..c4a75c4
--- /dev/null
+++ b/ocaml/test/year2024/day02/dune
@@ -0,0 +1,10 @@
+(tests
+ (names
+ test_part01)
+ (libraries
+ year2024
+ alcotest
+ qcheck-core
+ qcheck-alcotest)
+ (action (run %{test} -e))
+ (modes byte exe))
diff --git a/ocaml/test/year2024/day02/test_part01.ml b/ocaml/test/year2024/day02/test_part01.ml
new file mode 100644
index 0000000..4feea41
--- /dev/null
+++ b/ocaml/test/year2024/day02/test_part01.ml
@@ -0,0 +1,41 @@
+open Year2024.Day02.Part01
+
+let test_solve have want () =
+ Alcotest.(check int) "incorrect solution" want @@ solve have
+
+let test_report_safety_check have want () =
+ Alcotest.(check bool) "incorrect report safety" want
+ @@ check_report_safety have
+
+let () =
+ let open Alcotest in
+ run "test suite for day 2 part 1"
+ [ ( "test solutions"
+ , [ test_case "empty list should have no valid reports" `Quick
+ @@ test_solve [] 0
+ ; test_case "valid report should count as one" `Quick
+ @@ test_solve [[7; 6; 4; 2; 1]] 1
+ ; test_case "provided example" `Quick
+ @@ test_solve
+ [ [7; 6; 4; 2; 1]
+ ; [1; 2; 7; 8; 9]
+ ; [9; 7; 6; 2; 1]
+ ; [1; 3; 2; 4; 5]
+ ; [8; 6; 4; 4; 1]
+ ; [1; 3; 6; 7; 9] ]
+ 2 ] )
+ ; ( "test report safety check"
+ , [ test_case "all increasing" `Quick
+ @@ test_report_safety_check [1; 2; 3] true
+ ; test_case "all decreasing" `Quick
+ @@ test_report_safety_check [3; 2; 1] true
+ ; test_case "increasing and decreasing" `Quick
+ @@ test_report_safety_check [1; 3; 2] false
+ ; test_case "change of at least one" `Quick
+ @@ test_report_safety_check [1; 2; 3] true
+ ; test_case "no change" `Quick
+ @@ test_report_safety_check [1; 1; 2] false
+ ; test_case "change of at most three" `Quick
+ @@ test_report_safety_check [1; 2; 4; 7] true
+ ; test_case "change of at more than three" `Quick
+ @@ test_report_safety_check [1; 5] false ] ) ]
diff --git a/ocaml/test/year2024/day03/dune b/ocaml/test/year2024/day03/dune
new file mode 100644
index 0000000..c4a75c4
--- /dev/null
+++ b/ocaml/test/year2024/day03/dune
@@ -0,0 +1,10 @@
+(tests
+ (names
+ test_part01)
+ (libraries
+ year2024
+ alcotest
+ qcheck-core
+ qcheck-alcotest)
+ (action (run %{test} -e))
+ (modes byte exe))
diff --git a/ocaml/test/year2024/day03/test_part01.ml b/ocaml/test/year2024/day03/test_part01.ml
new file mode 100644
index 0000000..78d04e2
--- /dev/null
+++ b/ocaml/test/year2024/day03/test_part01.ml
@@ -0,0 +1,29 @@
+open Year2024.Day03.Part01
+
+let example_input =
+ "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
+
+let test_find_mul () =
+ Alcotest.(check (list string))
+ "incorrect mul list found"
+ ["mul(2,4)"; "mul(5,5)"; "mul(11,8)"; "mul(8,5)"]
+ (let result = find_mul example_input in
+ List.map (fun x -> Re2.Match.get_exn x ~sub:(`Index 0)) result )
+
+let test_extract_pairs () =
+ Alcotest.(check (list (pair int int)))
+ "incorrect pairs"
+ [(2, 4); (5, 5); (11, 8); (8, 5)]
+ (let matches = find_mul example_input in
+ extract_pairs matches )
+
+let test_solve () = Alcotest.(check int) "" 161 @@ solve example_input
+
+let () =
+ let open Alcotest in
+ run "test suite for day 3 part 1"
+ [ ( "test implementation"
+ , [ test_case "muls extracted from example correctly" `Quick
+ @@ test_find_mul
+ ; test_case "pairs extracted from matches" `Quick @@ test_extract_pairs
+ ; test_case "example correctly solved" `Quick @@ test_solve ] ) ]
diff --git a/ocaml/test/year2024/day04/dune b/ocaml/test/year2024/day04/dune
new file mode 100644
index 0000000..c4a75c4
--- /dev/null
+++ b/ocaml/test/year2024/day04/dune
@@ -0,0 +1,10 @@
+(tests
+ (names
+ test_part01)
+ (libraries
+ year2024
+ alcotest
+ qcheck-core
+ qcheck-alcotest)
+ (action (run %{test} -e))
+ (modes byte exe))
diff --git a/ocaml/test/year2024/day04/test_part01.ml b/ocaml/test/year2024/day04/test_part01.ml
new file mode 100644
index 0000000..5776e49
--- /dev/null
+++ b/ocaml/test/year2024/day04/test_part01.ml
@@ -0,0 +1,141 @@
+open Year2024.Day04.Part01
+
+let example_input =
+ [ "MMMSXXMASM"
+ ; "MSAMXMSMSA"
+ ; "AMXSXMAAMM"
+ ; "MSAMASMSMX"
+ ; "XMASAMXAMM"
+ ; "XXAMMXXAMA"
+ ; "SMSMSASXSS"
+ ; "SAXAMASAAA"
+ ; "MAMMMXMMMM"
+ ; "MXMXAXMASX" ]
+
+let is_in_bounds_tests =
+ let test_is_in_bounds expected length index _ =
+ let actual = is_in_bounds length index in
+ assert_equal ~printer:string_of_bool expected actual
+ in
+ [ "not in bounds if below 0" >:: test_is_in_bounds false 1 (-1)
+ ; "in bounds if gte 0 and lt length" >:: test_is_in_bounds true 1 0
+ ; "not in bounds if eq length" >:: test_is_in_bounds false 1 1
+ ; "not in bounds if gt length" >:: test_is_in_bounds false 1 2 ]
+
+let calculate_num_of_matches_tests =
+ let test_calculate_num_of_matches expected line row_offset character _ =
+ let actual = calculate_num_of_matches line row_offset character in
+ assert_equal ~printer:string_of_int expected actual
+ in
+ [ "is 0 when no matches present"
+ >:: test_calculate_num_of_matches 0 "SMMX" 1 {index= 3; character= 'X'}
+ ; "is 1 when only one match present - top to bottom"
+ >::
+ (*
+ |.|X|.|
+ |.|M|.|
+ |.|A|.|
+ |.|S|.|
+ *)
+ test_calculate_num_of_matches 1 ".X..M..A..S." 3 {index= 1; character= 'X'}
+ ; "is 1 when only one match present - top to bottom edge"
+ >::
+ (*
+ |X|.|.|
+ |M|.|.|
+ |A|.|.|
+ |S|.|.|
+ *)
+ test_calculate_num_of_matches 1 "X..M..A..S.." 3 {index= 0; character= 'X'}
+ ; "is 1 when only one match present - bottom to top"
+ >::
+ (*
+ |.|S|.|
+ |.|A|.|
+ |.|M|.|
+ |.|X|.|
+ *)
+ test_calculate_num_of_matches 1 ".S..A..M..X." 3 {index= 10; character= 'X'}
+ ; "is 1 when only one match present - left to right"
+ >::
+ (*
+ |X|M|A|S|
+ *)
+ test_calculate_num_of_matches 1 "XMAS" 4 {index= 0; character= 'X'}
+ ; "is 1 when only one match present - right to left"
+ >::
+ (*
+ |S|A|M|X|
+ *)
+ test_calculate_num_of_matches 1 "SAMX" 4 {index= 3; character= 'X'}
+ ; "is 1 when only one match present - bottom right to top left"
+ >::
+ (*
+ |S|.|.|.|
+ |.|A|.|.|
+ |.|.|M|.|
+ |.|.|.|X|
+ *)
+ test_calculate_num_of_matches 1 "S....A....M....X" 4
+ {index= 15; character= 'X'}
+ ; "is 1 when only one match present - top left to bottom right"
+ >::
+ (*
+ |X|.|.|.|
+ |.|M|.|.|
+ |.|.|A|.|
+ |.|.|.|S|
+ *)
+ test_calculate_num_of_matches 1 "X....M....A....S" 4
+ {index= 0; character= 'X'}
+ ; "is 1 when only one match present - bottom left to top right"
+ >::
+ (*
+ |.|.|.|S|
+ |.|.|A|.|
+ |.|M|.|.|
+ |X|.|.|.|
+ *)
+ test_calculate_num_of_matches 1 "...S..A..M..X..." 4
+ {index= 12; character= 'X'}
+ ; "is 1 when only one match present - top right to bottom left"
+ >::
+ (*
+ |.|.|.|X|
+ |.|.|M|.|
+ |.|A|.|.|
+ |S|.|.|.|
+ *)
+ test_calculate_num_of_matches 1 "...X..M..A..S..." 4
+ {index= 3; character= 'X'}
+ ; "is 8 when matches present in all possible directions"
+ >::
+ (*
+ |S|.|.|S|.|.|S|
+ |.|A|.|A|.|A|.|
+ |.|.|M|M|M|.|.|
+ |S|A|M|X|M|A|S|
+ |.|.|M|M|M|.|.|
+ |.|A|.|A|.|A|.|
+ |S|.|.|S|.|.|S|
+ *)
+ test_calculate_num_of_matches 8
+ "S..S..S.A.A.A...MMM..SAMXMAS..MMM...A.A.A.S..S..S" 7
+ {index= 24; character= 'X'} ]
+
+let solve_tests =
+ let test_solve have want () =
+ let actual = solve have in
+ Alcotest.(check int) "incorrect solution" want actual
+ in
+ [ ( "test solution"
+ , [ Alcotest.test_case "example is solved correctly" `Quick
+ @@ test_solve example_input 18
+ ; Alcotest.test_case "minimal example is solved correctly" `Quick
+ @@ test_solve ["..X..."; ".SAMX."; ".A..A."; "XMAS.S"; ".X...."] 4 ] )
+ ]
+
+let () =
+ let open Alcotest in
+ run "test suite for day 4 part 1" is_in_bounds_tests
+ @ calculate_num_of_matches_tests @ solve_tests