AtCoder in OCaml: ABC121 B
In the Rust version, cargo-compete and proconio
handled most of the competitive-programming setup. The input looks like this (so nice):
input! {
n: usize,
m: usize,
c: i32,
b: [i32; m],
rows: [[i32; m]; n],
}
I don't want to write loops and scanfs in Ocaml. I wanted a similar small and composable
workflow, so I replicated it with a vibe-coded helper and a few input
reader combinators.
The problem is ABC121 B — Can you solve
this?: for each row, take its
dot product with B, add C, and count it if the result is greater than zero.
Small readers that compose
The base reader consumes one integer:
let int () = Scanf.scanf " %d" Fun.id
Then list turns any reader into a reader for n values:
let list n r () = List.init n (fun -> r ())
This means list m int reads one row, while list n (list m int) reads the
whole matrix. Here is the complete solution:
open Printf
let int () = Scanf.scanf " %d" Fun.id
let str () = Scanf.scanf " %s" Fun.id
let list n r () = List.init n (fun -> r ())
let array n r () = Array.init n (fun -> r ())
let pair r s () = let a = r () in let b = s () in (a, b)
type problem = {
c : int;
b : int list;
rows : int list list;
}
let read_problem () =
let n = int () in
let m = int () in
let c = int () in
let b = list m int () in
let rows = list n (list m int) () in
{ c; b; rows }
let can_solve c b row =
List.fold_left2
(fun score a_i b_i -> score + (a_i * b_i))
c
b
row
> 0
let solve problem =
problem.rows
|> List.filter (can_solve problem.c problem.b)
|> List.length
let () =
let problem = read_problem () in
printf "%d\n" (solve problem)
Ocaml has some nice builtins like List.fold_left2. Also solve and helper functions can stay pure. The result is the style I wanted. Also, I don't need to care about memory, ownership or types for the most part.
For this problem, OCaml feels just as concise as Rust.