Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
/target
/classes
/checkouts
profiles.clj
/pom.xml
*jar
/pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
.hgignore
.hg/
/lib
/classes
/native
/.lein-failures
/checkouts
/.lein-deps-sum
*.DS_Store
*.DS_Store
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
coding-exercises
Coding Exercises
================

**Worki in progress**

Currently refactoring this code to write tests for each challenge. The challenges are going to be empty functions which will fail the test. When the refactoring is completed, the solutions wil exist in a different branch as a reference.

Coding exercises, handy practice for technical interview questions. I will put up my solutions to some popular questions and exercises in this repo, and welcome any feedback or suggestions!

All of the exercises are coded in my favorite language, Clojure.
Expand All @@ -12,3 +16,4 @@ Most of the exercises are taken from "Cracking the Coding Interview, 4th Edition
Copyright (C) 2012 David Petrovics

Distributed under the Eclipse Public License, the same as Clojure.

10 changes: 8 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
(defproject coding-exercises "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/math.numeric-tower "0.0.1"]])
:url "http://example.com/FIXME"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/math.numeric-tower "0.0.1"]]
:main ^:skip-aot coding-exercises.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
111 changes: 88 additions & 23 deletions src/coding_exercises/core.clj
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
(ns coding-exercises.core
(:require [clojure.string :as str]
(:require [clojure.set :as set :only [union]]
[clojure.math.numeric-tower :as math]))

(defn basic-fib
^{:doc "Returns the n-th number in the fibonacci sequence."}
[num]
(if (= num 0)
(if (<= num 0)
0
(if (= num 1)
1
(+ (basic-fib (- num 2))
(basic-fib (- num 1))))))

(defn lazy-fib
^{:doc "Returns a lazy sequnence of the fibonacci sequence. Use with 'take' or 'nth'"}
[]
(map first
(iterate (fn [[a b]] [b (+ a b)]) [0 1])))

(def map-example
"You have a collection of 2-tuples (user, follower). You want to get out (user, [followers]). Solution: put them all into a map, and use merge-with.")
;(defn basic-fib
; ^{:doc "Returns the n-th number in the fibonacci sequence."}
; [num])

(def inputs
'(("Angie" "Dave") ("Angie" "Max") ("Bill" "Joe") ("Joe" "Moe") ("Bill" "Dave") ("Mike" "Dave") ("Angie" "Bill")))
(defn user-followers
"You have a collection of 2-tuples (user, follower). You want to get out (user, [followers]). Solution: put them all into a map, and use merge-with."
[input]
(reduce (fn [r n]
(assoc r
(first n)
(set (conj (r (first n)) (last n)))))
{} input))

(defn user-followers
[uf-list]
(let [usr-map (map #(apply hash-map %1) uf-list)]
(let [usr-map (map #(hash-map (first %1) #{(last %1)}) uf-list)]
(apply merge-with
#(if (seq? %1)
(conj %1 %2)
(list %1 %2))
#(set/union %1 %2)
usr-map)))

;(defn user-followers
; "You have a collection of 2-tuples (user, follower). You want to get out (user, [followers]). Solution: put them all into a map, and use merge-with."
; [input])

(defn lazy-fib
^{:doc "Returns a lazy sequnence of the fibonacci sequence. Use with 'take' or 'nth'"}
[]
(map first
(iterate (fn [[a b]] [b (+ a b)]) [0 1])))

;(defn lazy-fib
; ^{:doc "Returns a lazy sequnence of the fibonacci sequence. Use with 'take' or 'nth'"}
; [])

(defn clock-angle
^{:doc "Finds the angle in degrees between the hour hand and minute hand."}
[hr min]
Expand All @@ -42,18 +55,70 @@
hr-angle (* (+ (mod hr 12) (/ min 60))
(/ 360 12))]
(float
(math/abs (- hr-angle min-angle)))))
(math/abs (- hr-angle min-angle)))))

;(defn clock-angle
; ^{:doc "Finds the angle in degrees between the hour hand and minute hand."}
; [hr min])

(defn word-frequencies
^{:doc "My implementation of the Clojure 'frequency' function. Takes in a sentence (string) and outputs a map with words as keys and their frequency as values."}
^{:doc "Create a function to accept a string and return a map of word (case insensitive) and its frequency"}
[sentence]
(reduce
(fn [res wrd] (assoc res wrd
(inc (get res wrd 0))))
{}
(re-seq #"\w+" sentence)))
(fn [res w]
(let [wrd (clojure.string/lower-case w)]
(assoc res (clojure.string/lower-case wrd)
(inc (get res wrd 0)))))
{}
(re-seq #"\w+" sentence)))

; (defn word-frequencies;
; ^{:doc "Create a fun;ction to accept a string and return a map of word and its frequency"}
; [sentence])

(defn power [base exp]
(nth
(iterate #(* %1 base) 1) exp))
(iterate #(* %1 base) 1) exp))

;(defn power
; "Write a function to calculate the power of a number using iterate"
; [base exp])

(defn fizz-buzz
[number]
(let [multiple? (fn [n number]
(zero? (mod n number)))
res (str
(if (multiple? number 3) "Fizz")
(if (multiple? number 5)
"Buzz"))]
(if (clojure.string/blank? res)
(str number)
res)))

;(defn fizz-buzz [number]
; "Write a program that prints the numbers from 1 to 100. But for
; multiples of three print \"Fizz\" instead of the number and for the
; multiples of five print \"Buzz\". For numbers which are multiples of
; both three and five print \"FizzBuzz\""
; ())

(defn insert-letter
^{:doc "Returns a collection of each new word produced by inserting the letter in all possible spots in the word."}
[word letter]
(let [length (count word)]
(for [num (range 0 (inc length))]
(str (subs word 0 num)
letter
(subs word num length)))))

(defn word-permutations
^{:doc "Returns a collection of all permutations of the given word."}
[s]
(if (= (count s) 1)
(list s)
(let [subword (subs s 0 (dec (count s))) ;;ex: 'bar', subword = 'ba'
letter (str (last (seq s)))] ;;the last letter, ie 'r' in 'bar'
(apply concat
(for [word (word-permutations subword)]
(insert-letter word letter))))))
45 changes: 0 additions & 45 deletions src/coding_exercises/string-permutations.clj

This file was deleted.

88 changes: 84 additions & 4 deletions test/coding_exercises/test/core.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,86 @@
(ns coding-exercises.test.core
(:use [coding-exercises.core])
(:use [clojure.test]))
(:require [clojure.test :refer [is testing] :as t])
(:use [coding-exercises.core]))

(deftest replace-me ;; FIXME: write
(is false "No tests have been written."))
(defn test-func
"Creates a function that validate result against the result of applying func with input"
([func pass?]
(fn [input result]
(let [actual (if (vector? input) (apply func input) (func input))]
(is (pass? actual result)
(format "(func %s) expected to result %s but found %s" input result actual)))))
([func]
(test-func func =)))

(defn run-tests!
"Funs all the test test cases by applying each element in tests"
([tests test-func]
(run! #(apply test-func %1) tests))
([tests test-func desc]
(testing desc
(run-tests! tests test-func))))

(comment defmacro deftest
[desc tests func pass?]
(list macroexpand
'(t/deftest testing-something
(testing 'desc (run-tests! 'tests (test-func 'func 'pass?))))))

(t/deftest test-finonacii
; nth fibonacii
(let [tests [[1 1] [2 1] [3 2] [4 3] [5 5] [14 377]]
tests-base-case [[0 0] [1 1] [-1 0] [-19900090090 0]]
func (test-func basic-fib)]
(run-tests! tests func "if the correct nth fibonacii is returned")
(run-tests! tests-base-case func "Test if the base case is returned for invalid input")))

(t/deftest test-user-followers
(let [tests [
[(list '("user" "follower1") '("user" "follower2") '(:user-2 "follower1"))
{"user" #{"follower1", "follower2"} :user-2 #{"follower1"}}]
[(list [:user :follower] [:user :follower-2])
{:user #{:follower :follower-2}}]]
func (test-func user-followers)]
(run-tests! tests func "Test tupples are mapped correctly")))

(t/deftest test-lazy-finonacii
(let [tests [[1 1] [2 1] [3 2] [4 3] [5 5] [14 377]]
lazy-fib-list (lazy-fib)
func (test-func #(nth lazy-fib-list %1))]
(run-tests! tests func "if the correct nth fibonacii is returned")))

(t/deftest test-test-word-frequencies
(let [tests [["this is a hello world example that is new."
{"this" 1 "that" 1 "a" 1 "hello" 1 "world" 1 "is" 2 "example" 1 "new" 1}]
["This Is a Hello world example that is new."
{"this" 1 "that" 1 "a" 1 "hello" 1 "world" 1 "is" 2 "example" 1 "new" 1}]]
func (test-func word-frequencies)]
(run-tests! tests func "Testing if word frequencies")))

(t/deftest test-power
(let [tests [[[2 2] 4] [[3 2] 9] [[4 4] 256] [[100 3] 1000000] [[7 3] 343]]
func (test-func power)]
(run-tests! tests func "Testing if power is calculated correctly")))

(t/deftest test-clock-angle
(let [tests [[[0 0] 0.0] [[3 0] 90.0] [[6 0] 180.0]]
func (test-func clock-angle)]
(run-tests! tests func "Testing if clock angle is calculted correctly")))

(t/deftest test-fizz-buzz
(let [tests [[2 "2"] [3 "Fizz"] [4 "4"] [5 "Buzz"] [6 "Fizz"] [7 "7"]
[8 "8"] [9 "Fizz"] [10 "Buzz"] [11 "11"] [12 "Fizz"] [13 "13"]
[14 "14"] [15 "FizzBuzz"] [16 "16"] [17 "17"] [18 "Fizz"] [19 "19"]
[20 "Buzz"] [21 "Fizz"] [22 "22"] [23 "23"]]
func (test-func fizz-buzz)]
(run-tests! tests func "Fizz Buzz is returned correctly")))

(t/deftest test-insert-letter
(let [tests [[["hello" "i"] "hieililioi"] [["you" "j"] "yjojuj"]]
f (test-func insert-letter)]
(run-tests! tests f "testing letter insrtion")))

(t/deftest test-word-permutations
(let [tests [["hel" (list "hel" "hle" "elh" "ehl" "lhe" "leh" )]]
f (test-func word-permutations)]
(run-tests! tests f "testing letter insrtion")))