1 # -*- coding: utf-8 -*-
3 $:.unshift File.dirname(__FILE__) + '/../lib'
6 Spec::Matchers.define :have_certain_param do |name, value|
8 object.instance_variable_get(name) == value
12 shared_examples_for 'generator' do
14 subject.should_receive(:setup).
15 exactly(1).times.with(no_args)
16 subject.should_receive(:generate_problem).
17 exactly(1).times.and_return('problem')
18 subject.should_receive(:teardown).
19 exactly(1).times.with('problem')
20 subject.stub(:validation_loop) {|r| r }
21 subject.generate.should have(1).problems
27 @options = { :range => (5..10) }
35 klass.__send__(:option, *@defaults[0])
36 klass.__send__(:option, *@defaults[1])
37 klass.__send__(:option, *@defaults[2])
39 subject.__send__(:options=, @options)
42 context 'set defaults' do
43 before { @default_options = subject.class.__send__(:class_variable_get, :@@default_options) }
44 it { @default_options.should include(*@defaults.map(&:first)) }
48 before { @opts = subject.__send__(:options) }
49 it { @opts.should include(:range) }
50 it { @opts.should include(:test1) }
51 it { @opts.should include(:test2) }
52 it { @opts.should include(:test3) }
53 it { @opts[:range].should == @options[:range] }
54 it { @opts[:test1].should == @defaults.assoc(:test1)[1] }
55 it { @opts[:test2].should == @defaults.assoc(:test2)[1] }
56 it { @opts[:test3].should == @defaults.assoc(:test3)[1] }
61 shared_examples_for 'Arithmetic' do
63 def set_options(options = {})
64 defaults = {:term_number => 1, :operators => ['@']}
65 subject.__send__(:options=, defaults.merge(options))
68 before { set_options }
70 it_should_behave_like 'generator'
80 subject.__send__(:teardown, from).should == to
90 ].each do |position, term_number|
94 :"#{position}_term_min" => term_number,
95 :"#{position}_term_max" => term_number,
97 subject.stub(:options => options)
99 it { subject.__send__(:term_number, position).should == term_number }
106 @msg ='This operand need these options:'
108 subject.stub(:create_integer => 1)
112 before { set_options(:min => nil, :max => nil, :minus => nil) }
113 it { subject.__send__(:integer).should == @int }
125 it { subject.__send__(:decimal).should match(/(?:#{@int}|0)\.\d\d?/) }
128 context 'fraction' do
131 :numerator_min => nil,
132 :numerator_max => nil,
133 :denominator_min => nil,
134 :denominator_max => nil,
137 subject.should_receive(:numerator_part).and_return('a')
138 subject.should_receive(:denominator_part).and_return('b')
140 it { subject.__send__(:fraction).should == "a/b" }
145 module ProblemExamples
148 types.inject([]) {|memo, type|
149 memo += __send__(type) }
155 ['7 / 12 + 17 / 12', '7 / 12 + 17 / 12'],
156 ['3 / 4 + 1 / 7', '3 / 4 + 1 / 7'],
157 ['2 / 9 - 3 / 5', '2 / 9 - 3 / 5'],
160 ['25/28', '25 / 28'],
161 ['-7/12', '-7 / 12'],
162 ['-17/45','-17 / 45' ],
163 ['(2a + 1)(3a - 2)', '(2 * a + 1) * (3 * a - 2)'],
164 ['(x + 2)^2', '(x + 2)^2'],
165 ['(3P - 2Q)^3', '(3 * P - 2 * Q)^3'],
166 ['1 / (x + 1)(x + 2)', '1 / ((x + 1) * (x + 2))'],
167 ['2x^3 + x - 1', '2 * x^3 + x - 1'],
168 ['(X^2 - Y^2)', '(X^2 - Y^2)'],
169 ['root(2)root(8)', 'sqrt(2) * sqrt(8)'],
170 ['sqrt(2)sqrt(8)', 'sqrt(2) * sqrt(8)'],
171 ['(1 + root(3))(2 - root(3))', '(1 + sqrt(3)) * (2 - sqrt(3))'],
172 ['(1 + sqrt(3))(2 - sqrt(3))', '(1 + sqrt(3)) * (2 - sqrt(3))'],
173 ['1 / root(2)', '1 / sqrt(2)'],
174 ['1 / sqrt(2)', '1 / sqrt(2)'],
175 ['2 / (root(3) - 1)', '2 / (sqrt(3) - 1)'],
176 ['2 / (sqrt(3) - 1)', '2 / (sqrt(3) - 1)'],
186 ['5 div 5', '5 div 5'],
187 ['-233/23', '-233 / 23'],
188 ['(x^2 + 4)(y^3 - 2)', '(x^2 + 4) * (y^3 - 2)'],
189 ['(x^3 + 2)(x^2- 3)', '(x^3 + 2) * (x^2 - 3)'],
190 ['2(x^2 + xy + y^2)', '2 * (x^2 + x * y + y^2)'],
191 ['sqrt(2(x^(2 + 3) + xyz^5 + y^2))', 'sqrt(2 * (x^(2 + 3) + x * y * z^5 + y^2))'],
192 ['sqrt(2(x^(2 + 3) + root(xyz^5) + y^2))', 'sqrt(2 * (x^(2 + 3) + sqrt(x * y * z^5) + y^2))'],
193 ['5xc*1div5 + 1 (34 - 1 /8 + 1)', '5 * x * c * 1 div 5 + 1 * (34 - 1 / 8 + 1)'],
195 ['5.8*5.8*PI', '5.8 * 5.8 * %pi'],
196 ['3e * 5x^2', '3 * %e * 5 * x^2'],
197 ['3E * 5x^2', '3 * %e * 5 * x^2'],
198 ['3 + 2i', '3 + 2 * %i'],
199 ['(-24x + 37)(71x - 33)', '(-24 * x + 37) * (71 * x - 33)'],
200 ['x^((3y^2+5y)(y^2+2-x))', 'x^((3 * y^2 + 5 * y) * (y^2 + 2 - x))'],
201 ['-x^(-(-3y^2+-5y)(y^-2+2-x))', '-x^(-(-3 * y^2 + -5 * y) * (y^-2 + 2 - x))'],
202 ['(x^3 + 1)(x^2 + 2)(x + 1)', '(x^3 + 1) * (x^2 + 2) * (x + 1)'],
203 ['(x^3 + 1)(x^2 + 2)(x + 1)(y^2 - 11)', '(x^3 + 1) * (x^2 + 2) * (x + 1) * (y^2 - 11)'],
204 ['(x^3 + 1)(x^2 + 2)(x + 1)(y^2 - 11)(y^3 - 4)', '(x^3 + 1) * (x^2 + 2) * (x + 1) * (y^2 - 11) * (y^3 - 4)'],
206 ['6a^2 - a - 1', '6 * a^2 - a - 1'],
207 ['5 div 4', '5 div 4'],
208 ['5.0 div 4', '5.0 div 4'],
210 ['5.0/4', '5.0 / 4'],
211 ['.04324134213', '0.043'],
212 ['- .04324134213', '-0.043'],
213 ['-50/12 div 12*32', '-50 / 12 div (12 * 32)'],
214 ['-sqrt(2)', '-sqrt(2)'],
215 ['-(5 - 2x)', '(2x - 5)'],
216 # TODO: need more pattern
220 def self.bad_patterns
222 '1 + ', ' * 2', ' * ', '4 / 4 5',
224 'sqrt(2(x^2 + 3) + xyz^5 + y^2))',
225 'sqrt(2(x^(2 + ) + rot(xyz^5) + y^2))',
226 '5xc*1/5 + 1 (34 - 1 /8 + 1)* / 1',
227 # TODO: need more pattern