Last active
July 1, 2020 00:57
-
-
Save KingCode/5ed247d4353e5d5652d58c4fd68e3594 to your computer and use it in GitHub Desktop.
Properties test for Functional-TV challenge #384
This file contains 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
;; see | |
;; https://gist.github.com/ericnormand/81722b80fc7d0b2972fda68652489f65 | |
(ns my-ns-test | |
(:require [my-ns :as sut] | |
[clojure.test.check.properties :as prop] | |
[clojure.test.check.generators :as gen] | |
[clojure.test.check.clojure-test :refer [defspec]])) | |
(let [alias-str "sut" | |
sym (symbol (str alias-str "/parallel?"))] | |
(def ||? (resolve sym))) | |
(defn line [a b c] [a b c]) | |
(defn y [x [a b c :as line]] | |
(-> c (- (* a x)) (/ b))) | |
(defn vertical-distance [x line-1 line-2] | |
(- (y x line-2) (y x line-1))) | |
(defn vertical? [[_ b _ :as line]] | |
(= 0 b)) | |
(defn not-vertical? [[_ b _ :as line]] | |
(not= 0 b)) | |
(def gen-smallint-nozero (gen/such-that #(not= 0 %) gen/small-integer)) | |
;; [0,0,c] is not a line | |
(def gen-line (gen/frequency [[1 (gen/tuple gen-smallint-nozero | |
gen/small-integer | |
gen/small-integer)], | |
[1 (gen/tuple gen/small-integer | |
gen-smallint-nozero | |
gen/small-integer)]])) | |
(def gen-line-diagonal (gen/tuple gen-smallint-nozero | |
gen-smallint-nozero | |
gen/small-integer)) | |
(defn z0->pos [x & excluded] | |
(if (= 0 x) | |
(rand-nth (remove (set excluded) | |
(range 1 100))) | |
x)) | |
(defn ->vertical [[a b c]] | |
;; ensure (not= 0 a b) | |
[(z0->pos a), 0, c]) | |
(defn ->non-vertical [[a b c]] | |
[a , (z0->pos b), c]) | |
(defn ->horizontal [[a b c]] | |
[0, (z0->pos b), c]) | |
(defn same? [[a1 b1 c1 :as line1] [a2 b2 c2 :as line2]] | |
(cond | |
(= 0 a1 a2) | |
(or (= 0 c1 c2) (= (* b1 c2) (* b2 c1))) | |
(= 0 b1 b2) | |
(or (= 0 c1 c2) (= (* a1 c2) (* a2 c1))) | |
(or (zero? b1) (zero? b2)) | |
(= (* c1 a2) (* c2 a1)) | |
(or (zero? a1) (zero? a2)) | |
(= (* c1 b2) (* c2 b1)) | |
:else | |
(and (= (* a1 b2) (* a2 b1)) | |
(= (y 1 line1) (y 1 line2))))) | |
(def gen-vertical-line (gen/fmap ->vertical gen-line)) | |
(def gen-line-pair (gen/tuple gen-line gen-line)) | |
(defn gen-distinct | |
([g] | |
(gen-distinct #(apply not= %) g)) | |
([pred g] | |
(gen/such-that pred g))) | |
(defn gen-line-pair-distinct | |
([] (gen-line-pair-distinct gen-line-pair)) | |
([g] | |
(gen-distinct (fn [[line1 line2]] | |
(not (same? line1 line2))) | |
g))) | |
(defn distinct-pair? [pair] | |
(not (apply same? pair))) | |
(defn gen-line-pair-n-vertical [n] | |
(let [fs (take 2 (concat (repeat n ->vertical) | |
(repeat 2 ->non-vertical)))] | |
(gen-line-pair-distinct (gen/fmap | |
(fn [pair] | |
(mapv #(% %2) fs pair)) | |
(gen-line-pair-distinct | |
gen-line-pair))))) | |
(def gen-line-pair-horizontals | |
(gen-line-pair-distinct (gen/fmap (fn [[[_ b1 c1] [_ b2 c2]]] | |
(let [b1 (z0->pos b1)] | |
[[0, (z0->pos b1), c1] | |
[0, (z0->pos b2 b1), c2]])) | |
(gen-line-pair-distinct)))) | |
(defn rand-nth-nozero [low hi] | |
(rand-nth (remove zero? (range low hi)))) | |
(defn pos-nth [upper] | |
(rand-nth (range 1 upper))) | |
(defn invert [[a b c :as line]] | |
[(- a) b c]) | |
(defn gen-pair-diagonals|| [limit] | |
(gen-line-pair-distinct | |
(gen/fmap (fn [[a b c :as line]] | |
(let [spice (pos-nth limit)] | |
[[a b c] [(* spice a), (* spice b), (+ c spice)]])) | |
gen-line-diagonal))) | |
(defmacro implies [pred-form then-form] | |
`(if ~pred-form ~then-form true)) | |
(defspec detects-parallel-lines 100 | |
(prop/for-all [[line1 line2 :as pair] | |
(gen/frequency [[6 (gen-line-pair-distinct | |
(gen-pair-diagonals|| 22))] | |
[3 (gen-line-pair-distinct | |
gen-line-pair-horizontals)] | |
[3 (gen-line-pair-n-vertical 2)]])] | |
(||? line1 line2))) | |
(defspec detects-non-parallel-lines 100 | |
(prop/for-all [[line1 line2 :as pair] | |
(gen/frequency [[3 (gen-line-pair-n-vertical 1)] | |
[3 (gen/fmap (fn [line] | |
[line (invert line)]) | |
(gen/such-that not-vertical? | |
gen-line))] | |
[1 (gen/fmap (fn [line] | |
[line line]) | |
gen-line)]])] | |
(not (||? line1 line2)))) | |
(defspec non-vertical-||s-points-sharing-x-coord-have-same-vertical-distance | |
100 | |
(prop/for-all [[line1 line2 :as pair] | |
(gen/frequency [[3 (gen-pair-diagonals|| 7)], | |
[1 gen-line-pair-horizontals]]) | |
xs (gen/set gen/small-integer {:min-elements 2 | |
:max-tries 1000})] | |
(let [no-vert? (not-any? vertical? pair)] | |
(implies (and no-vert? (||? line1 line2)) | |
(->> xs | |
(map #(vertical-distance % line1 line2)) | |
(apply =)))))) | |
(defspec both-or-none-vertical-if-|| 100 | |
(prop/for-all [[line1 line2 :as pair] | |
(gen/frequency [[2 (gen-line-pair-n-vertical 2)] | |
[2 (gen-line-pair-n-vertical 1)] | |
[3 (gen-pair-diagonals|| 10)]])] | |
(implies (||? line1 line2) | |
(or (every? vertical? pair) | |
(not-any? vertical? pair))))) | |
(defspec not-parallel-to-itself 100 | |
(prop/for-all [[line1 line2] | |
(gen/frequency [[1 (gen/fmap (fn [line] | |
[line line]) | |
gen-line)] | |
[9 (gen/fmap (fn [line] | |
(let [fact (rand-nth-nozero -20 20)] | |
[line, | |
(mapv #(* fact %) line)])) | |
gen-line)]])] | |
(not (||? line1 line2)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment