Hatena::ブログ(Diary)

(gensym) このページをアンテナに追加 RSSフィード

2011-01-12 当ったらUbuntu入れて、StumpWMで使う このエントリーを含むブックマーク このエントリーのブックマークコメント

実に2年近く更新していなかった。

MacBook Air 11インチ欲しい!

2009-03-29

[][][]skype.elまでの道


skype.elを試してみたのでメモ

skype.elはemacs23前提とのこと

手元にemacs23がなかったのでビルド

$ cvs -z3 -d :pserver:anonymous@cvs.sv.gnu.org:/sources/emacs checkout -P emacs 
$ cd emacs
$ ./configure --with-dbus
$ make bootstrap
$ make install

skype.el

$ svn co http://svn.codecheck.in/lang/elisp/skype/trunk/ skype

.emacsに設定を追加

;; (require 'cl)前提で書いています
(when (<= 23 emacs-major-version)
  (pushnew "skype.elのディレクトリへのパス" load-path :test #'equal)
  (require 'skype)
  (setq skype--my-user-handle "skypeのID"))

まだ、ちょっとしか試していませんが、これは良い!

2009-03-21

[][]RspecでL-99 (P16〜P17)


今日もL-99を題材にRubyのコードを書いてみていました。

今日は、RSpecを自動で実行してくれる、autospecをどうにか使いつつコードを書いてみようというのが目標です。

やりたいこと

とりあえず、コードを書いてファイルがセーブされると、テストが自動で実行されるようになりたい。

autospec設定

ということで、ググったりして調べてみたのですが、autospecを利用するには、ディレクトリの構成を作法に則った構成にする必要があるようです。

とりあえず、

lib/ -- ライブラリ(L99のコード)

spec/ -- テスト用のコード

という風に配置するようになるようです。

l99のディレクトリがl99だとすると、

l99/lib

l99/spec

となります。

どうも、specの中の*_spec.rbという名前のファイルをspecが片っ端から実行してるだけに思えるのですが、今のところそういう理解で行くことにします。

そして、specを利用していたときに渡していた表示用のオプションは、spec/spec.optに記述します。

  • spec/spec.opt


			

これらの設定をして、l99のディレクトリで、

$ autospec

とするとファイル監視 & 更新時の自動テスト実行が始まります。

ループから抜けるには、Ctrl-Cの2回押し。

これで当初の目的は達成したので、とりあえずはこれで良いかなという感じです。

テストのファイル構成ですが、*_spec.rbを全部実行するようなので、1つのメソッドにつき1つという感じで小分けにしてみています。

この構成の方がテスト用の変数を書くのが楽だと思ったからなのですが、果してこれで良いんでしょうか(*'-')

次の目標としては、コンソールを眺めるのが面倒なのでEMACSに表示されたりして欲しいので、その辺を探ってみたいと思います。

ちなみに、L-99のコードについては、Rubyとしては信じられないような作法になっていますが、元がPrologの問題で、それがLISP用に編集されたという変った問題集なのでその辺はスルーして下さい(*'-')

# P16 (**) Drop every N'th element from a list.
#     Example:
#     * (drop '(a b c d e f g h i k) 3)
#     (A B D E G H K)
class Array
  def drop(n = 0) 
    if self.empty? || 0 >= n
      []
    else
      internal_drop(n, 1, [])
    end
  end
  
  def internal_drop(n, cnt, acc)
    head, *tail = self
    if self.empty?
      acc
    elsif 0 == cnt % n
      tail.internal_drop(n, 1 + cnt, acc)
    else
      tail.internal_drop(n, 1 + cnt, acc + [head])
    end
  end
end

# P17 (*) Split a list into two parts; the length of the first part is given.
#     Do not use any predefined predicates.
#     Example:
#     * (split '(a b c d e f g h i k) 3)
#     ( (A B C) (D E F G H I K))
class Array
  def my_split(n = 0)
    if self.empty? || 0 >= n
      []
    elsif n >= self.size
      self
    else
      internal_my_split(n, [])
    end
  end
  
  def internal_my_split(cnt, acc)
    head, *tail = self
    if self.empty? || 0 == cnt
      [acc , [head] + tail]
    else
      tail.internal_my_split(cnt - 1, acc + [head])
    end
  end
end

  • l99-16_spec.rb

require File.dirname(__FILE__) + '/../lib/l99'

describe Array, "L-99: P16 drop" do
  before do 
    @array = %w(a b c d e f g h i k)
    @result_array = %w(a b d e g h k)
  end

  it "を与えたらを返す" do
    [].drop.should be_empty
  end

  it "@arrayを与えたら@dropped_arrayを返す" do
    @array.drop(3).should == @result_array
  end

  it "周期nに0を与えると[]を返す" do
    @array.drop(0).should be_empty
  end

  it "周期nにマイナスの数値を与えると[]を返す" do
    @array.drop(-100).should be_empty
  end

  it "周期nに配列のサイズより大きい数値を与えると元の配列を返す" do
    @array.drop(@array.size + 1).should == @array
  end
end

  • l99-17_spec.rb

require File.dirname(__FILE__) + '/../lib/l99'

describe Array, "L-99: "P17 my_split" do
  before do 
    @array = %w(a b c d e f g h i k)
    @result_array = "a", "b", "c"], ["d", "e", "f", "g", "h", "i", "k"
  end

  it "を与えたらを返す" do
    [].my_split().should be_empty
  end

  it "@arrayを与えたら@my_splitped_arrayを返す" do
    @array.my_split(3).should == @result_array
  end

  it "nに0を与えると[]を返す" do
    @array.my_split(0).should be_empty
  end

  it "nにマイナスの数値を与えると[]を返す" do
    @array.my_split(-100).should be_empty
  end

  it "nに配列のサイズより大きい数値を与えると元の配列を返す" do
    @array.my_split(@array.size).should == @array
  end
end

  • 結果表示

...
Array L-99: P16 drop

			
  • []を与えたら[]を返す
  • @arrayを与えたら@dropped_arrayを返す
  • 周期nに0を与えると[]を返す
  • 周期nにマイナスの数値を与えると[]を返す
  • 周期nに配列のサイズより大きい数値を与えると元の配列を返す
Array L-99: P17 my_split
  • []を与えたら[]を返す
  • @arrayを与えたら@my_splitped_arrayを返す
  • nに0を与えると[]を返す
  • nにマイナスの数値を与えると[]を返す
  • nに配列のサイズより大きい数値を与えると元の配列を返す
Finished in 0.051752 seconds 27 examples, 0 failures

2009-03-20

[][]RspecでL-99


折角なのでTDDにも親しんでおきたいということで、Rspecも普段から積極的に使うことにしてみました。

$ spec -cfs l99_spec.rb

のように実行しているのですが、autospecとかどうやるんだろうという感じです。

テストそのものに関しては、やっぱり書くとそれなりに見落していたバグを潰せるんだなという感じですが、今のところ書くのが面倒なので、簡単に テスト→書く→テスト の流れに乗れるように環境を整備したいところです。

ツールも沢山あるようなのですが、どれがどういう機能なんだかいまいち理解できていません…。

l99.rb

# P09 (**) Pack consecutive duplicates of list elements into sublists.
#     If a list contains repeated elements they should be placed in
#     separate sublists.
#
#     Example:
#     * (pack '(a a a a b c c a a d e e e e))#     *1

class Array
  def pack
    self.internal_pack([], [:dummy])
  end

  protected
  def internal_pack(ans, acc)
    head, *tail = self
    if self.empty?
      (ans + [acc])[1..-1]
    elsif head == acc[0]
      tail.internal_pack(ans ,acc + [head])
    else
      tail.internal_pack(ans + [acc], [head])
    end
  end
end

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

# P10 (*) Run-length encoding of a list.
#     Use the result of problem P09 to implement the so-called
#     run-length encoding data compression method. Consecutive
#     duplicates of elements are encoded as lists (N E) where N is the
#     number of duplicates of the element E.
#
#     Example:
#     * (encode '(a a a a b c c a a d e e e e))#     *2

class Array 
  def encode
    self.pack.map do |x|
      [x.size, x.first]
    end
  end
end

%w(a a a a b c c a a d e e e e).encode
#=> 4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e"?


# P11 (*) Modified run-length encoding.
#     Modify the result of problem P10 in such a way that if an
#     element has no duplicates it is simply copied into the result
#     list. Only elements with duplicates are transferred as (N E)
#     lists.
#
#     Example:
#     * (encode-modified '(a a a a b c c a a d e e e e))#     *3

class Array 
  def encode_modified
    self.pack.map do |x|
      if 1 == x.size
        x.first
      else
        [x.size, x.first]
      end
    end
  end
end

%w(a a a a b c c a a d e e e e).encode_modified
#=> 4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e"?


# P12 (**) Decode a run-length encoded list.
#     Given a run-length code list generated as specified in problem
#     P11. Construct its uncompressed version.

class Array
  def decode
    self.inject([]) do |ans, x|
      ans + if x.class == Array
              Array.new(x[0], x[1])
            else
              Array.new(1, x)
            end
    end
  end
end

# 2
class Array
  def decode
    t = Array
    self.inject([]) do |ans, x|
      ans.+ x.class == Array ? Array.new(x[0], x[1]) : Array.new(1, x)
    end
  end
end

4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e".decode
#=> ["a", "a", "a", "a", "b", "c", "c", "a", "a", "d", "e", "e", "e", "e"]

# P13 (**) Run-length encoding of a list (direct solution).
#     Implement the so-called run-length encoding data compression
#     method directly. I.e. don't explicitly create the sublists
#     containing the duplicates, as in problem P09, but only count
#     them. As in problem P11, simplify the result list by replacing
#     the singleton lists (1 X) by X.
#
#     Example:
#     * (encode-direct '(a a a a b c c a a d e e e e))#     *4

class Array
  def encode_direct
    if self.empty?
      self
    else
      (self + [:dummy]).internal_encode_direct([], 1, :dummy)[1..-1]
    end
  end

  protected
  def internal_encode_direct(ans, cnt, prev)
    head, *tail = self
    if self.empty?
      ans
    elsif head == prev
      tail.internal_encode_direct(ans, cnt + 1, head)
    elsif 1 == cnt
      tail.internal_encode_direct(ans + [prev], 1, head)
    else
      tail.internal_encode_direct(ans + cnt, prev?, 1, head)
    end
  end
end

%w(a a a a b c c a a d e e e e).encode_direct
[].encode_direct
#=> 4, "a"], [1, "b"], [2, "c"], [2, "a"], [1, "d"], [4, "e"?

# P14 (*) Duplicate the elements of a list.
#     Example:
#     * (dupli '(a b c c d))
#     (A A B B C C C C D D)

class Array
  def dupli 
    if self.empty?
      []
    else
      inject([]) do |ans, x|
        ans + [x, x]
      end
    end
  end
end
%w(a b c).dupli

# P15 (**) Replicate the elements of a list a given number of times.
#     Example:
#     * (repli '(a b c) 3)
#     (A A A B B B C C C)

class Array
  def repli(n = 0)
    return [] if 0 >= n || self.empty?

    inject([]) do |ans, x|
      ans + Array.new(n, x)
    end
  end
end

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

l99_spec.rb

require File.dirname(__FILE__) + '/../src/l99'

describe Array, "L-99:" do
  before do 
    @array = %w(a a a a b c c a a d e e e e)
    @packed_array = "a", "a", "a", "a"], 
                     ["b"], 
                     ["c", "c"],
                     ["a", "a"],
                     ["d"], 
                     ["e", "e", "e", "e"
    @encoded_array1 = 4, "a"], [1, "b"], [2, "c"], 
                       [2, "a"], [1, "d"], [4, "e"
    @encoded_array2 = 4, "a"], "b", [2, "c"], [2, "a"], "d", [4, "e"
    @duplicated_array = %w(a a a a a a a a b b c c c c 
                           a a a a d d e e e e e e e e)
    @replicated_array = ["a", "a", "a", "a", "a", "a", 
                         "a", "a", "a", "a", "a", "a", 
                         "b", "b", "b", 
                         "c", "c", "c", "c", "c", "c", 
                         "a", "a", "a", "a", 
                         "a", "a", 
                         "d", "d", "d", 
                         "e", "e", "e", "e", "e", "e", 
                         "e", "e", "e", "e", "e", "e"]
  end
  
  ## P09 ##
  it "P09 pack: を与えたらを返す" do
    [].pack.should be_empty
  end

  it "P09 pack: @arrayを与えたら、@packed_arrayを返す" do
    @array.pack.should == @packed_array
  end

  ## P10 ##
  it "P10 encod: を与えたらを返す" do
    [].encode.should be_empty
  end

  it "P09 encode: @arrayを与えたら、@encoded_array1を返す" do
    @array.encode.should == @encoded_array1
  end

  ## P11 ##
  it "P11 encod_modified : を与えたらを返す" do
    [].encode_modified.should be_empty
  end

  it "P11 encode_modified: @arrayを与えたら、@encoded_array2を返す" do
    @array.encode_modified.should == @encoded_array2
  end

  ## P12 ##
  it "P12 decode : を与えたらを返す" do
    [].decode.should be_empty
  end

  it "P12 decode : @encoded_array2を与えたら@arrayを返す" do
    @encoded_array2.decode.should == @array
  end

  ## P13 ##
  it "P13 encode_direct : を与えたらを返す" do
    [].encode_direct.should be_empty
  end

  it "P13 encode_modified: @arrayを与えたら、@encoded_array2を返す" do
    @array.encode_direct.should == @encoded_array2
  end

  ## P14 ##
  it "P14 dupli : を与えたらを返す" do
    [].dupli.should be_empty
  end

  it "P14 dupli : @arrayを与えたら@duplicated_arrayを返す" do
    @array.dupli.should == @duplicated_array
  end

  ## P15 ##
  it "P15 repli : を与えたらを返す" do
    [].repli(1).should be_empty
  end

  it "P15 repli : 繰り返しの引数が空なら[]を返す" do
    [].repli.should be_empty
  end

  it "P15 repli : 繰り返しの引数が0なら[]を返す" do
    [].repli(0).should be_empty
  end

  it "P15 repli : 繰り返しの引数がマイナスなら[]を返す" do
    [].repli(-100).should be_empty
  end

  it "P15 repli : @arrayを与えたら@replicated_arrayを返す" do
    @array.repli(3).should == @replicated_array
  end

end

*1:A A A A) (B) (C C) (A A) (D) (E E E E

*2:4 A) (1 B) (2 C) (2 A) (1 D)(4 E

*3:4 A) B (2 C) (2 A) D (4 E

*4:4 A) B (2 C) (2 A) D (4 E

2009-02-12

タイトル変更


考えてみれば、同じタイトルでブログが2あるのも紛らわしいので、こちらの名前は変更することにした。