Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

130, 139, 148, 150, 153, 154 #7

Merged
merged 1 commit into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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