Skip to content

Commit

Permalink
049, 073, 081, 089, 108, 114, 128 (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
WeetHet authored Aug 27, 2024
1 parent 81c15b5 commit 719cde8
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 12 deletions.
22 changes: 22 additions & 0 deletions 049-modp.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
function modp_rec(n: int, p: int): int
requires p > 0
requires n >= 0
{
if n == 0 then 1 % p else (modp_rec(n - 1, p) * 2) % p
}

method modp(n: int, p: int) returns (r: int)
requires p > 0
requires n >= 0
ensures r == modp_rec(n, p)
{
r := 1 % p;
var i := 0;
while i < n
invariant 0 <= i <= n
invariant r == modp_rec(i, p)
{
r := (r * 2) % p;
i := i + 1;
}
}
19 changes: 19 additions & 0 deletions 073-smallest_change.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
method smallest_change(s: seq<int>) returns (c: int)
ensures c == |set i {:trigger s[i]} | 0 <= i < |s| / 2 && s[i] != s[|s| - 1 - i]|
{
ghost var pos := {};
c := 0;

var i := 0;
while i < |s| / 2
invariant 0 <= i <= |s| / 2
invariant pos == set j {:trigger s[j]} | 0 <= j < i && s[j] != s[|s| - 1 - j]
invariant c == |pos|
{
if s[i] != s[|s| - 1 - i] {
pos := pos + {i};
c := c + 1;
}
i := i + 1;
}
}
67 changes: 67 additions & 0 deletions 081-numerical_letter_grade.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
method numerical_letter_grade(grades: seq<real>) returns (letters: seq<string>)
requires forall i :: 0 <= i < |grades| ==> 0.0 <= grades[i] <= 4.0
ensures |letters| == |grades|
ensures forall i :: 0 <= i < |grades| && grades[i] == 4.0 ==> letters[i] == "A+"
ensures forall i :: 0 <= i < |grades| && grades[i] < 4.0 && grades[i] > 3.7 ==> letters[i] == "A"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 3.7 && grades[i] > 3.3 ==> letters[i] == "A-"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 3.3 && grades[i] > 3.0 ==> letters[i] == "B+"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 3.0 && grades[i] > 2.7 ==> letters[i] == "B"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 2.7 && grades[i] > 2.3 ==> letters[i] == "B-"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 2.3 && grades[i] > 2.0 ==> letters[i] == "C+"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 2.0 && grades[i] > 1.7 ==> letters[i] == "C"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 1.7 && grades[i] > 1.3 ==> letters[i] == "C-"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 1.3 && grades[i] > 1.0 ==> letters[i] == "D+"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 1.0 && grades[i] > 0.7 ==> letters[i] == "D"
ensures forall i :: 0 <= i < |grades| && grades[i] <= 0.7 && grades[i] > 0.0 ==> letters[i] == "D-"
ensures forall i :: 0 <= i < |grades| && grades[i] == 0.0 ==> letters[i] == "E"
{
letters := [];
var i := 0;
while i < |grades|
invariant 0 <= i <= |grades|
invariant |letters| == i
invariant forall j :: 0 <= j < i && grades[j] == 4.0 ==> letters[j] == "A+"
invariant forall j :: 0 <= j < i && grades[j] < 4.0 && grades[j] > 3.7 ==> letters[j] == "A"
invariant forall j :: 0 <= j < i && grades[j] <= 3.7 && grades[j] > 3.3 ==> letters[j] == "A-"
invariant forall j :: 0 <= j < i && grades[j] <= 3.3 && grades[j] > 3.0 ==> letters[j] == "B+"
invariant forall j :: 0 <= j < i && grades[j] <= 3.0 && grades[j] > 2.7 ==> letters[j] == "B"
invariant forall j :: 0 <= j < i && grades[j] <= 2.7 && grades[j] > 2.3 ==> letters[j] == "B-"
invariant forall j :: 0 <= j < i && grades[j] <= 2.3 && grades[j] > 2.0 ==> letters[j] == "C+"
invariant forall j :: 0 <= j < i && grades[j] <= 2.0 && grades[j] > 1.7 ==> letters[j] == "C"
invariant forall j :: 0 <= j < i && grades[j] <= 1.7 && grades[j] > 1.3 ==> letters[j] == "C-"
invariant forall j :: 0 <= j < i && grades[j] <= 1.3 && grades[j] > 1.0 ==> letters[j] == "D+"
invariant forall j :: 0 <= j < i && grades[j] <= 1.0 && grades[j] > 0.7 ==> letters[j] == "D"
invariant forall j :: 0 <= j < i && grades[j] <= 0.7 && grades[j] > 0.0 ==> letters[j] == "D-"
invariant forall j :: 0 <= j < i && grades[j] == 0.0 ==> letters[j] == "E"
{
if grades[i] == 4.0 {
letters := letters + ["A+"];
} else if grades[i] > 3.7 {
letters := letters + ["A"];
} else if grades[i] > 3.3 {
letters := letters + ["A-"];
} else if grades[i] > 3.0 {
letters := letters + ["B+"];
} else if grades[i] > 2.7 {
letters := letters + ["B"];
} else if grades[i] > 2.3 {
letters := letters + ["B-"];
} else if grades[i] > 2.0 {
letters := letters + ["C+"];
} else if grades[i] > 1.7 {
letters := letters + ["C"];
} else if grades[i] > 1.3 {
letters := letters + ["C-"];
} else if grades[i] > 1.0 {
letters := letters + ["D+"];
} else if grades[i] > 0.7 {
letters := letters + ["D"];
} else if grades[i] > 0.0 {
letters := letters + ["D-"];
} else {
letters := letters + ["E"];
}

i := i + 1;
}
}
30 changes: 30 additions & 0 deletions 089-encrypt.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function rot_sym(c: char): char
requires 'a' <= c <= 'z'
ensures 'a' <= rot_sym(c) <= 'z'
{
var alph := c as int - 'a' as int;
((alph + 2 * 2) % 26 + 'a' as int) as char
}

method encrypt(s: string) returns (r: string)
requires forall i :: 0 <= i < |s| ==> 'a' <= s[i] <= 'z'
ensures |r| == |s|
ensures forall i :: 0 <= i < |s| ==> r[i] == rot_sym(s[i])
{
r := "";
var i := 0;
while i < |s|
invariant 0 <= i <= |s|
invariant |r| == i
invariant forall j :: 0 <= j < i ==> r[j] == rot_sym(s[j])
{
r := r + [rot_sym(s[i])];
i := i + 1;
}
}

method Main() {
var s := "asdfghjkl";
var r := encrypt(s);
assert r == "ewhjklnop";
}
32 changes: 32 additions & 0 deletions 108-count_nums.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
method count_nums(s: seq<int>) returns (cnt: nat)
ensures cnt == |set i | 0 <= i < |s| && digits_sum(s[i]) > 0|
{
ghost var found := {};

cnt := 0;
var i := 0;
while i < |s|
invariant 0 <= i <= |s|
invariant found == set j | 0 <= j < i && digits_sum(s[j]) > 0
invariant cnt == |found|
{
if digits_sum(s[i]) > 0 {
found := found + {i};
cnt := cnt + 1;
}
i := i + 1;
}
}

function digits_sum(x: int): int
decreases abs(x)
{
if abs(x) < 10 then x else x % 10 + digits_sum(x / 10)
}

function abs(x: int): int
ensures abs(x) >= 0
ensures abs(x) == x || abs(x) == -x
{
if x >= 0 then x else -x
}
28 changes: 28 additions & 0 deletions 114-minSubArraySum.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function Sum(a: seq<int>, s: int, t: int): int
requires 0 <= s <= t <= |a|
{
if s == t then 0 else Sum(a, s, t-1) + a[t-1]
}

method minSubArraySum(a: seq<int>) returns (s: int)
ensures forall p,q :: 0 <= p <= q <= |a| ==> Sum(a, p, q) >= s
ensures exists k, m :: 0 <= k <= m <= |a| && s == Sum(a, k, m)
{
var k, m := 0, 0;
s := 0;
var n := 0;
var c, t := 0, 0;
while n < |a|
invariant 0 <= c <= n <= |a| && t == Sum(a, c, n)
invariant forall b :: 0 <= b <= n ==> Sum(a, b, n) >= Sum(a, c, n)
invariant 0 <= k <= m <= n && s == Sum(a, k, m)
invariant forall p,q :: 0 <= p <= q <= n ==> Sum(a, p, q) >= Sum(a, k, m)
{
t, n := t + a[n], n + 1;
if t > 0 {
c, t := n, 0;
} else if s > t {
k, m, s := c, n, t;
}
}
}
71 changes: 71 additions & 0 deletions 128-prod_signs.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
function abs(x: int): int
ensures abs(x) >= 0
ensures abs(x) == x || abs(x) == -x
ensures x >= 0 ==> abs(x) == x
ensures x < 0 ==> abs(x) == -x
{
if x >= 0 then x else -x
}

function sum_abs(s: seq<int>) : int
ensures sum_abs(s) >= 0
{
if |s| == 0 then 0 else abs(s[0]) + sum_abs(s[1..])
}

lemma sum_prop(s: seq<int>)
requires |s| > 0
ensures sum_abs(s) == sum_abs(s[..|s| - 1]) + abs(s[|s| - 1])
{
if (|s| > 1) {
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1];
}
}

method prod_signs(numbers: seq<int>) returns (s: int)
ensures abs(s) == sum_abs(numbers)
ensures |set i | 0 <= i < |numbers| && numbers[i] < 0| % 2 == 1 ==> s <= 0
ensures |set i | 0 <= i < |numbers| && numbers[i] < 0| % 2 == 0 ==> s >= 0
{
s := 0;
var i := 0;
while (i < |numbers|)
invariant 0 <= i <= |numbers|
invariant s == sum_abs(numbers[..i])
{
s := s + abs(numbers[i]);
assert sum_abs(numbers[..i + 1]) == sum_abs(numbers[..i]) + abs(numbers[i]) by {
assert numbers[..i+1][..i] == numbers[..i];
sum_prop(numbers[..i + 1]);
}
i := i + 1;
}

assert numbers == numbers[..|numbers|];

i := 0;
ghost var negatives := {};
var cnt := 0;
while (i < |numbers|)
invariant 0 <= i <= |numbers|
invariant cnt == |negatives|
invariant negatives == set j | 0 <= j < i && numbers[j] < 0
{
if (numbers[i] < 0) {
negatives := negatives + {i};
cnt := cnt + 1;
}
i := i + 1;
}
assert negatives == set i | 0 <= i < |numbers| && numbers[i] < 0;

if (cnt % 2 == 1) {
s := -s;
}
}

method Main() {
var nums := [1, 2, 2, -4];
var s := prod_signs(nums);
print s;
}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Current status:
- [x] 46. fib4
- [ ] 47. median
- [x] 48. is_palindrome
- [ ] 49. modp
- [x] 49. modp
- [ ] 50. encode_shift
- [x] 51. remove_vowels
- [x] 52. below_threshold
Expand All @@ -75,23 +75,23 @@ Current status:
- [x] 70. strange_sort_list
- [ ] 71. ~triangle_area~ -- requires real square root
- [x] 72. will_it_fly
- [ ] 73. smallest_change
- [x] 73. smallest_change
- [x] 74. total_match
- [x] 75. is_multiply_prime
- [x] 76. is_simple_power
- [x] 77. iscube
- [x] 78. hex_key
- [ ] 79. decimal_to_binary
- [x] 80. is_happy
- [ ] 81. numerical_letter_grade
- [x] 81. numerical_letter_grade
- [x] 82. prime_length
- [x] 83. starts_one_ends
- [ ] 84. solve
- [x] 85. add
- [ ] 86. anti_shuffle - complex strings
- [ ] 87. get_row - sorting
- [x] 88. sort_array - sorting
- [ ] 89. encrypt
- [x] 89. encrypt
- [ ] 90. next_smallest - nullable
- [ ] 91. is_bored - complex strings
- [x] 92. any_int
Expand All @@ -110,7 +110,7 @@ Current status:
- [x] 105. by_length - sorting
- [x] 106. f
- [ ] 107. even_odd_palindrome
- [ ] 108. count_nums
- [x] 108. count_nums
- [ ] 109. move_one_ball
- [x] 110. exchange
- [ ] 111. histogram
Expand All @@ -130,7 +130,7 @@ Current status:
- [ ] 125. split_words - complex strings
- [x] 126. is_sorted
- [x] 127. intersection
- [ ] 128. prod_signs
- [x] 128. prod_signs
- [ ] 129. minPath
- [x] 130. tri
- [ ] 131. digits
Expand Down
6 changes: 0 additions & 6 deletions REMAINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,16 @@ Current status:
- [ ] 38. encode_cyclic
- [ ] 44. change_base
- [ ] 47. median
- [ ] 49. modp
- [ ] 50. encode_shift
- [ ] 56. correct_bracketing
- [ ] 61. correct_bracketing
- [ ] 65. circular_shift
- [ ] 73. smallest_change
- [ ] 79. decimal_to_binary
- [ ] 81. numerical_letter_grade
- [ ] 84. solve
- [ ] 89. encrypt
- [ ] 90. next_smallest - nullable
- [ ] 93. encode
- [ ] 103. rounded_avg
- [ ] 107. even_odd_palindrome
- [ ] 108. count_nums
- [ ] 109. move_one_ball
- [ ] 111. histogram
- [ ] 112. reverse_delete
Expand All @@ -32,7 +27,6 @@ Current status:
- [ ] 119. match_parens
- [ ] 121. solution - sum
- [ ] 124. valid_date
- [ ] 128. prod_signs
- [ ] 129. minPath
- [ ] 131. digits
- [ ] 132. is_nested
Expand Down

0 comments on commit 719cde8

Please sign in to comment.