Advertisement
Guest User

Untitled

a guest
Jan 24th, 2018
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 2.58 KB | None | 0 0
  1. (* Autor: Jan Kociniak
  2.    Reviewer: Piotr Wojtczak
  3.    WPF 2017Z - Przelewanka  *)
  4.  
  5.  
  6. exception Solution of int
  7.  
  8. (* funkcja generujaca liste osiagalnych stanów, ktore nie sa jeszcze rozwiazaniem  *)
  9. (* arr - poczatkowy stan, d - liczba krokow, comp - to co chcemy osiagnac          *)
  10.  
  11. let states (arr, d) comp =
  12.   let n = Array.length arr and d1 = d+1 and l = ref [] in
  13.     for i = 0 to n-1 do
  14.       let (xi, yi) = arr.(i) in
  15.       (* dolanie do pełna i-tej szklanki *)
  16.       if yi <> xi then begin
  17.         arr.(i) <- (xi, xi);
  18.         if arr = comp then raise (Solution (d1))
  19.         else
  20.           l := (Array.copy arr, d1)::!l;
  21.       end;
  22.       (* oproznienie i-tej szklanki *)
  23.       if yi <> 0 then begin
  24.         arr.(i) <- (xi, 0);
  25.         if arr = comp then raise (Solution (d1))
  26.         else
  27.           l := (Array.copy arr, d1)::!l;
  28.       end;
  29.         (* reset *)
  30.         arr.(i) <- (xi, yi);
  31.       for j = i+1 to n-1 do
  32.         let (xj, yj) = arr.(j) in
  33.         (* przelanie z i do j *)
  34.         if yj <> xj  && yi <> 0 then begin
  35.         arr.(j) <- (xj, min (yj + yi) xj);
  36.         arr.(i) <- (xi, max 0 (yi - xj + yj));
  37.         if arr = comp then raise (Solution (d1))
  38.         else
  39.           l := (Array.copy arr, d1)::!l;
  40.       end;
  41.         (* przelanie z j do i *)
  42.         if yi <> xi && yj <> 0 then begin
  43.         arr.(i) <- (xi, min (yi + yj) xi);
  44.         arr.(j) <- (xj, max 0 (yj - xi + yi));
  45.         if arr = comp then raise (Solution (d1))
  46.         else
  47.           l := (Array.copy arr, d1)::!l;
  48.       end;
  49.         (* reset *)
  50.         arr.(i) <- (xi, yi);
  51.         arr.(j) <- (xj, yj);
  52.       done;
  53.     done;
  54.     !l
  55.  
  56. let gcd arr =
  57.   let rec euclid a b =
  58.     let (m, n) = (max a b, min a b) in
  59.     if n = 0 then m else euclid (m mod n) n
  60.   in
  61.   let gcd_x = Array.fold_left (fun a (x, _) -> euclid a x) 0 arr in
  62.   Array.fold_left (fun a (_, y) -> a && y mod gcd_x = 0) true arr
  63.  
  64.  
  65. let bfs arr =
  66.   if arr = Array.map (fun (x, _) -> (x, 0)) arr then 0 else
  67.   if not (gcd arr) then -1 else
  68.     let q = Queue.create()
  69.     and been = Hashtbl.create 1000000
  70.     and start = Array.map (fun (x, _) -> (x, 0)) arr in
  71.     let filter (x, d) =
  72.       if Hashtbl.mem been x = false then begin
  73.            Queue.add (x, d) q;
  74.            Hashtbl.add been x true; end
  75.       in
  76.          Hashtbl.add been start true;
  77.          Queue.add (start, 0) q;
  78.          while not (Queue.is_empty q) do
  79.            let act = Queue.take q in
  80.            List.iter filter (states act arr);
  81.          done;
  82.          -1
  83.  
  84. let przelewanka arr =
  85.   try bfs arr with
  86.   | Solution(x) -> x
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement