solve_2.ml 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. open Stdio
  2. open Str
  3. let read_input =
  4. let rec aux rules updates=
  5. let line = In_channel.input_line In_channel.stdin in
  6. match line with
  7. | None -> rules, updates
  8. | Some x -> if (Str.string_match (regexp {|[0-9]+|[0-9]+|}) x 0) then
  9. let z = (List.map int_of_string (Str.split (regexp {|||}) x)) in
  10. aux ((List.nth z 0, List.nth z 1)::rules) updates else
  11. (if (Str.string_match (regexp {|[0-9]+\|,|}) x 0) then
  12. aux rules ((List.map int_of_string (Str.split (regexp {|,|}) x))::updates) else aux rules updates)
  13. in
  14. aux [] []
  15. ;;
  16. let rules_graph = (fst read_input)
  17. let updates = (snd read_input)
  18. let neighbors a =
  19. let aux g a =
  20. let edge l (b, c) = if b = a then (c,'a') :: l
  21. else if c = a then (b,'b') :: l
  22. else l in
  23. List.fold_left edge [] g in
  24. aux rules_graph a
  25. ;;
  26. let rec get_order nei = function
  27. | (n,o)::tl -> if (nei == n) then o else get_order nei tl
  28. | [] -> 'e'
  29. ;;
  30. let rec is_page_ordered neighbors_p = function
  31. | [] -> true
  32. | hd :: tl -> if ((get_order hd neighbors_p) == 'a') then
  33. is_page_ordered neighbors_p tl else false
  34. ;;
  35. let get_middle_page u = let u_len = List.length u in List.nth u (u_len/2);;
  36. let sort u =
  37. let rec aux sorted_u u visited = (match visited with
  38. | [] -> sorted_u
  39. | hd::tl -> let taint_order = List.map (fun x -> (x, get_order x (neighbors hd))) sorted_u in
  40. let correct_pages = (List.map fst (List.filter (fun x -> (snd x) == 'a') taint_order)) in
  41. let uncorrect_pages = (List.map fst (List.filter (fun x -> (snd x) != 'a') taint_order)) in
  42. aux (uncorrect_pages@correct_pages) u tl)
  43. in
  44. aux u u u;;
  45. let solve =
  46. let rec is_valid_update u =
  47. match u with
  48. | hd :: tl ->
  49. (let hd_neighbors = neighbors hd in
  50. if (is_page_ordered hd_neighbors tl) then (is_valid_update tl) else false
  51. )
  52. | [] -> true
  53. in
  54. let rec aux accum = function
  55. | [] -> accum
  56. | hd::tl -> if (is_valid_update hd) then aux accum tl
  57. else aux (accum + get_middle_page (sort hd)) tl in
  58. aux 0 updates
  59. ;;
  60. let () = printf "Total: %d\n" solve