Last active
February 26, 2016 15:28
-
-
Save yenda/116dca46c5a6ad984f99 to your computer and use it in GitHub Desktop.
Zalando interview
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; I had a really hard time programming and thinking in Clojure within a raw text editor and under stress, | |
;; so I took gave a new try to the problem using the repl and my usual editor (emacs) for a second shot | |
;; using the repl helped me quickly discard poor solutions and fix small quirks. | |
;; Here is what I came up with : | |
;; First I get the headers with the max width of each columns and print them, the way I started it during the interview | |
;; Then I completed each row with the missing keys using a sorted map and adding the whitespaces | |
;; Then I printed all the rows | |
;; There still could be some refactoring to minimize recalculation of some of the structures but it is suppose to be a 30 min exercice | |
(def input [{:foo "b" :b "bar"}, {:zal "ando" :b "x"}]) | |
;; PPRINT THE HEADERS | |
(defn headers | |
"Get a set of the headers" | |
[input] | |
(reduce #(into %1 (keys %2)) #{} input)) | |
(defn headers-map | |
"Get a sorted map of the headers with empty lists as values" | |
[headers] | |
(->> headers | |
(reduce #(assoc %1 %2 '()) {}) | |
(into (sorted-map)))) | |
(defn headers-map-list | |
"Get a sorted map of the headers with empty strings as values" | |
[headers] | |
(->> headers | |
(reduce #(assoc %1 %2 "") {}) | |
(into (sorted-map)))) | |
(defn sort-row | |
"Add the row of attributes to the sorted input maps" | |
[sorted-input row] | |
(reduce #(update-in %1 [(key %2)] conj (val %2)) sorted-input row)) | |
(defn sort-attributes-by-header | |
"Sort all the attributes in a single map with headers as keys" | |
[input] | |
(let [headers-map (-> input headers headers-map)] | |
(reduce #(sort-row %1 %2) headers-map input))) | |
(defn max-length | |
"Returns a map with headers as keys and max length of a column as value" | |
[input] | |
(->> input | |
sort-attributes-by-header | |
(reduce #(assoc %1 (key %2) (max (count (name (key %2))) | |
(apply max (map count (val %2))))) {}))) | |
(defn header-whitespaces | |
"Take a header/max-length pair and return a string of whitespaces to fill a header" | |
[header] | |
(let [whitespaces (- (second header) (count (name (first header))))] | |
(if (> 0 whitespaces) | |
" " | |
(apply str " " (take whitespaces (repeat " ")) )))) | |
(defn headers->str | |
"Returns the headers as a string" | |
[input] | |
(let [max-length (max-length input) | |
headers (map name (keys max-length)) | |
whitespaces (map header-whitespaces max-length) | |
to-print (clojure.string/join (interleave headers whitespaces))] | |
(str to-print "\n" (apply str (take (dec (count to-print)) (repeat "-"))) "\n"))) | |
;; PPRINT THE ATTRIBUTES | |
(defn attributes | |
"Returns an ordered map similar to input but with the missing columns" | |
[input] | |
(let [headers-map (-> input headers headers-map-list)] | |
(map #(merge headers-map (into (sorted-map) %)) input))) | |
(defn attribute->str | |
"Returns an attribute as a string" | |
[attr max-length] | |
(let [length (count attr)] | |
(if (< length max-length) | |
(apply str attr (take (- max-length length) (repeat " "))) | |
attr))) | |
(defn row->str | |
"Returns a row as a string" | |
[row max-length] | |
(->> (map #(attribute->str (val %) ((key %) max-length)) row) | |
(clojure.string/join " "))) | |
(defn attributes->str | |
[input] | |
(->> (map #(row->str %1 (max-length input)) (attributes input)) | |
(clojure.string/join "\n"))) | |
(defn pprint-input | |
"Pretty print headers and attributes" | |
[input] | |
(print (headers->str input)) | |
(print (attributes->str input))) | |
(pprint-input input) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment