Then there are problems elsewhere in your code; you didn’t share the full thing.
For example if you did not follow my instruction to replace map
with doseq
, then your swap!
would never have been called, for the reasons I explained above.
It will be easier to do that if you follow my advice and move the string/split
inside of parse-input
, then you only need a single doseq
call over the instruction data, rather than worrying about how to map over the splitting and then feed the results into the doseq
.
A great excuse to learn about reduce
:
user> (let [input ["forward 5"
"down 5"
"forward 8"
"up 3"
"down 8"
"forward 2"]]
(reduce (fn [eax s]
(let [[dir amount] (clojure.string/split s #"\s+")]
(condp = dir
"forward" (update eax :x + (Long. amount))
"down" (update eax :y + (Long. amount))
"up" (update eax :y - (Long. amount)))))
{:x 0 :y 0}
input))
{:x 15, :y 10}
Some questions stemming from the order of arguments passed to the update
function, and the commutativity of subtraction - worth of some tests and further exploration.
Following conventions and keeping things simple I solved it like this:
(ns demo
(:require [clojure.string :as str])
(:gen-class))
(def data (-> "filename"
slurp
str/split-lines))
(defn track
"For instruction `s` return position delta."
[acc s]
(let [[dir dist] (str/split s #" ")
dist (parse-long dist)]
(map + acc (case dir
"forward" [dist 0]
"up" [0 (- dist)]
"down" [0 dist]))))
(defn -main
[]
(println (apply * (reduce track [0 0] data))))
(-main)
I could clean it up a little, but I just threw this together on my break.
The case should probably go in a helper funtion, so the result could be bound in the let of “track”.