-
Notifications
You must be signed in to change notification settings - Fork 0
/
superfizzbuzz.rb
197 lines (158 loc) · 3.89 KB
/
superfizzbuzz.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# The below is the first, most intuitive way to do superfizzbuzz without class
# methods
100.times do |num|
num % 7 == 0
puts "Super!"
num % 5 == 0
puts "Buzz!"
num % 3 == 0
puts "Fizz!"
num % 7 == 0 && num % 5 == 0 && num % 3 == 0
puts "SuperFizzBuzz!"
num % 7 == 0 && num % 5 == 0
puts "SuperBuzz!"
num % 7 == 0 && num % 3 == 0
puts "SuperFizz!"
num % 5 == 0 && num % 3 == 0
puts "FizzBuzz!"
num % 7 != 0 && num % 5 != 0 && num % 3 != 0
puts num
end
# Here we define a class, SuperFizz
class SuperFizz
# Here we use attr_reader to make sure we can read and change the initialized
# variables, num and result
attr_reader :num, :result
def initialize(num)
@num = num
@result = ""
end
# The below is the implementation of the first way above, but using a method
# implementation that we define
def run1
if num % 7 == 0 && num % 5 == 0 && num % 3 == 0
"SuperFizzBuzz!"
elsif num % 7 == 0 && num % 5 == 0
"SuperBuzz!"
elsif num % 7 == 0 && num % 3 == 0
"SuperFizz!"
elsif num % 5 == 0 && num % 3 == 0
"FizzBuzz!"
elsif num % 7 == 0
"Super!"
elsif num % 5 == 0
"Buzz!"
elsif num % 3 == 0
"Fizz!"
else
puts num
end
# The above is a cleaner, shorter refactoring of the above superfizzbuzz with
# our own homemade methods
def run
if num % 7 == 0
result << "Super"
end
if num % 3 == 0
result << "Fizz"
end
if num % 5 == 0
result << "Buzz"
end
if result.empty?
result << num.to_s
end
result
end
## The below is an even shorter refactor of the above method; it's called a
## predicate method - it's predicated on the arguments provided in other
## methods
def divisible_by?(amount)
num % amount == 0
end
def run
if divisible_by?(7)
result << "Super"
end
if divisible_by?(3)
result << "Fizz"
end
if divisible_by?(5)
result << "Buzz"
end
if result.empty?
result << num.to_s
end
result
end
# The below takes our big, long run method from direclty above and transforms
# each divisor into its own method, then recreates run at the bottom to
# include each individual number method. This is based on Sandi Metz' principle that
# methods should be as short as possible, in order to let us reuse them more
# easily later in other applications, as well as make our code more flexible.
# i.e. what if we want to ask if the number is divisible by 4, 16, 743? We
# can now make divisible_by methods for each of those, then just add them to
# run, and now we're there.
def divisible_by?(amount)
num % amount == 0
end
def divide_by_7
if divisible_by?(7)
result << "Super"
end
end
def divide_by_3
if divisible_by?(3)
result << "Fizz"
end
end
def divide_by_5
if divisible_by?(5)
result << "Buzz"
end
end
def validate_result
if result.empty?
result << num.to_s
end
end
def run
divide_by_7
divide_by_3
divide_by_5
validate_result
result
end
# The below implements the previous configuration using guard clauses,
# which are conditional statements without an else. This eliminates lines.
def divisible_by?(amount)
num % amount == 0
end
def divide_by_7
result << "Super" if divisible_by?(7)
end
def divide_by_3
result << "Fizz" if divisible_by?(3)
end
def divide_by_5
result << "Buzz" if divisible_by?(5)
end
def validate_result
if result.empty?
result << num.to_s
end
end
def run
divide_by_7
divide_by_3
divide_by_5
validate_result
result
end
end
p SuperFizz.new(315).run
# Finally, the below combines our 1-100 range from the original enumerable with our
# class-based configuration.
100.times do |num|
p SuperFizz.new(num).run
end