トップ «前の日記(2005-04-28) 最新 次の日記(2005-04-30)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2005-04-29

_ 今日のバグ

えらく梃子摺った。

public class FooSet {
    List<Param> params = new ArrayList<Param>();
    public Param add(Foo f) {
        Param p = new Param(f);
        params.add(p);
        return p;
    }
    public Param add(Param p) {
        Param op = (Param)p.clone();
        params.add(op);
        return op;
    }
    public Param findByName(String s) {
        for (Param p : params) {
            if (s.equals(p.getFoo().getName())) {
                return p;
            }
        }
        return null;
    }
    public class Param implements Cloneable {
        Foo foo; // Fooはイミュータブル。
        Param(Foo f) {
            foo = f;
        }
        public Object clone() {
            return super.clone();
        }
        public String bar() {
            return foo.bar(this);
        }
        public Foo getFoo() {
            return foo;
        }
        ...
    }
}
 
public class Foo {
    String name;
    public Foo(String initName) {
        name = initName;
    }
    public String getName() {
        return name;
    }
    public String bar(FooSet.Param p) {
       ....
       return barResult;
    }
} 
というような感じ。FooSet.ParamはFooの入れ物兼Foo用のデータの提供/保持者、Fooはストラテジ。で、たまたま特殊なFooが必要となった。
public FooSet {
    public Param {
        ...
        public Param find(String key) {  // 追加
            return findByName(key);
        }
    }
}
public class SpecialFoo extends Foo {
    public SpecialFoo(String name) {
        super(name);
    }    
    public String getData(FooSet.Param p) {
        StringBuilder sb = new StringBuilder();
        FooSet.Param o = p.find("BAR");
        if (o != null) {
            sb.append(o.bar(p));
        }
        sb.append(super.bar(p));
        return new String(sb);
    }
}
こんなのも作る。
public class FooSetTest extends TestCase {
    // 追加
    public void specialFooTest() throws Exception {
        FooSet f = new FooSet();
        f.add(new Foo("BAR"));
        f.add(new SpecialFoo("BAZ"));
        FooSet.Param p = f.findBy("BAZ");
        assertEqulas("BARRRRBAZZZZ", p.getData());
    }
}

すべてはうまく行くかのように見える。でも、うまく行かない。
次のように修正。

public class FooSet {
...
    public Param add(Param p) {
        Param np = new Param(p);
        params.add(np);
        return np;
    }
    ...
    public class Param {
        ...
        Param(Param p) { // 追加
            foo = p.foo;
        }
        // clone()は削除だ。
    }
}

_ モンティホール問題

matobaaさんのとこ経由

数の悪戯だろうと思ったが、試してみた。

if ARGV.length != 1
  puts 'usage: ruby montyhall.rb count'
  exit(1)
end
 
class Gamer
  def initialize()
    @win = 0
    @door = [false, false, false]
    @door[rand(3)] = true
  end
  attr_reader :win
end
 
class NoMover < Gamer
  def play()
    @select = rand(3)
    @win += 1 if @door[@select]
  end
end
 
class Mover < Gamer
  def play()
    @selection = rand(3)
    open = next_number(@selection)
    if !@door[@selection]
      if @door[open]
        open = next_number(open)
      end
    end
    new_selection = next_number(@selection)
    if new_selection == open
      new_selection = next_number(new_selection)
    end
    @win += 1 if @door[new_selection]
  end
  private
  def next_number(n)
    (n + 1) % 3
  end
end
 
def show(title, player)
  (1...ARGV[0].to_i).each do |x|
    player.play()
  end
  puts "#{title} won #{player.win} times."
end
 
show("no-mover", NoMover.new())
show("mover", Mover.new())

とりあえず100000回やりゃいいだろう。

c:\home\arton\test>ruby montyhall.rb 100000
no-mover won 33554 times.
mover won 66698 times.

まじですか!

と、落ち着いて考えればMover#playにプログラムしてる通りじゃん。なんかごちゃごちゃ書いているが結局これってこういうことだな。

  def play()
    @select = rand(3)
    @win += 1 if !@door[@select]
  end

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|

ジェズイットを見習え