整数の割り算で小数点を返す

小江戸ラグの活動報告会で、

 p 1 / 3 #=> 0
 p 1.0 / 3 #=> 0.333333333333333

となっていて、0.33333という結果を得たいが、
計算が複雑で長い為、数字を一つ一つ小数点使って書きたくないって話があって
どうすればいいのか?って話がありました。

class Fixnum
  alias old_division :/

  def /(value) 
    old_division value.to_f
  end
end

p 1/2 #=> 0.5

こんなふうだとどうだろうか


ひどい手抜き

Autopagerizeにて、一回次のページ読み込んだら機能しなくなる現象

なんか表題の通り、firefoxで使っているautopagerizeが、
最近、1回目次のページ読み込んだらいつも出てる右上の■がなくなって
2回目以降読み込まなくなってたので、最新のバージョンにしたら直った。
http://github.com/swdyh/autopagerize/tree

なんだったんだろう。

吉野家と松屋の270円や250円のセールの時に行ってみた

この間、吉野家が270円の時に久しぶりに吉野家に行ったんですよ。

こんな広告に対して


出てきたのがこれ

肉少なくない……?


後日、250円セールしてた上の吉野家の駅の反対側の松屋

この広告に対して


こんなの

肉が十分あって味噌汁もついてて20円安い。

twitterの発言をmixiエコーにコピーするrubyスクリプト

自分の発言をコピーするrubyスクリプト作りました。

#!/usr/local/bin/ruby

$KCODE = 'u'
require 'rubygems'
require 'mechanize'
require 'twitter'
require 'kconv'
require 'net/http'
require 'cgi'
require 'yaml'
require 'optparse'

class Twitter2Mixi

  def initialize
    Net::HTTP.version_1_2
    option_parse
    set_options
    twitter_base
    twitter_update
  end

  def option_parse
    @option_parameter = Hash.new
    opt = OptionParser.new
    opt.on("-c", "--configfile=CONFIGFILE") {|v| @configfile = v }
    opt.on("-e", "--email=EMAIL") {|v| @option_parameter[:email] = v }
    opt.on("-p", "--password=PASSWORD") {|v| @option_parameter[:password] = v }
    opt.on("-d", "--debug") {|v| @debug = true}
    opt.parse(ARGV)
  end

  def set_options
    @configfile ||= File.join(File.dirname(__FILE__), "config.yaml")
    yaml = YAML.load(File.read(@configfile))
    account = yaml["account"] || Hash.new
    account.each do | key, value | 
      @option_parameter[key.to_sym] ||= value
    end
  end

  def twitter_base
    httpauth = Twitter::HTTPAuth.new(@option_parameter[:email], @option_parameter[:password])
    @twitter = Twitter::Base.new(httpauth)
  end

  def twitter_update
    timelines = @twitter.user_timeline(:since => CGI.escape("Sat Mar 13 05:29:08 +0000 2010"))
    last_time = get_last_time
    timelines.reverse.each do | s | 
      now_time = Time.parse s.created_at
      unless last_time >= now_time
        last_time = now_time
        unless /(^@)|(RT)|(QT)/ =~  s.text
          sendmixi(s.text)
          puts "send #{ s.text}" 
        end
      end
    end
    @timefile ||= File.join(File.dirname(__FILE__), "timefile")
    file =  File.open(@timefile, "w")
    file.puts last_time
    file.close
  end
 
  def get_last_time 
    @timefile ||= File.join(File.dirname(__FILE__), "timefile")
    time_string =  File.read(@timefile)
    Time.parse(time_string) 
  end

  def sendmixi(text)
    mixi_login unless @mixi_login 
    page = @mixi_login.get("http://mixi.jp/recent_echo.pl")
    form = page.forms[2]
    form['body'] = text.toeuc
    form.submit
  end

  def mixi_login
    @mixi_login = WWW::Mechanize.new()
    page = @mixi_login.get("http://mixi.jp/")
    form = page.forms.first
    form['email'] = @option_parameter[:mixi_email] 
    form['password'] = @option_parameter[:mixi_password]
    form.submit
 end
end
Twitter2Mixi.new

こちらを保存して
プログラムのファイルと同じディレクトリにconfig.yamlという名前で

account: 
  email: twitterのメアド
  password: twitterのパスワード
  mixi_email: mixiのメアド
  mixi_password: mixiのパスワード

と記載して保存してやればOKです
一時ファイルとしてtimefileって名前のファイルが出来ます。
前回実行した時間を記録しておいて、新しい発言だけコピーする様にしてます。


だいぶ前に小江戸らぐの活動報告会中に作ったんだけど今更公開。

上野のさくらみてきた。

ちょっと上野によってきましたが、上野公園は人も多いですがやっぱり桜すごいですね。


平日昼間に、日本酒入れた水筒と、漬物持ってあそこで酒飲みたい。
今週土曜日に花見が予定されてるのですがそれまで持つかなあ。

飯は食えるらしい

ここに課題があったので、試しにといてみた。
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002.html

問題

麻雀の手牌が入力として与えられたとき、「待ち」を出力するプログラムを書いてください。

  1. 字牌なし・萬子のみの想定、つまり、いわゆる「チンイツ」限定で結構です(プログラミングの本質的にはこの限定でまったく問題ないため)
  2. 1〜9の数字13個からなる文字列を受け取り、できている順子・刻子・アタマを()、待ちの部分を[]でくくって出力してください
  3. 面前かつ槓子は存在しない前提でOKです
  4. ()[]の出力順は自由ですが、順序だけが違うものは同一視してください(例:111222を刻子2つで構成するとき、(111)(222)が (222)(111)に入れ替わるだけのものは同一解答とします)
  5. 多面待ちのときも含めすべての待ちを出力してください
  6. 待ちがないときは何も出力しないでください


コメント


無駄な探索をできるだけしないための工夫、デバッグを効率化するための工夫などがあればソースコードにコメントとして記入してください。


出力例


1112224588899 :


単純なケースです。45を軸にする両面の待ちなので、(111)(222)(888)(99)[45]になります。


1122335556799 :
“99”をアタマの両面か“55”“99”のシャボであるので、(123)(123)(555)(99)[67]、(123)(123)(55)(567) [99]、(123)(123)(99)(567)[55]が正解です。


1112223335559 :
待ちは“9”単騎ですが、(123)(123)(123)(555)[9]と(111)(222)(333)(555)[9]の2つあります。


1223344888999 :
1-4の“ノベタン”待ちですが、4をアタマにしての[23]待ちと、1単騎、4単騎で3個の答えになります。


1112345678999 :
九蓮宝燈」という役です。1〜9すべてが待ちになっています。これに正しく答えが出るのであれば、プログラムはほぼ正しいでしょう。


* 麻雀を知らない人は、順子・刻子・アタマ・待ちといった用語の意味だけ調べてから解答に取りかかってください。これを調べる時間は計算外とします。

とりあえずといてみた。
twitterで確認してみたところ8:39に解き始めて10:20で終わってるので、100分で一応解けたみたい。
ただしコードは雑。

# 手牌が空かどうか
def end_check_tehai(tehai)
  tehai.each do | key, value |
    return tehai if value > 0
  end
  return nil
end

def get_juntu(hai, tehai)
  if tehai[hai].to_i > 0 && tehai[hai + 1].to_i > 0 && tehai[hai + 2].to_i > 0
    (0..2).each do | i |
      tehai[hai + i] -= 1
    end
    return [(0..2).map{|i|hai + i},  end_check_tehai( tehai )]
  end
  return false
end

#頭チェックも兼ねる。 
def get_kotu(hai, tehai, idx = 3)
  if tehai[hai].to_i >= idx
    tehai[hai] -= idx
    return [[hai]*idx, end_check_tehai( tehai )]
  end
  return false
end

def check_loop_inner(data, return_array)
  if data[1]
    data_2 = check_loop(data[1])
    if data_2.empty?
      return_array << [data[0]]
    else
      data_2.each do | d |
        return_array << [data[0]] + d
      end
    end
  else
    return_array << [data[0]]
  end
end

#取り敢えず、ジャンツとかコーツとか頭とか、取れるケースを全部あげる。
def check_loop(tehai)
  return_array = Array.new
  (1..9).each do | i |
    if data = get_juntu(i, tehai.dup)
      check_loop_inner(data, return_array)
    end
    if data = get_kotu(i, tehai.dup)
      check_loop_inner(data, return_array)
    end
    if data = get_kotu(i, tehai.dup, 2)
      check_loop_inner(data, return_array)
    end
  end
  return return_array
end

#あげたケースが、ちゃんと成り立つかチェック
def answer_check(answer, tehai)
  atama = Array.new
  nomal = Array.new
  answer.each do | a |
    if a.size == 2
      atama << a
    else
      nomal << a
    end
    a.each do | i |
      tehai[i] = tehai[i] - 1
    end
  end
  amari = []
  tehai.each do | t , v|
    v.times do
      amari << t
    end
  end
  atama_count = atama.size
  tehai_count = amari.size

  if atama_count == 0 && tehai_count == 1
    amari = amari.sort.join
    return nomal.map{|n| "(#{n.to_s})" } << "[#{amari}]"
  elsif atama_count == 1 && tehai_count == 2
    if ( amari[0] - amari [1]).abs < 3
      return answer.map{|n| "(#{n.to_s})" } << "[#{amari}]"
    else
      return nil
    end
  elsif atama_count  == 2 && tehai_count == 0
    return [ (nomal + [atama[0]]).map{|n| "(#{n.to_s})" } << "[#{atama[1].to_s}]" ,
             (nomal + [atama[1]]).map{|n| "(#{n.to_s})" } << "[#{atama[0].to_s}]" ]
  elsif atama_count  == 6 && tehai_count == 1
      return answer.map{|n| "(#{n.to_s})" } << "[#{amari}]"
  end
  return nil
end

def get_machi(tehai_string)
  tehai = Hash.new
  input_strings = tehai_string.split(//).delete_if{|c| !( c =~ /^\d$/) }

  input_strings.each do|c|
    tehai[c.to_i] = (tehai[c.to_i] || 0) + 1
  end

  answers = []
  nocheck_answers =  check_loop(tehai.dup)
  nocheck_answers.each do | answer |
    answer_check_return = answer_check(answer, tehai.dup)
   if answer_check_return.class == Array && answer_check_return.size == 2
     answer_check_return.each do | a |
       answers << a.sort
     end
   elsif answer_check_return
     answers << answer_check_return.sort
   end
  end
  puts "check #{tehai_string}"
  puts answers.uniq.map{|a| a.to_s}.join("\n")
end

get_machi("1112224588899")
get_machi("1122335556799")
get_machi("1112223335559")
get_machi("1223344888999")
get_machi("1112345678999")
get_machi("1444477888999")  # => 待ち無しのテスト

出力結果は

ruby majan.rb
check 1112224588899
(111)(222)(888)(99)[54]
check 1122335556799
(123)(123)(55)(567)[99]
(123)(123)(567)(99)[55]
(123)(123)(555)(99)[67]
check 1112223335559
(123)(123)(123)(555)[9]
(111)(222)(333)(555)[9]
check 1223344888999
(123)(234)(888)(999)[4]
(123)(44)(888)(999)[23]
(234)(234)(888)(999)[1]
check 1112345678999
(11)(123)(456)(789)[99]
(123)(456)(789)(99)[11]
(11)(123)(456)(999)[78]
(11)(123)(678)(999)[54]
(111)(234)(567)(999)[8]
(111)(234)(567)(99)[89]
(111)(234)(678)(999)[5]
(111)(234)(789)(99)[56]
(111)(345)(678)(999)[2]
(111)(456)(789)(99)[23]
(11)(345)(678)(999)[12]
check 1444477888999

こんな感じ
全然アルゴリズム考えた事がなかったので、ちょっと楽しかった。


10:53 チートイツにも対応した。

  elsif atama_count  == 6 && tehai_count == 1
      return answer.map{|n| "(#{n.to_s})" } << "[#{amari}]"

だけ追加。