Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 3.09 KB | None | 0 0
  1. (* Zadnie przelewanki
  2. Autor: Michał Kardaś
  3. Reviewer: Witalis Domitrz *)
  4.  
  5. (* Sprawdza czy jakaś oczekiwana szklanka jest pusta
  6. lub pełna. Warunek konieczny do istnienia rozwiązania
  7. ponieważ każda operacja zostawia jedna szklankę pustą lub pełną*)
  8.  
  9. let pelna_pusta arr =
  10. let czy = ref false in
  11. for i = 0 to (Array.length arr - 1) do
  12. let (pojemnosc, stan) = arr.(i) in
  13. czy := !czy || stan = 0 || stan = pojemnosc
  14. done;
  15. !czy
  16.  
  17. let rec nwd a b =
  18. if b = 0 then a else nwd b (a mod b);;
  19.  
  20. (* Liczy nwd ze wszystkich objętości szklanek *)
  21. let licz_NWD arr =
  22. let (a, _) = arr.(0) in
  23. let nwd_szklanek = ref a in
  24. for i = 0 to (Array.length arr - 1) do
  25. let (pojemnosc, _) = arr.(i) in
  26. nwd_szklanek := nwd !nwd_szklanek pojemnosc
  27. done;
  28. !nwd_szklanek
  29.  
  30. (* Sprawdza czy kandydat jest oczekiwanym stanem szklanek *)
  31. let rowne szklanki kandydat =
  32. let czy = ref true in
  33. for i = 0 to (Array.length szklanki - 1) do
  34. let (_, stan) = szklanki.(i) in
  35. czy := !czy && stan = kandydat.(i)
  36. done;
  37. !czy
  38.  
  39. (* Sprawdza czy oczekiwana ilość wody w szklance nie jest
  40. względnie pierwsza z NWD objętości szklanek jeżeli NWD
  41. nie jest równe 1. Warunek konieczny do istnienia rozwiązania *)
  42. let sprawdz_NWD arr nwd_szklanek =
  43. let czy = ref true in
  44. if nwd_szklanek = 1 then true
  45. else
  46. begin
  47. for i = 0 to (Array.length arr - 1) do
  48. let (_, stan) = arr.(i) in
  49. czy := !czy && (nwd nwd_szklanek stan) != 1
  50. done;
  51. !czy
  52. end
  53.  
  54. (* Sprawdza czy oczekiwanym stanem nie są puste szklanki *)
  55. let gotowe arr =
  56. let czy = ref true in
  57. for i = 0 to (Array.length arr - 1) do
  58. let (_, stan) = arr.(i) in
  59. czy := !czy && stan = 0
  60. done;
  61. !czy
  62.  
  63.  
  64.  
  65. let przelewanka szklanki =
  66. let n = Array.length szklanki in
  67. if n = 0 || gotowe szklanki then 0 else
  68. if not (sprawdz_NWD szklanki (licz_NWD szklanki) ||
  69. (pelna_pusta szklanki) ) then -1 else
  70. let queue = Queue.create () in
  71. let wyn = ref (-1) in
  72. (* Tablica, która spamiętuje, które stany zostały już przetworzone *)
  73. let vis = Hashtbl.create n in
  74. let sprawdz stan warstwa =
  75. if rowne szklanki stan && !wyn = -1 then wyn := warstwa
  76. else if not (Hashtbl.mem vis stan) then
  77. begin
  78. Hashtbl.add vis (Array.copy stan) true;
  79. Queue.add (Array.copy stan, warstwa + 1) queue;
  80. end in
  81. begin
  82. sprawdz (Array.make n 0) 0;
  83. (* Dopóki nie znaleziono wyniku i sa jeszcze jakieś
  84. nierozpatrzone stany *)
  85. while  !wyn = (-1) && not (Queue.is_empty queue)  do
  86.  
  87. let (stany, warstwa) = Queue.take queue in
  88. begin
  89. (* Symuluje wylewanie i wlewanie wody do szklanek *)
  90. for i = 0 to n - 1 do
  91. let pom = stany.(i) in
  92. let (pojemnosc, _) = szklanki.(i) in
  93. stany.(i) <- pojemnosc;
  94. sprawdz stany warstwa;
  95. stany.(i) <- 0;
  96. sprawdz stany warstwa;
  97. stany.(i) <- pom;
  98. done;
  99. (* Symuluje przelanie ze szklanki j do szklanki i *)
  100. for i = 0 to n - 1 do
  101. for j = 0 to n - 1 do
  102. if i != j then
  103. let (pojemnosc_i, _) = szklanki.(i) in
  104. let stan_i = stany.(i) and stan_j = stany.(j) in
  105. begin
  106. stany.(i) <- min pojemnosc_i (stan_i + stan_j);
  107. stany.(j) <- max 0 (stan_j - pojemnosc_i + stan_i);
  108. sprawdz stany warstwa;
  109. stany.(i) <- stan_i;
  110. stany.(j) <- stan_j;
  111. end;
  112. done;
  113. done;
  114. end
  115. done;
  116. !wyn
  117. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement