Facebook Careers Puzzle—hoppity in Clojure

Puzzle is from Facebook’s Job Puzzles page.

I try to learn as many languages as I can in my spare time, and Clojure is my latest subject. I think it has potential to replace Ruby as my primary general purpose language.

To make sure I had the build process right for the puzzle submission, I decided to solve the easy hoppity puzzle in Clojure. However, I hit a stumbling block almost immediately… I didn’t know how to read from a file!

I have Stuart Halloway’s beta book on Clojure and tried to look up how to do file I/O, but couldn’t find anything. (I do recommend the book though, it is quite good, especially on concurrency).

Buy it from Amazon

Neither is it explained on the official Clojure website. These little things need to be mentioned more prominently for fast adoption. Anyways, I realized that using the standard Java approach would work, so I used the BufferedReader and FileReader stack.

Note that Clojure looks just like Lisp, and has basically all of the features of Lisp that make it good. The fact that it can use any Java library is a huge win as well.

In Clojure, arguments passed in from the command line are kept as a vector called *command-line-args*, and you can get the nth argument by unsurprisingly using the nth function, like I do below.

Anything with a period in the function name is a Java method call, so it’s easy to tell what’s pure Clojure and what’s Java. Clojure seems to rely on Java for all I/O, which is not a bad decision, but should be better documented.

I will be posting more on Clojure as I play with it!

The following solution passed the Facebook puzzle robot:

(hoppity.clj) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
; Hoppity hop in Clojure
; Kanwei Li, 2009

(def *input-file* (nth *command-line-args* 0))
(def *input* (java.io.BufferedReader. (java.io.FileReader. *input-file*)))

(defn get-num []
  (Integer. (first (.split (.readLine *input*) "\n"))))

(dotimes [i (get-num)]
  (let [num (+ i 1)
        answer (cond (= 0 (rem num 15)) "Hop"
                     (= 0 (rem num 5)) "Hophop"
                     (= 0 (rem num 3)) "Hoppity")]
    (if (not (nil? answer))
      (println answer))))

In contrast to my Ruby version, there is no LOC difference, and they are both well-readable to me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env ruby
# Hoppity puzzle
# Kanwei Li, 2009

filename = ARGV[0]
input = File.open(filename)

n = input.gets.to_i
1.upto(n) do |i|
  if i % 15 == 0
    puts "Hop\n"
  elsif i % 5 == 0
    puts "Hophop\n"
  elsif i % 3 == 0
    puts "Hoppity\n"
  end
end
Posted on