Repository: exercism/clojure
Pull request #195 (2017-10-29 16:08:15)

Implementing complex-numbers


Patch:
diff --git a/config.json b/config.json
index 7499938..336751d 100644
--- a/config.json
+++ b/config.json
@@ -105,6 +105,14 @@
       "unlocked_by": null,
       "uuid": "f4cf3676-4399-4d1c-b21f-8e735c7af8cc"
     },
+    {
+      "core": false,
+      "difficulty": 1,
+      "slug": "complex-numbers",
+      "topics": null,
+      "unlocked_by": null,
+      "uuid": "95580d10-92db-4809-b5e7-4085319d19e9"
+    },
     {
       "core": false,
       "difficulty": 1,
@@ -510,4 +518,4 @@
   ],
   "foregone": [],
   "language": "Clojure"
-}
\ No newline at end of file
+}
diff --git a/exercises/complex-numbers/README.md b/exercises/complex-numbers/README.md
new file mode 100644
index 0000000..5ee41f9
--- /dev/null
+++ b/exercises/complex-numbers/README.md
@@ -0,0 +1,37 @@
+A complex number is a number in the form `a + b * i` where `a` and `b` are real and `i` satisfies `i^2 = -1`.
+
+`a` is called the real part and `b` is called the imaginary part of `z`.
+The conjugate of the number `a + b * i` is the number `a - b * i`.
+The absolute value of a complex number `z = a + b * i` is a real number `|z| = sqrt(a^2 + b^2)`. The square of the absolute value `|z|^2` is the result of multiplication of `z` by its complex conjugate.
+
+The sum/difference of two complex numbers involves adding/subtracting their real and imaginary parts separately:
+`(a + i * b) + (c + i * d) = (a + c) + (b + d) * i`,
+`(a + i * b) - (c + i * d) = (a - c) + (b - d) * i`.
+
+Multiplication result is by definition
+`(a + i * b) * (c + i * d) = (a * c - b * d) + (b * c + a * d) * i`.
+
+The reciprocal of a non-zero complex number is
+`1 / (a + i * b) = a/(a^2 + b^2) - b/(a^2 + b^2) * i`.
+
+Dividing a complex number `a + i * b` by another `c + i * d` gives:
+`(a + i * b) / (c + i * d) = (a * c + b * d)/(c^2 + d^2) + (b * c - a * d)/(c^2 + d^2) * i`.
+
+Exponent of a complex number can be expressed as
+`exp(a + i * b) = exp(a) * exp(i * b)`,
+and the last term is given by Euler's formula `exp(i * b) = cos(b) + i * sin(b)`.
+
+
+Implement the following operations:
+ - addition, subtraction, multiplication and division of two complex numbers,
+ - conjugate, absolute value, exponent of a given complex number.
+
+
+Assume the programming language you are using does not have an implementation of complex numbers.
+
+## Source
+
+[wikipedia page](https://en.wikipedia.org/wiki/Complex_number)
+
+## Submitting Incomplete Solutions
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/exercises/complex-numbers/project.clj b/exercises/complex-numbers/project.clj
new file mode 100644
index 0000000..33a63c4
--- /dev/null
+++ b/exercises/complex-numbers/project.clj
@@ -0,0 +1,4 @@
+(defproject complex-numbers "0.1.0-SNAPSHOT"
+  :description "complex-numbers exercise"
+  :url "https://github.com/exercism/xclojure/tree/master/exercises/complex-numbers"
+  :dependencies [[org.clojure/clojure "1.8.0"]])
diff --git a/exercises/complex-numbers/src/complex_numbers.clj b/exercises/complex-numbers/src/complex_numbers.clj
new file mode 100644
index 0000000..f3afb62
--- /dev/null
+++ b/exercises/complex-numbers/src/complex_numbers.clj
@@ -0,0 +1,17 @@
+(ns complex-numbers)
+
+(defn real [[a b]])
+
+(defn imaginary [[a b]])
+
+(defn abs [[a b]])
+
+(defn conjugate [[a b]])
+
+(defn add [[a b] [c d]])
+
+(defn sub [[a b] [c d]])
+
+(defn mul [[a b] [c d]])
+
+(defn div [[a b] [c d]])
diff --git a/exercises/complex-numbers/src/example.clj b/exercises/complex-numbers/src/example.clj
new file mode 100644
index 0000000..d0e46e0
--- /dev/null
+++ b/exercises/complex-numbers/src/example.clj
@@ -0,0 +1,20 @@
+(ns complex-numbers)
+
+(defn real [[a _]] a)
+
+(defn imaginary [[_ b]] b)
+
+(defn abs [[a b]] (Math/sqrt (apply + (map #(Math/pow % 2) [a b]))))
+
+(defn conjugate [[a b]] [a (- b)])
+
+(defn add [[a b] [c d]] [(+ a c) (+ b d)])
+
+(defn sub [[a b] [c d]] [(- a c) (- b d)])
+
+(defn mul [[a b] [c d]] [(- (* a c) (* b d)) (+ (* a d) (* b c))])
+
+(defn div [[a b] [c d]]
+  (let [denominator (apply + (map #(Math/pow % 2) [c d]))]
+    [(/ (+ (* a c) (* b d)) denominator)
+     (/ (- (* b c) (* a d)) denominator)]))


Test patch:
diff --git a/exercises/complex-numbers/test/complex_numbers_test.clj b/exercises/complex-numbers/test/complex_numbers_test.clj
new file mode 100644
index 0000000..310f9bf
--- /dev/null
+++ b/exercises/complex-numbers/test/complex_numbers_test.clj
@@ -0,0 +1,141 @@
+(ns complex-numbers-test
+  (require [clojure.test :refer [deftest is testing]]
+           [complex-numbers :as c]))
+
+;; Tests for Addition
+(deftest add-purely-real-numbers
+  (testing "Add purely real numbers"
+    (is (= (c/add [1 0] [2 0])
+           [3 0]))))
+
+(deftest add-purely-imaginary-numbers
+  (testing "Add purely imaginary numbers"
+    (is (= (c/add [0 1] [0 2])
+           [0 3]))))
+
+(deftest add-numbers-with-real-and-imaginary-part
+  (testing "Add numbers with real and imaginary part"
+    (is (= (c/add [1 2] [3 4])
+           [4 6]))))
+
+;; Tests for Subtraction
+(deftest subtract-purely-real-numbers
+  (testing "Subtract purely real numbers"
+    (is (= (c/sub [1 0] [2 0])
+           [-1 0]))))
+
+(deftest subtract-purely-imaginary-numbers
+  (testing "Subtract purely imaginary numbers"
+    (is (= (c/sub [0 1] [0 2])
+           [0 -1]))))
+
+(deftest subtract-numbers-with-real-and-imaginary-part
+  (testing "Subtract numbers with real and imaginary part"
+    (is (= (c/sub [1 2] [3 4])
+           [-2 -2]))))
+
+;; Tests for Multiplication
+(deftest multiply-purely-real-numbers
+  (testing "Multiply purely real numbers"
+    (is (= (c/mul [1 0] [2 0])
+           [2 0]))))
+
+(deftest multiply-purely-imaginary-numbers
+  (testing "Multiply purely imaginary numbers"
+    (is (= (c/mul [0 1] [0 2])
+           [-2 0]))))
+
+(deftest multiply-numbers-with-real-and-imaginary-part
+  (testing "Multiply numbers with real and imaginary part"
+    (is (= (c/mul [1 2] [3 4])
+           [-5 10]))))
+
+;; Tests for division
+(deftest divide-purely-real-numbers
+  (testing "Divide purely real numbers"
+    (is (= (c/div [1 0] [2 0])
+           [0.5 0.0]))))
+
+(deftest dividey-purely-imaginary-numbers
+  (testing "Divide purely imaginary numbers"
+    (is (= (c/div [0 1] [0 2])
+           [0.5 0.0]))))
+
+(deftest divide-numbers-with-real-and-imaginary-part
+  (testing "Divide numbers with real and imaginary part"
+    (is (= (c/div [1 2] [3 4])
+           [0.44 0.08]))))
+
+;; Tests for Absolute Value
+(deftest absolute-of-positive-purely-real-number
+  (testing "Absolute value of a positive purely real number"
+    (is (= (c/abs [5 0])
+           5.0))))
+
+(deftest absolute-of-negative-purely-real-number
+  (testing "Absolute value of a negative purely real number"
+    (is (= (c/abs [-5 0])
+           5.0))))
+
+(deftest absolute-of-positive-purely-imaginary-number
+  (testing "Absolute value of a purely imaginary number with positive imaginary part"
+    (is (= (c/abs [0 5])
+           5.0))))
+
+(deftest absolute-of-negative-purely-imaginary-number
+  (testing "Absolute value of a purely imaginary number with negative imaginary part"
+    (is (= (c/abs [0 -5])
+           5.0))))
+
+(deftest absolute-of-real-and-imaginary-number
+  (testing "Absolute value of a number with real and imaginary part"
+    (is (= (c/abs [3 4])
+           5.0))))
+
+;; Tests for Conjugate
+(deftest conjugate-of-purely-real-number
+  (testing "Conjugate a purely real number"
+    (is (= (c/conjugate [5 0])
+           [5 0]))))
+
+(deftest conjugate-of-purely-imaginary-number
+  (testing "Conjugate a purely imaginary number"
+    (is (= (c/conjugate [0 5])
+           [0 -5]))))
+
+(deftest conjugate-of-real-and-imaginary-number
+  (testing "Conjugate a number with real and imaginary part"
+    (is (= (c/conjugate [1 1])
+           [1 -1]))))
+
+;; Tests for Real Part
+(deftest real-of-purely-real-number
+  (testing "Real part of a purely real number"
+    (is (= (c/real [1 0])
+           1))))
+
+(deftest real-of-purely-imaginary-number
+  (testing "Real part of a purely imaginary number"
+    (is (= (c/real [0 1])
+           0))))
+
+(deftest real-of-real-and-imaginary-number
+  (testing "Real part of a number with real and imaginary part"
+    (is (= (c/real [1 2])
+           1))))
+
+;; Tests for Imaginary Part
+(deftest imaginary-of-purely-real-number
+  (testing "Imaginary part of a purely real number"
+    (is (= (c/imaginary [1 0])
+           0))))
+
+(deftest imaginary-of-purely-imaginary-number
+  (testing "Imaginary part of a purely imaginary number"
+    (is (= (c/imaginary [0 1])
+           1))))
+
+(deftest imaginary-of-real-and-imaginary-number
+  (testing "Imaginary part of a number with real and imaginary part"
+    (is (= (c/imaginary [1 2])
+           2))))