Functions are fun
Zadáno v pondělí 21. 9.
K odevzdání v neděli 4. 10.
Získat můžete až 20 bodů
Pochopení této látky je naprosto zásadní. Nemyslím tím to, že by bylo nutné vše pochopit hned, spíše se snažím naznačit, že opsat úkol od kamaráda vám v tomto případě z dlouhodobého hlediska nepomůže.
Toto je jeden z delších úkolů, proto doporučuji nedělat jej na poslední chvíli, ale každý den si nad ním sednout, trochu se zamyslet a kousek vyřešit. Kdyžtak se mrkněte na zápisy ze čtvrté přednášky.
Zadání
Každý úkol má několik podúkolů (úrovní). Podmínky pro získání základního počtu bodů (10) jsou:
- Splnit z každého úkolu alespoň jeho nejlehčí úroveň
- Alespoň z jednoho úkolu splnit i nějakou složitější úroveň
Za každý podúkol nad rámec těchto dvou podmínek dostanete extra body (podle jeho složitosti) až do maximálního cekového počtu 20 bodů. Podúkoly spolu soouvisí jen velmi volně, tj. úroveň 2 není nutně rozšířenou verzí funkce z úrovně 1 ani nic podobného.
Není-li řečeno jinak, řešte všechny úlohy jedinou funkcí, a nepoužívejte jiné funkce než ty, se kterými jsme pracovali v hodině. Svá řešení pište způsobem, jaký jsme si ukazovali na poslední přednášce (tj. funkce volá samu sebe).
Všechna zadání u sebe mají testy s několika modelovými vstupy a výstupy; to by vám mělo pomoci zjistit, zda se vaše řešení ubírá správným směrem. Doporučuji vám proto prostě zkopírovat zadání i s testy a dopsat do něj své řešení.
První úkol (number)
Úroveň 1
fun sum-n(n :: Number) -> Number: doc: "Returns the sum of all numbers from 0 to [n]: 0 + 1 + 2 + ... + n" ... where: sum-n(-10) is 0 sum-n(-5) is 0 sum-n(0) is 0 sum-n(1) is 1 sum-n(2) is 1 + 2 sum-n(3) is 1 + 2 + 3 end
Úroveň 2 (1 bod)
fun num-power(base :: Number, power :: Number) -> Number: doc: "Returns [base] to the power of [power]. [power] is always non-negative (i.e. 0 or higher)" ... where: num-power(-1, 3) is -1 num-power(-1, 2) is 1 num-power(3, 3) is 27 num-power(3, 0) is 1 num-power(5, 2) is 25 end
Úroveň 3 (2 body)
Raději zde připomínám, že máte všechny úlohy řešit pomocí metody "funkce volá samu sebe".
fun count-factors(upper-bound :: Number, n :: Number) -> Number: doc: "Counts the positive numbers that are less than or equal to [upper-bound] that are divisible by [n]" ... where: count-factors(10, 2) is 5 # i.e. 2, 4, 6, 8, 10 count-factors(10, 5) is 2 # i.e. 5, 10 count-factors(7, 1) is 7 # i.e. 1, 2, 3, 4, 5, 6, 7 end
Jak zjistíte, kdy je jedno číslo dělitelné jiným (beze zbytku)? Mrkněte na funkci num-modulo
.
Druhý úkol (string)
Ke všem třem úrovním budete potřebovat funkce string-first
a string-rest
, které můžete naimportovat pomocí
include shared-gdrive("string-utils", "1QChebN-p7mUEmccxwsn-3Xz6X-4k9gFd")
Funkce string-first(str)
vrací první písmeno ve stringu str
, zatímco string-rest
vrací zbytek stringu (tj. od druhého písmena dál). Příklady:
string-first("Evžen") # -> "E" string-rest("Evžen") # -> "vžen" string-first("retPy") # -> "r" string-rest("retPy") # -> "etPy" string-first("n") # -> "n" string-rest("n") # -> "" string-first("") # -> "" string-rest("") # -> "" # Vždy platí string-first(str) + string-rest(str) is str
Úroveň 1
fun drop-n(n :: Number, str :: String) -> String: doc: "Returns [str] with its first [n] characters removed. [n] is always non-negative." ... where: drop-n(0, "Evžen") is "Evžen" drop-n(1, "Evžen") is "vžen" drop-n(2, "Evžen") is "žen" drop-n(5, "Evžen") is "" drop-n(20, "Evžen") is "" end
Úroveň 2 (2 body)
fun char-at(index :: Number, str :: String) -> String: doc: "Returns the character at the index [index]. [index] will always point to a valid location in [str]" ... where: char-at(0, "Pyret") is "P" char-at(1, "Pyret") is "y" char-at(4, "Pyret") is "t" end
Úroveň 3 (2 body)
fun replace-character( char :: String, replacement :: String, str :: String) -> String: doc: "Returns [str] with all occurences of [char] replaced by [replacement]. [char] is always one character." ... where: replace-character("E", "e", "Evžen") is "evžen" replace-character("E", "Ne", "Evžen") is "Nevžen" replace-character("ž", "", "Evžen") is "Even" replace-character("a", "b", "Evžen") is "Evžen" replace-character("e", "oo", "bumblebee") is "bumblooboooo" replace-character("E", "EE", "Evžen") is "EEvžen" end
Třetí úkol (boolean)
U druhé a třetí úrovně se opět budou chodit funkce string-first
a string-rest
, viz kapitola "Druhý úkol (string)" výše.
Úroveň 1
fun divides(n :: Number, k :: Number) -> Boolean: doc: "Returns true if [n] is divisible by [k], false otherwise. [k] is always positive (i.e. greater than 0)" ... where: divides(1, 1) is true divides(2, 2) is true divides(3, 2) is false divides(4, 2) is true divides(10, 10) is true divides(10, 1) is true divides(10, 5) is true divides(10, 7) is false divides(10, 20) is false end
Úroveň 2 (1 bod)
fun string-has-character(character :: String, str :: String) -> Boolean: doc: "Returns true if [character] is somewhere in [str], false otherwise. [character] is always one character" ... where: string-has-character("E", "Evžen") is true string-has-character("V", "Evžen") is false string-has-character("v", "Evžen") is true string-has-character("v", "") is false string-has-character("a", "abracadabra") is true end
Úroveň 3 (1 bod)
Parametry str
budou u obou následujících funkcí stringy skládající se pouze z f
a t
, kde f
představuje false
a t
zase true
.
fun all(str :: String) -> Boolean: doc: "Returns true if [str] doesn't have any 'f' in it, false otherwise" # In other words, it is a bit like a generalization of 'and', everything has to be true ... where: all("") is true all("t") is true all("f") is false all("tttt") is true all("tttttf") is false end fun at-least-one(str :: String) -> Boolean: doc: "Returns true if [str] has at least one 't' in it, false otherwise" # In other words, it is a bit like a generalization of 'or', at least one thing has to be true ... where: at-least-one("") is false at-least-one("t") is true at-least-one("f") is false at-least-one("tttt") is true at-least-one("tttttf") is true end
Čtrvtý úkol (image)
Úroveň 1
fun repeat-image-h(n :: Number, img :: Image ) -> Image: doc: "Repeats the image [n] times (horizontally). [n] is always non-negative" ... where: test-img = rectangle(100, 100, "solid", "blue") # empty-image is imported automatically with include image repeat-image-h(0, test-img) is empty-image repeat-image-h(1, test-img) is beside(empty-image, test-img) repeat-image-h(2, test-img) is beside(test-img, test-img) repeat-image-h(3, test-img) is beside(beside(test-img, test-img), test-img) end
Úroveň 2 (1 bod)
fun stripe(n :: Number) -> Image: doc: "Returns a striped line made from [n] 50x50 squares with alternating blue/red colors. [n] is non-negative." ... where: blue-square = square(50, "solid", "blue") red-square = square(50, "solid", "red") # empty-image is imported automatically with include image stripe(0) is empty-image stripe(1) is beside( blue-square, empty-image) stripe(2) is beside( red-square, beside(blue-square, empty-image)) stripe(3) is beside( blue-square, beside(red-square,beside(blue-square, empty-image))) end
Na lichých místech (od konce) chcete modré čtverce, na sudých červené. Bude se vám hodit funkce num-modulo
.
Příklady:

Úroveň 3 (3 body)
Podívejte se na příklady níže.
fun rotate-n-times(n :: Number, img :: Image) -> Image: doc: """Constructs a symmetric image in [n] steps. In each step, [img] is rotated by some computed angle in such a way that in the end the images 'fill' the whole circle""" # Compute the angle here and pass it to rotate-n-times-angle ... end fun rotate-n-times-angle(n :: Number, angle :: Number, img :: Image): doc: "Overlays [n] images over themselves by rotating each image by [angle]" ... end
Příklady:
