Skip to content

Instantly share code, notes, and snippets.

@lagenorhynque
Last active January 1, 2018 14:57
Show Gist options
  • Select an option

  • Save lagenorhynque/84241a95eff3411d1e25d9610537552e to your computer and use it in GitHub Desktop.

Select an option

Save lagenorhynque/84241a95eff3411d1e25d9610537552e to your computer and use it in GitHub Desktop.
(ns cli
(:require [clojure.spec.alpha :as s]))
(s/fdef sum
:args (s/cat :coll (s/coll-of number?))
:ret number?)
(defn sum [coll]
(if (empty? coll)
0
(+ (first coll) (sum (rest coll)))))
(s/fdef length
:args (s/cat :coll coll?)
:ret nat-int?)
(defn length [coll]
(if (empty? coll)
0
(inc (length (rest coll)))))
;; foldを利用した版
(s/fdef fold
:args (s/cat :f ifn?
:val any?
:coll coll?)
:ret any?)
(defn fold [f val coll]
(if (empty? coll)
val
(recur f (f val (first coll)) (rest coll))))
(defn sum' [coll]
(fold + 0 coll))
(defn length' [coll]
(fold (fn [len _] (inc len)) 0 coll))
(s/fdef get-at
:args (s/and (s/cat :idx nat-int?
:coll (s/coll-of any? :min-count 1))
(fn [{:keys [idx coll]}]
(< idx (count coll))))
:ret any?)
(defn get-at [idx coll]
(if (zero? idx)
(first coll)
(recur (dec idx) (rest coll))))
(s/fdef group-count
:args (s/cat :coll coll?)
:ret (s/map-of any? nat-int?))
(defn group-count [coll]
(letfn [(group-count-impl [coll m]
(if (empty? coll)
m
(recur (rest coll)
(update m (first coll) (fnil inc 0)))))]
(group-count-impl coll {})))
(defn group-count'
([coll]
(group-count' coll {}))
([coll m]
(if (empty? coll)
m
(recur (rest coll)
(update m (first coll) (fnil inc 0))))))
(s/fdef max-count
:args (s/cat :coll (s/coll-of (s/tuple any? nat-int?)))
:ret (s/nilable nat-int?))
(defn max-count [coll]
(letfn [(max-count-impl [coll max-elem max-cnt]
(if (empty? coll)
max-elem
(let [[[head-elem head-cnt] & tail] coll]
(if (> head-cnt max-cnt)
(recur tail head-elem head-cnt)
(recur tail max-elem max-cnt)))))]
(max-count-impl (sort coll) nil 0)))
(defn max-count' [coll]
(letfn [(max-count-impl [coll max-elem max-cnt]
(if (empty? coll)
max-elem
(let [[[head-elem head-cnt] & tail] coll]
(if (>= head-cnt max-cnt)
(recur tail head-elem head-cnt)
(recur tail max-elem max-cnt)))))]
(max-count-impl (sort coll) nil 0)))
(s/fdef mean
:args (s/cat :numbers (s/coll-of number? :min-count 1))
:ret number?)
(defn mean [numbers]
(/ (sum numbers) (length numbers)))
(s/fdef median
:args (s/cat :numbers (s/coll-of number? :min-count 1))
:ret number?)
(defn median [numbers]
(get-at (quot (length numbers) 2) (sort numbers)))
(s/fdef mode
:args (s/cat :numbers (s/coll-of number?))
:ret (s/nilable number?))
(defn mode [numbers]
(-> numbers group-count max-count))
(defn -main [& args]
(let [numbers (map #(Integer/parseInt %) args)]
(println "mean:" (mean numbers))
(println "median:" (median numbers))
(println "mode:" (mode numbers))))
{:deps {org.clojure/clojure {:mvn/version "1.9.0-RC1"}
org.clojure/test.check {:mvn/version "0.9.0"}
funcool/cats {:mvn/version "2.1.0"}}
:paths ["."]}
(ns handson-tp
(:require [cats.context :as ctx]
[cats.core :as m]
[cats.protocols :as p]
[cats.util :as util]
[clojure.spec.alpha :as s]))
(s/fdef length
:args (s/cat :coll coll?)
:ret nat-int?)
(defn length [coll]
(if (empty? coll)
0
(inc (length (rest coll)))))
(s/fdef sum
:args (s/cat :coll coll?
:ctx (s/? #(satisfies? p/Monoid %)))
:ret any?)
(def sum-monoid
(reify
p/Context
p/Semigroup
(-mappend [_ a b]
(+ a b))
p/Monoid
(-mempty [_]
0)
p/Printable
(-repr [_]
"#<SumMonoid>")))
(util/make-printable (type sum-monoid))
(def prod-monoid
(reify
p/Context
p/Semigroup
(-mappend [_ a b]
(* a b))
p/Monoid
(-mempty [_]
1)
p/Printable
(-repr [_]
"#<ProdMonoid>")))
(util/make-printable (type prod-monoid))
(def string-monoid
(reify
p/Context
p/Semigroup
(-mappend [_ a b]
(str a b))
p/Monoid
(-mempty [_]
"")
p/Printable
(-repr [_]
"#<StringMonoid>")))
(util/make-printable (type string-monoid))
(defn sum
([coll]
(reduce m/mappend (m/mempty) coll))
([coll ctx]
(ctx/with-context ctx
(reduce m/mappend (m/mempty) coll))))
(defn -main [& args]
(doseq [monoid [sum-monoid prod-monoid string-monoid]]
(ctx/with-context monoid
(println "with" monoid)
(println " sum []:" (sum []))
(println " sum [1 2 3 4 5]:" (sum [1 2 3 4 5])))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment