Instantly share code, notes, and snippets.

# ericnormand/00 Roboto.md

Created August 1, 2022 22:00
Show Gist options
• Save ericnormand/d6fa214ed0733998a2e0a3f4d3fb62e5 to your computer and use it in GitHub Desktop.
472 Eric Normand Newsletter

Roboto

A futuristic robot is programmed to take in a sequence of numbers. Each number is the distance to travel in a cardinal direction (north, south, east, west). It starts facing north at `(0, 0)`, travels straight ahead by the distance given in the first number, then turns 90 degrees clockwise, now facing east. Then it repeats with the next number. Your job is to calculate where it ends up at the end of the sequence.

Examples

```(move []) ;=> [0 0] ;; No motion
(move [10]) ;=> [0 10] ;; move 10 straight north
(move [10 2]) ;=> [2 10]
(move [10 2 3]) ;=> [2 7]```

Thanks to this site for the problem idea, where it is rated Very Hard in Ruby. The problem has been modified.

### wevre commented Aug 1, 2022 • edited Loading

```(defn move [xs]
(reduce (fn [val [x [k f]]] (update val k f x))
[0 0]
(map vector xs (cycle [[1 +] [0 +] [1 -] [0 -]]))))```

### rickerbh commented Aug 2, 2022

```  (defn move
[xs]
(let [dir-moves (fn [every moves] (apply + (take-nth 4 (drop every moves))))]
[(- (dir-moves 1 xs) (dir-moves 3 xs)) (- (dir-moves 0 xs)  (dir-moves 2 xs))]))```

### KingCode commented Aug 2, 2022

```(def ops (cycle [[nil +] [+ nil] [nil -] [- nil]]))

(defn move [deltas]
(let [step (fn [[x y :as loc] [d & deltas] [[xop yop] & ops]]
(if d
(recur [((or xop (constantly x)) x d)
((or yop (constantly y)) y d)]
deltas
ops)
loc))]
(step [0 0] deltas ops)))```

### mchampine commented Aug 2, 2022 • edited Loading

```;; version 1
(defn movenr [[px py] [n [dx dy]]] [(+ px (* n dx)) (+ py (* n dy))])

(defn move [xs]
(reduce movenr [0 0] (map vector xs [[0 1] [1 0] [0 -1] [-1 0]])))

;; version 2
(defn point* [[px py] n] [(* n px) (* n py)])
(defn pair+ [[ax ay] [bx by]] [(+ ax bx) (+ ay by)])

(defn move [xs]
(reduce pair+ [0 0] (map point* (cycle [[0 1] [1 0] [0 -1] [-1 0]]) xs)))```

### jonasseglare commented Aug 2, 2022

Version 1

```(defn move [step-sizes]
(first (reduce (fn [[[x y] [dx dy]] l]
[[(+ x (* l dx))
(+ y (* l dy))]
[dy (- dx)]])
[[0 0] [0 1]]
step-sizes)))```

Version 2

```(defn component [step-sizes]
(apply + (map * (take-nth 2 step-sizes) (iterate - 1))))

(def move (juxt (comp component rest) component))```

### ethan-rambacher commented Aug 2, 2022 • edited Loading

Consider the y coordinate. Start with 0, add the 0th element, subtract the 2nd element, add the 4th, and so on.
Consider the x coordinate. Start with 0, add the 1st element, subtract the 3rd element, add the 5th, and so on.
To use `(reduce +)` let's also multiply each element by 0, 1, or -1, using `cycle`. We can do this with the x and y coords separately.

```(defn move [moves]
[(reduce + (map * (cycle [0 1 0 -1]) moves))
(reduce + (map * (cycle [1 0 -1 0]) moves))])```

We can reduce the repeated code by using `drop` and `mapv`:

```(defn move [moves]
(mapv
#(reduce + (map * (drop % (cycle [0 1 0 -1])) moves))
[0 1]))```

### nbardiuk commented Aug 2, 2022

```(defn move [distances]
(let [start [0 0]
directions [[0 1] [1 0] [0 -1] [-1 0]]
scale (fn [[x y] n] [(* x n) (* y n)])
add (fn [[ax ay] [bx by]] [(+ ax bx) (+ ay by)])]
(->> (map scale (cycle directions) distances)

### wevre commented Aug 2, 2022

I like @michaelteter's solution because the names and logic align directly to the real world movements. But it doesn't seem to handle an input sequence longer than 4 items. Here is an adapted approach that does:

```(defn move [xs]
(loop [[x y] [0 0] [n e s w & r] (concat xs (repeat 4 0))]
(if (seq r)
(recur [(+ x (- e w)) (+ y (- n s))] r)
[x y])))```

### nwjsmith commented Aug 2, 2022

```(defn move
[magnitudes]
(let [directions (map vector (cycle [0 1 0 -1]) (cycle [1 0 -1 0]))
movements (map (fn [direction magnitude] (map #(* % magnitude) direction))
directions
magnitudes)]
(reduce (fn [location movement] (map + location movement))
[0 0]
movements)))```

### michaelteter commented Aug 2, 2022 • edited Loading

As @wevre noted, my original solution was not valid for inputs beyond 4 items... I thought the problem seemed weird! :P

Here's a cave-man solution. It's somewhat lengthy, but I think it could be comprehended by someone with little or no Clojure experience.

```(defn move [steps]
(loop [[step & remaining-steps] steps
[x y] [0 0]
step-count 0]
(if (nil? step)
[x y]
(recur remaining-steps
(case (mod step-count 4)
0 [x (+ y step)]
1 [(+ x step) y]
2 [x (- y step)]
3 [(- x step) y])
(inc step-count)))))```

### JonathanHarford commented Aug 2, 2022

```(defn move [path]
(reduce (fn [[x y] [n e s w]]
[(+ x (or e 0) (- (or w 0)))
(+ y (or n 0) (- (or s 0)))])
[0 0]
(partition-all 4 path)))```

### gdw2 commented Aug 2, 2022

```(defn move
[moves]
(->>
(apply concat (repeat ['(0 1) '(1 0) '(0 -1) '(-1 0)]))
(interleave (conj moves 0))
(partition 2)
(map (fn [[m d]] (map (partial * m) d)))
(apply mapv +)))```

### miner commented Aug 3, 2022

```(defn move [moves]
(pop (reduce (fn [[east north dir] m]
(case dir
:north [east (+ north m) :east]
:east [(+ east m) north  :south]
:south [east (- north m) :west]
:west [(- east m) north  :north]))
[0 0 :north]
moves)))```

### miner commented Aug 3, 2022

```(defn move [moves]
(let [sum4th (fn [d] (transduce (comp (drop d) (take-nth 4)) + 0 moves))]
[(- (sum4th 1) (sum4th 3))
(- (sum4th 0) (sum4th 2))]))```

### Archenoth commented Aug 3, 2022 • edited Loading

It's fun how so many programming challenges can boil down to "use loop, but..."

```(defn move [moves]
(loop [[dist & moves] moves
[[xdir ydir] & dirs] (cycle [[0 1] [1 0] [0 -1] [-1 0]])
[x y] [0 0]]
(if-not dist
[x y]
(recur moves dirs [(+ x (* xdir dist)), (+ y (* ydir dist))]))))```

### kauppilainen commented Aug 5, 2022

```(defn do-move [[x y] direction len]
(case direction
:north [x (+ y len)]
:east  [(+ x len) y]
:south [x (- y len)]
:west  [(- x len) y]))

(defn move [moves]
(let [moves' (zipmap moves (cycle [:north :east :south :west]))]
(reduce (fn [s [len dir]] (do-move s dir len))
[0 0]
moves')))```

### cmaus00 commented Aug 7, 2022 • edited Loading

```(defn move [steps]
(let [weights (map (fn [i] (if (< 1 (mod i 4)) -1 1)) (range))]
(->> steps
(map vector weights)
(map #(apply * %1))
(map-indexed #(if (= (mod %1 2) 0) [0 %2] [%2 0]) )
(reduce #(map + %1 %2) [0 0]))))```

### cmaus00 commented Aug 7, 2022

```(defn move [steps]
(let [directions (cycle [[0 1] [1 0] [0 -1] [-1 0]])
vecmult (fn [v s] (map #(* s %) v))
vecadd (fn [& vs] (apply map + vs))]
(->> steps
(map vector directions)
(map #(apply vecmult %))
(reduce vecadd [0 0]))))```

### ericnormand commented Aug 8, 2022

map-reduce has been on my mind.

```(def directions
[[0 1]  ;; north
[1 0]  ;; east
[0 -1] ;; south
[-1 0] ;; west
])

(defn vec+ [a b]
(mapv + a b))

(defn vec-scalar* [v s]
(mapv #(* s %) v))

(defn move [xs]
(reduce vec+
[0 0]
(map vec-scalar* (cycle directions) xs)))```

### barrosfelipe commented Aug 8, 2022

Bit late to this party but here is mine:

```(defn move [xs]
(if-not (seq xs)
[0 0]
(->> xs
(partition 4 4 [0 0 0 0])
(apply #(map + %))
((fn [[a b c d]] [(- b d) (- a c)])))))```

to join this conversation on GitHub. Already have an account? Sign in to comment