| [2fa0abd] | 1 | /*
|
|---|
| 2 | COST Verification Competition. vladimir@cost-ic0701.org
|
|---|
| 3 |
|
|---|
| 4 | Challenge 3: Two equal elements
|
|---|
| 5 |
|
|---|
| 6 | Given: An integer array a of length n+2 with n>=2. It is known that at
|
|---|
| 7 | least two values stored in the array appear twice (i.e., there are at
|
|---|
| 8 | least two duplets).
|
|---|
| 9 |
|
|---|
| 10 | Implement and verify a program finding such two values.
|
|---|
| 11 |
|
|---|
| 12 | You may assume that the array contains values between 0 and n-1.
|
|---|
| 13 | */
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 | #define NULL (void*)0
|
|---|
| 17 |
|
|---|
| 18 | /* equality between an integer and a possibly null int* */
|
|---|
| 19 | /*@ predicate eq_opt{L}(integer x, int *o) =
|
|---|
| 20 | @ o != \null && x == *o ;
|
|---|
| 21 | @*/
|
|---|
| 22 |
|
|---|
| 23 | /* A duplet in array a is a pair of indexes (i,j) in the bounds of array
|
|---|
| 24 | a such that a[i] = a[j] */
|
|---|
| 25 | /*@ predicate is_duplet{L}(int *a, integer len, integer i, integer j) =
|
|---|
| 26 | @ 0 <= i < j < len && a[i] == a[j];
|
|---|
| 27 | @*/
|
|---|
| 28 |
|
|---|
| 29 | /* duplet(a) returns the indexes (i,j) of a duplet in a.
|
|---|
| 30 | * moreover, if except is not null, the value of this duplet must
|
|---|
| 31 | * be different from it.
|
|---|
| 32 | */
|
|---|
| 33 | /*@ requires 2 <= len &&
|
|---|
| 34 | @ \valid_range(a,0,len-1) && \valid(pi) && \valid(pj) &&
|
|---|
| 35 | @ ( except == \null || \valid(except)) &&
|
|---|
| 36 | @ \exists integer i,j;
|
|---|
| 37 | @ is_duplet(a,len,i,j) && ! eq_opt(a[i],except) ;
|
|---|
| 38 | @ assigns *pi,*pj;
|
|---|
| 39 | @ ensures
|
|---|
| 40 | @ is_duplet(a,len,*pi,*pj) &&
|
|---|
| 41 | @ ! eq_opt(a[*pi],except);
|
|---|
| 42 | @*/
|
|---|
| 43 | void duplet(int *a, int len, int *except, int *pi, int *pj) {
|
|---|
| 44 | /*@ loop invariant 0 <= i <= len-1 &&
|
|---|
| 45 | @ \forall integer k,l; 0 <= k < i && k < l < len ==>
|
|---|
| 46 | @ ! eq_opt(a[k],except) ==> ! is_duplet(a,len,k,l);
|
|---|
| 47 | @ loop variant len - i;
|
|---|
| 48 | @*/
|
|---|
| 49 | for(int i=0; i <= len - 2; i++) {
|
|---|
| 50 | int v = a[i];
|
|---|
| 51 | if (except == NULL || *except != v) {
|
|---|
| 52 | /*@ loop invariant i+1 <= j <= len &&
|
|---|
| 53 | @ \forall integer l; i < l < j ==> ! is_duplet(a,len,i,l);
|
|---|
| 54 | @ loop variant len - j;
|
|---|
| 55 | @*/
|
|---|
| 56 | for (int j=i+1; j < len; j++) {
|
|---|
| 57 | if (a[j] == v) {
|
|---|
| 58 | *pi = i; *pj = j; return;
|
|---|
| 59 | }
|
|---|
| 60 | }
|
|---|
| 61 | }
|
|---|
| 62 | }
|
|---|
| 63 | // assert \forall integer i j; ! is_duplet(a,i,j);
|
|---|
| 64 | //@ assert \false;
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | /*@ requires 4 <= len &&
|
|---|
| 68 | @ \valid_range(a,0,len-1) && \valid(pi) && \valid(pj) &&
|
|---|
| 69 | @ \valid(pk) && \valid(pl) &&
|
|---|
| 70 | @ \exists integer i,j,k,l;
|
|---|
| 71 | @ is_duplet(a,len,i,j) && is_duplet(a,len,k,l) && a[i] != a[k];
|
|---|
| 72 | @ assigns *pi,*pj,*pk,*pl;
|
|---|
| 73 | @ ensures is_duplet(a,len,*pi,*pj) &&
|
|---|
| 74 | @ is_duplet(a,len,*pk,*pl) &&
|
|---|
| 75 | @ a[*pi] != a[*pk];
|
|---|
| 76 | @*/
|
|---|
| 77 | void duplets(int a[], int len, int *pi, int *pj, int *pk, int *pl) {
|
|---|
| 78 | duplet(a,len,NULL,pi,pj);
|
|---|
| 79 | duplet(a,len,&a[*pi],pk,pl);
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|