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

036, 087, 161 #37

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions 036-fizz_buzz.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
method fizz_buzz(n: nat) returns (result: nat)
// post-conditions-start
ensures result == sum(
seq(n, i requires 0 <= i < n => (if i % 11 == 0 || i % 13 == 0 then count7_r(i) else 0))
)
// post-conditions-end
{
// impl-start
ghost var values := [];
result := 0;
var i := 0;
while i < n
// invariants-start
invariant 0 <= i <= n
invariant |values| == i
invariant result == sum(values[..i])
invariant values == seq(i, j requires 0 <= j < i => (if j % 11 == 0 || j % 13 == 0 then count7_r(j) else 0))
// invariants-end
{
ghost var pre := values;
if i % 11 == 0 || i % 13 == 0 {
var cnt := count7(i);
result := result + cnt;
values := values + [cnt];
} else {
values := values + [0];
}
assert values[..i] == pre[..i]; // assert-line
// assert-start
assert sum(values[..i + 1]) == sum(values[..i]) + values[i] by {
assert values[..i+1][..i] == values[..i];
sum_prop(values[..i + 1]);
}
// assert-end
i := i + 1;
}
assert values[..|values|] == values; // assert-line
// impl-end
}

method count7(x: nat) returns (count: nat)
// post-conditions-start
ensures count == count7_r(x)
// post-conditions-end
{
// impl-start
count := 0;
var y := x;
while y > 0
// invariants-start
invariant count + count7_r(y) == count7_r(x)
// invariants-end
{
if y % 10 == 7 {
count := count + 1;
}
y := y / 10;
}
// impl-end
}

function count7_r(x: nat): nat {
var lst := if x % 10 == 7 then 1 else 0;
if x < 10 then lst else lst + count7_r(x / 10)
}

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];
}
}
113 changes: 113 additions & 0 deletions 087-get_row.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
method get_row(lst: seq<seq<int>>, x: int) returns (pos: seq<(int, int)>)
// post-conditions-start
ensures forall i :: 0 <= i < |pos| ==> (
var (a, b) := pos[i];
0 <= a < |lst| && 0 <= b < |lst[a]| && lst[a][b] == x
)
ensures forall i, j :: 0 <= i < |lst| && 0 <= j < |lst[i]| && lst[i][j] == x ==> (i, j) in pos
ensures forall i, j :: 0 <= i < j < |pos| ==> less_eq(pos[i], pos[j])
// post-conditions-end
{
// impl-start
pos := [];
var i := 0;
while i < |lst|
// invariants-start
invariant 0 <= i <= |lst|
invariant forall j :: 0 <= j < |pos| ==> (
var (a, b) := pos[j];
0 <= a < i && 0 <= b < |lst[a]| && lst[a][b] == x
)
invariant forall j, k :: 0 <= j < i && 0 <= k < |lst[j]| && lst[j][k] == x ==> (j, k) in pos
// invariants-end
{
var j := 0;
var pos_i := [];
ghost var row := lst[i];
while j < |lst[i]|
// invariants-start
invariant 0 <= j <= |lst[i]|
invariant forall k :: 0 <= k < |pos_i| ==> var (a, b) := pos_i[k];
a == i && 0 <= b < |row|
invariant forall k :: 0 <= k < |pos_i| ==> var (a, b) := pos_i[k]; row[b] == x
invariant forall k :: 0 <= k < j && lst[i][k] == x ==> (i, k) in pos_i
// invariants-end
{
if lst[i][j] == x {
pos_i := pos_i + [(i, j)];
}
j := j + 1;
}

pos := pos + pos_i;

i := i + 1;
}
ghost var unsorted := pos;
pos := SortSeq(pos);
// assert-start
assert forall i, j :: 0 <= i < |lst| && 0 <= j < |lst[i]| && lst[i][j] == x ==> (i, j) in pos by {
assert forall i, j :: 0 <= i < |lst| && 0 <= j < |lst[i]| && lst[i][j] == x ==> (i, j) in multiset(pos);
}
// assert-end

// assert-start
assert forall i :: 0 <= i < |pos| ==> (
var (a, b) := pos[i]; 0 <= a < |lst| && 0 <= b < |lst[a]| && lst[a][b] == x
) by {
assert forall i :: 0 <= i < |pos| ==> pos[i] in multiset(unsorted);
}
// assert-end
// impl-end
}

function less(a: (int, int), b: (int, int)): bool {
var (x, y) := a; var (u, v) := b;
x < u || (x == u && y > v)
}

function less_eq(a: (int, int), b: (int, int)): bool {
var (x, y) := a; var (u, v) := b;
(x == u && y == v) || less(a, b)
}

method SortSeq(s: seq<(int, int)>) returns (sorted: seq<(int, int)>)
// post-conditions-start
ensures forall i, j :: 0 <= i < j < |sorted| ==> less_eq(sorted[i], sorted[j])
ensures |sorted| == |s|
ensures multiset(s) == multiset(sorted)
// post-conditions-end
{
// impl-start
sorted := s;
var i := 0;
while i < |sorted|
// invariants-start
invariant 0 <= i <= |sorted|
invariant forall j, k :: 0 <= j < k < i ==> less_eq(sorted[j], sorted[k])
invariant multiset(s) == multiset(sorted)
invariant forall j :: 0 <= j < i ==> forall k :: i <= k < |sorted| ==> less_eq(sorted[j], sorted[k])
invariant |sorted| == |s|
// invariants-end
{
var minIndex := i;
var j := i + 1;
while j < |sorted|
// invariants-start
invariant i <= minIndex < j <= |sorted|
invariant forall k :: i <= k < j ==> less_eq(sorted[minIndex], sorted[k])
// invariants-end
{
if less(sorted[j], sorted[minIndex]) {
minIndex := j;
}
j := j + 1;
}
if minIndex != i {
var temp := sorted[i];
sorted := sorted[i := sorted[minIndex]][minIndex := temp];
}
i := i + 1;
}
// impl-end
}
68 changes: 68 additions & 0 deletions 161-solve.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
method solve(s: string) returns (t: string)
// post-conditions-start
ensures |s| == |t|
ensures (forall i :: 0 <= i < |s| ==> !is_alpha(s[i])) ==> (forall i :: 0 <= i < |s| ==> s[i] == t[|t| - 1 - i])
ensures (exists i :: 0 <= i < |s| && is_alpha(s[i])) ==>
(forall i :: 0 <= i < |t| ==> if is_alpha(s[i]) then t[i] == flip_case(s[i]) else t[i] == s[i])
// post-conditions-end
{
// impl-start
var flag := false;
t := "";

var i := 0;
while i < |s|
// invariants-start
invariant 0 <= i <= |s|
invariant |t| == i
invariant flag <==> exists j :: 0 <= j < i && is_alpha(s[j])
invariant forall j :: 0 <= j < i ==> t[j] == if is_alpha(s[j]) then flip_case(s[j]) else s[j]
// invariants-end
{
if is_alpha(s[i]) {
t := t + [flip_case(s[i])];
flag := true;
} else {
t := t + [s[i]];
}
i := i + 1;
}

if !flag {
t := reverse(t);
}
// impl-end
}

method reverse(s: string) returns (rev: string)
// pre-conditions-start
ensures |rev| == |s|
ensures forall k :: 0 <= k < |s| ==> rev[k] == s[|s| - 1 - k]
// pre-conditions-end
{
// impl-start
rev := "";
var i := 0;
while (i < |s|)
// invariants-start
invariant i >= 0 && i <= |s|
invariant |rev| == i
invariant forall k :: 0 <= k < i ==> rev[k] == s[|s| - 1 - k]
// invariants-end
{
rev := rev + [s[|s| - i - 1]];
i := i + 1;
}
// impl-end
}

predicate is_alpha(c: char) {
'a' <= c <= 'z' || 'A' <= c <= 'Z'
}

function flip_case(c: char): (flipped: char)
requires is_alpha(c)
ensures is_alpha(flipped)
{
if 'a' <= c <= 'z' then c - 'a' + 'A' else c - 'A' + 'a'
}
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Current status:
- [x] 33. sort_third
- [x] 34. unique
- [x] 35. max_element
- [ ] 36. fizz_buzz
- [x] 36. fizz_buzz
- [x] 37. sort_even - sorting
- [ ] 38. encode_cyclic
- [ ] 39. ~prime_fib~ -- unbounded loop, probably impossible
Expand Down Expand Up @@ -89,7 +89,7 @@ Current status:
- [x] 84. solve
- [x] 85. add
- [ ] 86. anti_shuffle - complex strings
- [ ] 87. get_row - sorting
- [x] 87. get_row - sorting
- [x] 88. sort_array - sorting
- [x] 89. encrypt
- [ ] 90. next_smallest - nullable
Expand Down Expand Up @@ -122,7 +122,7 @@ Current status:
- [ ] 117. select_words - complex strings
- [x] 118. get_closest_vowel
- [ ] 119. match_parens
- [ ] 120. maximum - sorting
- [x] 120. maximum - sorting
- [x] 121. solution - sum
- [x] 122. add_elements
- [x] 123. get_odd_collatz - sorting
Expand All @@ -147,7 +147,7 @@ Current status:
- [x] 142. sum_squares
- [ ] 143. words_in_sentence - complex strings
- [ ] 144. simplify
- [ ] 145. order_by_points - sorting
- [x] 145. order_by_points - sorting
- [x] 146. specialFilter
- [ ] 147. get_max_triples
- [x] 148. bf
Expand Down
21 changes: 7 additions & 14 deletions REMAINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,51 @@ Current status:

## Priority
- [ ] 25. factorize
- [ ] 36. fizz_buzz
- [ ] 147. get_max_triples

## Other

- [ ] 32. poly
- [ ] 38. encode_cyclic
- [ ] 44. change_base
- [ ] 47. median
- [ ] 65. circular_shift
- [ ] 79. decimal_to_binary
- [ ] 90. next_smallest - nullable
- [ ] 103. rounded_avg
- [ ] 107. even_odd_palindrome
- [ ] 111. histogram
- [ ] 113. odd_count
- [ ] 119. match_parens
- [ ] 124. valid_date
- [ ] 129. minPath
- [ ] 131. digits
- [ ] 132. is_nested
- [ ] 141. file_name_check
- [ ] 156. int_to_mini_roman
- [ ] 161. solve
- [ ] 162. string_to_md5 - needs hash


## Complex strings
## Strings
- [ ] 15. string_sequence
- [ ] 17. parse_music
- [ ] 18. how_many_times
- [ ] 19. sort_numbers
- [ ] 28. concatenate
- [ ] 44. change_base
- [ ] 56. correct_bracketing
- [ ] 61. correct_bracketing
- [ ] 67. fruit_distribution
- [ ] 86. anti_shuffle
- [ ] 91. is_bored
- [ ] 99. closest_integer
- [ ] 101. words_string
- [ ] 113. odd_count
- [ ] 117. select_words
- [ ] 125. split_words
- [ ] 140. fix_spaces
- [ ] 141. file_name_check
- [ ] 144. simplify
- [ ] 143. words_in_sentence
- [ ] 156. int_to_mini_roman
- [ ] 160. do_algebra
- [ ] 162. string_to_md5 - needs hash

## Ill-typed
- [ ] 22. filter_integers
- [ ] 137. compare_one

## Sorting
- [ ] 87. get_row - sorting
- [ ] 120. maximum - sorting
- [ ] 145. order_by_points - sorting
- [ ] 137. compare_one