Screw diamonds. Ruby is a girl's best friend.

Surfing the waters of programming

Ruby Exercise 1: Triangle of Numbers

| Comments

Fun exercise that will allow you to practice iteration and loops as well as look into ARGV in Ruby. I will include my detailed logic how I came to resolve this issue because I find it most helpful when learning new concepts in any language to see all nuts and bolts that went into it.

Assignment:
Create an application that will take a number in Terminal and output the same number of lines with the same number of digits in each line. Note: elements continue to grow in order.

Enter in terminal:

1
$ ruby triangle.rb 4

Expected result:

1
2
3
4
1
2 3
4 5 6
7 8 9 10

If you don’t need a full step-by-step explanation of this exercise, please scroll to the bottom of this page for final solution.

Being yet a newbie, I quickly have found myself struggling with logic of this application. Obviously, you need to loop through the numbers but where do you ensure that the first element of the next line is the next element in the original array.

Quick sketch on paper and it becomes visible that we are dealing with two elements: One (we’ll call it number) is responsible for line number and number of displayed elements. And another one (order) that is responsible for the location of the next element that will be displayed.

1
2
3
4
#1 // 1
#2 // 2 3
#3 // 4 5 6
#4 // 7 8 9 10

We are working with an array[1, 2, 3, 4, 5, 6, 7 .. n] orarray[1..n]. Keeping in mind that we start counting elements in an array from 0, let’s quickly write the logic:

When we need to show one number on first row: number = 1, position of this element order = 0
Second row, two numbers, number = 2, position in an array order = 1
Third row, three numbers, number = 3, order = 3
Fourth row, four number, number = 4, order = 6

It becomes a little more clear that in order to find our next order element we need to add the value of the number to previous order element.

1
2
3
4
5
order = 1              # we have to set default value for order
(1..n).each do |number|
  number               # number will grow continuously from 1 to finite number n
end
order += number      # order will grow proportionally to the increase in value of number    

Great.
Now, let’s look into ARGV. We can pass arguments to our ruby program from command line of our terminal. Will look something like this:

1
$ ruby triangle.rb 4

We are asking our terminal to run file triangle.rb with ruby while passing the value 4 to the application. ARGV’s responsibility is to accept given arguments and make them available within our application.
Your goal is to provide a place for these values and ensure its correct format.

While testing the format of my argument, I found that 4 came into the application as an Array and I needed it to be an Integer so I could use it to set the limit of my array. There is no easy way to turn array to an integer(please leave comments if you have any suggestions), for the purpose of simplicity and my sanity:

1
limit = ARGV[0].to_i

This took an array of arguments that were passed from the terminal, picked the first value and turned it into an integer while saving it in a variable limit for future use.

Final solution:

1
2
3
4
5
6
7
8
9
array = (1..100000).to_a
order = 1
limit = ARGV[0].to_i

(1..limit).each do |number| 
  array[order - 1, number].each{|i| print "#{i} " }   # will print it in line
  order += number
  puts                                                # will print a break between your lines 
end

P.S. Note to anyone (and my future self) whoever laughs at how long it took me to solve this: @#%&@#$@#%@# you!

Now, that ARGV finally makes sense, I’m going to work on another interview exercise for one really awesome company in DC. As I was told on my first day @Flatironschool, “It will all make sense one day”

Comments