-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
96, 97, 100, 104, 110, 118, 122, 127 (#8)
- Loading branch information
Showing
10 changed files
with
320 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
**/.DS_Store | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
predicate IsPrime(n: int) | ||
{ | ||
n > 1 && forall k :: 2 <= k < n ==> n % k != 0 | ||
} | ||
|
||
method CountUpTo(n: int) returns (primes: seq<int>) | ||
requires n >= 0 | ||
ensures forall i :: 0 <= i < |primes| ==> IsPrime(primes[i]) | ||
ensures forall i :: 0 <= i < |primes| ==> primes[i] < n | ||
ensures forall p :: 2 <= p < n && IsPrime(p) <==> p in primes | ||
{ | ||
primes := []; | ||
if n <= 2 { return; } | ||
var i := 2; | ||
while i < n | ||
invariant 2 <= i <= n | ||
invariant forall j :: 0 <= j < |primes| ==> IsPrime(primes[j]) | ||
invariant forall j :: 0 <= j < |primes| ==> 2 <= primes[j] < i | ||
invariant forall p :: 2 <= p < i && IsPrime(p) <==> p in primes | ||
invariant forall j, k :: 0 <= j < k < |primes| ==> primes[j] < primes[k] | ||
{ | ||
if IsPrime(i) { | ||
primes := primes + [i]; | ||
} | ||
i := i + 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
function last_digit(n: int): int | ||
ensures n >= 0 ==> last_digit(n) == n % 10 | ||
ensures n < 0 ==> last_digit(n) == (-n) % 10 | ||
{ | ||
if n < 0 then (-n) % 10 else n % 10 | ||
} | ||
|
||
method multiply(a: int, b: int) returns (c: int) | ||
requires a >= 0 | ||
requires b >= 0 | ||
ensures c == last_digit(a) * last_digit(b) | ||
{ | ||
c := last_digit(a) * last_digit(b); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
method make_a_pile(n: int) returns (pile: seq<int>) | ||
requires n >= 0 | ||
ensures |pile| == n | ||
ensures forall i :: 1 <= i < n ==> pile[i] == pile[i - 1] + 2 | ||
ensures n > 0 ==> pile[0] == n | ||
{ | ||
pile := []; | ||
if n == 0 { | ||
return; | ||
} | ||
pile := [n]; | ||
var i := 1; | ||
while i < n | ||
invariant 0 <= i <= n | ||
invariant |pile| == i | ||
invariant forall j :: 1 <= j < i ==> pile[j] == pile[j - 1] + 2 | ||
invariant n > 0 ==> pile[0] == n | ||
{ | ||
pile := pile + [pile[i - 1] + 2]; | ||
i := i + 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
predicate HasNoEvenDigit(n: int) | ||
decreases n | ||
{ | ||
n >= 0 && (n < 10 || (n % 10 % 2 != 0 && HasNoEvenDigit(n / 10))) | ||
} | ||
|
||
method UniqueDigits(x: seq<int>) returns (result: seq<int>) | ||
ensures forall i :: 0 <= i < |result| ==> HasNoEvenDigit(result[i]) | ||
ensures forall i, j :: 0 <= i < j < |result| ==> result[i] <= result[j] | ||
ensures forall e :: e in x && HasNoEvenDigit(e) ==> e in result | ||
ensures forall e :: e in result ==> e in x | ||
{ | ||
result := []; | ||
|
||
for i := 0 to |x| | ||
invariant forall j :: 0 <= j < |result| ==> HasNoEvenDigit(result[j]) | ||
invariant forall e :: e in result ==> e in x[..i] | ||
invariant forall e :: e in x[..i] && HasNoEvenDigit(e) ==> e in result | ||
{ | ||
if HasNoEvenDigit(x[i]) { | ||
result := result + [x[i]]; | ||
} | ||
} | ||
|
||
ghost var unsorted := result; | ||
|
||
var i := 0; | ||
while i < |result| | ||
invariant 0 <= i <= |result| | ||
invariant forall j, k :: 0 <= j < k < i ==> result[j] <= result[k] | ||
invariant multiset(unsorted) == multiset(result) | ||
invariant forall j :: 0 <= j < i ==> forall k :: i <= k < |result| ==> result[j] <= result[k] | ||
invariant forall e :: e in result ==> HasNoEvenDigit(e) | ||
invariant forall e :: e in result ==> e in x | ||
{ | ||
var minIndex := i; | ||
var j := i + 1; | ||
while j < |result| | ||
invariant i <= minIndex < j <= |result| | ||
invariant forall k :: i <= k < j ==> result[minIndex] <= result[k] | ||
{ | ||
if result[j] < result[minIndex] { | ||
minIndex := j; | ||
} | ||
j := j + 1; | ||
} | ||
if minIndex != i { | ||
var temp := result[i]; | ||
result := result[i := result[minIndex]][minIndex := temp]; | ||
} | ||
i := i + 1; | ||
} | ||
|
||
assert forall e :: e in result ==> HasNoEvenDigit(e); | ||
assert forall e :: e in result ==> e in x; | ||
assert forall e :: e in x && HasNoEvenDigit(e) ==> e in result by { | ||
assert forall e :: e in unsorted ==> e in multiset(result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
predicate IsEven(n: int) | ||
{ | ||
n % 2 == 0 | ||
} | ||
|
||
function CountEvens(lst: seq<int>): nat | ||
{ | ||
if |lst| == 0 then 0 | ||
else (if IsEven(lst[0]) then 1 else 0) + CountEvens(lst[1..]) | ||
} | ||
|
||
method Exchange(lst1: seq<int>, lst2: seq<int>) returns (result: string) | ||
requires |lst1| > 0 && |lst2| > 0 | ||
ensures result == "YES" || result == "NO" | ||
ensures result == "YES" ==> CountEvens(lst1) + CountEvens(lst2) >= |lst1| | ||
ensures result == "NO" ==> CountEvens(lst1) + CountEvens(lst2) < |lst1| | ||
{ | ||
var totalEvens := CountEvens(lst1) + CountEvens(lst2); | ||
if totalEvens >= |lst1| { | ||
result := "YES"; | ||
} else { | ||
result := "NO"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
predicate IsVowel(c: char) | ||
{ | ||
c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || | ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' | ||
} | ||
|
||
predicate IsConsonant(c: char) | ||
{ | ||
('A' <= c <= 'Z' || 'a' <= c <= 'z') && !IsVowel(c) | ||
} | ||
|
||
method get_closest_vowel(word: string) returns (result: string) | ||
requires forall i :: 0 <= i < |word| ==> ('A' <= word[i] <= 'Z' || 'a' <= word[i] <= 'z') | ||
ensures |result| <= 1 | ||
ensures |result| == 1 ==> IsVowel(result[0]) | ||
ensures |result| == 1 ==> exists i {:trigger word[i]} :: | ||
1 <= i && i + 1 < |word| | ||
&& IsVowel(word[i]) && IsConsonant(word[i - 1]) && IsConsonant(word[i + 1]) | ||
&& (forall j :: i < j < |word| - 1 ==> !IsVowel(word[j]) || !IsConsonant(word[j - 1]) || !IsConsonant(word[j + 1])) | ||
{ | ||
if |word| < 3 { | ||
return ""; | ||
} | ||
|
||
var i := |word| - 2; | ||
while i > 0 | ||
invariant 0 <= i <= |word| - 2 | ||
invariant forall j :: i < j < |word| - 1 ==> !IsVowel(word[j]) || !IsConsonant(word[j - 1]) || !IsConsonant(word[j + 1]) | ||
{ | ||
if IsVowel(word[i]) && IsConsonant(word[i - 1]) && IsConsonant(word[i + 1]) { | ||
return [word[i]]; | ||
} | ||
i := i - 1; | ||
} | ||
|
||
return ""; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
function select_at_most_two_digits_rec(arr: seq<int>): seq<int> | ||
requires |arr| >= 0 && |arr| <= 100 | ||
{ | ||
if |arr| == 0 then [] | ||
else if 0 <= arr[0] < 100 then [arr[0]] + select_at_most_two_digits_rec(arr[1..]) | ||
else select_at_most_two_digits_rec(arr[1..]) | ||
} | ||
|
||
lemma select_prop(s: seq<int>) | ||
requires |s| > 0 && |s| <= 100 | ||
ensures select_at_most_two_digits_rec(s) == select_at_most_two_digits_rec(s[..|s| - 1]) + if 0 <= s[|s| - 1] < 100 then [s[|s| - 1]] else [] | ||
{ | ||
if (|s| > 1) { | ||
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1]; | ||
} | ||
} | ||
|
||
method select_at_most_two_digits(arr: seq<int>) returns (result: seq<int>) | ||
requires |arr| > 0 && |arr| <= 100 | ||
ensures forall i :: 0 <= i < |result| ==> 0 <= result[i] < 100 | ||
ensures forall i :: 0 <= i < |result| ==> result[i] in arr | ||
ensures result == select_at_most_two_digits_rec(arr) | ||
{ | ||
result := []; | ||
var i := 0; | ||
while i < |arr| | ||
invariant 0 <= i <= |arr| | ||
invariant forall j :: 0 <= j < |result| ==> result[j] in arr | ||
invariant forall j :: 0 <= j < |result| ==> 0 <= result[j] < 100 | ||
invariant |result| <= i | ||
invariant result == select_at_most_two_digits_rec(arr[..i]) | ||
{ | ||
if 0 <= arr[i] < 100 { | ||
result := result + [arr[i]]; | ||
} | ||
assert select_at_most_two_digits_rec(arr[..i + 1]) == select_at_most_two_digits_rec(arr[..i]) + if 0 <= arr[i] < 100 then [arr[i]] else [] by { | ||
assert arr[..i+1][..i] == arr[..i]; | ||
select_prop(arr[..i + 1]); | ||
} | ||
i := i + 1; | ||
} | ||
assert arr[..|arr|] == arr; | ||
} | ||
|
||
function sum(s: seq<int>) : int { | ||
if |s| == 0 then 0 else s[0] + sum(s[1..]) | ||
} | ||
|
||
lemma sum_prop(s: seq<int>) | ||
requires |s| > 0 | ||
ensures sum(s) == sum(s[..|s| - 1]) + s[ |s| - 1 ] | ||
{ | ||
if (|s| > 1) { | ||
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1]; | ||
} | ||
} | ||
|
||
method SumElementsWithAtMostTwoDigits(arr: seq<int>, k: int) returns (s: int) | ||
requires |arr| > 0 && |arr| <= 100 | ||
requires 1 <= k <= |arr| | ||
ensures var two_digits := select_at_most_two_digits_rec(arr[..k]); | ||
s == sum(two_digits) | ||
{ | ||
var two_digits := select_at_most_two_digits(arr[..k]); | ||
s := 0; | ||
var i := 0; | ||
while i < |two_digits| | ||
invariant 0 <= i <= |two_digits| | ||
invariant s == sum(two_digits[..i]) | ||
{ | ||
s := s + two_digits[i]; | ||
assert sum(two_digits[..i + 1]) == sum(two_digits[..i]) + two_digits[i] by { | ||
assert two_digits[..i+1][..i] == two_digits[..i]; | ||
sum_prop(two_digits[..i + 1]); | ||
} | ||
i := i + 1; | ||
} | ||
assert two_digits[..|two_digits|] == two_digits; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
predicate IsPrime(n: nat) | ||
{ | ||
n > 1 && | ||
forall k :: 2 <= k < n ==> n % k != 0 | ||
} | ||
|
||
function min(a: int, b: int): int | ||
{ | ||
if a <= b then a else b | ||
} | ||
|
||
function max(a: int, b: int): int | ||
{ | ||
if a >= b then a else b | ||
} | ||
|
||
method Intersection(start1: int, end1: int, start2: int, end2: int) returns (result: string) | ||
requires start1 <= end1 && start2 <= end2 | ||
ensures result == "YES" || result == "NO" | ||
ensures result == "YES" <==> | ||
(max(start1, start2) <= min(end1, end2) && | ||
IsPrime((min(end1, end2) - max(start1, start2) + 1) as nat)) | ||
{ | ||
var intersectionStart := max(start1, start2); | ||
var intersectionEnd := min(end1, end2); | ||
|
||
if intersectionStart <= intersectionEnd { | ||
var length := (intersectionEnd - intersectionStart + 1) as nat; | ||
if IsPrime(length) { | ||
return "YES"; | ||
} | ||
} | ||
|
||
return "NO"; | ||
} | ||
|
||
method {:test} Main() | ||
{ | ||
var result1 := Intersection(1, 2, 2, 3); | ||
assert result1 == "NO"; | ||
|
||
var result2 := Intersection(-1, 1, 0, 4); | ||
// The intersection is [0, 1], which has length 2, a prime number | ||
assert result2 == "YES"; | ||
|
||
var result3 := Intersection(-3, -1, -5, 5); | ||
assert result3 == "YES"; | ||
|
||
print "All tests passed!\n"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters