Skip to content

Commit 11313be

Browse files
committed
Add converting numbers text, specs, and solution
1 parent 42b64fa commit 11313be

4 files changed

Lines changed: 127 additions & 7 deletions

File tree

2_Numbers/2_Basic_operators/solution.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# e.g.
1+
# e.g.:
22
sum = Rational(1, 3) + Rational(2)
33
difference = 1_000_000_000_000_000_000_000_000 - 1.9
44
product = 2.4 * 5.6 * 2.3
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# e.g.:
2+
integer = Complex(2.5).to_i
3+
float = 42.to_f
4+
rational = 10.25.to_r
5+
complex = Rational(1.1, 3.3).to_c
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
require 'rspec'
2+
require 'rspec/expectations'
3+
4+
# requires code_breaker gem to be installed
5+
# (https://github.com/daigaku-ruby/code_breaker)
6+
require 'code_breaker'
7+
8+
RSpec::Matchers.define :run_number_conversions do |expected|
9+
METHODS = {
10+
to_i: 'to integer',
11+
to_f: 'to float',
12+
to_r: 'to Rational number',
13+
to_c: 'to Complex number'
14+
}
15+
16+
match do |actual|
17+
lines = actual.split("\n").compact.map(&:strip).reject(&:empty?)
18+
called_conversions(lines).include?(expected)
19+
end
20+
21+
def called_conversions(lines)
22+
lines.map { |line|
23+
CodeBreaker.parse(line) unless line.start_with?('#')
24+
}.compact
25+
end
26+
27+
failure_message do |actual|
28+
expected_operants = expected.values.first
29+
variable_name = expected_operants[0]
30+
31+
expected_method = METHODS[expected_operants[1][1]]
32+
expected_conversion = "#{variable_name} = #{expected_operants[1][0]} #{expected_method}"
33+
34+
actual_line = actual.split("\n").select do |output|
35+
output.match(/#{variable_name} =.+/)
36+
end
37+
38+
actual_parsed = CodeBreaker.parse(actual_line.join)
39+
actual_operants = actual_parsed.values.first
40+
actual_conversion = "#{variable_name} = #{[actual_operants[1]].flatten.join(' ')}"
41+
42+
%Q{Your code doesn't run the number conversion "#{expected_conversion}".
43+
------- Instead you defined "#{actual_conversion}".}
44+
end
45+
end
46+
47+
# code_breaker outputs
48+
CONVERSIONS = [
49+
{ lvasgn: [:integer, [Complex, :to_i]] },
50+
{ lvasgn: [:float, [Fixnum, :to_f]] },
51+
{ lvasgn: [:rational, [Float, :to_r]] },
52+
{ lvasgn: [:complex, [Rational, :to_c]] }
53+
].freeze
54+
55+
describe "Your code" do
56+
[['solution::code']]
57+
58+
CONVERSIONS.each do |conversion|
59+
variable_name = conversion.first.last.first
60+
values = conversion.values.first.last
61+
62+
it "defines a variable with name \"#{variable_name}\"" do
63+
expect(local_variables.include?(variable_name)).to be true
64+
end
65+
66+
if local_variables.include?(variable_name)
67+
article = !!variable_name.match(/^[eioa]/) ? 'an' : 'a'
68+
69+
it "converts a #{values.first} number to #{article} #{variable_name}" do
70+
code_lines = %Q{ [['solution::code']] }
71+
expect(code_lines).to run_number_conversions(conversion)
72+
end
73+
end
74+
end
75+
end

2_Numbers/3_Converting_numbers/task.md

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,50 @@
77

88
---
99

10-
There are several methods you can apply on numbers to convert a number to another
11-
number format:
10+
There are several methods you can apply on numbers to explicitly convert a number
11+
to another number format:
1212

13-
`to_i` converts to an Integer number
14-
`to_f` converts to a Float number
15-
`to_r` converts to a Rational values
16-
`to_c` converts to a Complex number
13+
` to_i` converts to an *Integer* number
14+
` to_f` converts to a *Float* number
15+
` to_r` converts to a *Rational* values
16+
` to_c` converts to a *Complex* number
17+
18+
Converting a number to its own type will just return the number, e.g.:
19+
20+
` 123.to_i` *# => 123*
21+
` 4.75.to_f` *# => 4.75*
22+
` Rational(3, 7).to_r` *# => (3,7)*
23+
` Complex(2.1, 3.2).to_c` *# => (2.1+3.2i)*
24+
25+
If you convert a Float, a Rational or a Complex number to an Integer by calling
26+
the `to_i` method then the digits after the decimal point are just cut off.
27+
Note that the size of the fraction doesn't matter:
28+
29+
` 2.01.to_i` and `2.95.to_i` will both return *2*.
30+
31+
If you want to convert a float to an integer based on its digits after the decimal point,
32+
you should have a look at the `#floor`, `#ceil`, and `#round` methods of a Numeric:
33+
34+
- (ruby-doc core: Numeric#ceil)
35+
- (ruby-doc core: Numeric#floor)
36+
- (ruby-doc core: Numeric#round)
37+
38+
One thing you can't do is converting a Complex number with an imaginary part other
39+
than `0` to an integer, float, or rational number.
40+
41+
For instance `Complex(5.3, 0.5).to_i` will throw an Error (*RangeError: can't convert 5.3+0.5i into Integer*),
42+
whereas `Complex(5.3).to_i` will give you a *5*.
43+
44+
---
45+
46+
Convert numbers into other formats:
47+
48+
1. Convert a *Complex* number into an *Integer*
49+
2. Convert a *Fixnum* integer into a *Float*
50+
3. Convert a *Float* into a *Rational* number
51+
4. Convert a *Rational* number into an *Complex* number
52+
53+
Store each result in a variable that is named like the resulting type of the conversion, e.g.
54+
for 1. *integer*,
55+
for 2. *float*,
56+
and so on.

0 commit comments

Comments
 (0)