Skip to content

Instantly share code, notes, and snippets.

@ghoseb
Last active November 9, 2022 03:19
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 ghoseb/7318102 to your computer and use it in GitHub Desktop.
Save ghoseb/7318102 to your computer and use it in GitHub Desktop.
Mars rover problem solved in Clojure.
(ns mars.rover)
;; A squad of robotic rovers are to be landed by NASA on a plateau on
;; Mars.
;; This plateau, which is curiously rectangular, must be navigated by the
;; rovers so that their on-board cameras can get a complete view of the
;; surrounding terrain to send back to Earth.
;; A rover's position and location is represented by a combination of x and
;; y co-ordinates and a letter representing one of the four cardinal
;; compass points. The plateau is divided up into a grid to simplify
;; navigation. An example position might be 0, 0, N, which means the rover
;; is in the bottom left corner and facing North.
;; In order to control a rover , NASA sends a simple string of letters. The
;; possible letters are "L", "R" and "M". "L" and "R" makes the rover spin
;; 90 degrees left or right respectively, without moving from its current
;; spot. "M" means move forward one grid point, and maintain the same
;; heading.
;; Assume that the square directly North from (x, y) is (x, y+1).
;; INPUT:
;; The first line of input is the upper-right coordinates of the plateau,
;; the lower-left coordinates are assumed to be 0,0.
;; The rest of the input is information pertaining to the rovers that have
;; been deployed. Each rover has two lines of input. The first line gives
;; the rover's position, and the second line is a series of instructions
;; telling the rover how to explore the plateau.
;; The position is made up of two integers and a letter separated by
;; spaces, corresponding to the x and y co-ordinates and the rover's orientation.
;; Each rover will be finished sequentially, which means that the second
;; rover won't start to move until the first one has finished moving.
;; OUTPUT
;; The output for each rover should be its final co-ordinates and heading.
;; INPUT AND OUTPUT
;; Test Input:
;; 5 5
;; 1 2 N
;; LMLMLMLMM
;; 3 3 E
;; MMRMMRMRRM
;; Expected Output:
;; 1 3 N
;; 5 1 E
(def ^:private directions (vec "NEWS"))
(def ^:private shifts [[0 1] [1 0] [0 -1] [-1 0]])
(def ^:private instructions
(zipmap "RLM" [(fn [x y d] [x y (mod (inc d) 4)])
(fn [x y d] [x y (mod (+ (dec d) 4) 4)])
(fn [x y d]
[(+ x (first (nth shifts d)))
(+ y (second (nth shifts d)))
d])]))
(defn ^:private position
"Find the position of item in coll."
[coll item]
(first
(for [[idx x] (map-indexed vector coll) :when (= x item)]
idx)))
(defn ^:private process-command
"Take an initial state and process a new instruction."
[init-pos instruction]
(apply (instructions instruction) init-pos))
(defn ^:private process-commands*
"Take an initial state and process a bunch of instructions."
[init-pos instructions]
(reduce process-command init-pos instructions))
(defn process-commands
"Take an initial state and process a bunch of instructions."
[[x y d] instructions]
(when-let [direction (position directions d)]
(let [[x y d] (process-commands* [x y direction] instructions)]
[x y (directions d)])))
;; Examples
;; (process-commands [1 2 \N] "LMLMLMLMM") -> [1 3 \N]
;; (process-commands [3 3 \E] "MMRMMRMRRM") -> [5 1 \E]
@gja
Copy link

gja commented Nov 6, 2013

I think you meant s/find-in/position

@anildigital
Copy link

Get error for #89
clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: find-in in this context, compiling:(NO_SOURCE_PATH:3:22)

@ghoseb
Copy link
Author

ghoseb commented Jun 9, 2016

@anildigital It should be fixed now. There was a typo.

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