diff --git a/065-circular_shift.dfy b/065-circular_shift.dfy new file mode 100644 index 0000000..e2d580c --- /dev/null +++ b/065-circular_shift.dfy @@ -0,0 +1,92 @@ +method circular_shift(a: nat, shift: nat) returns (shifted: string) + // post-conditions-start + ensures |shifted| == |natToString(a)| + ensures var s := natToString(a); shift > |s| ==> forall i :: 0 <= i < |s| ==> shifted[i] == s[|s| - 1 - i] + ensures var s := natToString(a); shift <= |s| ==> shifted == s[|s| - shift..] + s[..|s| - shift] + // post-conditions-end +{ + // impl-start + var s := natToString(a); + if shift > |s| { + s := reverse(s); + return s; + } + + shifted := ""; + var i := 0; + var start := |s| - shift; + while i < shift + // invariants-start + invariant 0 <= i <= shift + invariant shifted == s[|s| - shift..][..i] + // invariants-end + { + shifted := shifted + [s[start + i]]; + i := i + 1; + } + var added := ""; + i := 0; + while i < |s| - shift + // invariants-start + invariant 0 <= i <= |s| - shift + invariant added == s[..|s| - shift][..i] + // invariants-end + { + added := added + [s[i]]; + i := i + 1; + } + assert shifted == s[|s| - shift..]; // assert-line + assert added == s[..|s| - shift]; // assert-line + shifted := shifted + added; + // impl-end +} + +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 +{ +} + +method reverse(str: string) returns (rev: string) + // post-conditions-start + ensures |rev| == |str| + ensures forall k :: 0 <= k < |str| ==> rev[k] == str[|str| - 1 - k] + // post-conditions-end +{ + // impl-start + rev := ""; + var i := 0; + while (i < |str|) + // invariants-start + invariant i >= 0 && i <= |str| + invariant |rev| == i + invariant forall k :: 0 <= k < i ==> rev[k] == str[|str| - 1 - k] + // invariants-end + { + rev := rev + [str[|str| - i - 1]]; + i := i + 1; + } + // impl-end +} diff --git a/079-decimal_to_binary.dfy b/079-decimal_to_binary.dfy new file mode 100644 index 0000000..c6ad7b1 --- /dev/null +++ b/079-decimal_to_binary.dfy @@ -0,0 +1,39 @@ +type stringBin = s: string | + |s| > 0 && (|s| > 1 ==> s[0] != '0') && + forall i | 0 <= i < |s| :: s[i] in "01" + witness "1" + +function decimal_to_binary(n: nat): (s: string) + // post-conditions-start + ensures |s| == |decimal_to_binary_helper(n)| + 4 + ensures s[..2] == "db" + ensures s[|s| - 2..] == "db" + ensures s[2..|s| - 2] == decimal_to_binary_helper(n) + // post-conditions-end +{ + // impl-start + "db" + decimal_to_binary_helper(n) + "db" + // impl-end +} + +function decimal_to_binary_helper(n: nat): stringBin + // post-conditions-start + ensures binary_to_decimal(decimal_to_binary_helper(n)) == n + // post-conditions-end +{ + // impl-start + match n + case 0 => "0" case 1 => "1" + case _ => decimal_to_binary_helper(n / 2) + decimal_to_binary_helper(n % 2) + // impl-end +} + +function binary_to_decimal(s: stringBin): nat + decreases |s| +{ + if |s| == 1 then + match s[0] + case '0' => 0 case '1' => 1 + else + binary_to_decimal(s[..|s|-1])*2 + binary_to_decimal(s[|s|-1..|s|]) +} diff --git a/README.md b/README.md index e273db8..e2864e4 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Current status: - [x] 62. derivative - [x] 63. fibfib - [x] 64. vowels_count -- [ ] 65. circular_shift +- [x] 65. circular_shift - [x] 66. digitSum - [ ] 67. fruit_distribution - complex strings, possibly doable - [x] 68. pluck @@ -81,7 +81,7 @@ Current status: - [x] 76. is_simple_power - [x] 77. iscube - [x] 78. hex_key -- [ ] 79. decimal_to_binary +- [x] 79. decimal_to_binary - [x] 80. is_happy - [x] 81. numerical_letter_grade - [x] 82. prime_length diff --git a/REMAINING.md b/REMAINING.md index c08b502..8d3c9b1 100644 --- a/REMAINING.md +++ b/REMAINING.md @@ -10,8 +10,6 @@ Current status: - [ ] 32. poly - [ ] 38. encode_cyclic - [ ] 47. median -- [ ] 65. circular_shift -- [ ] 79. decimal_to_binary - [ ] 90. next_smallest - nullable - [ ] 103. rounded_avg - [ ] 113. odd_count