Skip to content

Commit

Permalink
107, 111 (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
WeetHet authored Sep 2, 2024
1 parent f13de1b commit a45dad3
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 4 deletions.
69 changes: 69 additions & 0 deletions 107-even_odd_palindrome.dfy
Original file line number Diff line number Diff line change
@@ -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
{
}
63 changes: 63 additions & 0 deletions 111-histogram.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
method count(a: seq<int>) returns (biggest: map<int, int>)
// 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
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions REMAINING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a45dad3

Please sign in to comment.