○P 10分間コーディング2009/05/18

10分でコーディング(プログラミングに自信があるやつこい!!) viaときどきの雑記帖 i戦士篇

を見付けたので、特にこだわりなくrubyでコーディング

def deal(num_of_player, deck)
  cards = Array.new(num_of_player){""}
  deck.scan(/./).each_slice(num_of_player) do |slice|
    next if slice.size < num_of_player
    slice.each_with_index do |card, index|
      cards[index] << card
    end
  end
  cards
end

p deal(3, "123123123")
#=> ["111", "222", "333"]
p deal(4, "123123123")
#=> ["12", "23", "31", "12"]
p deal(6, "012345012345012345")
#=> ["000", "111", "222", "333", "444", "555"]
p deal(4, "111122223333")
#=> ["123", "123", "123", "123"]
p deal(1, "012345012345012345")
#=> ["012345012345012345"]
p deal(6, "01234")
#=> ["", "", "", "", "", ""]
p deal(2, "")
#=> ["", ""]

配列の転置の問題ですな。

末尾を捨てるのを忘れていたので5分ぐらいかかった。 精進が足りない。

あと、末尾を捨てるのは、breakする方が正しいね。

で、コード・カタ的に、他の実装にも思いを馳せてみることにする。

とは言え、あまり考える余地は無いような気もする。

  • 入力のdeckからArrayを得る方法
    • scan(/./) (↑で使った)
    • split(//) (これを別実装と呼ぶか?)
    • each_byte (普通に使うならblockの中に後の処理を入れる必要がある。each にaliasするか、1.9を使う)
    • unpack("C*") (Arrayの中身はInteger)
  • Arrayの転置
    • sliceを作ってそこでindexを取って配る (↑)
    • 全体で回して随時modを取って配る
  • 末尾の処理
    • 事前に数を揃えておく
    • 残数が足りなくなったら終わる (↑)

の組み合わせぐらいだろうか?

で色々考えてみたけど、

上記のバリエーション

def deal(num_of_player, deck)
  class << deck
    alias each each_byte
  end
  cards = Array.new(num_of_player){""}
  deck.each_slice(num_of_player) do |slice|
    break if slice.size < num_of_player
    slice.each_with_index do |card, index|
      cards[index] << card
    end
  end
  cards
end
def deal(num_of_player, deck)
  cards = Array.new(num_of_player){""}
  deck.unpack("C*").each_slice(num_of_player) do |slice|
    break if slice.size < num_of_player
    slice.each_with_index do |card, index|
      cards[index] << card.chr
    end
  end
  cards
end
def deal(num_of_player, deck)
  cards = Array.new(num_of_player){[]}
  deck.unpack("C*").each_slice(num_of_player) do |slice|
    break if slice.size < num_of_player
    slice.each_with_index do |card, index|
      cards[index] << card
    end
  end
  cards.map{|card| card.pack("C*")}
end

引数Deckに対するindexを取り回す

def deal(num_of_player, deck)
  num_of_card = deck.size / num_of_player
  deck = deck[0, num_of_card * num_of_player]
  cards = Array.new(num_of_player){""}
  class << deck
    alias each each_byte
  end
  deck.each_with_index do |card, index|
    cards[index % num_of_player] << card
  end
  cards
end

出力用のArrayを仮り組みしてそこでindexを回す

def deal(num_of_player, deck)
  num_of_card = deck.size / num_of_player
  Array.new(num_of_player) do |i|
    (0...num_of_card).map{|j| deck[i + j * num_of_player, 1]}.join
  end
end
def deal(num_of_player, deck)
  num_of_card = deck.size / num_of_player
  Array.new(num_of_player){" " * num_of_card}.each_with_index do |cards, i|
    cards.gsub!(/./){deck[i + $`.size * num_of_player, 1]}
  end
end
def deal(num_of_player, deck)
  num_of_card = deck.size / num_of_player
  Array.new(num_of_player){[*(0...num_of_card)] * ""}.each_with_index do |cards, i|
    cards.gsub!(/./){|j| deck[i + j.to_i * num_of_player, 1]}
  end
end

ぐらいしか思いつかなかった。

Golf

def deal(num_of_player, deck)
  num_of_card = deck.size / num_of_player
  Array.new(num_of_player) do |i|
    (0...num_of_card).map{|j| deck[i + j * num_of_player, 1]}.join
  end
end

これを

def deal(n,d)(0...n).map{|i|(0...d.size/n).map{|j|d[i+j*n,1]}*""};end

ぐらいにして、このお題は終了。

Excel と Tab区切りテキスト と .xls2009/04/30

あ…ありのまま 今 起こった事を話すぜ!

『おれはxlsファイルの解析をしいていたと 思ったらいつのまにかテキストファイルだった』

な… 何を言ってるのか わからねーと思うが おれも何をされたのかわからなかった…

頭がどうにかなりそうだった…

催眠術だとか超スピードだとか そんなチャチなもんじゃあ 断じてねえ

もっと恐ろしいものの片鱗を味わったぜ…

解説

いやまあ、拡張子なんて何をつけようが勝手だけどさ、Tab区切りテキストの拡張子に'.xls'は無いんじゃないかな。

拡張子だけ見て spreadsheet に食わせていたら、

Ole::Storage::FormatError: OLE2 signature is invalid

と謎のエラー。

エクスプローラーからは、何事も無くExcelが立ち上がるので油断していたら、 実は中身は Tab区切りテキストファイルでした。

という話。

CouchDB とか MapReduce on TT とか2009/04/23

ドキュメント指向のDB(というかシリアライズされたオブジェクトの入ったDBM?)を MapReduce モデルでいじれるらしい。

後で試す。

http://wota.jp/ac/?date=20090415#p01
http://alpha.mixi.co.jp/blog/?p=566