Advertisement
martinmazur

Przelewanka bez hashy

Jan 21st, 2020
1,276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 6.04 KB | None | 0 0
  1. (* Przelewanka
  2. Recenzent: Piotr Prabucki
  3. Autor: Marcin Mazur *)
  4.  
  5. (* Exception, ktore konczy program, jesli znajdzie odpowiedz *)
  6. exception Koniec of int
  7.  
  8. let przelewanka int_array =
  9.  
  10. (* Array bez kubków zer, poniewaz nie wplywaja one na rozwiazanie *)
  11.     let good_input_array =
  12.         Array.of_list (List.filter (fun (x, _) -> if x = 0 then false else true) (Array.to_list int_array)) in
  13.  
  14. (* Dlugosc naszej tablicy *)
  15.     let dlugosc = Array.length good_input_array in
  16.  
  17. (* Pojemnosci szklanek *)
  18.     let pojemnosci = Array.map (fun (y, _) -> y) good_input_array in
  19.  
  20. (* Licze NWD pojemnosci kubkow *)
  21.     let nwd =
  22.         let rec nwd_licz x y =
  23.             if x = 0 then y
  24.             else nwd_licz (y mod x) x in
  25.         Array.fold_left nwd_licz 0 pojemnosci in
  26.  
  27. (* Czy to nie jest juz odpowiedz*)
  28.     if Array.for_all (fun (_, y) -> y = 0) good_input_array || dlugosc = 0 then 0
  29.  
  30. (* Sprawdzam czy istnieje kubek, ktoy trzeba napelnic do pelna lub
  31.     kubek, ktorego nie trzeba napelniac *)
  32.     else if Array.for_all (fun (x, y) -> x <> y && y <> 0) good_input_array then -1
  33.  
  34. (* Sprawdzam czy wszystkie stany koncowe sa podzielne przez NWD *)
  35.     else if not (Array.for_all (fun (_, x) -> (x mod nwd) = 0) good_input_array) then  -1
  36.  
  37. (* Tutaj zaczyna sie implementacja i wyliczanie stanow*)
  38.     else
  39.  
  40. (* Wynik / stan koncowy *)
  41.     let dream_state = Array.map (fun (_, y) -> y) good_input_array in
  42.  
  43. (* Hashtable, ktory przechowuje stany *)
  44.     let mapa_stanow = Hashtbl.create 420420 in
  45.  
  46. (* Kolejka trzymajaca stany do rozpatrzenia *)
  47.     let do_rozpatrzenia = Queue.create () in
  48.     Queue.add ((Array.make dlugosc 0), 0) do_rozpatrzenia;
  49.  
  50. (* Funkcja nalania wody ze szklanki *)
  51.     let nalej (tablica, kroki) numer_szklanki =
  52.         let kopia = Array.copy tablica in
  53.         Array.set kopia numer_szklanki (Array.get pojemnosci numer_szklanki);
  54.         (kopia, kroki + 1) in
  55.  
  56. (* Funkcja wylania wody ze szklanki *)
  57.     let wylej (tablica, kroki) numer_szklanki =
  58.         let kopia = Array.copy tablica in
  59.         Array.set kopia numer_szklanki 0;
  60.         (kopia, kroki + 1) in
  61.  
  62. (* Funkcja przelania z jednej szklanki do drugiej *)
  63.     let przelej (tablica, kroki) z_tej do_tej =
  64.         let kopia = Array.copy tablica in
  65.         let z_tej_ile_ma = (Array.get kopia z_tej) in
  66.         let do_tej_ile_ma = (Array.get kopia do_tej) in
  67.         let do_tej_ile_moze_miec = (Array.get pojemnosci do_tej) in
  68.         if do_tej_ile_moze_miec - do_tej_ile_ma >= z_tej_ile_ma then
  69.         begin
  70.             Array.set kopia z_tej 0;
  71.             Array.set kopia do_tej (do_tej_ile_ma + z_tej_ile_ma);
  72.             (kopia, kroki + 1)
  73.         end
  74.         else
  75.         begin
  76.             Array.set kopia z_tej (z_tej_ile_ma - (do_tej_ile_moze_miec - do_tej_ile_ma));
  77.             Array.set kopia do_tej do_tej_ile_moze_miec;
  78.             (kopia, kroki + 1)
  79.         end in
  80.  
  81. (* Pelna *)
  82.     let pelna stan i_numer =
  83.         (Array.get pojemnosci i_numer) = (Array.get (fst stan) i_numer) in
  84.  
  85. (* Pusta *)
  86.     let pusta stan i_numer =
  87.         0 = (Array.get (fst stan) i_numer) in
  88.  
  89. (* Obslugiwanie nowego stanu *)
  90.     let obsluz zmieniony_stan =
  91.         let tablica = fst zmieniony_stan in
  92.         if (tablica) = dream_state then
  93.         begin
  94.             raise (Koniec (snd zmieniony_stan));
  95.         end
  96.         else if not (Hashtbl.mem mapa_stanow tablica) then
  97.         begin
  98.             Hashtbl.add mapa_stanow tablica [zmieniony_stan];
  99.             Queue.add zmieniony_stan do_rozpatrzenia;
  100.         end
  101.         else
  102.         let wyjeta_lista = Hashtbl.find mapa_stanow tablica in
  103.         let rec nie_ma zmieniony_stan lista =
  104.             match lista with
  105.             | hd :: tl -> if (fst hd) = (fst zmieniony_stan) then false else nie_ma zmieniony_stan tl
  106.             | [] -> true in
  107.         if nie_ma zmieniony_stan wyjeta_lista then
  108.         begin
  109.             Hashtbl.replace mapa_stanow tablica (zmieniony_stan :: wyjeta_lista);
  110.             Queue.add zmieniony_stan do_rozpatrzenia;
  111.         end
  112.         else () in
  113.  
  114. (* Looper *)
  115.     try
  116.         while not (Queue.is_empty do_rozpatrzenia) do
  117.             let aktualny_stan = Queue.take do_rozpatrzenia in
  118.             (* nalewanie *)
  119.             for i = 0 to dlugosc - 1 do
  120.                 if not (pelna aktualny_stan i) then
  121.                 let changed = nalej aktualny_stan i in
  122.                 obsluz changed
  123.             done;
  124.             (* wylewanie *)
  125.             for i = 0 to dlugosc - 1 do
  126.                 if not (pusta aktualny_stan i) then
  127.                 let changed = wylej aktualny_stan i in
  128.                 obsluz changed
  129.             done;
  130.             (* przelewanie *)
  131.             for i = 0 to dlugosc - 1 do
  132.                 if not (pusta aktualny_stan i) then
  133.                 begin
  134.                 for j = 0 to dlugosc - 1 do
  135.                     if j <> i && not (pelna aktualny_stan j) then
  136.                     begin
  137.                     let changed = przelej aktualny_stan i j in
  138.                     obsluz changed
  139.                     end
  140.                 done
  141.                 end
  142.             done
  143.         done;
  144.     -1
  145.     with Koniec wynik -> wynik ;;
  146.  
  147. (* Testy:
  148. assert(przelewanka [|(1, 0); (3, 0); (1, 0) |] = 0);;
  149. assert(przelewanka [|(1, 5); (3, 3); (1, 1) |] = 3);;
  150. assert(przelewanka [|(1, 0); (3, 0); (1, 0) |] = 0);;
  151. assert(przelewanka [|(3, 5); (3, 3); (1, 1) |] = 3);;
  152. assert(przelewanka [|(3, 3); (3, 3); (1, 0) |] = 3);;
  153. assert(przelewanka [|(3, 2); (3, 2); (1, 0) |] = 4);;
  154. assert(przelewanka [|(3, 1); (3, 1); (7, 1) |] = -1);;
  155. assert(przelewanka [|(3, 1); (3, 1); (7, 0) |] = 7);;
  156. assert(przelewanka [|(2,1); (1, 1); (7, 7) |] = 7);;
  157. assert(przelewanka [|(2,0); (1, 1); (7, 1) |] = 6);;
  158. assert(przelewanka [|(5,1); (1, 0); (7, 1) |] = 7);;
  159. assert(przelewanka [|(5,5); (1, 1); (7, 1) |] = 5);;
  160. assert(przelewanka [|(5,1); (1, 0); (7, 1) |] = 7);;
  161. assert(przelewanka [|(5,3); (3, 3); (7, 1) |] = 4);;
  162. assert(przelewanka [|(5,3); (3, 0); (7, 4) |] = 3);;
  163. assert(przelewanka [|(5,0); (3, 3); (7, 4) |] = 2);;
  164. assert(przelewanka [|(5,0); (3, 0); (7, 7) |] = 1);; *)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement