Source

spoj-ocaml / 00005.PALIN / palin.ml

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

let (|>) x y = y x
let id x = x


let solve x =
  let x = String.copy x in

  let n  = String.length x in
  let n2 = n / 2 in

  let rec pass1 i is_le =
    (* Make palindrome. *)
    if i >= n2 then is_le
    else
      let is_le = x.[i] <= x.[n - i - 1] in
      x.[n - i - 1] <- x.[i] ;
      pass1 (i + 1) is_le
  in

  let rec pass2 i =
    (* Fix the palindrome, obtained on first pass, if it's less or equal then
       the source number. *)
    if i == -1 then
      (* The whole string proceeded. *)
      if x.[0] == '0' then begin
        (* 1 + string[:-1] + 1 *)
        x.[n - 1] <- '1' ; String.concat "" ["1"; x]
      end
      else
        x

    else begin
      x.[i] <- if x.[i] == '9' then '0'
               else                 x.[i] |> Char.code |> ((+) 1) |> Char.chr ;

      x.[n - i - 1] <- x.[i] ;

      if x.[i] == '0' then pass2 (i - 1)
      else                 x
    end
  in

  if pass1 0 false then
    pass2 (if n mod 2 == 0 then n2 - 1 else n2)
  else
    x


let main () =
  let t = Scanf.scanf "%d\n" id in
  for i = 1 to t do
    let k = Scanf.scanf "%s\n" id in
    let x = solve k in
    Printf.printf "%s\n" x
  done

let () = main ()