samjones-calculator 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/calculator/string_calculator.rb +9 -7
- data/lib/tokenizer/tokenizer.rb +1 -1
- data/spec/calculator/calculator_spec.rb +144 -95
- data/spec/tokenizer/tokenizer_spec.rb +35 -23
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8496db06a4c79a55168cfdb0355a03c85a3f83e5
|
4
|
+
data.tar.gz: 198891de801f830dcfc595546b2daa693535e00c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b10f9ab5b17660bbc280f01cc3e9d94146db21c3e15810edbae24a801b55b1e7b0e5f2044c803b512f990fb5df01e02617c42426742bfb14327fa2ed8d51a20
|
7
|
+
data.tar.gz: fe8d3c61d4a48877c0560f000cd013955e1dfd176c0d7def246c836ce75925580b87fff26a48e2966506acf06a2db40c8ec8b8986ebc600d6ccc2de08724d9ee
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'tokenizer/tokenizer'
|
2
|
+
|
1
3
|
class StringCalculator
|
2
|
-
|
4
|
+
include Tokenizer
|
5
|
+
def initialize(value = 0)
|
3
6
|
@value = value
|
4
|
-
@tokenizer = tokenizer
|
5
7
|
end
|
6
8
|
|
7
9
|
def value
|
@@ -9,14 +11,13 @@ class StringCalculator
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def add(string)
|
14
|
+
check_negatives(string)
|
12
15
|
@value += sum_ints(string)
|
13
16
|
self
|
14
17
|
end
|
15
18
|
|
16
19
|
def sum_ints(string)
|
17
|
-
ints
|
18
|
-
@negs = ints.select { |i| i<0 }
|
19
|
-
ints.inject(:+)
|
20
|
+
ints(string).inject(:+)
|
20
21
|
end
|
21
22
|
|
22
23
|
|
@@ -25,8 +26,9 @@ class StringCalculator
|
|
25
26
|
self
|
26
27
|
end
|
27
28
|
|
28
|
-
def check_negatives
|
29
|
-
|
29
|
+
def check_negatives(string)
|
30
|
+
negs = ints(string).select { |i| i<0 }
|
31
|
+
raise "Negatives not allowed! #{negs.join(', ')}" if negs.any?
|
30
32
|
self
|
31
33
|
end
|
32
34
|
end
|
data/lib/tokenizer/tokenizer.rb
CHANGED
@@ -1,116 +1,165 @@
|
|
1
1
|
require 'calculator/string_calculator'
|
2
|
-
require 'tokenizer/tokenizer'
|
3
2
|
|
4
|
-
def tokenizer(test)
|
5
|
-
tokenizer = instance_double('Tokenizer')
|
6
|
-
allow(tokenizer).to receive(:ints) { test[:ints] }
|
7
|
-
expect(tokenizer).to receive(:ints).with(test[:string])
|
8
|
-
tokenizer
|
9
|
-
end
|
10
3
|
|
11
4
|
describe 'StringCalculator' do
|
12
5
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
expect(StringCalculator.new(10).value).to eq(10)
|
17
|
-
end
|
18
|
-
|
19
|
-
context 'add' do
|
20
|
-
it 'should add' do
|
21
|
-
[{
|
22
|
-
:initial_value => 0,
|
23
|
-
:string => '10',
|
24
|
-
:ints => [10],
|
25
|
-
:result => 10
|
26
|
-
},
|
27
|
-
{
|
28
|
-
:initial_value => 10,
|
29
|
-
:string => '10',
|
30
|
-
:ints => [10],
|
31
|
-
:result => 20
|
32
|
-
},
|
33
|
-
{
|
34
|
-
:initial_value => 10,
|
35
|
-
:string => '0',
|
36
|
-
:ints => [0],
|
37
|
-
:result => 10
|
38
|
-
}
|
39
|
-
].each { |test|
|
40
|
-
expect(StringCalculator.new(test[:initial_value], tokenizer(test)).add(test[:string]).value).to eq(test[:result])
|
41
|
-
}
|
6
|
+
context 'initial values' do
|
7
|
+
it 'should have a default value' do
|
8
|
+
expect(StringCalculator.new.value).to eq(0)
|
42
9
|
end
|
43
10
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
11
|
+
|
12
|
+
[
|
13
|
+
{
|
14
|
+
:initial_value => 0,
|
15
|
+
:value => 0
|
16
|
+
},
|
17
|
+
{
|
18
|
+
:initial_value => 10,
|
19
|
+
:value => 10
|
20
|
+
}
|
21
|
+
].each do |test_case|
|
22
|
+
it 'should have a value' do
|
23
|
+
expect(StringCalculator.new(test_case[:initial_value]).value).to eq(test_case[:value])
|
24
|
+
end
|
54
25
|
end
|
26
|
+
end
|
27
|
+
|
55
28
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
29
|
+
context 'sum' do
|
30
|
+
[
|
31
|
+
{
|
32
|
+
:initial_value => 0,
|
33
|
+
:string => '10,20',
|
34
|
+
:ints => [10, 20],
|
35
|
+
:sum => 30
|
36
|
+
},
|
37
|
+
{
|
38
|
+
:initial_value => 10,
|
39
|
+
:string => '10,20',
|
40
|
+
:ints => [10, 20],
|
41
|
+
:sum => 30
|
42
|
+
},
|
43
|
+
{
|
44
|
+
:initial_value => 0,
|
45
|
+
:string => '10,-20',
|
46
|
+
:ints => [10, -20],
|
47
|
+
:sum => -10
|
48
|
+
},
|
49
|
+
{
|
50
|
+
:initial_value => 10,
|
51
|
+
:string => '10,-20',
|
52
|
+
:ints => [10, -20],
|
53
|
+
:sum => -10
|
54
|
+
}
|
55
|
+
].each do |test_case|
|
56
|
+
it 'should sum ints' do
|
57
|
+
calculator = StringCalculator.new(test_case[:initial_value])
|
58
|
+
allow(calculator).to receive(:ints).and_return(test_case[:ints])
|
59
|
+
expect(calculator.sum_ints(test_case[:string])).to eq(test_case[:sum])
|
60
|
+
end
|
66
61
|
end
|
67
62
|
end
|
68
63
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
64
|
+
|
65
|
+
context 'check negatives' do
|
66
|
+
[
|
67
|
+
{
|
68
|
+
:initial_value => 0,
|
69
|
+
:string => '10,20',
|
70
|
+
:ints => [10, 20],
|
71
|
+
:raise => false
|
72
|
+
},
|
73
|
+
{
|
74
|
+
:initial_value => 0,
|
75
|
+
:string => '10,-20',
|
76
|
+
:ints => [10, -20],
|
77
|
+
:raise => true,
|
78
|
+
:error => 'Negatives not allowed! -20'
|
79
|
+
},
|
80
|
+
{
|
81
|
+
:initial_value => 0,
|
82
|
+
:string => '10,-20,-30',
|
83
|
+
:ints => [10, -20, -30],
|
84
|
+
:raise => true,
|
85
|
+
:error => 'Negatives not allowed! -20, -30'
|
86
|
+
}
|
87
|
+
].each do |test_case|
|
88
|
+
it 'should check negatives' do
|
89
|
+
calculator = StringCalculator.new(test_case[:initial_value])
|
90
|
+
allow(calculator).to receive(:ints).and_return(test_case[:ints])
|
91
|
+
expect { calculator.check_negatives(test_case[:string]) }.to raise_error(test_case[:error]) if test_case[:raise]
|
92
|
+
expect(calculator.check_negatives(test_case[:string])).to eq(calculator) unless test_case[:raise]
|
93
|
+
end
|
86
94
|
end
|
95
|
+
end
|
96
|
+
|
87
97
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
+
context 'add' do
|
99
|
+
[
|
100
|
+
{
|
101
|
+
:initial_value => 0,
|
102
|
+
:string => '10,20',
|
103
|
+
:ints => [10, 20],
|
104
|
+
:value => 30,
|
105
|
+
:raise => false
|
106
|
+
},
|
107
|
+
{
|
108
|
+
:initial_value => 10,
|
109
|
+
:string => '10,20',
|
110
|
+
:ints => [10, 20],
|
111
|
+
:value => 40,
|
112
|
+
:raise => false
|
113
|
+
},
|
114
|
+
{
|
115
|
+
:initial_value => 0,
|
116
|
+
:string => '10,20',
|
117
|
+
:ints => [10, 20],
|
118
|
+
:raise => true
|
119
|
+
}
|
120
|
+
].each do |test_case|
|
121
|
+
it 'should add' do
|
122
|
+
calculator = StringCalculator.new(test_case[:initial_value])
|
123
|
+
allow(calculator).to receive(:ints).and_return(test_case[:ints])
|
124
|
+
allow(calculator).to receive(:check_negatives) { raise 'Error' if test_case[:raise] }
|
125
|
+
expect { calculator.add(test_case[:string]) }.to raise_error('Error') if test_case[:raise]
|
126
|
+
expect(calculator.add(test_case[:string]).value).to eq(test_case[:value]) unless test_case[:raise]
|
127
|
+
end
|
98
128
|
end
|
129
|
+
end
|
99
130
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
131
|
+
|
132
|
+
context 'subtract' do
|
133
|
+
[
|
134
|
+
{
|
135
|
+
:initial_value => 0,
|
136
|
+
:string => '10,20',
|
137
|
+
:ints => [10, 20],
|
138
|
+
:value => -30,
|
139
|
+
},
|
140
|
+
{
|
141
|
+
:initial_value => 50,
|
142
|
+
:string => '10,20',
|
143
|
+
:ints => [10, 20],
|
144
|
+
:value => 20,
|
145
|
+
}
|
146
|
+
].each do |test_case|
|
147
|
+
it 'should subtract' do
|
148
|
+
calculator = StringCalculator.new(test_case[:initial_value])
|
149
|
+
allow(calculator).to receive(:ints).and_return(test_case[:ints])
|
150
|
+
expect(calculator.subtract(test_case[:string]).value).to eq(test_case[:value])
|
151
|
+
end
|
110
152
|
end
|
111
153
|
end
|
112
154
|
|
113
|
-
|
114
|
-
|
155
|
+
|
156
|
+
context 'preserve value' do
|
157
|
+
it 'should preserve value calls' do
|
158
|
+
calculator = StringCalculator.new(0)
|
159
|
+
allow(calculator).to receive(:ints).and_return([10, 20])
|
160
|
+
expect(calculator.subtract('10,20').value).to eq(-30)
|
161
|
+
allow(calculator).to receive(:ints).and_return([30, 40])
|
162
|
+
expect(calculator.add('30,40').value).to eq(40)
|
163
|
+
end
|
115
164
|
end
|
116
165
|
end
|
@@ -1,44 +1,56 @@
|
|
1
1
|
require 'tokenizer/tokenizer.rb'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
describe Tokenizer do
|
4
|
+
|
5
|
+
let(:tokenizer) { Class.new { include Tokenizer }.new }
|
6
|
+
|
7
|
+
|
8
|
+
it 'should not blow up' do
|
9
|
+
expect(tokenizer.ints).to eq([])
|
10
|
+
expect(tokenizer.ints('')).to eq([])
|
7
11
|
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
expect(
|
13
|
+
|
14
|
+
it 'should tokenize' do
|
15
|
+
expect(tokenizer.tokens('abc')).to eq(['abc'])
|
16
|
+
expect(tokenizer.tokens('abc,123')).to eq(['abc', '123'])
|
12
17
|
end
|
13
18
|
|
14
|
-
|
15
|
-
|
19
|
+
|
20
|
+
it 'should handle multiple delimiters' do
|
21
|
+
expect(tokenizer.tokens("1,2\n3")).to eq(['1', '2', '3'])
|
16
22
|
end
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
|
25
|
+
it 'should handle setting delimiter' do
|
26
|
+
expect(tokenizer.tokens("//'\n1'2")).to eq(['1', '2'])
|
20
27
|
end
|
21
28
|
|
22
|
-
|
23
|
-
|
29
|
+
|
30
|
+
it 'should handle setting multiple delimiters' do
|
31
|
+
expect(tokenizer.tokens("//['][#]\n1'2#3")).to eq(['1', '2', '3'])
|
24
32
|
end
|
25
33
|
|
26
|
-
|
27
|
-
|
34
|
+
|
35
|
+
it 'should handle complex delimiters' do
|
36
|
+
expect(tokenizer.tokens("//['#]\n1'#2")).to eq(['1', '2'])
|
28
37
|
end
|
29
38
|
|
30
|
-
|
31
|
-
|
32
|
-
expect(
|
39
|
+
|
40
|
+
it 'should test for int' do
|
41
|
+
expect(tokenizer.is_i?("123")).to eq(true)
|
42
|
+
expect(tokenizer.is_i?("abc")).to eq(false)
|
33
43
|
end
|
34
44
|
|
35
|
-
|
36
|
-
|
37
|
-
expect(
|
45
|
+
|
46
|
+
it 'should return ints' do
|
47
|
+
expect(tokenizer.ints('1')).to eq([1])
|
48
|
+
expect(tokenizer.ints('1,2')).to eq([1, 2])
|
38
49
|
end
|
39
50
|
|
40
|
-
|
41
|
-
|
51
|
+
|
52
|
+
it 'should filter non ints' do
|
53
|
+
expect(tokenizer.ints('abc,123')).to eq([123])
|
42
54
|
end
|
43
55
|
|
44
56
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: samjones-calculator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Jones
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -115,8 +115,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
115
|
version: '0'
|
116
116
|
requirements: []
|
117
117
|
rubyforge_project:
|
118
|
-
rubygems_version: 2.4
|
118
|
+
rubygems_version: 2.6.4
|
119
119
|
signing_key:
|
120
120
|
specification_version: 4
|
121
121
|
summary: String Calculator
|
122
122
|
test_files: []
|
123
|
+
has_rdoc:
|