OSDN Git Service

d6162f163ce482e2730669cd904e5b3fe5576443
[mint/mint-lib.git] / lib / mint / generator / arithmetic_base.rb
1 # -*- coding: nil -*-
2
3 module Mint::Generator
4
5   #
6   # 四則演算を行う式のジェネレータの基底クラス
7   #
8   class Arithmetic < Base
9
10     # 使用する演算子
11     DEFAULT_OPERATORS = %w[+ - * div]
12
13     private
14
15     include Utilities
16
17     option :term_number, 2
18     option :operators, DEFAULT_OPERATORS
19
20     def generate_problem
21       expression
22     end
23
24     #
25     # 後処理 (継承した時は super を呼ぶこと)
26     #
27     def teardown(problem)
28       String(problem).gsub(%r! (-[0-9./]+)!, ' (\\1)')
29     end
30
31     #
32     # 1つの項を返すメソッド
33     # 各ジェネレータでオーバライドする必要あり
34     #
35     def operand
36       raise 'need to overwrite'
37     end
38
39     #
40     # 最後に生成したオペランドを返す。
41     #
42     def last_operand(operand = nil)
43       @last_operand = operand if operand
44       @last_operand
45     end
46
47     #
48     # 最後に生成したオペレータを返す
49     #
50     def last_operator(operator = nil)
51       @last_operator = operator if operator
52       @last_operator
53     end
54
55     #
56     # 式を生成するメソッド
57     #
58     def expression
59       result = []
60       options[:term_number].times do
61         result << last_operand(operand)
62         result << last_operator(options[:operators].sample)
63       end
64       # except last operator
65       result[0..-2].join(" ")
66     end
67
68     #
69     # 整数を返すメソッド
70     #
71     def integer
72       create_integer(options[:min], options[:max], options[:minus]).to_s
73     end
74
75     #
76     # 小数を返すメソッド
77     #
78     def decimal
79       use_integer = rand(3) == 0
80       integer_part = 0
81       unless use_integer
82         integer_part = create_integer(options[:min].to_i, options[:max].to_i, false)
83       end
84       decimal_part = rand(10**options[:digits])
85       ("#{integer_part}.#{decimal_part}".to_f * sign(options[:minus])).to_s
86     end
87
88     #
89     # 分数を返すメソッド
90     #
91     def fraction
92       begin
93         numerator   = numerator_part
94         denominator = denominator_part
95       end while numerator == denominator
96       "#{numerator}/#{denominator}"
97     end
98
99     def numerator_part
100       create_integer(options[:numerator_min], options[:numerator_max], options[:minus])
101     end
102
103     def denominator_part
104       create_integer(options[:denominator_min], options[:denominator_max], false)
105     end
106
107     #
108     # 最大値、最小値から項数をランダムに生成するメソッド
109     #
110     def term_number(position)
111       min, max = options.values_at(:"#{position}_term_min", :"#{position}_term_max")
112       create_integer(min, max, false)
113     end
114   end
115 end
116