"If I had a nickel for every time I've written "for (i = 0; i < N; i++)" in C I'd be a millionaire."
- Mike Vanier
Taka mała zagadka: Ilu programistów .NET potrzeba, by zabić karalucha?
(odpowiedź na końcu wpisu.).
Problem 27: for the win
Makro to bierze za pierwszy argument wektor powiązań (podobnie jak let i opcjonalnie trzy modyfikatory:
- :let [ powiązania dla dodatkowych zmiennych pomocniczych ]
- :when ( test ) - zmienne w iteracji zostaną przekazane po spełnieniu testu
- :while ( test ) - for zakończy działanie po negatywnym wyniku testu
Powiązania (nie dotyczy :let) muszą być sekwencjami np.: (for [x '(3 4) z [1 2]] (...) ). Elementy sekwencji będą łączone na zasadzie każdy z każdym. To jest dla każdego elementu x zostanie przypisany każdy element z i taka postać przekazana jako parametry do bloku wykonania. Blok wykonania zwraca wartość, z której po każdej iteracji będzie budowana sekwencja. Tak, że for służy do budowania sekwencji na podstawie innych sekwencji.
W teście T1 mam for, które będzie się wykonywać dla każdego x z sekwencji zbudowanej przy pomocy funkcji range). W tym przypadku range zwróci kolekcję liczb od 0 do 39 włącznie z krokiem 1. Iterując po każdym elemencie zostaje sprawdzony warunek :when, który zwraca prawdę jeżeli reszta z dzielenia elementu x kolekcji przez 4 (funkcja rem będzie równa 1. Dzięki temu zostanie zbudowana kolekcja elementów, których reszta z dzielenia przez 4 jest 1. Wynik w ostateczności powinien wyglądać tak: (1 5 9 13 17 21 25 29 33 37).
W teście T2 x jest nieskończoną kolekcją zwróconą przez funkcję iterate. Funkcja ta bierze za pierwszy argument funkcję, a za drugi wartość początkową. Funkcja anonimowa zwraca wartość argumentu powiększonego o 4. Stąd x będzie mieć postać: (0 4 8 12 ... ). Modyfikator :let tworzy zmienną pomocniczą z, która będzie mieć wartość elementu x powiększonego o 1. Modyfikator :while sprawdza, czy z jest mniejsze od 40, jeżeli nie, to kończy działanie for
W teście T3 for iteruje po parach liczb utworzonych poprzez utworzenie kolekcji liczb
(0 1 2 3 ... 19) podzielonej na kolekcję dwuelementowych list : ( (0 1) (2 3) (4 5) .... (18 19) ).
Wynikiem jest lista, której elementy to sumy par liczb.
Pary i większe kolekcje liczb można przypisywać do zmiennych lokalnych w rózny sposób, np:
(let [ x 1 y 2 ] (+ x y)) |
(let [ [x y] '(1 2) ] (+ x y)) |
(let [ x (first '(1 2)) y (second '(1 2)) ] (+ x y)) |
T1: (= __ (for [x (range 40) :when (= 1 (rem x 4))] x)) T2: (= __ (for [x (iterate #(+ 4 %) 0) :let [z (inc x)] :while (< z 40)] z)) T3: (= __ (for [[x y] (partition 2 (range 20))] (+ x y)))
E1: '(1 5 9 13 17 21 25 29 33 37). E2: [1 5 9 13 17 21 25 29 33 37].
|
Problem 28: Logical falsity and truth
T1: (= __ (if-not false 1 0)) T2: (= __ (if-not nil 1 0)) T3: (= __ (if true 1 0)) T4: (= __ (if [] 1 0)) T5: (= __ (if [0] 1 0)) T6: (= __ (if 0 1 0)) T7: (= __ (if 1 1 0)) E1: 1
|
Problem 29: Map defaults
(:k {:a 0, :b 1, :c nil} :not_exist) |
A co jeżeli chcemy utworzyć mapę i nadać kluczom jakaś domyślną wartość?
Zadanie polega na utworzeniu funkcji, która pobierze sekwencję kluczy, wartość domyślną i utworzy z nich mapę. Mapę w najprostszy sposób tworzy się poprzez (hash-map klucz dane) lub {klucz dane}. Wiadomo, że przez elementy sekwencji można iterować przez użycie map lub for. Funkcja map bierze za parametr funkcję, którą stosuje dla każdego elementu sekwencji. Stąd mając domyślą wartość klucza i sekwencję kluczy można zwrócić sekwencję map. Złączyć to można poleceniem conj i funkcją apply lub reduce.
Rozpiszę główne etapy:
1. map ... : ({:a 0} {:b 0} {:c 0})
2. apply conj ... : {:a 0 :b 0 :c 0}
z czego apply tworzy listę w sposób: (conj {:a 0} {:b 0} {:c 0})
reduce: (conj {:a 0} {:b 0}) -> (conj {:a 0 :b 0} {:c 0}) ...
Zadanie:
(= (__ 0 [:a :b :c]) {:a 0 :b 0 :c 0}) (= (__ "x" [1 2 3]) {1 "x" 2 "x" 3 "x"}) (= (__ [:a :b] [:foo :bar]) {:foo [:a :b] :bar [:a :b]})
E1: #(reduce conj (map (fn [d] {d %1}) %2)) E2: #(apply conj (map (fn [d] {d %1}) %2)) |
Odpowiedź na zagadkę: Dwóch. Jeden trzyma karalucha, by nie uciekł, a drugi instaluje na nim Windows.
Brak komentarzy:
Prześlij komentarz