Skip to content

Instantly share code, notes, and snippets.

@zobar
Last active August 29, 2015 13:57
Show Gist options
  • Save zobar/9607820 to your computer and use it in GitHub Desktop.
Save zobar/9607820 to your computer and use it in GitHub Desktop.
Look and say, ruby & clojure
(ns look-and-say)
(defn- consecutive [string]
(map first (re-seq #"(.)\1*" string)))
(defn- say [chars]
[(count chars) (first chars)])
(defn- get-next [string]
(apply str (mapcat say (consecutive string))))
(defn look-and-say [string]
(iterate get-next string))
; (def las (look-and-say/look-and-say "1"))
; (take 2 las)
; => ("1" "11")
; (take 2 las)
; => ("1" "11")
module LookAndSay
class << self
def look_and_say(string)
Enumerator.new do |yielder|
current = string
loop do
yielder << current
current = get_next current
end
end
end
private
def consecutive(string)
string.scan(/((.)\2*)/).map &:first
end
def say(chars)
[chars.length, chars[0]]
end
def get_next(string)
consecutive(string).map(&method(:say)).join ''
end
end
end
# las = LookAndSay.look_and_say '1'
# las.take 2
# => ["1", "11"]
# las.take 2
# => ["1", "11"]
@mark
Copy link

mark commented Mar 17, 2014

Ah... heh. Well, for my solution, yeah, #take doesn't work perfectly. There's a slightly longer way to write it where it works correctly, but harder to fit into a tweet:

def iterate(meth, arg)
  Enumerator.new do |yielder|
    current = arg
    loop do
      yielder << current
      current = send(meth, current)
    end
  end
end

By reassigning the method parameter, it prevents #take from working correctly.

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