From 9e7521d89a49a7bdb4210ad04899fcb764f0395f Mon Sep 17 00:00:00 2001 From: Stanislav Alekseev <43210583+WeetHet@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:50:27 +0300 Subject: [PATCH] 055, 057, 062, 063, 064, 066 (#16) --- 055-fib.dfy | 35 +++++++++++++++++++++++++++++++++++ 057-monotonic.dfy | 28 ++++++++++++++++++++++++++++ 062-derivative.dfy | 16 ++++++++++++++++ 063-fibfib.dfy | 37 +++++++++++++++++++++++++++++++++++++ 064-vowel_count.dfy | 28 ++++++++++++++++++++++++++++ 066-digitSum.dfy | 44 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 12 ++++++------ 7 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 055-fib.dfy create mode 100644 057-monotonic.dfy create mode 100644 062-derivative.dfy create mode 100644 063-fibfib.dfy create mode 100644 064-vowel_count.dfy create mode 100644 066-digitSum.dfy diff --git a/055-fib.dfy b/055-fib.dfy new file mode 100644 index 0000000..6c00931 --- /dev/null +++ b/055-fib.dfy @@ -0,0 +1,35 @@ +function fib(n: nat): nat + decreases n +{ + if n == 0 then 0 + else if n == 1 then 1 + else fib(n - 1) + fib(n - 2) +} + +method ComputeFib(n: nat) returns (result: nat) + ensures result == fib(n) +{ + if n == 0 { + return 0; + } + + if n == 1 { + return 1; + } + + var a, b := 0, 1; + var i := 2; + + while i <= n + invariant 2 <= i <= n + 1 + invariant a == fib(i - 2) + invariant b == fib(i - 1) + { + var temp := a + b; + a := b; + b := temp; + i := i + 1; + } + + return b; +} \ No newline at end of file diff --git a/057-monotonic.dfy b/057-monotonic.dfy new file mode 100644 index 0000000..0b26359 --- /dev/null +++ b/057-monotonic.dfy @@ -0,0 +1,28 @@ +method monotonic(xs: seq) returns (result: bool) + requires |xs| > 0 + ensures result <==> (forall i, j :: 0 <= i < j < |xs| ==> xs[i] < xs[j]) || (forall i, j :: 0 <= i < j < |xs| ==> xs[i] > xs[j]) +{ + if |xs| == 1 { + return true; + } + + var increasing := true; + var decreasing := true; + var i := 1; + + while i < |xs| + invariant 1 <= i <= |xs| + invariant increasing <==> (forall j, k :: 0 <= j < k < i ==> xs[j] < xs[k]) + invariant decreasing <==> (forall j, k :: 0 <= j < k < i ==> xs[j] > xs[k]) + { + if xs[i - 1] >= xs[i] { + increasing := false; + } + if xs[i - 1] <= xs[i] { + decreasing := false; + } + i := i + 1; + } + + result := increasing || decreasing; +} \ No newline at end of file diff --git a/062-derivative.dfy b/062-derivative.dfy new file mode 100644 index 0000000..5bd4692 --- /dev/null +++ b/062-derivative.dfy @@ -0,0 +1,16 @@ +method derivative(xs: seq) returns (result: seq) + requires |xs| > 0 + ensures |result| == |xs| - 1 + ensures forall i :: 0 <= i < |result| ==> result[i] == xs[i+1] * (i+1) +{ + result := []; + var i := 1; + while i < |xs| + invariant 1 <= i <= |xs| + invariant |result| == i - 1 + invariant forall j :: 0 <= j < |result| ==> result[j] == xs[j+1] * (j+1) + { + result := result + [xs[i] * i]; + i := i + 1; + } +} \ No newline at end of file diff --git a/063-fibfib.dfy b/063-fibfib.dfy new file mode 100644 index 0000000..d242c53 --- /dev/null +++ b/063-fibfib.dfy @@ -0,0 +1,37 @@ +function fibfib(n: nat): nat + decreases n +{ + if n == 0 || n == 1 then 0 + else if n == 2 then 1 + else fibfib(n - 1) + fibfib(n - 2) + fibfib(n - 3) +} + +method ComputeFibFib(n: nat) returns (result: nat) + ensures result == fibfib(n) +{ + if n == 0 || n == 1 { + return 0; + } + + if n == 2 { + return 1; + } + + var a, b, c := 0, 0, 1; + var i := 3; + + while i <= n + invariant 3 <= i <= n + 1 + invariant a == fibfib(i-3) + invariant b == fibfib(i-2) + invariant c == fibfib(i-1) + { + var temp := c + b + a; + a := b; + b := c; + c := temp; + i := i + 1; + } + + return c; +} \ No newline at end of file diff --git a/064-vowel_count.dfy b/064-vowel_count.dfy new file mode 100644 index 0000000..8cfd755 --- /dev/null +++ b/064-vowel_count.dfy @@ -0,0 +1,28 @@ +method vowel_count(s: string) returns (count: int) + ensures count >= 0 + ensures count == |(set i | 0 <= i < |s| && is_vowel(s[i]))| + if |s| > 0 && s[|s| - 1] == 'y' then 1 else 0 +{ + ghost var found := {}; + count := 0; + var i := 0; + while i < |s| + invariant 0 <= i <= |s| + invariant count == |found| + invariant forall j :: 0 <= j < i && is_vowel(s[j]) ==> j in found + invariant forall x :: x in found ==> x < i + invariant found == (set j | 0 <= j < i && is_vowel(s[j])) + { + if is_vowel(s[i]) { + found := found + {i}; + count := count + 1; + } + i := i + 1; + } + count := count + if |s| > 0 && s[|s| - 1] == 'y' then 1 else 0; +} + +function is_vowel(c: char): bool + ensures is_vowel(c) <==> c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' +{ + c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' +} \ No newline at end of file diff --git a/066-digitSum.dfy b/066-digitSum.dfy new file mode 100644 index 0000000..6bc5042 --- /dev/null +++ b/066-digitSum.dfy @@ -0,0 +1,44 @@ +function upper_sum_rec(s: string): int + ensures upper_sum_rec(s) >= 0 +{ + if |s| == 0 then + 0 + else + var remaining := upper_sum_rec(s[1..]); + to_int(s[0]) + remaining +} + +lemma upper_sum_rec_prop(s: string) + requires |s| > 0 + ensures upper_sum_rec(s) == upper_sum_rec(s[..|s|-1]) + to_int(s[|s|-1]) +{ + if (|s| > 1) { + assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1]; + } +} + +function to_int(c: char): int + ensures 'A' <= c <= 'Z' ==> to_int(c) == c as int + ensures c < 'A' || c > 'Z' ==> to_int(c) == 0 +{ + if 'A' <= c <= 'Z' then c as int else 0 +} + +method upper_sum(s: string) returns (res: int) + ensures res == upper_sum_rec(s) +{ + res := 0; + var i := 0; + while (i < |s|) + invariant 0 <= i <= |s| + invariant res == upper_sum_rec(s[..i]) + { + res := res + to_int(s[i]); + assert upper_sum_rec(s[..i + 1]) == upper_sum_rec(s[..i]) + to_int(s[i]) by { + assert s[..i+1][..i] == s[..i]; + upper_sum_rec_prop(s[..i + 1]); + } + i := i + 1; + } + assert s == s[..|s|]; +} \ No newline at end of file diff --git a/README.md b/README.md index 89ff043..27b3fc4 100644 --- a/README.md +++ b/README.md @@ -57,18 +57,18 @@ Current status: - [x] 52. below_threshold - [x] 53. add - [x] 54. same_chars -- [ ] 55. fib +- [x] 55. fib - [ ] 56. correct_bracketing -- [ ] 57. monotonic +- [x] 57. monotonic - [x] 58. common - [x] 59. largest_prime_factor - [x] 60. sum_to_n - [ ] 61. correct_bracketing -- [ ] 62. derivative -- [ ] 63. fibfib -- [ ] 64. vowels_count +- [x] 62. derivative +- [x] 63. fibfib +- [x] 64. vowels_count - [ ] 65. circular_shift -- [ ] 66. digitSum +- [x] 66. digitSum - [ ] 67. fruit_distribution - [x] 68. pluck - [x] 69. search