LoginSignup
1
1

More than 5 years have passed since last update.

第四回オフラインリアルタイムどう書くの解答例(Rubyで3つ)

Posted at

第四回オフラインリアルタイムどう書くの解答例。
問題は
http://nabetani.sakura.ne.jp/hena/ord4tetroid/
当日より前に事前に書いておいた実装3つ。


まずは、最初に書いたもの

#!ruby
def rot(d)
    [d[1], -d[0]]
end

def count( axs, c, d )
    ( 4.times.inject([d]){ |a,b| 
        a+[rot(a.last)]
    }.map{ |i|
        c.zip(i).map{ |x| x.inject( &:+) }
    } & axs ).count
end

def key( input )
    axs=input.split(",").map{|xy| xy.to_i.divmod(10) }.uniq
    axs.map{ |i|
        count( axs, i, [1,0] )*10+count( axs, i, [1,1] )
    }.sort.join("-")
end

def solve( input )
    case key(input)
    when "10-11-20-21" then "L"
    when "10-10-20-20" then "I"
    when "11-11-12-30" then "T"
    when "21-21-21-21" then "O"
    when "11-11-21-21" then "S"
    else "-"
    end
end

DATA.each{ |line|
    /(?<num>\#\d+)\s+(?<input>[\d,]+)\s+(?<expected>\S)/=~line
    actual=solve(input)
    print "%s %s -> %s"%[num,input,actual]
    print "**EXPECTED** : "+expected unless actual==expected
    puts
}

__END__
#1  55,55,55,55 -
#2  07,17,06,05 L

例によって、テストデータは本当は 50件あるけど、ここでは省略。

注目点の8近傍を調べたらわかるよね、というアイディア。
ペントミノだとうまくいかない。


#!ruby
def dist( a, b )
    a.zip(b).map{ |i,j| (i-j)**2 }.inject( &:+ )
end

def solve( input )
    a=input.split( ',' ).map{ |i| i.to_i.divmod(10) }.sort.uniq
    return '-' unless a.size==4
    d=a.size.times.map{ |fst|
        fst.times.map{ |snd|
            dist( a[fst], a[snd] )
        }
    }.flatten.sort.join
    case d
    when '111245' then 'L'
    when '111449' then 'I'
    when '111224' then 'T'
    when '111122' then 'O'
    when '111225' then 'S'
    else
        '-'
    end
end

DATA.each 以降は最初のと同じなので省略。
与えられた点の間の距離(平方根を省略して、距離の自乗)をまとめると判別できるよね、というアイディア。
これでうまくいくのはなぜかと問われるとちょっと窮する。


#!ruby

def s(a)
    mins = [0,1].map{ |xy| a.map{ |i| i[xy] }.min }
    pat = a.map{ |i| [ i[0]-mins[0], i[1]-mins[1] ].join }.sort.flatten.join(",")
    case pat
    when '00,01,02,12' then 'L'
    when '00,10,20,30' then 'I'
    when "01,10,11,21" then 'T'
    when "00,01,10,11" then "O"
    when "01,10,11,20" then "S"
    else
        nil
    end
end

def sy(a)
    s(a) || s( a.map{ |i| [i[0], -i[1]] } )
end

def sxy(a)
    sy(a) || sy( a.map{ |i| [-i[0], i[1]] } )
end

def solve( input )
    a = input.split(',').map{ |i| i.to_i.divmod(10)}.sort.uniq
    return '-' unless a.size==4
    sxy(a) || sxy(a.map( &:reverse )) || '-'
end

回転したり鏡像反転したりするのも書いておこうということで書いたもの。
当日頂いた回答はパターンの方を回しておくものが多かったけど、これは入力の方を回している。
まあ、回しているんじゃなくて x軸反転・y軸反転・xy入れ替え の三つを組み合わせて実現してる。
メソッド名がグダグダですいません。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1