Skip to content

Commit

Permalink
130, 139, 148, 150, 153, 154 (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
WeetHet authored Aug 8, 2024
1 parent e83db6e commit 59b7fa3
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 17 deletions.
34 changes: 34 additions & 0 deletions 130-tri.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function tri(n: nat): nat
decreases if n % 2 == 0 then 0 else n
{
if n == 1 then 3
else if n % 2 == 0 then 1 + n / 2
else tri(n - 1) + tri(n - 2) + tri(n + 1)
}

method Tribonacci(n: nat) returns (result: seq<nat>)
ensures |result| == n + 1
ensures forall i :: 0 <= i <= n ==> result[i] == tri(i)
{
if n == 0 {
result := [1];
} else {
result := [1, 3];
var i := 2;
while i <= n
invariant 0 <= i <= n + 1
invariant |result| == i
invariant forall j :: 0 <= j < i ==> result[j] == tri(j)
{
if i % 2 == 0 {
result := result + [1 + i / 2];
} else {
assert result[i - 2] == tri(i - 2);
assert result[i - 1] == tri(i - 1);
assert (i + 3) / 2 == tri(i + 1);
result := result + [result[i - 2] + result[i - 1] + (i + 3) / 2];
}
i := i + 1;
}
}
}
31 changes: 31 additions & 0 deletions 139-special_factorial.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function factorial(n: nat): nat
decreases n
{
if n == 0 then 1 else n * factorial(n - 1)
}

function special_factorial_rec(n: nat): nat
decreases n
{
if n == 0 then 1 else factorial(n) * special_factorial_rec(n - 1)
}

method special_factorial(n: nat) returns (result: nat)
requires n > 0
ensures result == special_factorial_rec(n)
{
result := 1;
var fact := 1;

var i := 0;
while i < n
invariant 0 <= i <= n
invariant result == special_factorial_rec(i)
invariant fact == factorial(i)
decreases n - i + 1
{
i := i + 1;
fact := fact * i;
result := result * fact;
}
}
67 changes: 67 additions & 0 deletions 148-bf.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
datatype Planet = Mercury | Venus | Earth | Mars | Jupiter | Saturn | Uranus | Neptune
datatype Option<T> = Some(value: T) | None

function PlanetFromString(name: string): Option<Planet>
ensures PlanetFromString(name).Some? ==> 0 <= PlanetIndex(PlanetFromString(name).value) <= 7
{
match name
case "Mercury" => Some(Mercury)
case "Venus" => Some(Venus)
case "Earth" => Some(Earth)
case "Mars" => Some(Mars)
case "Jupiter" => Some(Jupiter)
case "Saturn" => Some(Saturn)
case "Uranus" => Some(Uranus)
case "Neptune" => Some(Neptune)
case _ => None
}

function PlanetIndex(p: Planet): int
{
match p
case Mercury => 0
case Venus => 1
case Earth => 2
case Mars => 3
case Jupiter => 4
case Saturn => 5
case Uranus => 6
case Neptune => 7
}

function GetPlanetsBetween(planet1: string, planet2: string): seq<string>
ensures |GetPlanetsBetween(planet1, planet2)| <= 6
{
var p1 := PlanetFromString(planet1);
var p2 := PlanetFromString(planet2);
if p1.None? || p2.None? then
[]
else
var i1 := PlanetIndex(p1.value);
var i2 := PlanetIndex(p2.value);
if i1 < i2 then
GetPlanetsBetweenIndices(i1 + 1, i2 - 1)
else if i1 > i2 then
GetPlanetsBetweenIndices(i2 + 1, i1 - 1)
else
[]
}

function GetPlanetsBetweenIndices(start: int, end: int): seq<string>
requires 0 <= start <= 7 && 0 <= end <= 7
ensures |GetPlanetsBetweenIndices(start, end)| <= (if start <= end then end - start + 1 else 0)
decreases if start <= end then end - start + 1 else 0
{
if start > end then
[]
else
match start
case 0 => ["Mercury"] + GetPlanetsBetweenIndices(1, end)
case 1 => ["Venus"] + GetPlanetsBetweenIndices(2, end)
case 2 => ["Earth"] + GetPlanetsBetweenIndices(3, end)
case 3 => ["Mars"] + GetPlanetsBetweenIndices(4, end)
case 4 => ["Jupiter"] + GetPlanetsBetweenIndices(5, end)
case 5 => ["Saturn"] + GetPlanetsBetweenIndices(6, end)
case 6 => ["Uranus"] + GetPlanetsBetweenIndices(7, end)
case 7 => ["Neptune"]
}
16 changes: 16 additions & 0 deletions 150-x_or_y.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
predicate IsPrime(n: nat)
{
n > 1 &&
forall k :: 2 <= k < n ==> n % k != 0
}

method x_or_y(n: nat, x: int, y: int) returns (result: int)
ensures IsPrime(n) ==> result == x
ensures !IsPrime(n) ==> result == y
{
if IsPrime(n) {
return x;
} else {
return y;
}
}
15 changes: 5 additions & 10 deletions 152-compare.dfy
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
method Compare(scores: array<int>, guesses: array<int>) returns (result: array<int>)
requires scores.Length == guesses.Length
ensures result.Length == scores.Length
ensures forall i :: 0 <= i < result.Length ==>
result[i] == if scores[i] == guesses[i] then 0 else abs(scores[i] - guesses[i])
ensures forall i :: 0 <= i < result.Length ==> result[i] == abs(scores[i] - guesses[i])
{
result := new int[scores.Length];
var i := 0;
while i < scores.Length
invariant 0 <= i <= scores.Length
invariant result.Length == scores.Length
invariant forall k :: 0 <= k < i ==>
result[k] == if scores[k] == guesses[k] then 0 else abs(scores[k] - guesses[k])
invariant forall k :: 0 <= k < i ==> result[k] == abs(scores[k] - guesses[k])
{
if scores[i] == guesses[i] {
result[i] := 0;
} else {
result[i] := abs(scores[i] - guesses[i]);
}
result[i] := abs(scores[i] - guesses[i]);
i := i + 1;
}
}

function abs(x: int): int
ensures 0 <= abs(x)
{
if x < 0 then -x else x
}
}
59 changes: 59 additions & 0 deletions 153-Strongest_Extension.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
class Extension {
var name: string
var strength: int

constructor(n: string)
ensures name == n
ensures strength == CalculateStrength(n)
{
name := n;
strength := CalculateStrength(n);
}

static function CalculateStrength(s: string): int
{
CountUpperCase(s) - CountLowerCase(s)
}

static function CountUpperCase(s: string): int
{
if |s| == 0 then 0
else (if 'A' <= s[0] <= 'Z' then 1 else 0) + CountUpperCase(s[1..])
}

static function CountLowerCase(s: string): int
{
if |s| == 0 then 0
else (if 'a' <= s[0] <= 'z' then 1 else 0) + CountLowerCase(s[1..])
}
}

method Strongest_Extension(className: string, extensions: seq<string>) returns (result: string)
requires |extensions| > 0
ensures |result| > |className|
ensures result[..|className|] == className
ensures result[|className|] == '.'
ensures var extName := result[|className| + 1..];
extName in extensions
ensures var extName := result[|className| + 1..];
forall i :: 0 <= i < |extensions| ==> Extension.CalculateStrength(extName) >= Extension.CalculateStrength(extensions[i])
{
var strongestExt := new Extension(extensions[0]);
ghost var strongestIndex := 0;

for i := 1 to |extensions|
invariant 0 <= strongestIndex < |extensions|
invariant strongestExt.name == extensions[strongestIndex]
invariant strongestExt.strength == Extension.CalculateStrength(extensions[strongestIndex])
invariant forall j :: 0 <= j < i ==> strongestExt.strength >= Extension.CalculateStrength(extensions[j])
invariant forall j :: 0 <= j < i ==> Extension.CalculateStrength(extensions[strongestIndex]) >= Extension.CalculateStrength(extensions[j])
{
var currentExt := new Extension(extensions[i]);
if currentExt.strength > strongestExt.strength {
strongestExt := currentExt;
strongestIndex := i;
}
}

result := className + "." + strongestExt.name;
}
27 changes: 27 additions & 0 deletions 154-cycpattern_check.dfy
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
predicate IsSubstring(s: string, sub: string)
{
|s| >= |sub| && exists i {:trigger s[i..i+|sub|]} :: 0 <= i <= |s| - |sub| && s[i..i+|sub|] == sub
}

function RotateString(s: string, n: nat): string
requires 0 <= n <= |s|
{
s[n..] + s[..n]
}

method CycpatternCheck(word: string, pattern: string) returns (result: bool)
ensures result ==> exists i :: 0 <= i <= |pattern| && IsSubstring(word, RotateString(pattern, i))
ensures !result ==> forall i :: 0 <= i <= |pattern| ==> !IsSubstring(word, RotateString(pattern, i))
{
var i := 0;
while i <= |pattern|
invariant 0 <= i <= |pattern| + 1
invariant forall j :: 0 <= j < i ==> !IsSubstring(word, RotateString(pattern, j))
{
if IsSubstring(word, RotateString(pattern, i)) {
return true;
}
i := i + 1;
}
return false;
}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ Current status:
- [ ] 127. intersection
- [ ] 128. prod_signs
- [ ] 129. minPath
- [ ] 130. tri
- [x] 130. tri
- [ ] 131. digits
- [ ] 132. is_nested
- [ ] 133. sum_squares
Expand All @@ -141,7 +141,7 @@ Current status:
- [ ] 136. largest_smallest_integers
- [ ] 137. compare_one
- [ ] 138. is_equal_to_sum_even
- [ ] 139. special_factorial
- [x] 139. special_factorial
- [ ] 140. fix_spaces
- [ ] 141. file_name_check
- [ ] 142. sum_squares
Expand All @@ -150,13 +150,13 @@ Current status:
- [ ] 145. order_by_points
- [ ] 146. specialFilter
- [ ] 147. get_max_triples
- [ ] 148. bf
- [x] 148. bf
- [ ] 149. sorted_list_sum
- [ ] 150. x_or_y
- [x] 150. x_or_y
- [ ] 151. double_the_difference
- [x] 152. compare
- [ ] 153. Strongest_Extension
- [ ] 154. cycpattern_check
- [x] 153. Strongest_Extension
- [x] 154. cycpattern_check
- [ ] 155. even_odd_count
- [ ] 156. int_to_mini_roman
- [x] 157. right_angle_triangle
Expand Down
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
perSystem = { pkgs, ... }: {
packages = rec {
packages = {
dafny-check = pkgs.writeShellScriptBin "dafny-check" ''
DIR=''${1:-.}
for f in "$DIR"/*.dfy
Expand Down

0 comments on commit 59b7fa3

Please sign in to comment.