Skip to content

Instantly share code, notes, and snippets.

@invasionofsmallcubes
Last active December 23, 2019 00:29
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 invasionofsmallcubes/623e5b816f6a040ffeaf855375ea3501 to your computer and use it in GitHub Desktop.
Save invasionofsmallcubes/623e5b816f6a040ffeaf855375ea3501 to your computer and use it in GitHub Desktop.
Advent of Code Day 3 #adventOfCode2019
;; https://adventofcode.com/2019/day/3
;; EXERCISES
(ns cljbrave.core)
(defrecord Movement [direction length])
(defrecord Coordinate [x y])
(def origin (->Coordinate 0 0))
(defn movements
"R6 becomes (:R 6)"
[string-coordinates]
(->Movement (keyword (str (first string-coordinates)))
(Integer. (apply str (rest string-coordinates)))))
(defn get-movements
"R6,U7 becomes [(:R, 6),(:U, 7)]"
[string-of-coordinates]
(map movements (.split string-of-coordinates ",")))
(defn moveUp [p] (+ p 1))
(defn moveDown [p] (- p 1))
(def directionsFn {
:R {:x moveUp :y identity}
:U {:x identity :y moveUp}
:L {:x moveDown :y identity}
:D {:x identity :y moveDown}
})
(defn moves1
[movement length directionFn]
(if (= length 0)
[]
(let [next (->Coordinate ((:x directionFn) (:x movement))
((:y directionFn) (:y movement)))]
(cons next (moves1 next (- length 1) directionFn)))))
(defn moves
"(0,0) and (:R, 2) will give ((1,0), (2,0))"
[start movement]
(moves1 start (:length movement) ((:direction movement) directionsFn)))
(defn path-accumulator
[result current]
(let [current-path (moves (:start result) current)]
{:start (last current-path) :acc (into (:acc result) current-path)}))
(defn generate-coordinates
"R1,D1 becomes [(1,0),(1,-1)]"
[raw-instructions]
(:acc (reduce path-accumulator {:start origin :acc []} (get-movements raw-instructions))))
(defn read-lists
[path]
(map generate-coordinates (.split (slurp path) "\n")))
(defn common-coordinates
[list-of-paths]
(let [a-list (first list-of-paths)
b-list (last list-of-paths)]
(clojure.set/intersection (set a-list) (set b-list))))
(defn min-distance
[coordinates]
(apply min (map #(+ (Math/abs (:x %)) (Math/abs (:y %))) coordinates)))
(defn sum-while
[f, coll]
(+ 1 (count (take-while #(not= % f) coll))))
(defn min-steps
[path]
(let [list-of-coordinates (read-lists path)
a-list (first list-of-coordinates)
b-list (last list-of-coordinates)
intersections (common-coordinates list-of-coordinates)]
(apply min (map #(+ (sum-while % a-list) (sum-while % b-list)) intersections))))
;; TESTS
(ns cljbrave.core-test
(:require [clojure.test :refer :all]
[cljbrave.core :refer :all]))
(deftest can-move-string-to-list
(testing "R6 become (R, 6)"
(is (= (movements "R6") (->Movement :R 6))))
(testing "U6 become (U, 16)"
(is (= (movements "U16") (->Movement :U 16)))))
(deftest can-get-list-and-transform-couple
(testing "R6,U7 becomes [(:R, 6),(:U, 7)]"
(is (= (get-movements "R6,U7") [(->Movement :R 6), (->Movement :U 7)]))))
(deftest can-get-moves
(testing "(0,0) and (:R, 2) will give [(1,0), (2,0)]"
(is (= (moves origin (->Movement :R 2))
[(->Coordinate 1 0), (->Coordinate 2 0)])))
(testing "(0,0) and (:U, 2) will give [(0,1), (0,2)]"
(is (= (moves origin (->Movement :U 2))
[(->Coordinate 0 1), (->Coordinate 0 2)])))
(testing "(0,0) and (:L, 2) will give [(-1,0), (-2,0)]"
(is (= (moves origin (->Movement :L 2))
[(->Coordinate -1 0), (->Coordinate -2 0)])))
(testing "(0,0) and (:D, 2) will give [(0,-1), (0,-2)]"
(is (= (moves origin (->Movement :D 2))
[(->Coordinate 0 -1), (->Coordinate 0 -2)])))
(testing "(0,0) and (:R, 0) will give []"
(is (= (moves origin (->Movement :R 0))
[]))))
(deftest can-generate-a-list-of-coordinates
(testing "R2,D1 becomes [(1,0),(2,0),(2,-1)]"
(is (= (generate-coordinates "R2,D1") [(->Coordinate 1 0), (->Coordinate 2 0), (->Coordinate 2 -1)]))))
(deftest can-slurp
(testing "can read file"
(is (= (slurp "test/cljbrave/test1.txt") "R1,U1,L1,D1\nU1,R1,D1,L1"))))
(deftest can-get-list-from-file
(testing "can get list from files"
(is (= (first (read-lists "test/cljbrave/test1.txt")) [(->Coordinate 1 0), (->Coordinate 1 1), (->Coordinate 0 1), (->Coordinate 0 0)])))
(testing "can get list from files"
(is (= (last (read-lists "test/cljbrave/test1.txt")) [(->Coordinate 0 1), (->Coordinate 1 1), (->Coordinate 1 0), (->Coordinate 0 0)]))))
(deftest calculate-interserctions
(testing "get-intersection"
(is (= (common-coordinates (read-lists "test/cljbrave/test1.txt")) (set [(->Coordinate 0 0), (->Coordinate 0 1), (->Coordinate 1 0), (->Coordinate 1 1)])))))
(deftest calculate-minimum-distance
(testing "minimum distance"
(is (= (min-distance (common-coordinates (read-lists "test/cljbrave/test2.txt"))) 6))))
(deftest calculate-minimum-distance2
(testing "minimum distance"
(is (= (min-distance (common-coordinates (read-lists "test/cljbrave/test3.txt"))) 159))))
(deftest calculate-minimum-distance3
(testing "minimum distance"
(is (= (min-distance (common-coordinates (read-lists "test/cljbrave/test4.txt"))) 135))))
(deftest calculate-minimum-distance3
(testing "minimum distance"
(is (= (min-distance (common-coordinates (read-lists "test/cljbrave/real.txt"))) 225))))
(deftest sumwhile
(testing "sumwhile"
(is (= (sum-while (->Coordinate 1 1)
[(->Coordinate 0 0), (->Coordinate 0 1), (->Coordinate 1 0), (->Coordinate 1 1)]) 4))))
(deftest calculate-minimum-steps
(testing "minimum steps"
(is (= (min-steps "test/cljbrave/test2.txt") 30)))
(testing "minimum steps"
(is (= (min-steps "test/cljbrave/test3.txt") 610)))
(testing "minimum steps"
(is (= (min-steps "test/cljbrave/test4.txt") 410)))
(testing "minimum steps"
(is (= (min-steps "test/cljbrave/real.txt") 35194))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment