(** Xstring *) let isub str i1 i2 = try String.sub str i1 (i2-i1+1) with Invalid_argument("String.sub") -> raise (Invalid_argument("Xstring.isub")) (** line format: '== +[a-z]+.?[a-z]* +[A-E][\+-]?' *) let parse_line line = let name1 = ref "" and name2 = ref "" in let mark = ref "" in let a = int_of_char 'a' and z = int_of_char 'z' in let is_a_z c = let c = int_of_char c in (a <= c) && (c <= z) in let len = String.length line in let i = ref 0 in let i0 = ref 0 in while (line.[!i] = '=' || line.[!i] = ' ') do incr i done; i0 := !i; while (is_a_z line.[!i]) do incr i done; name1 := isub line !i0 (!i-1); if (line.[!i] = '.') then ( incr i; i0 := !i ); i0 := !i; while (!i < len) && (is_a_z line.[!i]) do incr i done; if (!i > !i0) then name2 := isub line !i0 (!i-1); while (line.[!i] = ' ') do incr i done; if (!i+1 < len) then mark := isub line !i (!i+1) else mark := isub line !i !i; (!name1, !name2,!mark) let marks = ref [] let add_mark numtp name mark = try let ms = List.assoc name !marks in ms.(numtp) <- mark with Not_found -> ( let ms = Array.create 6 0 in ms.(numtp) <- mark; marks := (name, ms)::!marks ) let mark_of_alpha m = let n = match m.[0] with 'A' -> 13 | 'B' -> 10 | 'C' -> 7 | 'D' -> 4 | 'E' -> 0 | _ -> failwith ("mark_of_alpha: not an alpha mark "^m) in if (String.length m) > 1 then if m.[1] = '+' then n+1 else n-1 else n ;; let numtp = ref (-1) in let ic = open_in Sys.argv.(1) in try while true do let line = input_line ic in if String.length line > 2 then ( if (line.[0] = '=') then ( if (line.[2] = '=') then ( incr numtp ) else ( match parse_line line with name, "", mark -> add_mark !numtp name (mark_of_alpha mark) | name1, name2, mark -> ( add_mark !numtp name1 (mark_of_alpha mark); add_mark !numtp name2 (mark_of_alpha mark) ) ) ) ) done with End_of_file -> ( List.iter (fun (name, ms) -> Printf.printf"%s " name; Printf.printf"%.2f\n" ((float_of_int (Array.fold_right (+) ms 0)) /. (float_of_int (Array.length ms))) ) (List.sort compare !marks); close_in ic )