Skip to content

Instantly share code, notes, and snippets.

@jlemmett
Last active December 24, 2015 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlemmett/6883920 to your computer and use it in GitHub Desktop.
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"
;; 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