Skip to content

Commit

Permalink
96, 97, 100, 104, 110, 118, 122, 127 (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
WeetHet authored Aug 9, 2024
1 parent 4ce6d01 commit 2de9a2e
Show file tree
Hide file tree
Showing 10 changed files with 320 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
**/.DS_Store
.vscode
27 changes: 27 additions & 0 deletions 096-count_up_to.dfy
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;
}
}
14 changes: 14 additions & 0 deletions 097-multiply.dfy
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);
}
22 changes: 22 additions & 0 deletions 100-make_a_pile.dfy
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;
}
}
59 changes: 59 additions & 0 deletions 104-unique_digits.dfy
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);
}
}
24 changes: 24 additions & 0 deletions 110-exchange.dfy
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";
}
}
37 changes: 37 additions & 0 deletions 118-get_closest_vowel.dfy
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 "";
}
79 changes: 79 additions & 0 deletions 122-add_elements.dfy
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;
}
50 changes: 50 additions & 0 deletions 127-intersection.dfy
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";
}
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ Current status:
- [ ] 93. encode
- [ ] 94. skjkasdkd
- [x] 95. check_dict_case
- [ ] 96. count_up_to
- [ ] 97. multiply
- [x] 96. count_up_to
- [x] 97. multiply
- [ ] 98. count_upper
- [ ] 99. closest_integer
- [ ] 100. make_a_pile
- [x] 100. make_a_pile
- [ ] 101. words_string
- [x] 102. choose_num
- [ ] 103. rounded_avg
Expand All @@ -112,24 +112,24 @@ Current status:
- [ ] 107. even_odd_palindrome
- [ ] 108. count_nums
- [ ] 109. move_one_ball
- [ ] 110. exchange
- [x] 110. exchange
- [ ] 111. histogram
- [ ] 112. reverse_delete
- [ ] 113. odd_count
- [ ] 114. minSubArraySum
- [ ] 115. max_fill
- [ ] 116. sort_array
- [ ] 117. select_words
- [ ] 118. get_closest_vowel
- [x] 118. get_closest_vowel
- [ ] 119. match_parens
- [ ] 120. maximum
- [ ] 121. solution
- [ ] 122. add_elements
- [x] 122. add_elements
- [ ] 123. get_odd_collatz
- [ ] 124. valid_date
- [ ] 125. split_words
- [ ] 126. is_sorted
- [ ] 127. intersection
- [x] 127. intersection
- [ ] 128. prod_signs
- [ ] 129. minPath
- [x] 130. tri
Expand Down

0 comments on commit 2de9a2e

Please sign in to comment.