問題:http://nabetani.sakura.ne.jp/hena/ordf07chairs/
実装リンク集:https://qiita.com/Nabetani/items/de5b9d3230603033ed74
で。
最初に書いたのは ruby。
ORDER=[1,3,5,7,9,8,6,4,2]
def index( chairs, order )
(0...9).select{ |x|
chairs[x]=="-"
}.min_by{ |x|
s0 = chairs[(x+1)%9]=="-" ? -100 : 0
s1 = chairs[(x-1)%9]=="-" ? -100 : 0
[s0+s1+order[x]]
}
end
def process( chairs, ch )
case ch
when /[a-z]/
raise "hoge" unless chairs.count(ch.upcase)==1
chairs.gsub( ch.upcase, "-" )
when /[A-Z]/
ix = index( chairs, ch<"N" ? ORDER : ORDER.map{ |x| -x } )
raise "fuga" unless chairs[ix]=="-"
chairs[0,ix]+ch+chairs[ix+1,9]
end
end
def solve( src )
chairs="-"*9
src.chars.each do |ch|
chairs = process( chairs, ch )
end
chairs
end
DATA.map{ |line|
num, src, expected = line.split(/\s+/ )
actual = solve( src )
okay = actual == expected
p [ ( okay ? "ok" : "**NG**" ), num, src, actual, expected ]
okay
}.all?.tap{ |x| puts( x ? "ok" : "something wrong" ) }
__END__
0 NABETanI I-E--T-B-
1 A A--------
2 Aa ---------
48 WFNwBfbSAXCZzMDJUcKx AM-JSUNDK
いつも通りテストケースの大半は省略。
どの椅子に座りたいのかを得点にして表現した。点が小さい椅子に座りたい。
空席かどうかも得点に入れても良かったんだけど、そこは select にした。
得点にして表現すること(評価関数を用意すること)も大事なんだけど、それ以上に大事なのは、剰余。剰余で表現すると条件分岐がなくなって楽になる。
で。
これを python に移植したらこうなった:
python3
ORDER0 = [1,3,5,7,9,8,6,4,2]
ORDER1 = [ -x for x in ORDER0 ]
def score( chairs, order, r ):
s0 = ( -100 if chairs[(r+1)%9]=="-" else 0 )
s1 = ( -100 if chairs[(r-1)%9]=="-" else 0 )
return s0 + s1 + order[r]
def index(chairs, order):
indices = [ r for r in range(9) if chairs[r]=="-" ]
scores = [ score(chairs, order, r ) for r in indices ]
return min(zip(scores,indices))[1]
def process( chairs, cmd ):
if "a"<=cmd<="z":
return chairs.replace( cmd.upper(), "-" )
ix = index( chairs, ORDER0 if cmd<="M" else ORDER1 )
return chairs[0:ix]+cmd+chairs[(ix+1):9]
def solve( src ):
chairs = "-"*9
for i in range(len(src)):
chairs = process( chairs, src[i] )
return chairs
def test( src, expected ):
actual = solve(src)
okay = actual==expected
print( ", ".join( [("ok" if okay else "**NG**"), src, actual, expected ] ) )
test( "NABETanI", "I-E--T-B-" );
test( "A", "A--------" );
test( "Aa", "---------" );
test( "WFNwBfbSAXCZzMDJUcKx", "AM-JSUNDK" );
min_by
がわからなかったので zip
して min
した。
lambda
で長い処理を書くのはつらいので score を外に出した。
それぐらいかな。