fork(14) download
(*
 * UVa 10706. Number Sequence
 * 
 * http://u...content-available-to-author-only...e.org/external/107/10706.html
 *)
open System

let mutable numLength= 1
(*
 * :numbers:[int] -> length_each_num:[int]
 *)
let getNumLengths (l:int list) :int list = 
  (*
   * :num:Int -> numLength:Int 
   *)
  let computeLength (i:int):int =
    let rec computeLength' (i:int) (l:int) :int = 
      if ((i/(System.Math.Pow(10|>float,l|>float)|>int)) = 0) then 
        numLength <- l
        l 
      else 
        computeLength' i (l+1)
    computeLength' i numLength

  numLength <- 1 // setting numberLength <- 1 
  l
  |> List.map computeLength

(* Utility function to print a sequence 
 * :seq<'a> -> unit
 *)
let printSeq seq1 = Seq.iter (printf "%A ") seq1; printfn "" 


let cumulativeSumofLengths l = 
  let computeLengths list:int list =
    let rec computeNoOfElements' l acc = 
      match l with 
      | [] -> []
      | x::xs -> (x + acc)::(computeNoOfElements' xs (x + acc))
    computeNoOfElements' list 0  
  l 
  |> computeLengths  
  |> computeLengths 


(*
 * Performs a binary search on the cumulative sums of lengths. 
 * and return a tuple as (minBound, maxBound)
 * : arr: int[] -> n: int -> (int,int)
 *)
let getBounds a (n:int): int*int = 
  let binarySearch (arr:int[]) (n:int) : (int*int) =
    let rec binarySearch' (arr:int[]) (n:int)  (low:int) (high:int) = 
      if arr.[high] < n then 
         (high, System.Int32.MaxValue)
      else if high - low <= 1 then 
        if arr.[low] = n then
          (low, low)
        else  
          (low,high)
      else
        let mid = (high + low)/2
        match arr.[mid],n with 
        |  (a,b) when a <= b->  binarySearch' arr n  mid high
        |  _ ->  binarySearch' arr n  low mid
    binarySearch'  arr n 0 (arr.Length-1)
  binarySearch a n 
  
let numberAt a n = 
  let getDigitAtIndex (relLength:int) (index:int): int = 
    let rec getIntAtIndex' (relLength:int) (startNum:int)(endNum:int):int = 
      if startNum <= endNum then 
        let str = startNum.ToString()
        match  relLength  - str.Length with 
        | diff when diff <= 0 -> System.Int32.Parse(str.[relLength-1].ToString())
        | diff                ->  getIntAtIndex'  (relLength - str.Length)  (startNum+1) endNum
      
      else 
        -1
    getIntAtIndex' relLength 1 index  
  match  getBounds a n with 
  | 0,0  -> 1
  | l,h when h = System.Int32.MaxValue -> getDigitAtIndex (n-a.[l]) (l+1)  
  | l,h when l = h -> getDigitAtIndex (n-a.[l-1]) (l+1)
  | l,h            -> getDigitAtIndex (n-a.[l]) (l+2)


  
let solve_UVA10706 ()= 
  let arr = 
    [1..31267]
    |> getNumLengths 
    |> cumulativeSumofLengths 
    |> List.toArray

  let T = Console.ReadLine().Trim() |> int
  let mutable i:string = null

  for case_i = 1 to T do 
    i <- System.Console.ReadLine()
    if i <> null then 
      i
      |> Int32.Parse 
      |> numberAt arr
      |> printfn "%d"

// running script 
solve_UVA10706()

Success #stdin #stdout 0.17s 51280KB
stdin
18 
8 
3 
80 
546 
23423 
65753 
2345 
45645756 
546454 
6786797 
131231 
78934124 
68904565 
123487907 
5655 
778888 
101011 
2147483647
stdout
2
2
0
2
3
1
5
5
2
5
9
7
5
7
1
5
5
2