Skip to content

Commit 4b26915

Browse files
committed
2025 Day 1 and Day 2
1 parent 0c3d92f commit 4b26915

File tree

26 files changed

+4897
-0
lines changed

26 files changed

+4897
-0
lines changed

2025/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
_build

2025/aoc2025.opam

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# This file is generated by dune, edit dune-project instead
2+
opam-version: "2.0"
3+
synopsis: "AOC 2025 ocaml solutions"
4+
description: "Advent of Code 2025"
5+
authors: ["viandoxdev"]
6+
tags: ["add topics" "to describe" "your" "project"]
7+
homepage: "https://github.com/viandoxdev/aoc"
8+
bug-reports: "https://github.com/viandoxdev/aoc/issues"
9+
depends: [
10+
"ocaml"
11+
"dune" {>= "3.20"}
12+
"odoc" {with-doc}
13+
]
14+
build: [
15+
["dune" "subst"] {dev}
16+
[
17+
"dune"
18+
"build"
19+
"-p"
20+
name
21+
"-j"
22+
jobs
23+
"@install"
24+
"@runtest" {with-test}
25+
"@doc" {with-doc}
26+
]
27+
]
28+
dev-repo: "git+https://github.com/viandoxdev/aoc.git"
29+
x-maintenance-intent: ["(latest)"]

2025/bin/dune

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(executable
2+
(public_name aoc2025)
3+
(name main)
4+
(libraries aoc2025 lwt))

2025/bin/main.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
open Aoc2025
2+
3+
let () =
4+
let aoc = Aoc.new_ctx () in
5+
Aoc.run_days aoc

2025/days/Day01.ml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
open Utils
2+
3+
let (%%) x y =
4+
let res = x mod y in
5+
if res >= 0 then res else res + y
6+
7+
let parse input =
8+
let input = String.sub input 0 (String.length input - 1) in
9+
String.split_on_char '\n' input |> List.map (fun s ->
10+
let len = String.length s in
11+
let sign = if s.[0] == 'R' then 1 else -1 in
12+
let value = int_of_string (String.sub s 1 (len - 1)) in
13+
(sign, value)
14+
)
15+
16+
let solve_part1 clicks =
17+
List.fold_left (fun (p, a) (sign, value) ->
18+
match ((a + sign * value) mod 100) with
19+
| 0 -> (p + 1, 0)
20+
| a -> (p, a)) (0, 50) clicks |> fst
21+
22+
let solve_part2 clicks =
23+
List.fold_left (fun (p, a) (sign, value) ->
24+
let na = (a + (value mod 100) * sign) in
25+
let np = p + value / 100 + int_of_bool ((a > 0 && na <= 0) || na >= 100) in
26+
(np, na %% 100)
27+
)
28+
(0, 50) clicks |> fst
29+
30+
let day01 input =
31+
let clicks = parse input in
32+
let part1 = solve_part1 clicks in
33+
let part2 = solve_part2 clicks in
34+
(string_of_int part1, string_of_int part2)

2025/days/Day02.ml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
open Utils
2+
3+
let parse input =
4+
let len = String.length input in
5+
String.split_on_char ',' (String.sub input 0 (len - 1))
6+
|> List.map (fun s -> (
7+
let l = String.length s in
8+
let i = String.index_from s 0 '-' in
9+
(int_of_string (String.sub s 0 i), int_of_string (String.sub s (i+1) (l - i - 1)))
10+
))
11+
12+
let rec concat_n n x s =
13+
if n = 0 then 0
14+
else (concat_n (n - 1) x s) * s + x
15+
16+
(* Add all the passwords that are a sequence of d digits repeating rep times in the [a; b] range to list *)
17+
let invalid_in_range_length_repeat list a b d rep =
18+
let shift = p10 d in
19+
let limit = p10 (d * rep) in
20+
let start = max (a / (p10 (d * rep - d))) (shift / 10) in
21+
let rec aux acc x =
22+
let r = concat_n rep x shift in
23+
if r <= b && r < limit then if r >= a then (
24+
aux (r :: acc) (x + 1)
25+
) else aux acc (x + 1) else acc
26+
in
27+
aux list start
28+
(* Add all the passwords that are a sequence of d digits repeated at least twice in the [a; b] range to list *)
29+
let invalid_in_range_length ?(part1=true) list a b d =
30+
let da, db = ilog10 a + 1, ilog10 b + 1 in
31+
let rep_min = max ((da + d - 1) / d) 2 in
32+
let rep_max = if part1 then 2 else db / d in
33+
let rec aux list rep =
34+
if rep > rep_max then list
35+
else aux (invalid_in_range_length_repeat list a b d rep) (rep + 1)
36+
in
37+
aux list rep_min
38+
39+
(* Add all the passwords that are a sequence of digits repeated at least twice in the [a; b] range to list *)
40+
let invalid_in_range ?(part1=true) (a, b) =
41+
let db = ilog10 b + 1 in
42+
let rec aux list d = if d > (db / 2) then list else (
43+
aux (invalid_in_range_length ~part1: part1 list a b d) (d+1)) in
44+
aux [] 1 |> List.sort_uniq compare |> List.fold_left (+) 0
45+
46+
let solve_part1 = List.fold_left (fun a r -> a + invalid_in_range r) 0
47+
let solve_part2 = List.fold_left (fun a r -> a + invalid_in_range ~part1: false r) 0
48+
49+
let day02 input =
50+
let ranges = parse input in
51+
let part1 = solve_part1 ranges in
52+
let part2 = solve_part2 ranges in
53+
(string_of_int part1, string_of_int part2)
54+
55+

2025/days/Day03.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
open Utils
2+
3+
let day03 input =
4+
("TODO", "TODO")
5+
6+

2025/days/Day04.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
open Utils
2+
3+
let day04 input =
4+
("TODO", "TODO")
5+
6+

2025/days/Day05.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
open Utils
2+
3+
let day05 input =
4+
("TODO", "TODO")
5+
6+

2025/days/Day06.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
open Utils
2+
3+
let day06 input =
4+
("TODO", "TODO")
5+
6+

0 commit comments

Comments
 (0)