summaryrefslogtreecommitdiff
path: root/2024/OCaml/test/day_04_part_01.ml
blob: 9f43df02f4d7f69006e815c017334510b3ad831e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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