CodeIQ「中学入試から:正三角形?二等辺?」
CodeIQ の鍋谷武典さん出題の問題を解いてみた。
問題と解説はこちら。
「中学入試から:正三角形?二等辺?」の、解説・解題
解説を読んでから気づいたんだけど、ちょっと今回は力尽くなコードを書いてしまった。
言語は Ruby。
v.values - [nil] のところは v.values.compact のほうが良いというアドバイスを頂いた。
すぐに実行できるものを http://ideone.com/VJUSuo に置いておいた。
#! ruby -Ku # データは 'data.utf8.txt' から読み込む require 'mathn' # v[0], v[1], v[2] の間で成立している独立な等式の数 # 例えば v[0]=v[1]=v[2] のとき 2 を返し、v[0]=v[1]≠v[2] のとき 1 を返す def n_equalities(v) a = v.values - [nil] a.size - a.uniq.size end # 問題を解き、あ,い,う のいずれかを返す def solve(angle, edge) # このメソッドの戻り値は下の permutation が生成する順列の順序に依らない %w(A B C).permutation do |i, j, k| angle[i] = angle[j] if edge[i] && edge[i] == edge[j] && angle[j] angle[i] = 90 - angle[k] / 2 if edge[i] && edge[i] == edge[j] && angle[k] angle[k] = 180 - angle[i] - angle[j] if angle[i] && angle[j] end return %w(う い あ)[[n_equalities(angle), n_equalities(edge)].max] end def extract_values(data) # 例えば "角A=60度" のとき angle['A'] = 60 # "AB=10cm" のとき edge['C'] = 10 (辺には向かい合う角と同じ記号をあてる) angle, edge = {}, {} data.split(',').each do |d| if d =~ /^角([ABC])=(\d+)度$/ then angle[$1] = $2.to_i elsif d =~ /^([ABC])([ABC])=(\d+)cm$/ then edge[(%w(A B C) - [$1, $2])[0]] = $3.to_i else fail 'illegal data' end end [angle, edge] end open('data.utf8.txt') do |file| file.each do |line| id, data, expected = line.chomp.split("\t") angle, edge = extract_values(data) answer = solve(angle, edge) # 求めた答が用意されたものと合わないとき、 # id, 用意された答, 求めた答, 問題 を出力 puts "#{id} #{expected} #{answer} '#{data}'" unless expected == answer end end