Source

spoj-ocaml / 00006.ARITH / arith.ml

Full commit
(* https://www.spoj.pl/problems/ARITH/ *)

open Num


let id x = x


let print_prefixed_with_spaces n str =
  let len = String.length str in
  for i = 1 to n - len do print_char ' ' done ;
  print_endline str

let print_dashes n m =
  print_prefixed_with_spaces n (String.make m '-')

let print_pm opstr op left right =
  let res = string_of_num (op (num_of_string left) (num_of_string right)) in

  let right = String.concat "" [opstr; right] in
  let right_len = String.length right in
  let len = max (max (String.length left) right_len) (String.length res)
  in
  print_prefixed_with_spaces len left ;
  print_prefixed_with_spaces len right ;
  print_dashes len (max right_len (String.length res));
  print_prefixed_with_spaces len res

let print_m opstr left right =
  let res = string_of_num (( */ ) (num_of_string left) (num_of_string right)) in
  let right = String.concat "" [opstr; right] in
  let left_len = String.length left
  and right_len = String.length right
  and res_len = String.length res in
  let len = max (max left_len right_len) (String.length res)
  in
  print_prefixed_with_spaces len left ;
  print_prefixed_with_spaces len right ;

  if right_len > 2 then begin
    for i = 0 to right_len - 2 do
      let intr =
        string_of_num
          (( */ )
              (num_of_string left)
              (num_of_string (String.make 1 right.[right_len - i - 1])))
      in
      if i == 0 then
        print_dashes len (max right_len (String.length intr)) ;
      print_prefixed_with_spaces
        len (String.concat "" [intr; (String.make i ' ')])
    done ;
    print_dashes len res_len
  end
  else
    print_dashes len len ;
  print_prefixed_with_spaces len res

let print_expr left op right =
  match op with
    "+" -> print_pm op (+/) left right
  | "-" -> print_pm op (-/) left right
  | "*" -> print_m op left right
  | _   -> invalid_arg "impossible case"

let main () =
  let t = Scanf.scanf "%d\n" id in
  for i = 1 to t do
    let expr = Scanf.scanf "%s\n" id in
    let re = Str.regexp "\\([0-9]+\\)\\([-+*]\\)\\([0-9]+\\)" in
    let _ = Str.string_match re expr 0 in
    print_expr
      (Str.matched_group 1 expr)
      (Str.matched_group 2 expr)
      (Str.matched_group 3 expr) ;
    print_newline ()
  done

let () = main ()