Famous "99 problems", referring to https://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html, written in Clojure.
As an exercise when I read the book Clojure Programming (Emerick).
; P01 - general version for lists and vectors | |
(defn p01 [l] | |
(let [n (next l)] | |
(if (nil? n) (first l) (recur n)) | |
) | |
) | |
; P01 - use destructing assignment, works for lists and vectors | |
(defn p01' [l] | |
(let [[head & rest] l] | |
(if (nil? rest) head (recur rest)) | |
) | |
) | |
; P01 - version works only for vectors | |
(defn p01'' [l] | |
(get l (- (count l) 1)) | |
) | |
; P02 - modified from p01'; works for lists; slightly modification needed to work with vectors | |
(defn p02 [l] | |
(let [[first second & rest] l] | |
(if (nil? rest) (into (empty l) [second first]) (recur (next l))) | |
) | |
) | |
; P03 - general version for lists and vectors | |
(defn p03 [l n] | |
(if (= n 1) (first l) (recur (next l) (- n 1))) | |
) | |
; P03 - version works only for vectors | |
(def p03' #(% (- %2 1))) | |
; P04 - recursive version, for lists and vectors | |
(defn p04 [l] | |
(if (nil? l) 0 (+ 1 (p04 (next l)))) | |
) | |
; P04 - tail recursive version, for lists and vectors | |
(defn p04' | |
([l n] (if (nil? l) n (recur (next l) (inc n)))) | |
([l] (p04 l 0)) | |
) | |
; P04 - built-in version | |
(def p04'' count) | |
; P05 - tail recursive lisp-style, for lists and vectors, though it will reverses a vector to a list | |
(defn p05 | |
([l acc] (if (nil? l) | |
acc | |
(recur (next l) (cons (first l) acc)) | |
)) | |
([l] (p05 l nil)) | |
) | |
; P05 - built-in version, it will also reverses a vector to a list | |
(def p05' reverse) | |
; P06 - simple version using P05: only works for lists | |
(def p06 #(= % (reverse %))) | |
; P07 - based on P05; only works for lists | |
(defn p07 | |
([l acc] (if (nil? l) | |
acc | |
(if (list? l) | |
(recur (next l) (p07 (first l) acc)) | |
(cons l acc) | |
) | |
)) | |
([l] (reverse (p07 l nil))) | |
) | |
(def p07' flatten) | |
; P08 - based on P05; only works for lists | |
(defn p08 | |
([l acc] (if (nil? l) | |
acc | |
(recur (next l) | |
(if (= (first l) (first acc)) | |
acc | |
(cons (first l) acc) | |
) | |
) | |
)) | |
([l] (reverse (p08 l nil))) | |
) | |
; P09 - based on P05; only works for lists | |
(defn p09 | |
([l acc] (if (nil? l) | |
acc | |
(recur (next l) | |
(if (= (first l) (first (first acc))) | |
(cons (cons (first l) (first acc)) (next acc)) | |
(cons (list (first l)) acc) | |
) | |
) | |
)) | |
([l] (reverse (p09 l nil))) | |
) | |
; P10 - using built-in map and count function | |
(defn p10 [l] | |
(map #(list (count %) (first %)) (p09 l)) | |
) |
; P11 - slightly modified from P10 | |
(defn p11 | |
([l acc] | |
(if (nil? l) | |
acc | |
(recur (next l) | |
(let [facc (first acc)] | |
(if (= (first l) (first (next facc))) | |
(cons (cons (inc (first facc)) (next facc)) (next acc)) | |
(cons (list 1 (first l)) acc) | |
) | |
) | |
) | |
) | |
) | |
([l] | |
((fn [l acc] (if (nil? l) acc (recur (next l) (cons (let [fl (first l)] (if (= (first fl) 1) (first (next fl)) fl)) acc)))) | |
(p11 l nil) | |
nil | |
) | |
) | |
) | |
; P12 - using reverse again | |
(defn p12 | |
([l acc] | |
(let [group (fn | |
[content count acc] | |
(if (= count 0) | |
acc | |
(recur content (- count 1) (cons content acc)) | |
))] | |
(if (nil? l) | |
acc | |
(let [fl (first l)] | |
(recur (next l) | |
(if (list? fl) | |
(group (first (next fl)) (first fl) acc) | |
(cons fl acc) | |
) | |
) | |
) | |
) | |
) | |
) | |
([l] (reverse (p12 l nil))) | |
) | |
; P12 - using the built-in flatten and map functions | |
(defn p12' | |
[l] | |
(flatten (map (fn [item] | |
(if (list? item) (repeat (first item) (first (next item))) item) | |
) l)) | |
) | |
; P13 - slightly modified from P09; only works for lists | |
(defn p13 | |
([l acc] (if (nil? l) | |
acc | |
(recur (next l) | |
(let [facc (first acc)] | |
(if (= (first l) (first (next facc))) | |
(cons (cons (inc (first facc)) (next facc)) (next acc)) | |
(cons (list 1 (first l)) acc) | |
) | |
) | |
) | |
)) | |
([l] (reverse (p13 l nil))) | |
) | |
; P14 - recursive version | |
(defn p14 [l] | |
(if (nil? l) nil (cons (first l) (cons (first l) (p14 (next l))))) | |
) | |
; P14 - tail recursive version using reverse | |
(defn p14' | |
([l acc] (if (nil? l) | |
acc | |
(recur (next l) (cons (first l) (cons (first l) acc))) | |
)) | |
([l] (reverse (p14' l nil))) | |
) | |
; P14 - using the built-in flatten and map functions | |
(defn p14'' [l] | |
(flatten (map #(list % %) l)) | |
) | |
; P15 - modifying P14 for a bit | |
(defn p15 [l t] | |
(let [append (fn repeated [content remaining source] (if (= remaining 0) source (cons content (repeated content (- remaining 1) source))))] | |
(if (nil? l) nil (append (first l) t (p15 (next l) t))) | |
) | |
) | |
; P15 - using built-in functions | |
(defn p15' [l t] | |
(flatten (map #(repeat 3 %) l)) | |
) | |
; P16 - recursive version | |
(defn p16 | |
([l n t] | |
(if (nil? l) nil | |
(let [remaining (p16 (next l) n (inc t))] | |
(if (= 0 (mod t n)) remaining (cons (first l) remaining)) | |
) | |
) | |
) | |
([l n] (p16 l n 1)) | |
) | |
; P17 - recursive version using no predefined predicatess | |
(defn p17 [l n] | |
(if (= n 0) | |
(list nil l) | |
(let [tp (p17 (next l) (- n 1))] | |
(cons | |
(cons (first l) (first tp)) | |
(next tp) | |
) | |
) | |
) | |
) | |
; P18 - using P17 | |
(defn p18 [l s e] | |
(first (p17 (first (next (p17 l (- s 1)))) (- e (- s 1)))) | |
) | |
; P19 - using P17 and build-n flatten | |
(defn p19 [l r] | |
(let [n (mod r (count l))] | |
(let [parts (p17 l n)] | |
(if (= n 0) l (flatten (list (first (next parts)) (first parts)))) | |
) | |
) | |
) | |
; P20 - recursive version, stripped from P16 | |
(defn p20 [l n] | |
(if (nil? l) nil | |
(let [remaining (p20 (next l) (- n 1))] | |
(if (= 1 n) remaining (cons (first l) remaining)) | |
) | |
) | |
) |
; P21 - recursive version, modified from p20 | |
(defn p21 [i l n] | |
(if (= 1 n) (cons i l) | |
(if (nil? l) nil | |
(cons (first l) (p21 i (next l) (- n 1))) | |
) | |
) | |
) | |
; P22 - tail recursive version | |
(defn p22 | |
([s e acc] | |
(if (< e s) acc | |
(recur s (- e 1) (cons e acc)) | |
) | |
) | |
([s e] (p22 s e nil)) | |
) | |
; P22 - built-in version | |
(def p22' #(range % (inc %2))) | |
; P23 - using P20 | |
(defn p23 [l r] | |
(let [cl (count l)] | |
(if (= r cl) l | |
(recur (p20 l (rand-int cl)) r) | |
) | |
) | |
) | |
; P24 - using P22 and P23 | |
(def p24 #(p23 (p22 1 %2) %)) | |
; P25 - using P03 and P20 | |
(defn p25 | |
([l acc] | |
(if (nil? l) acc | |
(let [tk (inc (rand-int (count l)))] | |
(recur (p20 l tk) (cons (p03 l tk) acc)) | |
) | |
) | |
) | |
([l] (p25 l nil)) | |
) | |
; P26 - naive brute force algorithm | |
(defn p26 | |
[n l] | |
(let [aux (fn self [curr rem acc] | |
(if (= (count curr) n) (cons (reverse curr) acc) | |
(if (nil? rem) acc | |
(recur (cons (first rem) curr) (next rem) (self curr (next rem) acc)) | |
) | |
))] | |
(aux nil l nil) | |
) | |
) |
; P31 - get a list using sieve first | |
(defn p31 [t] | |
(let [test (fn [start coll] (every? #(not= 0 (mod start %)) coll))] | |
(test t ((fn [start acc target] | |
(if (> start target) | |
acc | |
(recur | |
(inc start) | |
(if (test start acc) | |
(cons start acc) | |
acc | |
) | |
target | |
) | |
) | |
) 2 nil (Math/sqrt t))) | |
) | |
) | |
; P32 - tail recursive | |
(defn p32 [a b] | |
(let [m (mod a b)] | |
(if (= m 0) b | |
(recur b m) | |
) | |
) | |
) | |
; P33 - using P32 and composition | |
(def p33 (comp (partial = 1) p32)) | |
; P34 ,- brute force using P33 | |
(defn p34 | |
([n c acc] | |
(if (> c n) acc | |
(recur n (inc c) (if (p33 c n) (inc acc) acc)) | |
) | |
) | |
([n] (p34 n 1 0)) | |
) | |
; P35 - modified from P31 | |
(defn p35 [num] | |
(let [prime-list | |
((fn [start acc target] | |
(if (> start target) | |
acc | |
(recur | |
(inc start) | |
(if (every? #(not= 0 (mod start %)) acc) | |
(cons start acc) | |
acc | |
) | |
target | |
) | |
) | |
) 2 nil (Math/sqrt num)) | |
find-factor | |
(fn [factor-list to-find acc] | |
(if (nil? factor-list) | |
(reverse (cons to-find (reverse acc))) | |
(if (= to-find 1) | |
acc | |
(let [h (first factor-list)] | |
(if (= 0 (mod to-find h)) | |
(recur factor-list (/ to-find h) (cons h acc)) | |
(recur (next factor-list) to-find acc) | |
) | |
) | |
) | |
) | |
)] | |
(find-factor prime-list num nil) | |
) | |
) | |
; P36 - composed from P13 and P35 | |
(def p36 (comp (partial map reverse) p13 p35)) | |
; P37 - using P36 | |
(def p37 | |
(comp | |
(partial reduce +) | |
(partial map (fn [group] | |
(let [p (first group) m (first (next group))] | |
(* (- p 1) | |
(Math/pow p (- m 1)) | |
) | |
) | |
)) | |
p36 | |
) | |
) |
Famous "99 problems", referring to https://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html, written in Clojure.
As an exercise when I read the book Clojure Programming (Emerick).