Skip to content

Instantly share code, notes, and snippets.

@werand
Created February 7, 2011 20:03
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 werand/815066 to your computer and use it in GitHub Desktop.
Save werand/815066 to your computer and use it in GitHub Desktop.
Learning Clojure
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
Dies ist ein aTest;;2;3;4;5;6;7;2
Dies ist ein bTest;1;2;3;4;5;6;7;2
Dies ist ein cTest;1;2;3;4;5;6;7;2
Dies ist ein dTest;1;2;3;4;5;6;7;2
Dies ist ein eTest;1;2;3;4;5;6;7;2
Dies ist ein fTest;1;2;3;4;5;6;7;2
Dies ist ein gTest;1;2;3;4;5;6;7;2
Dies ist ein hTest;1;2;3;4;5;6;7;2
Dies ist ein iTest;1;2;3;4;5;6;7;2
Dies ist ein jTest;;2;3;4;5;6;7;2
tes't;
(ns createinserts
(:import (java.io BufferedReader FileReader)))
; Die Spaltennamen in der CSV-Datei
(def *cols* '(col1 col2 col3 col4 col5))
; Die Txt_oid Spalte
(def *txt-oid* 'txt_oid)
(def
^{:private true}
*number-pattern* (re-pattern "\\d+"))
(defn
^{:doc "Liefert :number wenn der String nur aus Zahlen besteht, :string sonst"
:private true}
is-string-a-number? [s]
(if (re-matches *number-pattern* s)
:number
:string))
(defrecord Column-Value [column value])
(defmulti str-value
(fn [column-value]
(is-string-a-number? (:value column-value))))
(defn str-column [column-value] (:column column-value))
(defmethod
^{:doc "Setzt den String in Hochkomma und versieht enthaltene Hochkomma mit Escape-Charactern"}
str-value :string [column-value]
(str "'" (.replaceAll (:value column-value) "'" "'''" ) "'"))
(defmethod str-value :number [column-value] (str (:value column-value)))
(defn
^{:doc "Erzeugt eine Liste von Column-Value Records, für die aktuell zu verarbeiteten line-tokens"}
columns-and-values
([line-tokens]
(reverse (columns-and-values line-tokens *cols*)))
([line-tokens cols]
(loop [result []
my-tokens (seq line-tokens)
my-cols (seq cols)]
(if (and my-tokens my-cols)
(if (> (.length (first my-tokens)) 0)
(recur (cons (Column-Value. (first my-cols) (first my-tokens)) result) (next my-tokens) (next my-cols))
(recur result (next my-tokens) (next my-cols)))
result))))
; Hätte man auch einfach mit (join ", " list) realisieren können
(defn
^{:doc "Liefert die Liste durch Komma separiert als String zurück."}
comma-separated [list]
(reduce #(str %1 ", " %2) list))
(defn
^{:doc "Eigentliche Funktion die für jede Zeile der Input-Datei aufgerufen wird und ein entsprechendes Insert-Statement erzeugt.
acc - Die aktuelle Zeilennummer"}
process-line [acc line]
(let [line-tokens (.split line ";")
columns-and-values (cons (Column-Value. *txt-oid* (str acc)) (columns-and-values line-tokens))]
(println (str "insert into someTable ("
(comma-separated (map str-column columns-and-values))
") values ("
(comma-separated (map str-value columns-and-values))
");"))
)
(+ acc 1))
(defn
^{:doc "Verarbeitet eine Eingabedatei, und führt die übergebene Funktion darauf aus und schleift dabei acc durch"}
process-file [file-name line-func line-acc]
(with-open [rdr (BufferedReader. (FileReader. file-name))]
(reduce line-func line-acc (line-seq rdr))))
; Eigentlicher Aufruf der Verarbeitung
(process-file "src/abc.csv" process-line 1)
(ns hanoi)
(def num-disks 3)
(defn move
[from to state]
(conj state (format "Move from %s to %s" from to)))
; Hier hatte ich erst einen Denkfehler, ich habe imperativ gedacht und wollte den Zustand
; während der Verarbeitung ändern, so dass er den immer gerade 'aktuellen' Zustand widerspiegelt.
; Funktional muss man aber anders denken, d.h. man muss die Zustände erweitern nicht ändern.
; Dabei wird also niemals der Zustand geändert, sondern auf dem Stack, on the fly erweitert.
; Mit dem erweiterten Zustand muss man dann weiterarbeiten, daher das ->> Konstrukt
; Was ich noch nicht verstehe ist warum es mit dem -> (Thread-Operator) nicht funktioniert.
; -> fügt das Argument an das zweite Stelle der Form ein
; ->> fügt das Argument an letzter Stelle der Form ein
(defn towers-of-hanoi
[n from to via state]
(if (= n 1)
(do
(move from to state))
(do
(->> state
(towers-of-hanoi (dec n) from via to)
(move from to)
(recur (dec n) via to from)))))
#_(towers-of-hanoi 3 :1 :2 :3 [])
(defn orig-towers-of-hanoi
[n from to via]
(if (= n 1)
(println (format "Move from %s to %s" from to))
(do
(orig-towers-of-hanoi (dec n) from via to)
(println (format "Move from %s to %s" from to))
(recur (dec n) via to from))))
#_(orig-towers-of-hanoi 3 "a" "b" "c")
;;;
;;; The following code was found here: https://gist.github.com/132990/d450f4845801b0c37c4576ac715c85f9a1cb5ec3
;;;
(defn multtab [n]
(for [row (range n) col (range n)]
(* (inc row) (inc col))))
;; reasonably nicely formatted
(defn main [n]
(let [width (int (Math/ceil (/ (Math/log (* n n)) (Math/log 10))))
digit-str (str "%" (inc width) "d")]
(doseq [row (partition n (multtab n))]
(let [formatted-row (map #(format digit-str %) row)]
(println (apply str formatted-row))))))
;; if you don't care about formatting
(defn show-multtab [n]
(doseq [r (partition n (multtab n))]
(println (apply str (interpose " " r)))))
;;
;; Here is a differnt solution without the for loop, and with recursion instead
;; Just for practicing, the for loop solution is by far more elegant
;; and better readable, this are far too many parentheses ...
;;
(ns user
(:use [clojure.string :only [join]]))
(defn mymulttab [n]
"With this solution the table is already partitioned"
(loop [row n result '()]
(if (= row 0)
result
(recur (dec row) (cons (map * (range 1 (inc n)) (repeat (inc n) row)) result)))))
;; This is even faster than the original! Amazing ...
;; But still not as good readable
(defn mymulttab2 [n]
(for [row (range 1 (inc n))]
(map * (repeat (inc n) row) (range 1 (inc n)))))
;; Another way to print the table without formatting
(defn myshow-muttab [n] println (join "\n" (map #(join " " %) (mymulttab n))))
;; To measure the timings
#_(time (dotimes [_ 1000] (mymulttab 100)))
(time (dotimes [_ 1e6] (mymulttab2 100)))
(time (dotimes [_ 1e6] (multtab 100)))
(time (dotimes [_ 1e8] (mymulttab2 100)))
(time (dotimes [_ 1e8] (multtab 100)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment