Skip to content

Instantly share code, notes, and snippets.

@bendisposto
Last active August 29, 2015 13:56
Show Gist options
  • Save bendisposto/8997076 to your computer and use it in GitHub Desktop.
Save bendisposto/8997076 to your computer and use it in GitHub Desktop.
Lösungsvorschlag Blatt 9
(ns muster.core
(:use clojure.algo.monads))
(comment
;; Aufgabe 1
;; a)
(defn punkte [x k]
(let [p (* 2 (- x (/ k 2)))]
(max p 0)))
;; b)
;; bis 99 Punkte gibt es beim Raten 0 Punkte
(every? (fn [p] (let [p2 (* 2 p)] (= 0 (punkte p p2)))) (range 100))
;; Und nur Ergebnisse zwischen 0 und k
(every? (fn [[x k]] (<= 0 (punkte x k) k))
(for [k (range 100) x (range (inc k))] [x k]))
;; c)
;; Nein, durch Raten kann man sein Ergebnis nicht verschlechtern!
;; Aufgabe 2
(defrecord BankersQ [front rear])
(defprotocol PQueue
(bpush [t e])
(btake [t]))
(defn reorganize [{:keys [front rear] :as q}]
(if (<= (count front) (count rear))
(->BankersQ (concat front (reverse rear)) '())
q))
(extend-type
BankersQ
PQueue
(bpush [{:keys [front rear]} element]
(reorganize (->BankersQ front (cons element rear))))
(btake [{:keys [front rear]}]
(println (first front))
(reorganize (->BankersQ (rest front) rear))))
(defn q [] (->BankersQ '() '()))
(bpush (bpush (bpush (q) 1) 2) 3)
(btake (bpush (bpush (bpush (q) 1) 2) 3))
;; Die Queue muss das erste Argument sein, da das Dispatching bei
;; Protokollen auf dem ersten Argument stattfindet.
;; Wenn man die Reihenfolge umdrehen will ist es einfacher
;; Multimethods zu benutzen.
;; Aufgabe 3
(defmacro or-m
([] nil)
([x] x)
([x & more] `(let [or# ~x] (if or# or# (or-m ~@more)))))
(defn or-fn
([] nil)
([x] x)
([x & more]
(if x x (apply or-fn more))))
(or-m 1 (println :fail))
(or-fn 1 (println :fail))
;; Bei der Funktion werden alle Argumente inklusive (println :fail)
;; ausgewertet. Bei dem Macro wird das 2. Argument nur ausgewertet,
;; wenn das erste Argument falsey ist
;; Aufgabe 4
(defn iterate'' [f x]
(lazy-cat [x] (iterate'' f (f x))))
(take 10 (iterate'' inc 5))
;; Aufgabe 5
;; Monadisch (kann ja nicht schaden)
(defn m-cval [k]
(cond (number? k) [k]
(#{:bube :dame :koenig} k) [10]
:else [1 11]))
(defn m-opt-val [s]
(apply max
(remove #(< 21 %)
(domonad
sequence-m
[x (m-map m-cval s)] (reduce + x)))))
(defn winner [s]
(first (partition-by m-opt-val (reverse (sort-by m-opt-val s)))))
(winner [[:ass 9] [:ass :koenig] [:dame :dame] [7 3 :ass]])
;; Aufgabe 6
(defn !-1 [n] (double (/ 1 (reduce *' (range 1 (inc n))))))
(defn e []
(reduce
+
(take-while #(<= 0.001 %)
(for [x (iterate inc 0)] (!-1 x)))))
;; Aufgabe 7
(defn as-seq [s]
(read-string
(apply str
(replace {\newline "]["} (str "[[" s "]]")))))
(defrecord Vec2d [x y])
(defrecord Vec3d [x y z])
(defmulti as-vector count)
(defmethod as-vector 2 [[x y]] (->Vec2d x y))
(defmethod as-vector 3 [[x y z]] (->Vec3d x y z))
(def input "23 8 15\n11 0\n0 5\n-10 15 9")
(map as-vector (as-seq input))
;; Mit Protokollen kann man das nicht gut lösen, da wir eine Sequenz
;; haben in der die Typen der Element alle gleich sind. Das
;; Unterscheidungskriterium ist die Länge des Vektors.
;; Multimethods sind für solche Situationen besser geeignet
;; Aufgabe 8
(defn fizzbuzz-mnf [k]
(cond (= 0 (mod k 15)) [:fizz :buzz]
(= 0 (mod k 3)) [:fizz]
(= 0 (mod k 5)) [:buzz]
:else [k]))
(fizzbuzz-mnf 10)
(fizzbuzz-mnf 6)
(fizzbuzz-mnf 15)
(fizzbuzz-mnf 7)
(defn fizzbuzz-m [s]
(domonad sequence-m [x (m-map fizzbuzz-mnf s)] x))
(fizzbuzz-m [1 2 3 4 5 7 15 16 15])
;; Aufgabe 9
;; a) Die Funktion hat den Typ [a] -> [b].
;; b) Nein. Monadische Funktionen haben die Signatur a -> m b, also
;; im Falle der Sequenz Monade a -> [b]
;; Aufgabe 10
(defn abc [m n]
(if (or (< n 0) (< m 0)) 0
(cond (= 0 m) (inc n)
(= 0 n) (recur (dec m) 1)
:else (recur (dec m) (abc m (dec n))))))
(abc 3 9)
;; abc ist übrigends die Ackermann Funktion
;; Aufgabe 11
;; Die Funktion ist nicht tail-rekursiv, deswegen kommt es zu
;; StackOverflow Fehlern
(defn ! [n] (if (zero? n) 1 (*' n (! (dec n)))))
(! 10000)
(defn !2
([n] (!2 n 1))
([n a] (if (zero? n) a) (recur (dec n) (*' n a))))
(!2 1000)
;; idiomatischer
(defn !3 [n] (reduce * (range 1 (inc n))))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment