package sv_esc; /* Solution: */ class Bag { int[] contents; //@ invariant contents != null; int n; //@ invariant 0 <= n; //@ invariant n <= contents.length; //@ requires input != null; Bag(int[] input) { n = input.length; contents = new int[n]; arraycopy(input, 0, contents, 0, n); } //@ requires b != null; Bag(Bag b) { contents = new int[0]; // error in code corrected this.add(b); } void removeOnce(int elt) { for (int i = 0; i < n; i++) { // error in code corrected if (contents[i] == elt ) { n--; contents[i] = contents[n]; return; } } } void removeAll(int elt) { // @ loop_invariant i>=0 && i<=n+1; for (int i = 0; i < n; i++) { // error in code corrected if (contents[i] == elt ) { n--; contents[i] = contents[n]; } } } //@ ensures \result >= 0; /*@ pure @*/ int getCount(int elt) { int count = 0; //@ loop_invariant i>=0 && i<=n; //@ loop_invariant count >= 0; for (int i = 0; i < n; i++) if (contents[i] == elt) count++; return count; } void add(int elt) { if (n == contents.length) { int[] new_contents = new int[2*n+1]; // error in code corrected //@ assert new_contents.length == 2*n+1 ; // this should not fail? //@ assert n >= 0; //@ assert 2*n+1 > n; //@ assert n < new_contents.length; arraycopy(contents, 0, new_contents, 0, n); contents = new_contents; } contents[n]=elt; n++; } //@ requires b != null; void add(Bag b) { int[] new_contents = new int[n+b.n]; arraycopy(this.contents, 0, new_contents, 0, n); arraycopy(b.contents, 0, new_contents, n, b.n); contents = new_contents; } //@ requires src != null; //@ requires srcOff >=0; //@ requires dest != null; //@ requires destOff >=0; //@ requires length >=0; //@ requires srcOff + length <= src.length; //@ requires destOff + length <= dest.length; //@ assignable dest[*]; private static void arraycopy(int[] src, int srcOff, int[] dest, int destOff, int length) { /*@ loop_invariant i>=0 && i<=length; @*/ for( int i=0 ; i<length; i++) { dest[destOff+i] = src[srcOff+i]; } } }