-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
135 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters