2011-05-15 22:41:28 +02:00
|
|
|
|
|
|
|
|
(*
|
|
|
|
|
We look for the first occurrence of zero in an array of integers.
|
|
|
|
|
The values have the following property: they never decrease by more than one.
|
|
|
|
|
The code makes use of that property to speed up the search.
|
|
|
|
|
*)
|
|
|
|
|
|
|
|
|
|
module Decrease1
|
|
|
|
|
|
|
|
|
|
use import int.Int
|
2011-05-16 18:02:53 +02:00
|
|
|
use import module ref.Ref
|
|
|
|
|
use import module array.Array
|
2011-05-15 22:41:28 +02:00
|
|
|
|
2011-06-29 19:13:18 +02:00
|
|
|
predicate decrease1 (a: array int) =
|
2011-05-19 18:24:09 +02:00
|
|
|
forall i: int. 0 <= i < length a - 1 -> a[i+1] >= a[i] - 1
|
2011-05-15 22:41:28 +02:00
|
|
|
|
|
|
|
|
lemma decrease1_induction:
|
|
|
|
|
forall a: array int. decrease1 a ->
|
|
|
|
|
forall i j: int. 0 <= i <= j < length a -> a[j] >= a[i] + i - j
|
|
|
|
|
|
2011-05-16 14:28:44 +02:00
|
|
|
exception Found
|
2011-05-15 22:41:28 +02:00
|
|
|
|
|
|
|
|
let search (a: array int) =
|
|
|
|
|
{ decrease1 a }
|
|
|
|
|
let i = ref 0 in
|
2011-05-16 14:28:44 +02:00
|
|
|
try
|
|
|
|
|
while !i < length a do
|
2011-06-29 19:13:18 +02:00
|
|
|
invariant { 0 <= !i /\
|
2011-05-19 18:24:09 +02:00
|
|
|
forall j: int. 0 <= j < !i -> j < length a -> a[j] <> 0 }
|
|
|
|
|
variant { length a - !i }
|
2011-05-16 15:59:52 +02:00
|
|
|
if a[!i] = 0 then raise Found;
|
|
|
|
|
if a[!i] > 0 then i := !i + a[!i] else i := !i + 1
|
2011-05-16 14:28:44 +02:00
|
|
|
done;
|
|
|
|
|
-1
|
2011-05-19 18:24:09 +02:00
|
|
|
with Found ->
|
2011-05-16 14:28:44 +02:00
|
|
|
!i
|
|
|
|
|
end
|
2011-06-29 19:13:18 +02:00
|
|
|
{ (result = -1 /\ forall j: int. 0 <= j < length a -> a[j] <> 0)
|
|
|
|
|
\/ (0 <= result < length a /\ a[result] = 0 /\
|
2011-05-16 14:28:44 +02:00
|
|
|
forall j: int. 0 <= j < result -> a[j] <> 0) }
|
|
|
|
|
|
|
|
|
|
let rec search_rec (a: array int) (i : int) =
|
2011-06-29 19:13:18 +02:00
|
|
|
{ decrease1 a /\ 0 <= i }
|
2011-05-16 14:28:44 +02:00
|
|
|
if i < length a then
|
2011-05-16 15:59:52 +02:00
|
|
|
if a[i] = 0 then i
|
2011-05-19 18:24:09 +02:00
|
|
|
else if a[i] > 0 then search_rec a (i + a[i])
|
2011-05-16 14:28:44 +02:00
|
|
|
else search_rec a (i + 1)
|
|
|
|
|
else
|
|
|
|
|
-1
|
2011-06-29 19:13:18 +02:00
|
|
|
{ (result = -1 /\ forall j: int. i <= j < length a -> a[j] <> 0)
|
|
|
|
|
\/ (i <= result < length a /\ a[result] = 0 /\
|
2011-05-16 14:28:44 +02:00
|
|
|
forall j: int. i <= j < result -> a[j] <> 0) }
|
2011-05-15 22:41:28 +02:00
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
(*
|
2011-05-19 18:24:09 +02:00
|
|
|
Local Variables:
|
2011-05-15 22:41:28 +02:00
|
|
|
compile-command: "unset LANG; make -C ../.. examples/programs/decrease1.gui"
|
2011-05-19 18:24:09 +02:00
|
|
|
End:
|
2011-05-15 22:41:28 +02:00
|
|
|
*)
|