1 (* Grands rectangles - Concours d'Informatique X-ENS PC 2014 *)
13 let nombreZeroDroite i tab n
14 requires { 1 <= i <= n < tab.length }
15 requires { forall k. i <= k <= n -> tab[k] = 1 \/ tab[k] = 0 }
16 ensures { i <= result <= n + 1 }
17 ensures { forall k. i <= k < result -> tab[k] = 0 }
18 ensures { result <= n -> tab[result] = 1 }
21 while !j <= n && tab[!j] = 0 do
23 invariant { i <= !j <= n + 1}
24 invariant { forall k. i <= k < !j -> tab[k] = 0 }
30 let nombreZeroMaximum tab n =
31 requires { 1 <= n < tab.length }
32 requires { forall k. 1 <= k <= n -> tab[k] = 1 \/ tab[k] = 0 }
33 ensures { let (p,q) = result in
34 (1 <= p <= q <= n + 1) /\
35 (forall k. p <= k < q -> tab[k] = 0) }
36 ensures { let (p,q) = result in
38 (1 <= i <= j <= n + 1) ->
39 (forall k. i <= k < j -> tab[k] = 0) ->
46 invariant { 1 <= !i <= n + 1 }
47 invariant { 1 <= !p <= !q <= !i }
48 invariant { forall k. !p <= k < !q -> tab[k]= 0 }
49 (*invariant { 2 <= !i -> !q <= n -> tab[!q] = 1 }*)
50 invariant { forall a b.
51 (1 <= a <= b <= !i) ->
52 (forall k. a <= k < b -> tab[k] = 0) ->
54 invariant { 1 < !i <= n -> (tab[!i] = 1 \/ tab[!i-1] = 1) }
55 let next = nombreZeroDroite !i tab n in
57 if next - !i > !q - !p then begin p:= !i; q := next end;
58 i:= if !i = next then !i + 1 else next;
66 let nombreZeroDroite i tab n
67 requires { 1 <= i <= n }
68 requires { n = tab.length - 1 }
69 requires { forall k. i <= k <= n -> tab[k] = 1 \/ tab[k] = 0 }
70 ensures { 0 <= result <= n - i + 1 }
71 ensures { forall k. 0 <= k < result -> tab[i + k] = 0 }
72 ensures { let j = i + result in j <= n -> tab[j] = 1 }
75 while !j <= n && tab[!j] = 0 do
77 invariant { 0 <= !j - i <= n - i + 1}
78 invariant { forall k. 0 <= k < (!j - i) -> tab[i + k] = 0 }
84 let tab = make 14 0 in
86 tab[1] <- 0; tab[2] <- 0;
87 tab[3] <- 1; tab[4] <- 1;
88 tab[5] <- 0; tab[6] <- 0; tab[7] <- 0;
90 tab[9] <- 0; tab[10] <- 0; tab[11] <- 0;
91 tab[12] <- 1; tab[13] <- 1;
92 let n1 = nombreZeroDroite 4 tab 13 in
94 let n2 = nombreZeroDroite 6 tab 13 in
101 let nombreZeroMaximum tab n =
102 requires { 1 <= n /\ n = tab.length - 1}
103 requires { forall k. 1 <= k <= n -> tab[k] = 1 \/ tab[k] = 0 }
106 (0 <= result <= n - i + 1) /\
107 (forall k. 0 <= k < result -> tab[i + k] = 0) /\
108 (i + result <= n -> tab[i + result] = 1) }
109 ensures { forall j ofs.
111 (0 <= ofs <= n - j + 1) ->
112 (forall k. 0 <= k < ofs -> tab[j + k] = 0) ->
114 let max = ref (nombreZeroDroite 1 tab n) in
115 let ghost max_i = ref 1 in
116 let i = ref (if !max = 0 then 2 else !max + 1) in
119 invariant { 1 <= !i <= n + 1}
120 invariant { 1 <= !max_i < !i }
121 invariant {0 <= !max < !i - !max_i + 1 }
122 invariant {forall k. 0 <= k < !max -> tab[!max_i + k]= 0 }
123 invariant {!max_i + !max <= n -> tab[!max_i + !max] = 1 }
124 invariant { forall j ofs.
126 (0 <= ofs <= !i - j + 1) ->
127 (forall k. 0 <= k < ofs -> tab[j + k] = 0) ->
130 let ofs_i = nombreZeroDroite !i tab n in
132 if ofs_i > !max then begin max := ofs_i; max_i := !i end;
133 if ofs_i = 0 then i := !i + 1 else i:= !i + ofs_i;
143 (* Partie II. De la 1D vers la 2D *)
147 (* Partie III. Algorithme optimisé *)
148 (*Questions 7 - 12 *)
150 let rec calculeL_aux i histo l =
152 while !j > 1 && histo.(!j-1) >= histo.(i) do
153 j := calculeL_aux (!j-1) histo l
158 let l = Array.make (Array.length histo) 0 in
159 let i = ref (Array.length histo - 1) in
161 let j = calculeL_aux !i histo l in
162 if j < !i then i := j else i := !i - 1
166 let rec calculeR_aux i histo r =
168 while !j < Array.length histo - 1 && histo.(!j+1) >= histo.(i) do
169 j := calculeR_aux (!j+1) histo r
174 let r = Array.make (Array.length histo) 0 in
176 while !i < Array.length histo do
177 let j = calculeR_aux !i histo r in
178 if j > !i then i := j else i := !i + 1
181 let calculeLR histo = (calculeL histo, calculeR histo)
183 let plusGrandRectangleHistogramme lx histo =
184 let l, r = calculeLR histo in
189 for i = 1 to Array.length histo - 1 do
190 let s' = (r.(i) - (l.(i) - 1)) * histo.(i) in
195 ly := lx - (histo.(i) - 1);
199 ((lx, !cx), (!ly, !cy), !s)
203 let lx, cx, ly, cy, s = ref 0, ref 0, ref 0,ref 0, ref 0 in
204 for i = 1 to Array.length col - 1 do
205 let (lx', cx'), (ly', cy'), s' = plusGrandRectangleHistogramme i col.(i) in
215 (!lx, !cx), (!ly, !cy), !s
218 let histo = [|-1;3;1;2;4;2;2;0;1|]
223 [|-1; 1; 1; 0; 0; 1; 1; 1; 0 |];
224 [|-1; 2; 2; 1; 1; 0; 2; 2; 0 |];
225 [|-1; 0; 3; 2; 2; 1; 3; 3; 0 |];
226 [|-1; 1; 0; 3; 3; 2; 4; 4; 0 |];
227 [|-1; 2; 1; 0; 0; 3; 5; 5; 0 |];
228 [|-1; 3; 2; 0; 1; 4; 6; 6; 0 |];
229 [|-1; 4; 0; 0; 0; 5; 0; 7; 0 |];
230 [|-1; 5; 1; 0; 0; 6; 1; 8; 0;|]
233 let _ = plusGrandRectangleHistogramme 4 histo
237 (************************************************)
239 module Recherche_bidimensionnelle
246 let rec calculeL_aux i histo l
247 requires {l.length = histo.length}
248 requires {0 <= i < histo.length }
249 ensures {0 <= result <= i}
250 ensures {forall k. result <= k <= i -> histo[k] >= histo[i]}
251 ensures {result > 0 -> histo[result-1] < histo[i]}
252 ensures {result = l[i]}
256 while !j > 0 && histo[!j-1] >= histo[i] do
258 invariant {forall k. !j <= k <= i -> histo[k] >= histo[i]}
259 invariant {0 <= !j <= i }
260 j := calculeL_aux (!j-1) histo l
264 let calculeL i histo l
265 requires {l.length = histo.length}
266 requires {0 <= i < histo.length }
267 ensures {forall k. result <= k <= i -> histo[k] >= histo[i]}
268 ensures {result > 0 -> histo[result-1] < histo[i]}
269 ensures {0 <= result <= i}
270 ensures {result = l[i]}
271 = calculeL_aux i histo l
273 let rec calculeR_aux i histo r
274 requires {r.length = histo.length}
275 requires {0 <= i < histo.length }
276 ensures {i <= result < histo.length}
277 ensures {forall k. i <= k <= result -> histo[k] >= histo[i]}
278 ensures {result < histo.length - 1 -> histo[result+1] < histo[i]}
279 ensures {result = r[i]}
280 variant { histo.length - i }
283 while !j < histo.length - 1 && histo[!j+1] >= histo[i] do
284 variant {histo.length - !j}
285 invariant {forall k. i <= k <= !j -> histo[k] >= histo[i]}
286 invariant {i <= !j < histo.length }
287 j := calculeR_aux (!j+1) histo r
291 let calculeR i histo r
292 requires {r.length = histo.length}
293 requires {0 <= i < histo.length }
294 ensures {forall k. i <= k <= result -> histo[k] >= histo[i]}
295 ensures {result < histo.length -1 -> histo[result+1] < histo[i]}
296 ensures {i <= result < histo.length}
297 ensures {result = r[i]}
298 = calculeR_aux i histo r
301 let calculeLR i histo l r
302 requires {r.length = histo.length}
303 requires {l.length = histo.length}
304 requires {0 <= i < histo.length }
306 let (li, ri) = result in forall k. li <= k <= ri -> histo[i] <= histo[k]}
307 = (calculeL i histo l, calculeR i histo r)
310 predicate is_li (i j: int) (histo : array int) =
311 0 <= j <= i < histo.length /\
312 (forall k. j <= k <= i -> histo[k] >= histo[i]) /\
313 (j > 0 -> histo[j-1] < histo[i])
317 let histo = make 8 0 in
319 histo[0] <- 3; histo[1] <- 1; histo[2] <- 2; histo[3] <- 4;
320 histo[4] <- 2; histo[5] <- 2; histo[6] <- 0; histo[7] <- 1;
321 let l0 = calculeL 0 histo l in
322 assert {l0 = 0 /\ is_li 0 0 histo};
323 let l1 = calculeL 1 histo l in
324 assert {l1 = 0 /\ is_li 1 0 histo};
325 let l2 = calculeL 2 histo l in
326 assert {histo[1] < histo[2]};
327 assert {not is_li 2 1 histo};
328 assert {l2 = 2 /\ is_li 2 2 histo};
329 let l3 = calculeL 3 histo l in
330 assert {l3 = 3 /\ is_li 3 3 histo};
331 let l4 = calculeL 4 histo l in
332 assert {l4 = 2 /\ is_li 4 2 histo};
333 let l5 = calculeL 5 histo l in
334 assert {l5 = 2 /\ is_li 5 2 histo};
335 let l6 = calculeL 6 histo l in
336 assert {l6 = 0 /\ is_li 6 0 histo};
337 let l7 = calculeL 7 histo l in
338 assert {l7 = 7 /\ is_li 7 7 histo};
339 assert {not is_li 7 6 histo};
340 assert {not is_li 7 5 histo};
341 assert {not is_li 7 2 histo};
348 requires {l.length > 0}
349 requires {l.length = histo.length}
350 requires {0 <= i < histo.length}
351 ensures {0 <= result <= i }
354 let li = (aux i i (k-1)) in
359 requires { l.length > 0 }
361 requires { l.length = histo.length }
362 requires { 0 <= i < histo.length }
363 requires { 0 <= j < histo.length }
364 requires { 0 <= j <= i}
365 ensures { 0 <= result <= j}
371 if histo[j-1] < histo[i]
373 else aux i (calcule (j-1) (k-1)) (k-1)
376 (* ((ri < histo.length -1 -> histo[ri+1] < histo[i]) /\ *)
377 (* li > 0 -> histo[li-1] < histo[i]) /\
378 (i <= ri < histo.length) /\
380 (*(* Partie II. De la 1D vers la 2D *)
381 module recherche_bidimen
387 predicate is_li (i j: int) (histo : array int) =
388 0 <= j <= i < histo.length /\
389 (forall k. j <= k <= i -> histo[k] >= histo[i]) /\
390 (j > 0 -> histo[j-1] < histo[i])
392 let rec f i j histo l =
393 requires {l.length = histo.length}
394 requires {forall k. j <= k <= i -> histo[k] >= histo[i]}
395 requires {0 <= j <= i < histo.length }
396 ensures {is_li i result histo}
397 ensures {result = l[i]}
401 else if histo[j-1] < histo[i] then j
402 else f i (f (j-1) (j-1) histo l) histo l
405 let calculeL i histo l =
406 requires {0 <= i < histo.length}
407 requires {l.length = histo.length}
408 ensures {is_li i result histo}
409 ensures {result = l[i]}
414 let histo = make 8 0 in
416 histo[0] <- 3; histo[1] <- 1; histo[2] <- 2; histo[3] <- 4;
417 histo[4] <- 2; histo[5] <- 2; histo[6] <- 0; histo[7] <- 1;
418 let l0 = calculeL 0 histo l in
419 assert {l0 = 0 /\ is_li 0 0 histo};
420 let l1 = calculeL 1 histo l in
421 assert {l1 = 0 /\ is_li 1 0 histo};
422 let l2 = calculeL 2 histo l in
423 assert {histo[1] < histo[2]};
424 assert {not is_li 2 1 histo};
425 assert {l2 = 2 /\ is_li 2 2 histo};
426 let l3 = calculeL 3 histo l in
427 assert {l3 = 3 /\ is_li 3 3 histo};
428 let l4 = calculeL 4 histo l in
429 assert {l4 = 2 /\ is_li 4 2 histo};
430 let l5 = calculeL 5 histo l in
431 assert {l5 = 2 /\ is_li 5 2 histo};
432 let l6 = calculeL 6 histo l in
433 assert {l6 = 0 /\ is_li 6 0 histo};
434 let l7 = calculeL 7 histo l in
435 assert {l7 = 7 /\ is_li 7 7 histo};
436 assert {not is_li 7 6 histo};
437 assert {not is_li 7 5 histo};
438 assert {not is_li 7 2 histo};
449 predicate is_li (i j: int) (histo : array int) =
450 0 <= j <= i < histo.length /\
451 (forall k. j <= k <= i -> histo[k] >= histo[i]) /\
452 (j > 0 -> histo[j-1] < histo[i])
454 let rec calculeL_aux i histo l
455 requires {l.length = histo.length}
456 requires {0 <= i < histo.length }
457 ensures {is_li i result histo}
458 ensures {result = l[i]}
462 while !j > 0 && histo[!j-1] >= histo[i] do
464 invariant {forall k. !j <= k <= i -> histo[k] >= histo[i]}
465 invariant {0 <= !j <= i }
466 j := calculeL_aux (!j-1) histo l
470 let calculeL i histo l
471 requires {l.length = histo.length}
472 requires {0 <= i < histo.length }
473 ensures {is_li i result histo}
474 ensures {result = l[i]}
475 = calculeL_aux i histo l
478 let histo = make 8 0 in
480 histo[0] <- 3; histo[1] <- 1; histo[2] <- 2; histo[3] <- 4;
481 histo[4] <- 2; histo[5] <- 2; histo[6] <- 0; histo[7] <- 1;
482 let l0 = calculeL 0 histo l in
483 assert {l0 = 0 /\ is_li 0 0 histo};
484 let l1 = calculeL 1 histo l in
485 assert {l1 = 0 /\ is_li 1 0 histo};
486 let l2 = calculeL 2 histo l in
487 assert {histo[1] < histo[2]};
488 assert {not is_li 2 1 histo};
489 assert {l2 = 2 /\ is_li 2 2 histo};
490 let l3 = calculeL 3 histo l in
491 assert {l3 = 3 /\ is_li 3 3 histo};
492 let l4 = calculeL 4 histo l in
493 assert {l4 = 2 /\ is_li 4 2 histo};
494 let l5 = calculeL 5 histo l in
495 assert {l5 = 2 /\ is_li 5 2 histo};
496 let l6 = calculeL 6 histo l in
497 assert {l6 = 0 /\ is_li 6 0 histo};
498 let l7 = calculeL 7 histo l in
499 assert {l7 = 7 /\ is_li 7 7 histo};
500 assert {not is_li 7 6 histo};
501 assert {not is_li 7 5 histo};
502 assert {not is_li 7 2 histo};