(* * $Id: re_match.ml,v 1.2 2001/10/03 15:04:59 vouillon Exp $ * http://www.bagley.org/~doug/shootout/ * from: Markus Mottl *) let rex = let three_digits = Re.seq [Re.digit; Re.digit; Re.digit] in Re.compile (Re.seq [(* Must be preceeded by a non-digit *) Re.alt [Re.bol; Re.compl [Re.digit; Re.char '(']]; (* Area code *) Re.group (Re.alt [Re.seq [Re.char '('; three_digits; Re.char ')']; three_digits]); (* One space *) Re.char ' '; (* Prefix of 3 digits *) three_digits; (* Separator: either a space or a dash *) Re.set " -"; (* Last for digits *) three_digits; Re.digit; (* Must be followed by a non-digit (or EOL) *) Re.alt [Re.eol; Re.compl [Re.digit]]]) let foreach_line ?(ic = stdin) f = try while true do f (input_line ic) done with End_of_file -> () let phones = let lines = ref [] in let ic = open_in "Input" in foreach_line ~ic (fun line -> lines := line :: !lines); close_in ic; List.rev !lines let check_phone cnt must_print line = try let matches = Re.exec rex line in let num = String.copy "(...) ...-...." and (pos, _) = Re.get_ofs matches 1 in let ofs = if line.[pos] = '(' then 1 else 0 in let pos = pos + ofs in String.blit line pos num 1 3; let pos = pos + ofs + 4 in String.blit line pos num 6 3; String.blit line (pos + 4) num 10 4; if must_print then Printf.printf "%d: %s\n" !cnt num; incr cnt with Not_found -> () let n = if Array.length Sys.argv > 1 then int_of_string Sys.argv.(1) else 1;; for i = 2 to n do List.iter (check_phone (ref 1) false) phones done; List.iter (check_phone (ref 1) true) phones