fork download
  1. #coding: utf-8
  2.  
  3. # 単位付1元1次方程式を解く。
  4. # CodeIQ q1058 「中学入試から:単位のある計算」
  5.  
  6. class UnitsEquation
  7. class Formula
  8. def initialize(formula, unknown='')
  9. @formula = formula
  10. @unknown = unknown
  11. end
  12.  
  13. def parse
  14. sign_before = '+'
  15. @formula.scan(/([-+]?)(\d+|#{@unknown})([^-+\d#{@unknown}]+)/).map do |sign, num_str, unit|
  16. sign = sign_before if sign.empty?
  17. sign_before = sign
  18. {sign: sign, num_str: num_str, unit: unit}
  19. end
  20. end
  21. end
  22.  
  23. attr_reader :equation, :answer
  24.  
  25. def initialize(equation, unknown)
  26. @equation = equation
  27. @unknown = unknown
  28. end
  29.  
  30. def solve
  31. left_formula, right_formula = @equation.split('=').map{|formula| Formula.new(formula, @unknown).parse}
  32. unit_nums = left_formula + right_formula.map{|r| r[:sign] = (r[:sign] == '-' ? '+' : '-'); r}
  33.  
  34. # 方程式の中で単位が換算出来ない場合の処理
  35. # return unless unit_nums.uniq{|un| @@unit_conversion_table[un[:unit]][:base_unit]}.size == 1
  36.  
  37. unknown = unit_nums.find{|un| un[:num_str] == @unknown}
  38. unit_nums.delete(unknown)
  39.  
  40. minimum_unit_nums = unit_nums.map do |unit_num|
  41. num = unit_num[:num_str].to_i
  42. num = -num if unit_num[:sign] == unknown[:sign]
  43. num * @@unit_conversion_table[unit_num[:unit]][:scale]
  44. end
  45.  
  46. @answer = minimum_unit_nums.inject(&:+) / @@unit_conversion_table[unknown[:unit]][:scale]
  47. end
  48.  
  49. @@unit_conversion_table =
  50. DATA.map(&:chomp).each_with_object({}) do |equation, memo|
  51. unit_nums = equation.split('=').each_with_object({}) do |formula, mm|
  52. Formula.new(formula).parse.each{|f| mm[f[:unit]] = f[:num_str].to_i}
  53. end
  54. base_unit, base_unit_scale = unit_nums.max_by{|unit, scale| scale}
  55. unit_nums.each{|unit, scale| memo[unit] = {scale: base_unit_scale / scale, base_unit: base_unit}}
  56. end
  57. @@unit_conversion_table.default = {base_unit: :base_unit}
  58.  
  59. end
  60.  
  61.  
  62.  
  63. if $0 == __FILE__
  64. ARGF.each do |line|
  65. no, *equ = line.chomp.split("\t")
  66. equation = equ.map{|e| UnitsEquation.new(e, '□')}
  67. equation.each{|e| e.solve}
  68. if equation.uniq(&:answer).size == 1
  69. puts "#{no}: Correct."
  70. else
  71. puts "#{no}: Wrong."
  72. puts equation.map{|e| " equation: #{e.equation}, answer: #{e.answer}"}
  73. end
  74. end
  75. end
  76.  
  77. __END__
  78. 1km=1000m=100000cm=1000000mm
  79. 1kg=1000g=1000000mg
  80. 1日=24時間=1440分=86400
  81.  
Success #stdin #stdout 0.02s 7604KB
stdin
T01	3m20cm-3m10cm-□mm=5mm	□kg=95000g
T02	2kg+500g+□g=3kg200g	□m=700000mm
T03	12kg+1kg500g+□g=13kg700g	720000秒=□時間
T04	2時間30分-□時間=90分	□km=1000m
T05	1日-□分=23時間20分	40000mm=□m
T06	3日-□秒-71時間59分30秒=7秒	23000g=□kg
T07	23時間30分+29分+60秒=□日	□km=1000m
T08	1日+23時間15分+□分+120秒=2日	43000m=□km
T09	1km-1m-1cm-1mm=□mm	□kg=998989000g
T10	3m20cm-5cm2mm-20cm8mm+□cm=312cm	□km=18000m
T11	1日-1時間-1分-1秒=□秒	297860400秒=□時間
T12	1kg-1g=□g	□日=23976時間
T13	□日-1時間-1分-1秒=82739秒	1000g=□kg
T14	4km-3995m-480cm-□mm=20cm	□km=0m
T15	12m30cm-7m43cm-45cm2mm-□mm=3m80cm	14832時間=□日
T16	0m+□km=0mm	0g=□kg
T17	24時間+□分=1日	□日=0時間
T18	4cm3mm+□km+5mm=48mm	0分=□時間
T19	□分+24時間+7日+14分34秒=777634秒	□日=2053440分
T20	122日+20時間35分24秒=□秒	10614924000g=□kg
T21	240km-218987m-8780cm-77648mm=□mm	□日=500341248時間
T22	120分+46分-□分=1時間19分	720分+9300分-4800分=□時間
T23	100kg+32kg-36kg=□kg	296mg-100mg-□mg=100mg
T24	533448650mm-□km-52122650mm=203326000mm	270840秒+□時間+683832秒=22日15時間11分12秒
T25	83m+□m+130m=626m	137km260m55cm2mm+377910000mm-□km=102km170m55cm2mm
T26	1000kg+1000kg-1609kg=□kg	4時間+3時間14分-43分=□分
T27	704kg720g-235kg-4kg720g=□kg	1425日-480日-480日=□日
T28	24629793500mg+4359473400mg-12783kg266g900mg=□kg	□kg=16206000000mg
T29	789m-250m-244m=□m	275210g+□kg+126380g=696590g
T30	625cm-□cm-300cm=1m	219km100m+□km+153km=597100m
T31	1564200g-498kg-404200g=□kg	331日3時間34分+658日20時間58分-□日=328日32分
T32	219kg645g600mg-□kg=66kg645g600mg	148387424mm+□km=301387424mm
T33	57m+10460cm+□m=32360cm	10cm+□mm=26cm2mm
T34	1437日3時間9分-□日-31733100秒=7071840秒	1157700分+748680分-□日=483660分
T35	4608816秒+□日=67940016秒	50cm+1000mm-□mm=76cm7mm
T36	220kg300g+60kg355g-□kg=50655g	□km+127km501m10cm=357501100mm
T37	5088分+4日3時間-5508分=□時間	137651880mg-28kg300g290mg-□kg=17kg351g590mg
T38	72460m-□km=4km460m	18時間14分+2日3時間40分+□時間=496440秒
T39	12000mg+28g-□g=0mg	98km125m71cm-3831300cm-1981271cm=□km
T40	55220mm+389910mm+□m=1km25m13cm	1604904秒+1957249秒-□時間=17日1時間29分13秒
stdout
Standard output is empty