Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More tasks completed #12

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
44 changes: 43 additions & 1 deletion tasks/human_eval_098.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,52 @@ HumanEval/98
### VERUS BEGIN
*/
use vstd::prelude::*;
use vstd::set::group_set_axioms;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
broadcast use group_set_axioms;

spec fn spec_is_upper_vowel(c: char) -> bool {
c == 'A' || c == 'E' || c == 'U' || c == 'I' || c == 'O'
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
}

fn is_upper_vowel(c: char) -> (is: bool)
ensures
is <==> spec_is_upper_vowel(c),
{
c == 'A' || c == 'E' || c == 'U' || c == 'I' || c == 'O'
}

#[verifier::loop_isolation(false)]
fn count_upper(s: &[char]) -> (cnt: usize)
ensures
cnt == Set::new(|i: int| 0 <= i < s.len() && i % 2 == 0 && spec_is_upper_vowel(s[i])).len(),
{
let ghost mut found = set![];
let mut cnt = 0;
for i in 0..s.len()
invariant
found.len() <= i,
found.finite(),
cnt == found.len(),
found =~= Set::new(|j: int| 0 <= j < i && j % 2 == 0 && spec_is_upper_vowel(s[j])),
{
if i % 2 == 0 && is_upper_vowel(s[i]) {
cnt = cnt + 1;
proof {
assert(!(0 <= i < i && i % 2 == 0 && spec_is_upper_vowel(s[i as int]))) by {
assert(!(0 <= i < i));
};
assert(found.insert(i as int).len() == found.len() + 1) by {
assert(!found.contains(i as int));
}
found = found.insert(i as int);
}
}
}
cnt
}

} // verus!
fn main() {}
Expand Down
25 changes: 24 additions & 1 deletion tasks/human_eval_100.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,30 @@ use vstd::prelude::*;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
fn make_a_pile(n: usize) -> (pile: Vec<usize>)
requires
n + (2 * n) <= usize::MAX,
ensures
pile.len() == n,
n > 0 ==> pile[0] == n,
forall|i: int| #![trigger pile[i]] 1 <= i < n ==> pile[i] == pile[i - 1] + 2,
{
if n == 0 {
return vec![];
}
let mut pile = vec![n];
for i in 1..n
invariant
pile.len() == i,
pile[i - 1] + (2 * (n - i)) <= usize::MAX,
forall|j: int| #![trigger pile[j]] 1 <= j < i ==> pile[j] == pile[j - 1] + 2,
n > 0 ==> pile[0] == n,
{
let prev = pile[i - 1];
pile.push(prev + 2);
}
pile
}

} // verus!
fn main() {}
Expand Down
20 changes: 19 additions & 1 deletion tasks/human_eval_102.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,25 @@ use vstd::prelude::*;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
fn choose_num(x: u32, y: u32) -> (ret: i32)
requires
x >= 0 && y >= 0,
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
x <= i32::MAX && y <= i32::MAX,
ensures
ret != -1 ==> (ret >= x && ret <= y),
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
ret != -1 ==> ret % 2 == 0,
ret != -1 ==> (forall|i: int| #![trigger i % 2] (x <= i <= y && i % 2 == 0) ==> i <= ret),
(ret == -1) <==> forall|i: int| #![trigger i % 2] x <= i <= y ==> i % 2 == 1,
{
if x > y || (x == y && y % 2 == 1) {
return -1;
}
(if y % 2 == 0 {
y
} else {
y - 1
}) as i32
}

} // verus!
fn main() {}
Expand Down
101 changes: 100 additions & 1 deletion tasks/human_eval_127.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,106 @@ use vstd::prelude::*;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
spec fn spec_min(a: int, b: int) -> int {
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
if a < b {
a
} else {
b
}
}

fn min(a: i32, b: i32) -> (m: i32)
ensures
m == a || m == b,
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
m <= a && m <= b,
m == spec_min(a as int, b as int),
{
if a < b {
a
} else {
b
}
}

spec fn spec_max(a: int, b: int) -> int {
if a > b {
a
} else {
b
}
}

fn max(a: i32, b: i32) -> (m: i32)
ensures
m == a || m == b,
m >= a && m >= b,
m == spec_max(a as int, b as int),
{
if a > b {
a
} else {
b
}
}

spec fn spec_prime_helper(num: int, limit: int) -> bool {
forall|j: int| 2 <= j < limit ==> (#[trigger] (num % j)) != 0
}

spec fn spec_prime(num: int) -> bool {
num >= 2 && spec_prime_helper(num, num)
}

fn is_prime_2(num: u32) -> (result: bool)
requires
num >= 2,
ensures
result <==> spec_prime(num as int),
{
let mut i = 2;
let mut result = true;
while i < num
invariant
2 <= i <= num,
result <==> spec_prime_helper(num as int, i as int),
{
if num % i == 0 {
result = false;
}
i += 1;
}
result
}

fn is_prime(num: i32) -> (is: bool)
requires
num >= 0,
ensures
is <==> (num >= 2 && spec_prime(num as int)),
{
num >= 2 && is_prime_2(num as u32)
}

fn intersection(a: (i32, i32), b: (i32, i32)) -> (result: &'static str)
requires
a.0 <= a.1 && b.0 <= b.1,
a.1 - a.0 + 1 <= i32::MAX && b.1 - b.0 + 1 <= i32::MAX,
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
ensures
result == "YES" || result == "NO",
result == "YES" <==> ((spec_max(a.0 as int, b.0 as int) <= spec_min(a.1 as int, b.1 as int))
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
&& spec_prime(
(spec_min(a.1 as int, b.1 as int) - spec_max(a.0 as int, b.0 as int) + 1) as int,
)),
{
let sect_start = max(a.0, b.0);
let sect_end = min(a.1, b.1);

if sect_start < sect_end && is_prime(sect_end - sect_start + 1) {
"YES"
} else {
"NO"
}
}

} // verus!
fn main() {}
Expand Down
88 changes: 87 additions & 1 deletion tasks/human_eval_130.rs
WeetHet marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,93 @@ use vstd::prelude::*;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
spec fn spec_tri(n: nat) -> nat
by (nonlinear_arith)
decreases
if n % 2 == 0 {
0
} else {
n
},
{
if n == 1 {
3
} else if n % 2 == 0 {
1 + n / 2
} else {
spec_tri((n - 1) as nat) + spec_tri((n - 2) as nat) + spec_tri(n + 1)
}
}

fn checked_add_three(a: Option<u32>, b: Option<u32>, c: Option<u32>) -> (r: Option<u32>)
by (nonlinear_arith)
ensures
r.is_some() && a.is_some() && b.is_some() && c.is_some() ==> r.unwrap() == a.unwrap()
+ b.unwrap() + c.unwrap(),
a.is_none() || b.is_none() || c.is_none() ==> r.is_none(),
{
a?.checked_add(b?)?.checked_add(c?)
}

#[verifier::loop_isolation(false)]
fn tri(n: u32) -> (result: Vec<Option<u32>>)
by (nonlinear_arith)
requires
n + 1 <= u32::MAX,
ensures
result.len() == n + 1,
forall|i: int|
#![trigger result[i]]
0 <= i < result.len() ==> result[i].is_some() ==> result[i].unwrap() == spec_tri(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we strengthen the None case to say that None implies that spec_tri(i) > u32::MAX?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, but I don't think it's very easy to prove that

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be straightforward to prove that spec_tri is monotonic, which then means that if you locally discover that your computation of spec_tri(x) overflows (i.e., doesn't stay in bounds), then you can use the monotonic property to say that spec_tri(n) for any n > x would also overflow, so you're justified in returning None

i as nat,
),
{
if n == 0 {
vec![Some(1)]
} else {
let mut result: Vec<Option<u32>> = vec![Some(1), Some(3)];
let mut i = 2;
while i <= n
invariant
2 <= i <= n + 1,
result.len() == i,
forall|j: int|
#![trigger result[j]]
0 <= j < i ==> (result[j].is_some() ==> result[j].unwrap() == spec_tri(
j as nat,
)),
{
if i % 2 == 0 {
result.push(Some(1 + (i / 2)));
assert(result[i as int].unwrap() == spec_tri(i as nat));
} else {
assert((i + 1) / 2 + 1 == (i + 3) / 2);
let cur = checked_add_three(
result[i as usize - 2],
result[i as usize - 1],
Some((i + 1) / 2 + 1),
);
proof {
if result[i - 2].is_some() && result[i - 1].is_some() {
assert(result[i - 2].unwrap() == spec_tri((i - 2) as nat));
assert(result[i - 1].unwrap() == spec_tri((i - 1) as nat));
assert((i + 3) / 2 == spec_tri((i + 1) as nat));
} else {
assert(cur.is_none());
}
assert(cur.is_some() ==> cur.unwrap() == spec_tri(i as nat));
}
result.push(cur);
assert(result[i as int].is_some() ==> result[i as int].unwrap() == spec_tri(
i as nat,
));
}
i += 1;
}
assert(result.len() == n + 1);
result
}
}

} // verus!
fn main() {}
Expand Down
27 changes: 26 additions & 1 deletion tasks/human_eval_135.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,32 @@ use vstd::prelude::*;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
#[verifier::loop_isolation(false)]
fn can_arrange(arr: &Vec<i32>) -> (pos: i32)
requires
forall|i: int, j: int| 0 <= i < j < arr.len() ==> arr[i] != arr[j],
arr.len() + 1 < i32::MAX,
ensures
pos == -1 ==> forall|i: int| #![trigger arr[i]] 1 <= i < arr.len() ==> arr[i] >= arr[i - 1],
pos >= 0 ==> 1 <= pos < arr.len() && arr[pos as int] < arr[pos - 1],
pos >= 0 ==> forall|i: int| #![trigger arr[i]] pos < i < arr.len() ==> arr[i] >= arr[i - 1],
{
if arr.len() == 0 {
return -1;
}
let mut pos = -1;
for i in 1..arr.len()
invariant
pos == -1 ==> forall|j: int| #![trigger arr[j]] 1 <= j < i ==> arr[j] >= arr[j - 1],
pos >= 0 ==> 1 <= pos < i && arr[pos as int] < arr[pos - 1],
pos >= 0 ==> forall|j: int| #![trigger arr[j]] pos < j < i ==> arr[j] >= arr[j - 1],
{
if arr[i] < arr[i - 1] {
pos = i as i32;
}
}
pos
}

} // verus!
fn main() {}
Expand Down
7 changes: 6 additions & 1 deletion tasks/human_eval_138.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ use vstd::prelude::*;

verus! {

// TODO: Put your solution (the specification, implementation, and proof) to the task here
fn is_equal_to_sum_even(n: u32) -> (b: bool) // 2 + 2 + 2 + (n - 6)
ensures
b <==> n % 2 == 0 && n >= 8,
{
n % 2 == 0 && n >= 8
}

} // verus!
fn main() {}
Expand Down
Loading