From a45dad3d83b8f52ae368a0aec72ec97c0700a881 Mon Sep 17 00:00:00 2001 From: Stanislav Alekseev <43210583+WeetHet@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:15:43 +0300 Subject: [PATCH] 107, 111 (#38) --- 107-even_odd_palindrome.dfy | 69 +++++++++++++++++++++++++++++++++++++ 111-histogram.dfy | 63 +++++++++++++++++++++++++++++++++ README.md | 4 +-- REMAINING.md | 3 +- 4 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 107-even_odd_palindrome.dfy create mode 100644 111-histogram.dfy diff --git a/107-even_odd_palindrome.dfy b/107-even_odd_palindrome.dfy new file mode 100644 index 0000000..6565595 --- /dev/null +++ b/107-even_odd_palindrome.dfy @@ -0,0 +1,69 @@ +predicate is_palindrome(n: nat) { + var s := natToString(n); + forall i | 0 <= i < |s| :: s[i] == s[|s|-1-i] +} + +method even_odd_palindrome(n: nat) returns (even: nat, odd: nat) + // post-conditions-start + ensures even == |set i | 0 <= i <= n && i % 2 == 0 && is_palindrome(i)| + ensures odd == |set i | 0 <= i <= n && i % 2 == 1 && is_palindrome(i)| +{ + // impl-start + even := 0; + odd := 0; + ghost var even_pal := {}; + ghost var odd_pal := {}; + + var i := 0; + while i <= n + // invariants-start + invariant 0 <= i <= n + 1 + invariant even_pal == set j | 0 <= j < i && j % 2 == 0 && is_palindrome(j) + invariant odd_pal == set j | 0 <= j < i && j % 2 == 1 && is_palindrome(j) + + invariant even == |even_pal| + invariant odd == |odd_pal| + // invariants-end + { + if is_palindrome(i) { + if i % 2 == 0 { + even := even + 1; + even_pal := even_pal + {i}; + } else { + odd := odd + 1; + odd_pal := odd_pal + {i}; + } + } + i := i + 1; + } + assert even_pal == set i | 0 <= i <= n && i % 2 == 0 && is_palindrome(i); + assert odd_pal == set i | 0 <= i <= n && i % 2 == 1 && is_palindrome(i); +} + +type stringNat = s: string | +|s| > 0 && (|s| > 1 ==> s[0] != '0') && +forall i | 0 <= i < |s| :: s[i] in "0123456789" +witness "1" + +function natToString(n: nat): stringNat { +match n +case 0 => "0" case 1 => "1" case 2 => "2" case 3 => "3" case 4 => "4" +case 5 => "5" case 6 => "6" case 7 => "7" case 8 => "8" case 9 => "9" +case _ => natToString(n / 10) + natToString(n % 10) +} + +function stringToNat(s: stringNat): nat +decreases |s| +{ +if |s| == 1 then + match s[0] + case '0' => 0 case '1' => 1 case '2' => 2 case '3' => 3 case '4' => 4 + case '5' => 5 case '6' => 6 case '7' => 7 case '8' => 8 case '9' => 9 +else + stringToNat(s[..|s|-1])*10 + stringToNat(s[|s|-1..|s|]) +} + +lemma natToStringThenStringToNatIdem(n: nat) +ensures stringToNat(natToString(n)) == n +{ +} diff --git a/111-histogram.dfy b/111-histogram.dfy new file mode 100644 index 0000000..f226917 --- /dev/null +++ b/111-histogram.dfy @@ -0,0 +1,63 @@ +method count(a: seq) returns (biggest: map) + // post-conditions-start + ensures forall i :: 0 <= i < |a| && a[i] in biggest ==> + biggest[a[i]] == |set j | 0 <= j < |a| && a[j] == a[i]| + ensures forall i, j :: 0 <= i < |a| && 0 <= j < |a| && a[i] in biggest ==> + biggest[a[i]] >= |set k | 0 <= k < |a| && a[k] == a[j]| + ensures forall i, j :: 0 <= i < |a| && 0 <= j < |a| && a[i] in biggest && a[j] in biggest ==> + biggest[a[i]] == biggest[a[j]] + // post-conditions-end +{ + // impl-start + if |a| == 0 { + return map[]; + } + var cnt := map[]; + ghost var positions := map[]; + var i := 0; + while i < |a| + // invariants-start + invariant 0 <= i <= |a| + invariant forall j :: 0 <= j < i ==> a[j] in positions && positions[a[j]] == set k | 0 <= k < i && a[k] == a[j] + invariant forall j :: 0 <= j < i ==> a[j] in cnt && cnt[a[j]] == |positions[a[j]]| + invariant forall j :: j in positions ==> forall k :: k in positions[j] ==> k < i + + invariant forall x :: x in positions ==> x in a[..i] + invariant forall x :: x in positions ==> x in cnt && cnt[x] == |positions[x]| + invariant forall x :: x in cnt ==> x in positions + // invariants-end + { + if a[i] in cnt { + ghost var pre := positions[a[i]]; + positions := positions[a[i] := pre + {i}]; + cnt := cnt[a[i] := cnt[a[i]] + 1]; + } else { + positions := positions[a[i] := {i}]; + cnt := cnt[a[i] := 1]; + } + i := i + 1; + } + var maxCount := cnt[a[0]]; + biggest := map[a[0] := maxCount]; + i := 1; + while i < |a| + // invariants-start + invariant 0 <= i <= |a| + invariant forall j :: 0 <= j < |a| ==> a[j] in cnt + invariant forall j :: 0 <= j < i ==> a[j] in cnt && maxCount >= cnt[a[j]] + invariant exists j :: 0 <= j < i && a[j] in cnt && cnt[a[j]] == maxCount + invariant forall j :: 0 <= j < i ==> cnt[a[j]] == maxCount ==> a[j] in biggest + invariant forall x :: x in biggest ==> x in cnt && cnt[x] == maxCount + invariant forall x :: x in biggest ==> biggest[x] == cnt[x] + // invariants-end + { + if cnt[a[i]] > maxCount { + maxCount := cnt[a[i]]; + biggest := map[a[i] := maxCount]; + } else if cnt[a[i]] == maxCount { + biggest := biggest[a[i] := maxCount]; + } + i := i + 1; + } + // impl-end +} diff --git a/README.md b/README.md index e79b115..fde3fd2 100644 --- a/README.md +++ b/README.md @@ -109,11 +109,11 @@ Current status: - [x] 104. unique_digits - sorting - [x] 105. by_length - sorting - [x] 106. f -- [ ] 107. even_odd_palindrome +- [x] 107. even_odd_palindrome - [x] 108. count_nums - [x] 109. move_one_ball - [x] 110. exchange -- [ ] 111. histogram +- [x] 111. histogram - [x] 112. reverse_delete - [ ] 113. odd_count - [x] 114. minSubArraySum diff --git a/REMAINING.md b/REMAINING.md index b9e9ea9..7288c22 100644 --- a/REMAINING.md +++ b/REMAINING.md @@ -15,8 +15,7 @@ Current status: - [ ] 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