-
Notifications
You must be signed in to change notification settings - Fork 10
/
iteration.rb
308 lines (154 loc) · 8.14 KB
/
iteration.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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#################################
# Automating repetition
#################################
# .times is a way to loop in Ruby.
# This is how you print "howdy" five times:
# 5.times do
# puts "howdy"
# end
# Everything that comes between the 'do' and 'end' gets repeated 5 times.
# Try it yourself.
# Challenge: Print the following.
# howdy 0
# howdy 1
# howdy 2
# howdy 3
# howdy 4
# using the .times method. Try adding to the code above.
# Hint: Try creating a placeholder variable and changing it each time through to keep track of where you are.
# Your code goes here:
# placeholder = 0
# 5.times do
# puts "howdy #{placeholder}"
# placeholder = placeholder + 1
# end
# Continued below...
# Like most patterns that happen often, Ruby gives us a way to clean
# this up a bit. It happens often that you use .times and want to know
# which round you are in, so you can just use this syntax instead:
# this_round = 0
# 5.times do
# puts "howdy #{this_round}"
# this_round = this_round + 2
# end
# 5.times do |placeholder|
# puts "howdy #{placeholder}"
# end
# It's just a neater way of keeping track of which round we're in. Just as before, you can name the placeholder variable anything you want. The way the .times method works is that if you choose a variable name between the pipes, it will assign to it the round number each time through.
# Challenge: Try printing the squares of the numbers 0-9.
# Your output should look like this:
# 0
# 1
# 4
# 9
# 16
# 25
# 36
# 49
# 64
# 81
# Your code goes here:
# 10.times do |n|
# puts n
# end
# Continued below...
#################################
# Lists of things
#################################
# Lets say I want to make a list to help me learn names.
# Suppose we want to build an app that helps us learn names. One way to keep track of a list of things in Ruby is with an Array:
names = ["Neal", "Mike", "Jeff", "Raghu"]
# You create Arrays by enclosing them in square brackets, and separating items in the list with commas.
# There are many methods you can call on Arrays, some of which you've already seen.
# Try the following in IRB: names.length, names.first, names.last
# But to access a thing in the middle of the list, I need to tell Ruby its index in the array.
# It's similar to referencing a cell in a column in Excel. Try this in IRB: names[1]
# Notice that the numbering of cells starts at 0, not at 1. Try accessing the 0th cell of names.
# So now I have a list of names to help me learn. But now I have to remember locations in order to look up a name, which is not a big improvement over just remembering the name itself.
# It would be nice if I could access a cell by something other than a number. Enter the hash: a list where the cells are named something meaningful rather than just numbered.
names_hash = { "hoodie" => "Neal", "snuggie" => "Mike", "blackhawks" => "Jeff", "beard" => "Raghu" }
# Now I don't need to remember the order; I just need to know what I'm looking for.
# puts "Key hoodie: #{names_hash["hoodie"]}"
# puts "Key blackhawks: #{names_hash["blackhawks"]}"
# Cool, huh? Now I can look things up in my list without needing to know the order.
# For my fellow Excel junkies, it's kind of like a VLOOKUP.
#################################
# Automating working with lists
#################################
# Anyway, back to arrays.
# Challenge: Using the .times method, print each element in the names array.
# Your output should look like this:
# *** Neal ***
# *** Mike ***
# *** Jeff ***
# *** Raghu ***
# Your code goes here:
names = ["Neal", "Mike", "Jeff", "Raghu", "Vince"]
# names.length.times do |position|
# puts "*** #{names[position]} ***"
# end
# Continued below...
# Does your solution work if we add a name to the list? If not, try using the .length method to make it smarter.
# Your code goes here:
# Look! It's a pattern that probably happens often: looping through an array. As you would expect, this happens often, so Ruby gives us a way to clean it up a bit:
# The Array#each_index method will count the length of the array for you, so you don't have to mess around with Array#length and Fixnum#times.
# names.length.times do |index|
# puts "*** #{names[index]} ***"
# end
# names.each_index do |index|
# puts "*** #{names[index]} ***"
# end
# But there's a way to clean it up even more. We're doing all this work to get cell numbers just so that we can use them to index into the array just so that we can pull out the thing that we want to do something interesting with.
# We don't care about the cell numbers, honestly. Ruby, can you please just give me each thing in the list one at a time?
# The .each method will count the length of the array for you, AND it will give you back each element without you needing to manually access the array.
names.each do |the_name|
puts "*** #{the_name} ***"
end
# Notice I named the block variable descriptively; before it made sense to call it 'index' because each time through, it was the index that got assigned to it (because that's what .each_index hands back each time through). This time I get the actual object in the cell (because that's what .each hands back each time through), so I called it 'name'.
# I can call the block variable anything I want! name, n, x, or zebra. There's nothing special about the fact that I chose to use the singular version of what I chose to call the list ("names"). It's just something I do to help keep things straight in my head. Try renaming variables and see what breaks; what has to match with what?
# What about hometowns? Let's use our other kind of list, hashes, to keep track of this info:
student1 = { "first" => "neal", "last" => "sales-griffin", "hometown" => "chicago" }
student2 = { "first" => "mike", "last" => "mcgee", "hometown" => "freeport" }
student3 = { "first" => "jeff", "last" => "cohen", "hometown" => "skokie" }
student4 = { "first" => "raghu", "last" => "betina", "hometown" => "goshen" }
# Create a new array of students containing these hashes.
students = [student1, student2, student3, student4]
# How would you access Jeff's hometown using the students array?
# Your code goes here:
# Continued below...
# Challenge: Automate the task of displaying the students' names along with their hometowns. Use the .each method. Your output should look like this:
# Neal Sales-griffin is from Chicago.
# Mike Mcgee is from Freeport.
# Jeff Cohen is from Skokie.
# Raghu Betina is from Goshen.
# Solution:
# Again, I could have named things differently. I nearly chose to remind myself what kind of thing I'm dealing with by naming the block variable "student_hash".
# Hard Challenge: Based on the data stored in the shopping_cart, sales_tax, and params variables below, write code that prints out the customer's total, including estimated sales tax, based on the shipping address they entered. Your code should work even if the values of the data change.
# Your output should look like this:
# Your total with tax is $4455.54.
shopping_cart = [
{'name' => "iPad 2", 'price' => 499, 'quantity' => 2},
{'name' => "iMac 27", 'price' => 1699, 'quantity' => 1},
{'name' => "MacBook Air 13", 'price' => 1299, 'quantity' => 1}
]
sales_tax = {"IL" => 0.115, "IN" => 0.09, "MI" => 0.06, "WI" => 0.056}
params = {
'name' => "Patrick McProgrammerson",
'address1' => "222 W. Merchandise Mart Plaza",
'address2' => "12th Floor",
'city' => "Chicago",
'state' => "IL",
'zip' => "60654"
}
# Hint: First try doing it yourself by hand, and notice the steps you are taking. You will have to translate these instructions into Ruby.
# Solution:
# Now change the value of the key 'state' in the params hash to "WI" and run your code again.
# Your output should look like this:
# Your total with tax is $4219.776.
# Encapsulate your code in a method if you haven't already. The method should accept a cart array, a tax hash, and a customer hash as arguments.
# def # call it print_total()
# Your code goes here.
# end
# Now change the quantity of iMacs to 3 and run your method.
# print_total(shopping_cart, sales_tax, params)
# Notice the differences. What had to match with what, now that we moved the logic into a method?