diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e840617b6..c942f3bc2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -37,4 +37,5 @@ - Ken Power - PaddyKe - nic-hartley +- Thijs Raymakers - crafter312 diff --git a/book.json b/book.json index 7fae5c319..9e872d1da 100644 --- a/book.json +++ b/book.json @@ -167,6 +167,10 @@ { "lang": "lolcode", "name": "LOLCODE" + }, + { + "lang": "piet", + "name": "Piet" } ] } diff --git a/contents/euclidean_algorithm/code/piet/euclidian_algorithm.piet b/contents/euclidean_algorithm/code/piet/euclidian_algorithm.piet new file mode 100644 index 000000000..d91499ae5 --- /dev/null +++ b/contents/euclidean_algorithm/code/piet/euclidian_algorithm.piet @@ -0,0 +1,146 @@ +This file describes the path that the Piet program takes in a more human readable form. +Two functions are implemented: +- GCD with subtraction +- GCD with the modulo operator + +------------------- +SUBTRACTION +------------------- + +Pseudo code: + +function gcd(a, b) + while a ≠ b + if a > b + a := a − b; + else + b := b − a; + return a; + + +Piet code: + +COMMAND STATE OF STACK +in(number) A // Take A as an input +duplicate AA // Start to take the absolute value of A +push 1 1AA +duplicate 11AA +subtract 0AA +greater 0/1A // 1 if A > 0, 0 if A <= 0 +not 1/0A // 0 if A > 0, 1 if A <= 0 +push 1 1 1/0 A +push 3 31 1/0 A +subtract -2 1/0 A +multiply -2/0 A +push 1 1 -2/0 A +add -1/1 A +multiply A // A should now be an absolute value + +in(number) BA // Take B as an input +duplicate BBA // Start to take the absolute value of B +push 1 1BBA +duplicate 11BBA +subtract 0BBA +greater 0/1BA // 1 if B > 0, 0 if B <= 0 +not 1/0BA // 0 if B > 0, 1 if B <= 0 +push 1 1 1/0 BA +push 3 31 1/0 BA +subtract -2 1/0 BA +multiply -2/0 BA +push 1 1 -2/0 BA +add -1/1 BA +multiply BA // B should now be an absolute value + +// Start of the main loop while a ≠ b +duplicate BBA +push 3 3BBA +push 2 23BBA +roll ABB +duplicate AABB +push 4 4AABB +push 1 14AABB +roll ABBA +subtract 0/x BA +not 1/0 BA // 1 if a = b and 0 if a ≠ b +not 0/1 BA // 1 if a ≠ b and 0 if a = b +pointer BA // If a ≠ b, the DP should change one clockwise, otherwise, go straight ahead. + + // Go left if a ≠ b (DP changed one clockwise) + duplicate BBA + push 3 3BBA + push 2 23BBA + roll ABB + duplicate AABB + push 4 4AABB + push 1 14AABB + roll ABBA + push 2 2ABBA + push 1 12ABBA + roll BABA + greater 0/1 BA // A > B; 1 if true; 0 if false + pointer BA // If A > B, DP goes one clockwise, otherwise, DP stays the same. + + // If A > B (DP has changed 1 clockwise) + duplicate BBA + push 3 3BBA + push 1 13BBA + roll BAB + subtract AB // A = A - B + push 2 2AB + push 1 12AB + roll BA + // Go back to start of loop + + // If B > A (DP stayed the same) + push 2 2BA + push 1 12BA + roll AB + duplicate AAB + push 3 3AAB + push 1 13AAB + roll ABA + subtract BA // B = B - A + // Go back to start of loop + +// Go down if a = b (end of while loop) +pop A +out(number) - // Print out A when done. + +--------------------------------------------------------------------------- + +------------------- +MODULO +------------------- + +Pseudo code: + +function gcd(a, b) + while b ≠ 0 + t := b; + b := a mod b; + a := t; + return a; + +Piet code: + +COMMAND STATE OF STACK +in(number) A +in(number) BA + +// Start of loop +duplicate BBA +not 0/1 BA +not 1/0 BA +pointer BA + + // Go down if b ≠ 0 + duplicate TBA + push 3 3TBA + push 1 13TBA + roll BAT + mod BA // b = a mod b; a = t + // Go back to the start of the loop + +// Go right if b = 0 +pop A +out(number) - // Print out A when done. diff --git a/contents/euclidean_algorithm/code/piet/mod/euclidian_algorithm_mod.png b/contents/euclidean_algorithm/code/piet/mod/euclidian_algorithm_mod.png new file mode 100644 index 000000000..62459a135 Binary files /dev/null and b/contents/euclidean_algorithm/code/piet/mod/euclidian_algorithm_mod.png differ diff --git a/contents/euclidean_algorithm/code/piet/mod/euclidian_algorithm_mod_large.png b/contents/euclidean_algorithm/code/piet/mod/euclidian_algorithm_mod_large.png new file mode 100644 index 000000000..026568aad Binary files /dev/null and b/contents/euclidean_algorithm/code/piet/mod/euclidian_algorithm_mod_large.png differ diff --git a/contents/euclidean_algorithm/code/piet/subtract/euclidian_algorithm_subtract.png b/contents/euclidean_algorithm/code/piet/subtract/euclidian_algorithm_subtract.png new file mode 100644 index 000000000..94070f61a Binary files /dev/null and b/contents/euclidean_algorithm/code/piet/subtract/euclidian_algorithm_subtract.png differ diff --git a/contents/euclidean_algorithm/code/piet/subtract/euclidian_algorithm_subtract_large.png b/contents/euclidean_algorithm/code/piet/subtract/euclidian_algorithm_subtract_large.png new file mode 100644 index 000000000..423b71776 Binary files /dev/null and b/contents/euclidean_algorithm/code/piet/subtract/euclidian_algorithm_subtract_large.png differ diff --git a/contents/euclidean_algorithm/euclidean_algorithm.md b/contents/euclidean_algorithm/euclidean_algorithm.md index ff05c7af9..8e336f174 100644 --- a/contents/euclidean_algorithm/euclidean_algorithm.md +++ b/contents/euclidean_algorithm/euclidean_algorithm.md @@ -63,6 +63,8 @@ The algorithm is a simple way to find the *greatest common divisor* (GCD) of two [import:25-40, lang="LOLCODE"](code/lolcode/euclid.lol) {% sample lang="bash" %} [import:24-38, lang="bash"](code/bash/euclid.bash) +{% sample lang="piet" %} +> ![](code/piet/subtract/euclidian_algorithm_subtract_large.png) ![](code/piet/subtract/euclidian_algorithm_subtract.png) {% endmethod %} Here, we simply line the two numbers up every step and subtract the lower value from the higher one every timestep. Once the two values are equal, we call that value the greatest common divisor. A graph of `a` and `b` as they change every step would look something like this: @@ -132,6 +134,8 @@ Modern implementations, though, often use the modulus operator (%) like so [import:9-23, lang="LOLCODE"](code/lolcode/euclid.lol) {% sample lang="bash" %} [import:10-22, lang="bash"](code/bash/euclid.bash) +{% sample lang="piet" %} +> ![](code/piet/mod/euclidian_algorithm_mod_large.png) ![](code/piet/mod/euclidian_algorithm_mod.png) {% endmethod %} Here, we set `b` to be the remainder of `a%b` and `a` to be whatever `b` was last timestep. Because of how the modulus operator works, this will provide the same information as the subtraction-based implementation, but when we show `a` and `b` as they change with time, we can see that it might take many fewer steps: @@ -209,6 +213,17 @@ and modulo method: [import, lang="LOLCODE"](code/lolcode/euclid.lol) {% sample lang="bash" %} [import, lang="bash"](code/bash/euclid.bash) +{% sample lang="piet" %} +A text version of the program is provided for both versions. +#### Subtraction +> ![](code/piet/subtract/euclidian_algorithm_subtract_large.png) ![](code/piet/subtract/euclidian_algorithm_subtract.png) + +[import:23-107](code/piet/euclidian_algorithm.piet) + +#### Modulo +> ![](code/piet/mod/euclidian_algorithm_mod_large.png) ![](code/piet/mod/euclidian_algorithm_mod.png) + +[import:126-146](code/piet/euclidian_algorithm.piet) {% endmethod %}