rpn-calculator 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67b5ea07408d666e0b0b1f0e564b989773f7e095
4
- data.tar.gz: 37623c7573e54025ff442b97c7c024b6ea09a9e7
3
+ metadata.gz: 72f8ad5a6504d98bb59d0bfcbac6e918dee44743
4
+ data.tar.gz: e34bb42f596a78a62ee1c94e570c89bc9e3dbd64
5
5
  SHA512:
6
- metadata.gz: e84986323f02c63a8dfa0cac0a144ff0ddb4916a83489a8f91088d2e0dbf24bd3d857749f1d8338bb9e971526f6c8b351b4f36851b855cee9c02a08b6ec43547
7
- data.tar.gz: eacb1e523c7b9d4d98c4468ae8982ba251f19409c0a9256859be731ede0a108fba549c3b22e44cfea3cf36eb2edb0643993827ab6032e9c293b1099220721d08
6
+ metadata.gz: 6f1355c0cd90e80345918f66771eb4311b8a983e1fee0bb09ffdbebfa75623cf337f24f4e410424d434f5d69daa2b5d17e300428c9908e611d5750689391acae
7
+ data.tar.gz: 55a42ddf85c9efbbf32b34e67acd1bc35d60d3abd4d1dab846e802512e44a0e006d0d35d061eebe85698d6260fe976c6d9a736f606096003b0c287f1bcd06890
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'rpn-calculator'
4
4
 
5
- RPNCalculator.start
5
+ RPNCalculator.start_cli_tool
@@ -10,20 +10,24 @@ module RPNCalculator
10
10
  '/' => Operation::Division
11
11
  }.freeze
12
12
  ALLOWED_OPERATORS = OPERATION_CLASSES.keys.freeze
13
- INVALID_ARGUMENTS_REGEX = /[^\d\s\+\-\/\*\.]/.freeze
13
+ INVALID_ARGUMENTS_REGEX = /[^\d\s\.#{Regexp.quote(ALLOWED_OPERATORS.join)}]/
14
+ OPERATION_PROCESSOR = OperationProcessor.new(OPERATION_CLASSES).freeze
15
+ INPUT_PROCESSOR = InputProcessor.new(
16
+ OPERATION_PROCESSOR,
17
+ Input::Validator.new(INVALID_ARGUMENTS_REGEX),
18
+ Input::Parser.new(ALLOWED_OPERATORS)
19
+ ).freeze
14
20
 
15
21
  module_function
16
22
 
17
- def start
18
- operation_processor = OperationProcessor.new(
19
- OPERATION_CLASSES,
20
- Input::Validator.new(INVALID_ARGUMENTS_REGEX),
21
- Input::Parser.new(ALLOWED_OPERATORS)
22
- )
23
-
23
+ def start_cli_tool
24
24
  # Here is where we could read and write to another input
25
25
  # using stdin and stdout by default
26
- processor = IoProcessor.new(IoInterface::Standard.new, operation_processor)
26
+ processor = CLI.new(IoInterface::Standard.new, INPUT_PROCESSOR)
27
27
  processor.start
28
28
  end
29
+
30
+ def calculate(expression)
31
+ INPUT_PROCESSOR.process(expression)
32
+ end
29
33
  end
@@ -1,14 +1,14 @@
1
1
  module RPNCalculator
2
- class IoProcessor
3
- def initialize(io_interface, operation_processor)
2
+ class CLI
3
+ def initialize(io_interface, input_processor)
4
4
  @io_interface = io_interface
5
5
  @input_stack = []
6
- @operation_processor = operation_processor
6
+ @input_processor = input_processor
7
7
  end
8
8
 
9
9
  def start
10
- while (input = io_interface.read_input)
11
- processor_result = operation_processor.process(input_stack, input)
10
+ while (input_expression = io_interface.read_input)
11
+ processor_result = input_processor.process(input_expression, input_stack)
12
12
 
13
13
  if processor_result.valid?
14
14
  print_result_array(processor_result.result)
@@ -21,7 +21,7 @@ module RPNCalculator
21
21
 
22
22
  private
23
23
 
24
- attr_reader :io_interface, :operation_processor, :input_stack
24
+ attr_reader :io_interface, :input_processor, :input_stack
25
25
 
26
26
  def print_result_array(result)
27
27
  io_interface.display_output(result.join(' '))
@@ -18,19 +18,19 @@ module RPNCalculator
18
18
  attr_reader :allowed_operators
19
19
 
20
20
  def input_without_whitespace(split_string)
21
- split_string.select { |e| e!= ' ' }
21
+ split_string.reject { |e| e == ' ' }
22
22
  end
23
23
 
24
24
  def parsed_input_errors(parsed_input)
25
25
  parsed_input.inject([]) do |result, element|
26
- result << element unless allowed_operators.include?(element) || is_number?(element)
26
+ result << element unless allowed_operators.include?(element) || number?(element)
27
27
  result
28
28
  end
29
29
  end
30
30
 
31
31
  def join_consecutive_numbers(split_string)
32
32
  split_string.each_with_index.inject([]) do |result, (element, index)|
33
- if index == 0 || any_operator?([split_string[index - 1], element])
33
+ if index.zero? || any_operator?([split_string[index - 1], element])
34
34
  result << element
35
35
  else
36
36
  result[-1] += element
@@ -40,14 +40,14 @@ module RPNCalculator
40
40
  end
41
41
 
42
42
  def any_operator?(elements)
43
- elements.any? { |e| !is_number_or_period?(e) }
43
+ elements.any? { |e| !number_or_period?(e) }
44
44
  end
45
45
 
46
- def is_number_or_period?(number_string)
47
- number_string == '.' || is_number?(number_string)
46
+ def number_or_period?(number_string)
47
+ number_string == '.' || number?(number_string)
48
48
  end
49
49
 
50
- def is_number?(number_string)
50
+ def number?(number_string)
51
51
  true if Float(number_string)
52
52
  rescue ArgumentError
53
53
  false
@@ -0,0 +1,32 @@
1
+ module RPNCalculator
2
+ class InputProcessor
3
+ def initialize(operation_processor, input_validator, input_parser)
4
+ @input_validator = input_validator
5
+ @input_parser = input_parser
6
+ @operation_processor = operation_processor
7
+ end
8
+
9
+ def process(input_expression, previous_operations = [])
10
+ validator_result = input_validator.validate(input_expression)
11
+ return invalid_processor_result(validator_result) unless validator_result.valid?
12
+
13
+ parser_result = input_parser.parse(input_expression)
14
+ return invalid_processor_result(parser_result) unless parser_result.valid?
15
+
16
+ operation_result = operation_processor.process(
17
+ previous_operations + parser_result.result
18
+ )
19
+ return invalid_processor_result(operation_result) unless operation_result.valid?
20
+
21
+ Result::Processor.new(operation_result.result)
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :input_validator, :input_parser, :operation_processor
27
+
28
+ def invalid_processor_result(result)
29
+ Result::Processor.new([], result.error)
30
+ end
31
+ end
32
+ end
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:+))
9
+ Result::Operation.new(operation_string, operands.reduce(&:+))
10
10
  end
11
11
 
12
12
  private
@@ -21,10 +21,6 @@ module RPNCalculator
21
21
  operands.size == 2
22
22
  end
23
23
 
24
- def float_operands
25
- operands.map { |operator| Float(operator) }
26
- end
27
-
28
24
  def invalid_operation_result(operation)
29
25
  Result::Operation.new(operation, [], operands)
30
26
  end
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:/))
9
+ Result::Operation.new(operation_string, operands.reduce(&:/))
10
10
  end
11
11
 
12
12
  private
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:*))
9
+ Result::Operation.new(operation_string, operands.reduce(&:*))
10
10
  end
11
11
 
12
12
  private
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:-))
9
+ Result::Operation.new(operation_string, operands.reduce(&:-))
10
10
  end
11
11
 
12
12
  private
@@ -1,44 +1,34 @@
1
1
  module RPNCalculator
2
2
  class OperationProcessor
3
- def initialize(operation_classes, input_validator, input_parser)
4
- @input_validator = input_validator
5
- @input_parser = input_parser
3
+ def initialize(operation_classes)
6
4
  @operation_classes = operation_classes
7
5
  @operation_symbols = @operation_classes.keys
8
6
  end
9
7
 
10
- # Refator needed, process should receive parsed input
11
- def process(previous_operations, input)
12
- validator_result = input_validator.validate(input)
13
- return Result::Processor.new([], validator_result.error) unless validator_result.valid?
14
-
15
- parser_result = input_parser.parse(input)
16
- return Result::Processor.new([], parser_result.error) unless parser_result.valid?
17
-
18
- process_operations(previous_operations + parser_result.parsed_elements)
19
- end
20
-
21
- private
22
-
23
- attr_reader :input_validator, :input_parser, :operation_classes, :operation_symbols
24
-
25
- def process_operations(operations)
26
- result_stack = operations.inject([]) do |stack, element|
8
+ def process(parsed_expression)
9
+ result_stack = parsed_expression.inject([]) do |stack, element|
27
10
  if operation_symbols.include?(element)
28
- result = operation_classes.fetch(element)
29
- .operate([stack.pop, stack.pop].reverse)
11
+ result = operation_classes.fetch(element).operate(stack.pop(2))
30
12
  return invalid_processor_result(result) unless result.valid?
31
13
  stack.push(result.result)
32
14
  else
33
- stack.push(element)
15
+ stack.push(as_float(element))
34
16
  end
35
17
  stack
36
18
  end
37
19
  Result::Processor.new(result_stack)
38
20
  end
39
21
 
22
+ private
23
+
24
+ attr_reader :operation_classes, :operation_symbols
25
+
40
26
  def invalid_processor_result(result)
41
27
  Result::Processor.new([], result.error)
42
28
  end
29
+
30
+ def as_float(num_string)
31
+ Float(num_string)
32
+ end
43
33
  end
44
34
  end
@@ -0,0 +1,21 @@
1
+ module RPNCalculator
2
+ module Result
3
+ class Input
4
+ def initialize
5
+ raise 'Can not instantiate abstract class'
6
+ end
7
+
8
+ def valid?
9
+ raise 'must implement in subclass'
10
+ end
11
+
12
+ def error
13
+ raise 'must implement in subclass'
14
+ end
15
+
16
+ def result
17
+ raise 'must implement in subclass'
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,8 @@
1
+ require 'rpn-calculator/result/input'
2
+
1
3
  module RPNCalculator
2
4
  module Result
3
- class Parser
5
+ class Parser < Input
4
6
  def initialize(parsed_elements = [], invalid_elements = [])
5
7
  @parsed_elements = parsed_elements
6
8
  @invalid_elements = invalid_elements
@@ -14,10 +16,14 @@ module RPNCalculator
14
16
  "Invalid operators or numbers: #{invalid_element_list}" unless valid?
15
17
  end
16
18
 
17
- attr_reader :parsed_elements, :invalid_elements
19
+ def result
20
+ @parsed_elements
21
+ end
18
22
 
19
23
  private
20
24
 
25
+ attr_reader :invalid_elements
26
+
21
27
  def invalid_element_list
22
28
  invalid_elements.join(', ')
23
29
  end
@@ -1,6 +1,8 @@
1
+ require 'rpn-calculator/result/input'
2
+
1
3
  module RPNCalculator
2
4
  module Result
3
- class Processor
5
+ class Processor < Input
4
6
  def initialize(result = [], error = nil)
5
7
  @result = result
6
8
  @error = error
@@ -1,6 +1,8 @@
1
+ require 'rpn-calculator/result/input'
2
+
1
3
  module RPNCalculator
2
4
  module Result
3
- class Validator
5
+ class Validator < Input
4
6
  def initialize(invalid_characters = [])
5
7
  @invalid_characters = invalid_characters
6
8
  end
@@ -13,6 +15,10 @@ module RPNCalculator
13
15
  "Invalid characters: #{invalid_character_list}" unless valid?
14
16
  end
15
17
 
18
+ def result
19
+ []
20
+ end
21
+
16
22
  private
17
23
 
18
24
  attr_reader :invalid_characters
@@ -1,3 +1,3 @@
1
1
  module RPNCalculator
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rpn-calculator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Celi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-29 00:00:00.000000000 Z
11
+ date: 2017-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -34,17 +34,19 @@ extra_rdoc_files: []
34
34
  files:
35
35
  - bin/rpn-calculator
36
36
  - lib/rpn-calculator.rb
37
+ - lib/rpn-calculator/cli.rb
37
38
  - lib/rpn-calculator/input/parser.rb
38
39
  - lib/rpn-calculator/input/validator.rb
40
+ - lib/rpn-calculator/input_processor.rb
39
41
  - lib/rpn-calculator/io_interface/abstract.rb
40
42
  - lib/rpn-calculator/io_interface/standard.rb
41
- - lib/rpn-calculator/io_processor.rb
42
43
  - lib/rpn-calculator/operation/addition.rb
43
44
  - lib/rpn-calculator/operation/base.rb
44
45
  - lib/rpn-calculator/operation/division.rb
45
46
  - lib/rpn-calculator/operation/multiplication.rb
46
47
  - lib/rpn-calculator/operation/subtraction.rb
47
48
  - lib/rpn-calculator/operation_processor.rb
49
+ - lib/rpn-calculator/result/input.rb
48
50
  - lib/rpn-calculator/result/operation.rb
49
51
  - lib/rpn-calculator/result/parser.rb
50
52
  - lib/rpn-calculator/result/processor.rb
@@ -62,7 +64,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
64
  requirements:
63
65
  - - ">="
64
66
  - !ruby/object:Gem::Version
65
- version: '0'
67
+ version: 1.9.3
66
68
  required_rubygems_version: !ruby/object:Gem::Requirement
67
69
  requirements:
68
70
  - - ">="