rpn_party 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d32325fb22bab5f4a740c85edf8209a0356975ff
4
+ data.tar.gz: 9995eb11a6c13ed816b470b80aa9e096351c7550
5
+ SHA512:
6
+ metadata.gz: 1e73c6c03d61a4b606cfc3411cbe920e9759ca9ec0b599a53499c6fd5d9248817891c3e7392de2ae78ba74790609bbd9b51316340bc8154a8ad82db4cb6cc63c
7
+ data.tar.gz: 2d8465d85f678ffa20e7446880ce1a3c606a7f040418765650dd9e80f3026082beeaf50f92ac38aef5bb9b389a39889c0948e7b6bde49b6c4ffc6092b1666e02
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Adds this gem's lib path the the Ruby load path. This allows
4
+ # us to test RPNParty::CLI without the gem being installed.
5
+ # Borrowed from https://stackoverflow.com/a/5294358/918507
6
+ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
7
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
8
+
9
+ require 'rpn_party/cli'
10
+
11
+ RPNParty::CLI.new
@@ -0,0 +1,90 @@
1
+ require 'rpn_party/errors'
2
+
3
+ module RPNParty
4
+ class Calculator
5
+ def initialize(calculation = '')
6
+ @stack = []
7
+ evaluate(calculation)
8
+ end
9
+
10
+ def result
11
+ if @stack.empty?
12
+ nil
13
+ elsif @stack.length == 1
14
+ @stack[0]
15
+ else
16
+ @stack
17
+ end
18
+ end
19
+
20
+ def evaluate(calculation)
21
+ calculation.split.map do |token|
22
+ case token
23
+ when /\A(?:\-)?\d+(?:\.\d+)?\z/
24
+ @stack.push token.to_f
25
+ when /\A\+\z/
26
+ add
27
+ when /\A\-\z/
28
+ subtract
29
+ when /\A\*\z/
30
+ multiply
31
+ when /\A\/\z/
32
+ divide
33
+ else
34
+ raise UnrecognizedInputError,
35
+ "Unrecognized value/operator: '#{token}'. Valid inputs are numbers (0, 1, 2.5, -3, etc.), or '+', '-', '*', '/'."
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def add
43
+ raise_if_insufficient_operands :addition
44
+
45
+ first_value, second_value = @stack.pop(2)
46
+ @stack.push(first_value + second_value)
47
+ end
48
+
49
+ def subtract
50
+ raise_if_insufficient_operands :subtraction
51
+
52
+ first_value, second_value = @stack.pop(2)
53
+ @stack.push(first_value - second_value)
54
+ end
55
+
56
+ def multiply
57
+ raise_if_insufficient_operands :multiplication
58
+
59
+ first_value, second_value = @stack.pop(2)
60
+ @stack.push(first_value * second_value)
61
+ end
62
+
63
+ def divide
64
+ raise_if_insufficient_operands :division
65
+ raise_if_second_value_is_zero
66
+
67
+ first_value, second_value = @stack.pop(2)
68
+ @stack.push(first_value / second_value)
69
+ end
70
+
71
+ def raise_if_second_value_is_zero
72
+ return unless @stack.last.zero?
73
+
74
+ raise ZeroDivisionError,
75
+ "Cannot divide #{@stack[-2]} by 0."
76
+ end
77
+
78
+ def raise_if_insufficient_operands(operation)
79
+ return if @stack.length >= 2
80
+
81
+ message = if @stack.empty?
82
+ "Could not perform #{operation}. At least two values are required, but there are none."
83
+ else
84
+ "Could not perform #{operation}. At least two values are required, but there is only one: '#{@stack.first}'."
85
+ end
86
+ raise InsufficientOperandsError,
87
+ message
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,40 @@
1
+ require 'rpn_party/calculator'
2
+
3
+ module RPNParty
4
+ class CLI
5
+ def initialize
6
+ @calc = RPNParty::Calculator.new
7
+
8
+ puts 'Welcome to RPNParty!'
9
+ print '> '
10
+
11
+ loop do
12
+ input = gets
13
+
14
+ if input.nil? || input.chomp == 'q'
15
+ puts 'Goodbye!'
16
+ exit
17
+ end
18
+
19
+ begin
20
+ @calc.evaluate(input.chomp)
21
+ rescue RPNParty::UnrecognizedInputError => error
22
+ puts error.message
23
+ rescue ZeroDivisionError => error
24
+ puts error.message
25
+ rescue RPNParty::InsufficientOperandsError => error
26
+ puts error.message
27
+ end
28
+
29
+ if @calc.result.nil?
30
+ puts 'nil'
31
+ elsif @calc.result.is_a? Array
32
+ puts @calc.result.join(', ')
33
+ else
34
+ puts @calc.result
35
+ end
36
+ print '> '
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ module RPNParty
2
+ class UnrecognizedInputError < StandardError
3
+ end
4
+
5
+ class InsufficientOperandsError < StandardError
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rpn_party
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Richard Jones
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An interactive Reverse Polish Notation calculator for the command line
14
+ email: rico@toasterlovin.com
15
+ executables:
16
+ - rpn_party
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/rpn_party
21
+ - lib/rpn_party/calculator.rb
22
+ - lib/rpn_party/cli.rb
23
+ - lib/rpn_party/errors.rb
24
+ homepage: https://github.com/toasterlovin/rpn_party
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.6.12
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: RPN Party
48
+ test_files: []