#:g1: RubyでL-99 (P1〜P8)

Posted 2009-03-16 14:59:00 GMT

Rubyを勉強しております。
Rubyにリストが無いのとブロックの引数がローカルのスコープをつくらないところ(1.8では)にびっくりしました。
びっくりというより若干ショックでしたが、別にLispじゃないので当然のことでした。
ちょっとMatz Lispという言葉を真に受け過ぎていたようです(笑)

無駄に再帰していますが、L-99はそういう問題なのでRubyでも再帰。
色々分からないことが多く、まったくRubyっぽく書けてないですが、10年後位にはRubyっぽく書けるようになるのかもしれません。

# P01 (*) Find the last box of a list.
#     Example:
#     * (my-last '(a b c d))
#     (D)
class Array
  def my_last 
    head, *tail = self
    if tail.empty?
      self
    else
      tail.my_last
    end
  end
end

%w(1 2 3).my_last #=> ["3"]

# P02 (*) Find the last but one box of a list. # Example: # * (my-but-last '(a b c d)) # (C D) class Array def last2 _, *tail = self if tail[1..-1].empty? self else tail.last2 end end end

%w(a b c d).last2 #=> ["c", "d"]

#P03 (*) Find the K'th element of a list. # The first element in the list is number 1. # Example: # * (element-at '(a b c d e) 3) # C class Array def element_at (pos) head, *tail = self if 0 > pos nil elsif self.empty? || 1 >= pos head else tail.element_at(pos - 1) end end end

%w(1 2 3 4).element_at(2) #=> "2"

# P04 (*) Find the number of elements of a list. class Array def my_size _, *tail = self if self.empty? 0 else 1 + tail.my_size end end end

%w(1 2 3 4).my_size #=> 4

# P05 (*) Reverse a list. class Array def my_reverse head, *tail = self if self.empty? [] else tail.my_reverse + [head] end end end

%w(1 2 3 4).my_reverse #=> ["4", "3", "2", "1"]

#P06 (*) Find out whether a list is a palindrome. # A palindrome can be read forward or backward; e.g. (x a m a x). class Array def palindrome? self.my_reverse == self end end

%w(x a m a x).palindrome? #=> true

%w(x m a x).palindrome? #=> false

# P07 (**) Flatten a nested list structure. # Transform a list, possibly holding lists as elements into a # `flat' list by replacing each list with its elements # (recursively). # Example: # * (my-flatten '(a (b (c d) e))) # (A B C D E) # Hint: Use the predefined functions list and append. class Array def my_flatten head, *tail = self if self.empty? [] elsif head.class == Array head.my_flatten + tail.my_flatten else [head] + tail.my_flatten end end end

[1, [2, [3, 4], 5]].my_flatten #=> [1, 2, 3, 4, 5]

# P08 (**) Eliminate consecutive duplicates of list elements. # If a list contains repeated elements they should be replaced # with a single copy of the element. The order of the elements # should not be changed. # Example: # * (compress '(a a a a b c c a a d e e e e)) # (A B C A D E) class Array def _compress(prev, acc) head, *tail = self if self.empty? acc elsif head == prev tail._compress(head, acc) else tail._compress(head, acc + [head]) end end

def compress self._compress(:dummy, []) end end

%w(a a a a b c c a a d e e e e).compress #=> ["a", "b", "c", "a", "d", "e"]

comments powered by Disqus