diff --git a/lib/util/list.ml b/lib/util/list.ml index e1b2404..b1c5c30 100644 --- a/lib/util/list.ml +++ b/lib/util/list.ml @@ -1,3 +1,11 @@ +module Syntax = struct + let ( let* ) t f = Core.List.bind t ~f + let ( and* ) = Core.List.Let_syntax.Let_syntax.both + let ( let+ ) t f = Core.List.map t ~f + let ( and+ ) = Core.List.Let_syntax.Let_syntax.both + let return = Core.List.return +end + let max_int l = Core.List.max_elt ~compare l |> Option.value_exn let min_int l = Core.List.min_elt ~compare l |> Option.value_exn let replicate a ~n = Core.List.init n ~f:(const a) diff --git a/lib/util/parser.ml b/lib/util/parser.ml index 498d428..844de49 100644 --- a/lib/util/parser.ml +++ b/lib/util/parser.ml @@ -7,6 +7,7 @@ module Syntax = struct ( >>= ), ( >>| ), ( *> ), ( <* ), ( <|> ), ( ), ( <$> ) ;; + let ( let* ), ( let+ ), ( and+ ) = ( let* ), ( let+ ), ( and+ ) let ( $> ) p a = p >>| const a let ( <$ ) a p = p >>| const a end diff --git a/lib/util/sequence.ml b/lib/util/sequence.ml index c9a3034..85bf433 100644 --- a/lib/util/sequence.ml +++ b/lib/util/sequence.ml @@ -1,3 +1,11 @@ +module Syntax = struct + let ( let* ) t f = Core.Sequence.bind t ~f + let ( and* ) = Core.Sequence.Let_syntax.Let_syntax.both + let ( let+ ) t f = Core.Sequence.map t ~f + let ( and+ ) = Core.Sequence.Let_syntax.Let_syntax.both + let return = Core.Sequence.Let_syntax.Let_syntax.return +end + let nats = Core.Sequence.unfold ~init:0 ~f:(fun i -> Some (i, i + 1)) let fold_result_exn s ~init ~f = diff --git a/lib/year2022/day04.ml b/lib/year2022/day04.ml index c7deaed..ac2f2f1 100644 --- a/lib/year2022/day04.ml +++ b/lib/year2022/day04.ml @@ -7,14 +7,14 @@ type range = } let range_p = - let%map start = P.integer <* P.char '-' - and stop = P.integer in + let+ start = P.integer <* P.char '-' + and+ stop = P.integer in { start; stop } ;; let range_pair_p = - let%map a = range_p <* P.char ',' - and b = range_p in + let+ a = range_p <* P.char ',' + and+ b = range_p in a, b ;; diff --git a/lib/year2022/day05.ml b/lib/year2022/day05.ml index 5d12dd6..8dce846 100644 --- a/lib/year2022/day05.ml +++ b/lib/year2022/day05.ml @@ -23,9 +23,9 @@ let crate_line_p = P.sep_by1 (P.char ' ') crate_p let crate_lines_p = P.sep_by1 P.end_of_line crate_line_p <* P.end_of_line let move_p = - let%map n = P.string "move " *> P.integer - and from = P.string " from " *> P.integer - and to' = P.string " to " *> P.integer in + let+ n = P.string "move " *> P.integer + and+ from = P.string " from " *> P.integer + and+ to' = P.string " to " *> P.integer in { n; from; to' } ;; @@ -48,8 +48,8 @@ let to_stacks crates = ;; let instructions_p = - let%map crate_lines = crate_lines_p <* drop_line_p <* drop_line_p - and moves = moves_p in + let+ crate_lines = crate_lines_p <* drop_line_p <* drop_line_p + and+ moves = moves_p in let crates = to_stacks crate_lines in { moves; crates } ;; diff --git a/lib/year2022/day07.ml b/lib/year2022/day07.ml index f263b2c..eba9503 100644 --- a/lib/year2022/day07.ml +++ b/lib/year2022/day07.ml @@ -18,20 +18,20 @@ let name_p = ;; let cd_p = - let%map dir = P.string "$ cd " *> name_p in + let+ dir = P.string "$ cd " *> name_p in Cd dir ;; let ls_p = Ls <$ P.string "$ ls" let dir_item_p = - let%map dir = P.string "dir " *> name_p in + let+ dir = P.string "dir " *> name_p in DirItem dir ;; let file_item_p = - let%map size = P.integer <* P.char ' ' - and file = name_p in + let+ size = P.integer <* P.char ' ' + and+ file = name_p in FileItem (size, file) ;; diff --git a/lib/year2022/day08.ml b/lib/year2022/day08.ml index 12b345f..c987762 100644 --- a/lib/year2022/day08.ml +++ b/lib/year2022/day08.ml @@ -16,10 +16,11 @@ let grid_size grid = ;; let coords grid = + let open Util.List.Syntax in let max_x, max_y = grid_size grid in - let%bind.List x = List.range 0 max_x - and y = List.range 0 max_y in - List.return (x, y) + let* x = List.range 0 max_x in + let+ y = List.range 0 max_y in + x, y ;; let rays x y grid = diff --git a/lib/year2022/day09.ml b/lib/year2022/day09.ml index 81e183d..e28ad29 100644 --- a/lib/year2022/day09.ml +++ b/lib/year2022/day09.ml @@ -17,8 +17,8 @@ let dir_p = ;; let step_p = - let%map dir = dir_p <* P.char ' ' - and num = P.integer in + let+ dir = dir_p <* P.char ' ' + and+ num = P.integer in dir, num ;; diff --git a/lib/year2022/day10.ml b/lib/year2022/day10.ml index b5d04d7..5b4fd56 100644 --- a/lib/year2022/day10.ml +++ b/lib/year2022/day10.ml @@ -6,7 +6,7 @@ type inst = | Noop let addx_p = - let%map i = P.string "addx " *> P.signed_integer in + let+ i = P.string "addx " *> P.signed_integer in [ Noop; AddX i ] ;; diff --git a/lib/year2022/day11.ml b/lib/year2022/day11.ml index d8c62d7..e854da0 100644 --- a/lib/year2022/day11.ml +++ b/lib/year2022/day11.ml @@ -25,12 +25,12 @@ let div_test_p = P.string "divisible by " *> P.integer >>| Z.of_int let throw_p = P.string "throw to monkey " *> P.integer let monkey_p = - let%map id = P.string "Monkey " *> P.integer <* P.string ":" <* P.end_of_line - and items = P.string " Starting items: " *> items_p <* P.end_of_line - and op = P.string " Operation: " *> op_p <* P.end_of_line - and div_test = P.string " Test: " *> div_test_p <* P.end_of_line - and if_true = P.string " If true: " *> throw_p <* P.end_of_line - and if_false = P.string " If false: " *> throw_p <* P.end_of_line in + let+ id = P.string "Monkey " *> P.integer <* P.string ":" <* P.end_of_line + and+ items = P.string " Starting items: " *> items_p <* P.end_of_line + and+ op = P.string " Operation: " *> op_p <* P.end_of_line + and+ div_test = P.string " Test: " *> div_test_p <* P.end_of_line + and+ if_true = P.string " If true: " *> throw_p <* P.end_of_line + and+ if_false = P.string " If false: " *> throw_p <* P.end_of_line in { id; items = List.map items ~f:Z.of_int; op; div_test; if_true; if_false } ;; diff --git a/lib/year2023/day02.ml b/lib/year2023/day02.ml index 132b889..529cd6c 100644 --- a/lib/year2023/day02.ml +++ b/lib/year2023/day02.ml @@ -24,8 +24,8 @@ let color_p = ;; let draw_p = - let%map count = P.integer <* P.char ' ' - and color = color_p in + let+ count = P.integer <* P.char ' ' + and+ color = color_p in { count; color } ;; @@ -33,8 +33,8 @@ let draws_p = P.sep_by1 (P.string ", ") draw_p let round_p = P.sep_by1 (P.string "; ") draws_p let game_p = - let%map id = P.string "Game " *> P.integer <* P.string ": " - and round = round_p in + let+ id = P.string "Game " *> P.integer <* P.string ": " + and+ round = round_p in { id; round } ;; diff --git a/lib/year2023/day04.ml b/lib/year2023/day04.ml index 49d845d..a0357f9 100644 --- a/lib/year2023/day04.ml +++ b/lib/year2023/day04.ml @@ -12,9 +12,9 @@ type card = let nums_p = P.sep_by1 P.spaces P.integer let card_p = - let%map id = P.string "Card" *> P.spaces *> P.integer <* P.char ':' <* P.spaces - and winners = nums_p <* P.spaces <* P.char '|' <* P.spaces - and picks = nums_p in + let+ id = P.string "Card" *> P.spaces *> P.integer <* P.char ':' <* P.spaces + and+ winners = nums_p <* P.spaces <* P.char '|' <* P.spaces + and+ picks = nums_p in { id; winners = IntSet.of_list winners; picks = IntSet.of_list picks } ;; diff --git a/lib/year2023/day05.ml b/lib/year2023/day05.ml index 0c84b16..10f8376 100644 --- a/lib/year2023/day05.ml +++ b/lib/year2023/day05.ml @@ -21,9 +21,9 @@ type almanac = let seeds_p = P.string "seeds: " *> P.sep_by1 (P.char ' ') P.integer let mapping_p = - let%map dest = P.integer <* P.char ' ' - and source = P.integer <* P.char ' ' - and length = P.integer in + let+ dest = P.integer <* P.char ' ' + and+ source = P.integer <* P.char ' ' + and+ length = P.integer in { source; dest; length } ;; @@ -34,16 +34,16 @@ let name_p = ;; let map_p = - let%map name = name_p <* P.string " map:" <* P.end_of_line - and mappings = P.sep_by1 P.end_of_line mapping_p in + let+ name = name_p <* P.string " map:" <* P.end_of_line + and+ mappings = P.sep_by1 P.end_of_line mapping_p in { name; mappings } ;; let maps_p = P.sep_by1 (P.count 2 P.end_of_line) map_p let almanac_p = - let%map seeds = seeds_p <* P.count 2 P.end_of_line - and maps = maps_p in + let+ seeds = seeds_p <* P.count 2 P.end_of_line + and+ maps = maps_p in { seeds; maps } ;; diff --git a/lib/year2023/day06.ml b/lib/year2023/day06.ml index 7ffbc3e..348474b 100644 --- a/lib/year2023/day06.ml +++ b/lib/year2023/day06.ml @@ -7,8 +7,8 @@ type race = } let data_p p = - let%map times = P.string "Time:" *> P.spaces *> P.sep_by1 P.spaces p <* P.end_of_line - and distances = P.string "Distance:" *> P.spaces *> P.sep_by1 P.spaces p in + let+ times = P.string "Time:" *> P.spaces *> P.sep_by1 P.spaces p <* P.end_of_line + and+ distances = P.string "Distance:" *> P.spaces *> P.sep_by1 P.spaces p in times, distances ;; @@ -22,7 +22,7 @@ let races_p = ;; let race_p = - let%map times, distances = data_p P.digits in + let+ times, distances = data_p P.digits in { time = times |> String.concat |> Int.of_string ; distance = distances |> String.concat |> Int.of_string } diff --git a/lib/year2023/day07.ml b/lib/year2023/day07.ml index 36d6c45..e830f5a 100644 --- a/lib/year2023/day07.ml +++ b/lib/year2023/day07.ml @@ -58,8 +58,8 @@ let card_p = ;; let hand_p = - let%map cards = P.many1 card_p <* P.spaces - and score = P.integer in + let+ cards = P.many1 card_p <* P.spaces + and+ score = P.integer in cards, score ;; diff --git a/lib/year2023/day08.ml b/lib/year2023/day08.ml index 8f370a1..36f7b1e 100644 --- a/lib/year2023/day08.ml +++ b/lib/year2023/day08.ml @@ -24,22 +24,22 @@ let token_p = ;; let pair_p = - let%map left = P.char '(' *> token_p <* P.string ", " - and right = token_p <* P.char ')' in + let+ left = P.char '(' *> token_p <* P.string ", " + and+ right = token_p <* P.char ')' in left, right ;; let entry_p = - let%map key = token_p <* P.string " = " - and value = pair_p in + let+ key = token_p <* P.string " = " + and+ value = pair_p in key, value ;; let map_p = P.sep_by1 P.end_of_line entry_p >>| StrMap.of_alist_exn let input_p = - let%map dirs = dirs_p <* P.end_of_line - and map = map_p in + let+ dirs = dirs_p <* P.end_of_line + and+ map = map_p in { dirs; map } ;; diff --git a/lib/year2023/day12.ml b/lib/year2023/day12.ml index 6c64bd4..aaad1c1 100644 --- a/lib/year2023/day12.ml +++ b/lib/year2023/day12.ml @@ -11,8 +11,8 @@ let is_token = function ;; let line_p = - let%map tokens = P.take_while is_token <* P.char ' ' - and counts = P.sep_by1 (P.char ',') P.integer in + let+ tokens = P.take_while is_token <* P.char ' ' + and+ counts = P.sep_by1 (P.char ',') P.integer in String.to_list tokens, counts ;; diff --git a/lib/year2023/day13.ml b/lib/year2023/day13.ml index 5fc3792..debb21a 100644 --- a/lib/year2023/day13.ml +++ b/lib/year2023/day13.ml @@ -46,9 +46,9 @@ let reflection_score' g = result in let coords = - let open Sequence.Let_syntax in - let%bind x = Sequence.range 0 (Array.length g) in - let%map y = Sequence.range 0 (Array.length g.(x)) in + let open Util.Sequence.Syntax in + let* x = Sequence.range 0 (Array.length g) in + let+ y = Sequence.range 0 (Array.length g.(x)) in x, y in coords diff --git a/lib/year2023/day15.ml b/lib/year2023/day15.ml index c9083c7..db7e78b 100644 --- a/lib/year2023/day15.ml +++ b/lib/year2023/day15.ml @@ -29,8 +29,8 @@ let token_p = let inst_p = P.choice [ Drop <$ P.char '-'; (P.char '=' *> P.integer >>| fun i -> Add i) ] let op_p = - let%map label = token_p - and inst = inst_p in + let+ label = token_p + and+ inst = inst_p in { label; hash = hash label; inst } ;; diff --git a/lib/year2023/day17.ml b/lib/year2023/day17.ml index 7bed490..4aa1114 100644 --- a/lib/year2023/day17.ml +++ b/lib/year2023/day17.ml @@ -35,8 +35,7 @@ let solve max drop grid = let expand_steps dir init_loss coords = coords |> List.filter_map ~f:(fun coord -> - let%map.Option loss = Map.find grid coord in - loss, coord) + coord |> Map.find grid |> Option.map ~f:(fun loss -> loss, coord)) |> List.folding_map ~init:init_loss ~f:(fun sum (loss, coord) -> let loss' = sum + loss in loss', (loss', coord, dir)) diff --git a/lib/year2023/day18.ml b/lib/year2023/day18.ml index c92f689..fe00168 100644 --- a/lib/year2023/day18.ml +++ b/lib/year2023/day18.ml @@ -24,9 +24,9 @@ let hex_p = ;; let command_p = - let%map dir = dir_p <* P.char ' ' - and length = P.integer <* P.char ' ' - and color = P.string "(#" *> hex_p <* P.char ')' in + let+ dir = dir_p <* P.char ' ' + and+ length = P.integer <* P.char ' ' + and+ color = P.string "(#" *> hex_p <* P.char ')' in { dir; length; color } ;; diff --git a/lib/year2023/day19.ml b/lib/year2023/day19.ml index 93deacb..035a92b 100644 --- a/lib/year2023/day19.ml +++ b/lib/year2023/day19.ml @@ -65,16 +65,16 @@ let state_p = P.choice [ Accept <$ P.char 'A'; Reject <$ P.char 'R' ] let dest_p = P.choice [ (state_p >>| fun s -> End s); (name_p >>| fun n -> Name n) ] let lt_p = - let%map attr = attr_p <* P.char '<' - and n = P.integer <* P.char ':' - and dest = dest_p in + let+ attr = attr_p <* P.char '<' + and+ n = P.integer <* P.char ':' + and+ dest = dest_p in LT { attr; n; dest } ;; let gt_p = - let%map attr = attr_p <* P.char '>' - and n = P.integer <* P.char ':' - and dest = dest_p in + let+ attr = attr_p <* P.char '>' + and+ n = P.integer <* P.char ':' + and+ dest = dest_p in GT { attr; n; dest } ;; @@ -82,29 +82,29 @@ let move_p = dest_p >>| fun d -> Move d let rule_p = P.choice [ lt_p; gt_p; move_p ] let workflow_p = - let%map name = name_p <* P.char '{' - and rules = P.sep_by1 (P.char ',') rule_p <* P.char '}' in + let+ name = name_p <* P.char '{' + and+ rules = P.sep_by1 (P.char ',') rule_p <* P.char '}' in { name; rules } ;; let workflows_p = - let%map workflows = P.sep_by1 P.end_of_line workflow_p in + let+ workflows = P.sep_by1 P.end_of_line workflow_p in workflows |> List.map ~f:(fun w -> w.name, w) |> StrMap.of_alist_exn ;; let part_p = - let%map x = P.string "{x=" *> P.integer <* P.char ',' - and m = P.string "m=" *> P.integer <* P.char ',' - and a = P.string "a=" *> P.integer <* P.char ',' - and s = P.string "s=" *> P.integer <* P.char '}' in + let+ x = P.string "{x=" *> P.integer <* P.char ',' + and+ m = P.string "m=" *> P.integer <* P.char ',' + and+ a = P.string "a=" *> P.integer <* P.char ',' + and+ s = P.string "s=" *> P.integer <* P.char '}' in { x; m; a; s } ;; let parts_p = P.sep_by1 P.end_of_line part_p let input_p = - let%map workflows = workflows_p <* P.string "\n\n" - and parts = parts_p in + let+ workflows = workflows_p <* P.string "\n\n" + and+ parts = parts_p in { workflows; parts } ;; diff --git a/lib/year2023/day20.ml b/lib/year2023/day20.ml index 3b1e49d..e0fe21f 100644 --- a/lib/year2023/day20.ml +++ b/lib/year2023/day20.ml @@ -50,26 +50,26 @@ let name_p = let outputs_p = P.sep_by1 (P.string ", ") name_p let broadcaster_p = - let%map outputs = P.string "broadcaster -> " *> outputs_p in + let+ outputs = P.string "broadcaster -> " *> outputs_p in Broadcaster { name = "broadcaster"; outputs } ;; let flip_flop_p = - let%map name = P.char '%' *> name_p <* P.string " -> " - and outputs = outputs_p in + let+ name = P.char '%' *> name_p <* P.string " -> " + and+ outputs = outputs_p in FlipFlop { name; state = Off; outputs } ;; let conjunction_p = - let%map name = P.char '&' *> name_p <* P.string " -> " - and outputs = outputs_p in + let+ name = P.char '&' *> name_p <* P.string " -> " + and+ outputs = outputs_p in Conjunction { name; last_inputs = StrMap.empty; outputs } ;; let module_p = P.choice [ flip_flop_p; conjunction_p; broadcaster_p ] let modules_p = - let%map modules = P.sep_by1 P.end_of_line module_p in + let+ modules = P.sep_by1 P.end_of_line module_p in modules |> List.map ~f:(fun m -> mod_name m, m) |> StrMap.of_alist_exn ;; diff --git a/lib/year2023/day22.ml b/lib/year2023/day22.ml index 06393a0..6987f72 100644 --- a/lib/year2023/day22.ml +++ b/lib/year2023/day22.ml @@ -15,20 +15,20 @@ end module BrickSet = Set.Make (Brick) let coord_p = - let%map x = P.integer <* P.char ',' - and y = P.integer <* P.char ',' - and z = P.integer in + let+ x = P.integer <* P.char ',' + and+ y = P.integer <* P.char ',' + and+ z = P.integer in { x; y; z } ;; let brick_p = - let%map a = coord_p <* P.char '~' - and b = coord_p in + let+ a = coord_p <* P.char '~' + and+ b = coord_p in a, b ;; let bricks_p = - let%map bricks = P.sep_by1 P.end_of_line brick_p in + let+ bricks = P.sep_by1 P.end_of_line brick_p in bricks |> List.mapi ~f:(fun i (a, b) -> i, a, b) |> BrickSet.of_list ;; diff --git a/lib/year2023/day24.ml b/lib/year2023/day24.ml index 6f80fcd..1a12395 100644 --- a/lib/year2023/day24.ml +++ b/lib/year2023/day24.ml @@ -17,12 +17,12 @@ type line = } let stone_p = - let%map x = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int - and y = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int - and z = P.signed_integer <* P.spaces <* P.char '@' <* P.spaces >>| Q.of_int - and dx = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int - and dy = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int - and dz = P.signed_integer >>| Q.of_int in + let+ x = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int + and+ y = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int + and+ z = P.signed_integer <* P.spaces <* P.char '@' <* P.spaces >>| Q.of_int + and+ dx = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int + and+ dy = P.signed_integer <* P.char ',' <* P.spaces >>| Q.of_int + and+ dz = P.signed_integer >>| Q.of_int in { x; y; z; dx; dy; dz } ;; diff --git a/lib/year2023/day25.ml b/lib/year2023/day25.ml index e78c33e..bfeca0c 100644 --- a/lib/year2023/day25.ml +++ b/lib/year2023/day25.ml @@ -19,8 +19,8 @@ let token_p = ;; let line_p = - let%map node = token_p <* P.string ": " - and nodes = P.sep_by1 (P.char ' ') token_p in + let+ node = token_p <* P.string ": " + and+ nodes = P.sep_by1 (P.char ' ') token_p in node, nodes ;;