1

I have to create the following pattern:

*
**
***
****
*****

Using a ARGV and this is what I have so far:

height = ARGV[0]
output = ""


height.to_i.times do |i|
  output << "*" * i
  output << "\n"
end
puts output

But every time I run ruby pyramid.rb 5 on my mac terminal, I get the following output:

$ ruby pyramid.rb 5

*
**
***
****

Why is it giving me 4 when it needs to have 5 of them?

Stefan
  • 109,145
  • 14
  • 143
  • 218
jBntz
  • 11
  • 1
  • 1
    I've edited the output - note the empty line? That's `"*" * 0`, as describe in [Chris Schmich's answer](http://stackoverflow.com/a/32751643/477037) – Stefan Sep 24 '15 at 06:53

3 Answers3

4

Integer#times yields values from 0 to n-1, so you're getting lines of 0 up to 4 stars.

You mentioned this was an exercise, so I'll leave the fix up to you.

In general, to troubleshoot these kinds of problems, it's best to use a debugger or add diagnostic printing (e.g. puts statements) to trace the values of variables and ensure they're what you expected.

For example, in this case, you could add puts i inside your loop to see what the value of i is at every iteration. You would see something like 0 1 2 3 4 printed, which isn't what you expected. From there, you can look at your code, documentation, or add more diagnostic output to determine why you get those values.

Community
  • 1
  • 1
Chris Schmich
  • 29,128
  • 5
  • 77
  • 94
  • Thanks for the reply and explanation. Yes, its an exercise done from the beginning. Our only instruction was that we needed to use `height = ARGV` and `output = ""` as our variables. Still scratching my head on how to get that final piece that I am missing. – jBntz Sep 24 '15 at 01:51
  • 1
    There are a couple approaches: 1) What would you need to do to `i` in your loop to have it be `1` to `5` instead of `0` to `4` as it is now? or 2) Consider looking at the [upto](http://ruby-doc.org/core-2.2.0/Integer.html#method-i-upto) method and how you could use that here – Chris Schmich Sep 24 '15 at 04:00
0

I know this thread is old but I felt it's better late than never. Chris hinted at the solution. If i is starting from zero, you just have to make it so that i starts from 1 by simple adding i += 1. see example below:

height = ARGV[0]
output = ""
height.to_i.times do |i|
  i += 1
  output << "*" * i
  output << "\n"
end
puts output
0

Analysis

The problem in your code is the use of Integer#times. Per the documentation, the #times method:

[i]terates the given block int times, passing in values from zero to int - 1.

So, here is your given code, with comments:

height.to_i.times do |i| # when `height = 5`, equivalent to `(0..4).each`
  output << "*" * i      # will be "" on the first pass when i == 0
  output << "\n"
end

Solution

In this case, you should use the Integer#upto method instead of Integer#times, with 1 as your starting value. Consider the following example, rewritten as a one-liner you can run from the command prompt:

$ ruby -e '1.upto(Integer(ARGV[0])) { |i| puts "*" * i }' 5
*
**
***
****
*****

In addition to giving the expected results on standard output, it also does away with string mutation, declaring an output variable, and other non-essentials. The use of Kernel#Integer will also raise an exception if ARGV[0] can't be cast as an integer, rather introducing subtle bugs such as when ARGV[0] == "".

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199