(*
 * $Id: wordfreq.ocaml,v 1.8 2001/05/26 01:48:48 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 *)

let max = 4096
let buf = String.create max
let count = Hashtbl.create 75000
let wbuf = Buffer.create 64

let rec scan_words i n inword =
  if i < n then
    let c = buf.[i] in
    if 'a' <= c && c <= 'z' then begin
      Buffer.add_char wbuf c;
      scan_words (i+1) n true
    end
    else if 'A' <= c && c <= 'Z' then begin
      Buffer.add_char wbuf (Char.unsafe_chr(Char.code c + 32));
      scan_words (i+1) n true
    end
    else if inword then begin
      let word = Buffer.contents wbuf in
      begin try incr (Hashtbl.find count word)
      with Not_found -> Hashtbl.add count word (ref 1) end;
      Buffer.clear wbuf;
      scan_words (i+1) n false
    end else
      scan_words (i+1) n false
  else
    let nread = input stdin buf 0 max in
    if nread = 0 then () else scan_words 0 nread inword

let _ =
  scan_words 0 0 false;
  let out_lines = ref [] in
  let to_list l w c =
    l := (Printf.sprintf "%7d\t%s" !c w) :: !l in
  Hashtbl.iter (to_list out_lines) count;
  List.iter print_endline (List.sort (fun a b -> compare b a) !out_lines)