@@ -5,11 +5,190 @@ HumanEval/34
55/*
66### VERUS BEGIN
77*/
8+ use vstd:: calc;
89use vstd:: prelude:: * ;
10+ use vstd:: seq_lib:: lemma_multiset_commutative;
11+ use vstd:: seq_lib:: lemma_seq_contains_after_push;
912
1013verus ! {
1114
12- // TODO: Put your solution (the specification, implementation, and proof) to the task here
15+ proof fn swap_preserves_multiset_helper( s: Seq <i32 >, i: int, j: int)
16+ requires
17+ 0 <= i < j < s. len( ) ,
18+ ensures
19+ ( s. take( j + 1 ) ) . to_multiset( ) =~= s. take( i) . to_multiset( ) . add(
20+ s. subrange( i + 1 , j) . to_multiset( ) ,
21+ ) . insert( s. index( j) ) . insert( s. index( i) ) ,
22+ {
23+ let fst = s. take( i) ;
24+ let snd = s. subrange( i + 1 , j) ;
25+
26+ assert( ( s. take( j + 1 ) ) . to_multiset( ) =~= fst. to_multiset( ) . insert( s. index( i) ) . add(
27+ snd. to_multiset( ) . insert( s. index( j) ) ,
28+ ) ) by {
29+ assert( s. take( i + 1 ) . to_multiset( ) =~= fst. to_multiset( ) . insert( s. index( i) ) ) by {
30+ fst. to_multiset_ensures( ) ;
31+ assert( fst. push( s. index( i) ) =~= s. take( i + 1 ) ) ;
32+ }
33+ assert( s. subrange( i + 1 , j + 1 ) . to_multiset( ) =~= snd. to_multiset( ) . insert( s. index( j) ) ) by {
34+ snd. to_multiset_ensures( ) ;
35+ assert( snd. push( s. index( j) ) =~= s. subrange( i + 1 , j + 1 ) ) ;
36+ }
37+ lemma_multiset_commutative( s. take( i + 1 ) , s. subrange( i + 1 , j + 1 ) ) ;
38+ assert( s. take( i + 1 ) + s. subrange( i + 1 , j + 1 ) =~= s. take( j + 1 ) ) ;
39+ }
40+ }
41+
42+ // Helper lemma to prove that swapping two elements doesn't change the multiset
43+ proof fn swap_preserves_multiset( s1: Seq <i32 >, s2: Seq <i32 >, i: int, j: int)
44+ requires
45+ 0 <= i < j < s1. len( ) == s2. len( ) ,
46+ forall|x: int| 0 <= x < s1. len( ) && x != i && x != j ==> s1. index( x) == s2. index( x) ,
47+ s1. index( i) == s2. index( j) ,
48+ s1. index( j) == s2. index( i) ,
49+ ensures
50+ s1. to_multiset( ) == s2. to_multiset( ) ,
51+ {
52+ calc! {
53+ ( ==)
54+ s1. to_multiset( ) ; {
55+ lemma_multiset_commutative( s1. take( j + 1 ) , s1. skip( j + 1 ) ) ;
56+ assert( s1 =~= s1. take( j + 1 ) + s1. skip( j + 1 ) ) ;
57+ }
58+ s1. take( j + 1 ) . to_multiset( ) . add( s1. skip( j + 1 ) . to_multiset( ) ) ; {
59+ assert( s1. take( j + 1 ) . to_multiset( ) =~= s2. take( j + 1 ) . to_multiset( ) ) by {
60+ assert( s1. take( i) == s2. take( i) ) ;
61+ assert( s1. subrange( i + 1 , j) =~= ( s2. subrange( i + 1 , j) ) ) ;
62+ swap_preserves_multiset_helper( s1, i, j) ;
63+ swap_preserves_multiset_helper( s2, i, j) ;
64+ }
65+ assert( s1. skip( j + 1 ) . to_multiset( ) =~= s2. skip( j + 1 ) . to_multiset( ) ) by {
66+ assert( s1. skip( j + 1 ) =~= s2. skip( j + 1 ) ) ;
67+ }
68+ }
69+ s2. take( j + 1 ) . to_multiset( ) . add( s2. skip( j + 1 ) . to_multiset( ) ) ; {
70+ lemma_multiset_commutative( s2. take( j + 1 ) , s2. skip( j + 1 ) ) ;
71+ assert( s2 =~= s2. take( j + 1 ) + s2. skip( j + 1 ) ) ;
72+ }
73+ s2. to_multiset( ) ;
74+ }
75+ }
76+
77+ fn sort_seq( s: & Vec <i32 >) -> ( ret: Vec <i32 >)
78+ ensures
79+ forall|i: int, j: int| 0 <= i < j < ret@. len( ) ==> ret@. index( i) <= ret@. index( j) ,
80+ ret@. len( ) == s@. len( ) ,
81+ s@. to_multiset( ) == ret@. to_multiset( ) ,
82+ {
83+ let mut sorted = s. clone( ) ;
84+ let mut i: usize = 0 ;
85+ while i < sorted. len( )
86+ invariant
87+ i <= sorted. len( ) ,
88+ forall|j: int, k: int| 0 <= j < k < i ==> sorted@. index( j) <= sorted@. index( k) ,
89+ s@. to_multiset( ) == sorted@. to_multiset( ) ,
90+ forall|j: int, k: int|
91+ 0 <= j < i <= k < sorted@. len( ) ==> sorted@. index( j) <= sorted@. index( k) ,
92+ sorted@. len( ) == s@. len( ) ,
93+ decreases ( sorted. len( ) - i) ,
94+ {
95+ let mut min_index: usize = i;
96+ let mut j: usize = i + 1 ;
97+ while j < sorted. len( )
98+ invariant
99+ i <= min_index < j <= sorted. len( ) ,
100+ forall|k: int| i <= k < j ==> sorted@. index( min_index as int) <= sorted@. index( k) ,
101+ decreases ( sorted. len( ) - j) ,
102+ {
103+ if sorted[ j] < sorted[ min_index] {
104+ min_index = j;
105+ }
106+ j += 1 ;
107+ }
108+ if min_index != i {
109+ let ghost old_sorted = sorted@;
110+ let curr_val = sorted[ i] ;
111+ let min_val = sorted[ min_index] ;
112+ sorted. set( i, min_val) ;
113+
114+ sorted. set( min_index, curr_val) ;
115+
116+ proof {
117+ swap_preserves_multiset( old_sorted, sorted@, i as int, min_index as int) ;
118+ assert( old_sorted. to_multiset( ) =~= sorted@. to_multiset( ) ) ;
119+ }
120+ }
121+ i += 1 ;
122+ }
123+ sorted
124+ }
125+
126+ fn unique_sorted( s: Vec <i32 >) -> ( result: Vec <i32 >)
127+ requires
128+ forall|i: int, j: int| 0 <= i < j < s. len( ) ==> s[ i] <= s[ j] ,
129+ ensures
130+ forall|i: int, j: int| 0 <= i < j < result. len( ) ==> result[ i] < result[ j] ,
131+ forall|i: int| #![ auto] 0 <= i < result. len( ) ==> s@. contains( result[ i] ) ,
132+ forall|i: int| #![ trigger s[ i] ] 0 <= i < s. len( ) ==> result@. contains( s[ i] ) ,
133+ {
134+ let mut result: Vec <i32 > = vec![ ] ;
135+ for i in 0 ..s. len( )
136+ invariant
137+ forall|i: int, j: int| 0 <= i < j < s. len( ) ==> s[ i] <= s[ j] ,
138+ forall|k: int, l: int| 0 <= k < l < result. len( ) ==> result[ k] < result[ l] ,
139+ forall|k: int|
140+ #![ trigger result[ k] ]
141+ 0 <= k < result. len( ) ==> ( exists|m: int| 0 <= m < i && result[ k] == s[ m] ) ,
142+ forall|m: int| #![ trigger s[ m] ] 0 <= m < i ==> result@. contains( s[ m] ) ,
143+ {
144+ let ghost pre = result;
145+ if result. len( ) == 0 || result[ result. len( ) - 1 ] != s[ i] {
146+ assert( result. len( ) == 0 || result[ result. len( ) - 1 ] < s[ i as int] ) ;
147+ result. push( s[ i] ) ;
148+ assert forall|m: int| #![ trigger s[ m] ] 0 <= m < i implies result@. contains( s[ m] ) by {
149+ assert( pre@. contains( s@[ m] ) ) ;
150+ lemma_seq_contains_after_push( pre@, s@[ i as int] , s@[ m] ) ;
151+ } ;
152+ }
153+ assert( forall|m: int|
154+ #![ trigger result@[ m] , pre@[ m] ]
155+ 0 <= m < pre. len( ) ==> pre@. contains( result@[ m] ) ==> result@. contains( pre@[ m] ) ) by {
156+ assert( forall|m: int| 0 <= m < pre. len( ) ==> result@[ m] == pre@[ m] ) ;
157+ }
158+ assert( result@. contains( s[ i as int] ) ) by {
159+ assert( result[ result. len( ) - 1 ] == s[ i as int] ) ;
160+ }
161+ }
162+ result
163+ }
164+
165+ fn unique( s: Vec <i32 >) -> ( result: Vec <i32 >)
166+ ensures
167+ forall|i: int, j: int| 0 <= i < j < result. len( ) ==> result[ i] < result[ j] ,
168+ forall|i: int| #![ auto] 0 <= i < result. len( ) ==> s@. contains( result[ i] ) ,
169+ forall|i: int| #![ trigger s[ i] ] 0 <= i < s. len( ) ==> result@. contains( s[ i] ) ,
170+ {
171+ let sorted = sort_seq( & s) ;
172+ assert( forall|i: int| #![ auto] 0 <= i < sorted. len( ) ==> s@. contains( sorted[ i] ) ) by {
173+ assert( forall|i: int|
174+ #![ auto]
175+ 0 <= i < sorted. len( ) ==> sorted@. to_multiset( ) . contains( sorted[ i] ) ) by {
176+ sorted@. to_multiset_ensures( ) ;
177+ }
178+ assert( forall|i: int|
179+ #![ auto]
180+ 0 <= i < sorted. len( ) ==> s@. to_multiset( ) . contains( sorted[ i] ) ) ;
181+ s@. to_multiset_ensures( ) ;
182+ }
183+ assert( forall|i: int| #![ trigger s[ i] ] 0 <= i < s. len( ) ==> sorted@. contains( s[ i] ) ) by {
184+ assert( forall|i: int| #![ auto] 0 <= i < s. len( ) ==> s@. to_multiset( ) . contains( s[ i] ) ) by {
185+ s@. to_multiset_ensures( ) ;
186+ }
187+ assert( forall|i: int| #![ auto] 0 <= i < s. len( ) ==> sorted@. to_multiset( ) . contains( s[ i] ) ) ;
188+ sorted@. to_multiset_ensures( ) ;
189+ }
190+ unique_sorted( sorted)
191+ }
13192
14193} // verus!
15194fn main ( ) { }
0 commit comments