From f13de1b45746dc075ed99dd95a5671ba96d23066 Mon Sep 17 00:00:00 2001 From: Stanislav Alekseev <43210583+WeetHet@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:59:58 +0300 Subject: [PATCH] 036, 087, 161 (#37) --- 036-fizz_buzz.dfy | 78 ++++++++++++++++++++++++++++++++ 087-get_row.dfy | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 161-solve.dfy | 68 ++++++++++++++++++++++++++++ README.md | 8 ++-- REMAINING.md | 21 +++------ 5 files changed, 270 insertions(+), 18 deletions(-) create mode 100644 036-fizz_buzz.dfy create mode 100644 087-get_row.dfy create mode 100644 161-solve.dfy diff --git a/036-fizz_buzz.dfy b/036-fizz_buzz.dfy new file mode 100644 index 0000000..936b132 --- /dev/null +++ b/036-fizz_buzz.dfy @@ -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 { + if |s| == 0 then 0 else s[0] + sum(s[1..]) +} + +lemma sum_prop(s: seq) + 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]; + } +} diff --git a/087-get_row.dfy b/087-get_row.dfy new file mode 100644 index 0000000..b5d628d --- /dev/null +++ b/087-get_row.dfy @@ -0,0 +1,113 @@ +method get_row(lst: seq>, 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 +} diff --git a/161-solve.dfy b/161-solve.dfy new file mode 100644 index 0000000..3e09ec4 --- /dev/null +++ b/161-solve.dfy @@ -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' +} \ No newline at end of file diff --git a/README.md b/README.md index 7644ea0..e79b115 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/REMAINING.md b/REMAINING.md index 759676d..b9e9ea9 100644 --- a/REMAINING.md +++ b/REMAINING.md @@ -4,14 +4,12 @@ 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 @@ -19,24 +17,20 @@ Current status: - [ ] 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 @@ -44,18 +38,17 @@ Current status: - [ ] 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 \ No newline at end of file