Last active
December 24, 2015 23:59
-
-
Save jlemmett/6883920 to your computer and use it in GitHub Desktop.
Clojure-esimerkki tehtävästä "etsi suurin viiden peräkkäisen numeron tulo annetusta lukumerkkijonosta"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Apufunktio, joka muuttaa merkkijonoluvun numeeriseksi tyypiksi | |
(defn as-int [char] | |
(Character/getNumericValue char)) | |
;; Funktio, joka palauttaa suurimman viiden peräkkäisen numeron tulon annetusta lukumerkkinonosta | |
(defn max-of-5-multiply-v1 [str] (apply max (map #(apply * %) (partition 5 1 (map as-int str))))) | |
;; Käyttöesimerkki | |
(def numbers-in-string (str "37900490610897696126265185408732594047834333441947" | |
"01850393807417064181700348379116686008018966949867" | |
"75587222482716536850061657037580780205386629145841" | |
"06964490601037178417735301109842904952970798120105" | |
"47016802197685547844962006690576894353336688823830" | |
"22913337214734911490555218134123051689058329294117" | |
"83011983450277211542535458190375258738804563705619" | |
"55277740874464155295278944953199015261800156422805" | |
"72771774460964310684699893055144451845092626359982" | |
"79063901081322647763278370447051079759349248247518")) | |
(max-of-5-multiply-v1 numbers-in-string) | |
;; palauttaa 34992 | |
;; Alla purettuna osiin | |
;; Määritellään funktio nimellä max-of-5-multiply-v1 | |
(defn max-of-5-multiply-v1 | |
;; Funktion ottaa parametrin `str` | |
[str] | |
;; Kutsutaan `max`-funktiota sekvenssille, joka muodostuu alempana tulevista funktiokutsuista. | |
;; Kun funktiota kutsutaan epäsuorasti apply-funktion kautta, purkaa apply viimeisenä parametrina | |
;; tulevan sekvenssin erillisiksi parametreiksi: (apply max [1 2 3 4]) on sama kuin (max 1 2 3 4) | |
;; max palauttaa lukusekvenssin suurimman arvon eli yllä se palauttaisi arvon 4 | |
(apply max | |
;; `map`-funktio suorittaa sille ensimmäisenä parametrina annetun funktion sille toisena parametrina | |
;; annetun kokoelman jokaiselle elementille ja palauttaa nämä funktion läpi ajetut elementit uudessa | |
;; kokoelmassa | |
(map | |
;; Anonyymi funktio, joka kutsuu kertolaskufunktiota (*) saamalleen parametrille. Prosenttimerkki on | |
;; merkkaa funktiolle tulevaa parametria tässä anonyymien funktioiden #()-syntaksissa. | |
;; apply purkaa taas mahdollisesti saamansa sekvenssin-tyyppisen parametrin yksittäisiksi | |
;; parametreiksi: (apply * [1 2 3]) on sama kuin (* 1 2 3) | |
#(apply * %) | |
;; `partition`-funktio ottaa sekvenssin ja jakaa sen n pituisiin osiin (tässä 5). Valinnainen | |
;; toinen parametri määrää kuinka paljon syötesekvenssissä edetään kunkin osituksen kohdalla. | |
;; Esim. (partition 2 '(1 2 3 4 5 6)) -> ((1 2) (3 4) (5 6)) , | |
;; mutta (partition 2 1 '(1 2 3 4 5 6)) -> ((1 2) (2 3) (4 5) (5 6)) | |
;; Tässä siis (partition 5 1 ...) jakaa saamansa sekvenssiin perättäisiin viiden elementin osiin. | |
(partition 5 1 | |
;; Numeroista koostuva merkkijono str muunnetaan tässä sekvenssiksi oikeita numeroita kutsumalla | |
;; jokaiselle merkille `as-int` -funktiota. Koska merkkijonotkin ovat sekvenssejä, voidaan niitä | |
;; transformoida `map`-funktiolla. | |
(map as-int str))))) | |
;; Funktion suoritus lähtee liikkeelle lopusta: | |
;; 1) Merkkijono "37900490610..." muutetaan sekvenssiksi yksittäisiä numeroita: '(3 7 9 0 0 4 ..) | |
;; 2) Numerosekvenssi osioidaan (partition 5 1 .. ) -kutsulla, jolloin ulos tulee sekvenssi viiden | |
;; luvun sekvenssejä: ((3 7 9 0 0) (7 9 0 0 4) (9 0 0 4 9) ..) | |
;; 3) Sekvenssien sekvenssi ajetaan map-funktion läpi kutsuen jokaiselle elementille (yksittäiselle | |
;; viiden luvun sekvenssille) funktiota (apply * %) joka kertoo viisi lukua yhteen. Tällöin ulos | |
;; tulee sekvenssi viiden luvun tuloja (0 0 0 ... 27216 ... ) | |
;; 4) Tulojen sekvenssille kutsutaan max-funktiota, joka palauttaa suurimman tulon | |
;; Helpompilukuisempi versio voidaan toteuttaa ->> -makrolla, joka 'vetää' sille annetun lausekkeen | |
;; (expression) (tässä str) sitä seuraavien lausekelistojen (form) läpi asettaen sen aina kunkin | |
;; lausekelistan viimeiseksi alkioksi: | |
(defn max-of-5-multiply-v2 [str] (->> str (map as-int) (partition 5 1) (map #(apply * %)) (apply max))) | |
;; Tässä siis str menee ensiksi map-kutsun viimeiseksi parametriksi: (map as-int str). Tämän jälkeen | |
;; tämä n tulos menee (partition 5 1)-kutsun viimeiseksi parametriksi: (partition 5 1 (map as-int str)) | |
;; ja niin edelleen. | |
;; Tämä siis tuottaa lopulta täysin saman koodin kuin ensimmäinen versio, mutta voidaan lukea | |
;; luonnollisemmin suoritusjärjestyksessä alusta loppuun. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment