Why does my iterator give wrong value? - ruby

I am expecting to print each number, not just one big value. This is my code:
i = 20
loop {
i -= 1
print i
break if i <= 0
}
# >> 191817161514131211109876543210
I have tried:
printing just i
switching braces with do and end
changing the value of i

puts adds a new line after each argument passed to it (unless there's already a newline ending the arg).
print does not add a new line.
Therefore, you need to switch to puts:
i = 20
loop {
i -= 1
puts i
break if i <= 0
}
This is roughly equivalent to using the following code:
i = 20
loop {
i -= 1
print "i\n"
break if i <= 0
}
\n is the newline character:
\n Insert a newline in the text at this point.
Here's an example of passing multiple args to a puts statement, to really simplify your code:
puts *(0..20)
Or, in the reverse order you're using:
puts *19.downto(0)
This uses the splat operator to send the range as arguments to puts, giving you the output you're after,
Hope this helps - let me know if you've any questions.

You are using print which will print lines to the console without the \n at the end.
change print to puts.

as you already got your solution, you need to replace print with puts. I am showing you an alternate solution to get the same output:
puts (0..20).to_a.reverse
OR
(0..20).to_a.reverse.each{|i| puts i}
Output:
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0

Related

Difference between `while ... end` and `while ... do ... end`

What's the difference between:
x = 1
while x < 5 do
x += 1
print x
end
and:
x = 1
while x < 5
x += 1
print x
end
whereby do is added to the first one? Or, is there difference?
There is no difference when you include the newline between the while loop declaration and the code. So:
while flag
#code here
end
is the same as:
while flag do
#code here
end
However, when you include do, you can put code on the same line, as in:
while flag do myMethod() end
It is just used to separate the actual loop code.
A while loop's conditional is separated from code by the reserved word
do, a newline, backslash \, or a semicolon ;.
https://www.tutorialspoint.com/ruby/ruby_loops.htm

Ruby doesn't read carriage return (\r) in output? [duplicate]

This question already has an answer here:
Ruby outputting to the same line as the previous output
(1 answer)
Closed 8 years ago.
in ruby, how do I make my output (via puts method) on one line, as opposed to line after line, and my console being flooded with output. Basically I want the output to continuously update on one line, and keep writing over the last output. I tried doing a '\r' character at the end of the string, but ruby just ignores it and keeps printing the output of my while loop line after line:
i=0
while i<90
puts "#{i} matt lao \r"
i+=1
end
I just want one continuously updated line. Thank you.
puts will always print a new line at the end, so it's doing your carriage return but then a new line after that. Use print instead.
90.times { |i| print "#{i} matt lao \r" }
To see it's actually doing the right thing, you can stick in a sleep:
90.times { |i| print "#{i} matt lao \r"; sleep 0.01 }
You could use print without any carriage return which will work just fine.
like this
2.1.1 :016 > 0.upto(4){|i| print "#{i} "}
0 1 2 3 4 => 0
puts automatically appends a new line whereas print doesn't.
You need to use print instead of puts.
For example:
90.times do |i|
print "#{i} matt lao \r"; sleep 0.02
end

Regex for a number 1-31 Ruby

I am trying to match any number 1-31 (inclusively).
This is the closest I have:
([1-9]|[12]\d|3[01])
But numbers like 324 are accepted.
Any chance there's a regex out there that can capture just 1-31?
The following regex satisfies your condition:
^([1-9]|[12][0-9]|3[01])$
Demo here
Use a Numeric Comparison Instead
Depending on what you are really trying to do, or to communicate with your code, it may make more sense to simply extract all integers and reject those outside your desired range. For example:
str = '0 1 20 31 324'
str.scan(/\d+/).map(&:to_i).reject { |i| i < 1 or i > 31 }
#=> [1, 20, 31]
Try with this one:/^([0-9]|1[0-9]|2[0-9]|3[01])$/
Here an example:
str = STDIN.gets.chomp
if str =~ /^([0-9]|1[0-9]|2[0-9]|3[01])$/
puts "Match!"
else
puts "No match!"
end
Here's one:
/^(#{(1..31).to_a * '|'})$/
#=> /^(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)$/

Loop won't break and string won't capitalize properly?

I am trying to get a simple Ruby program to run correctly.
I need it to take user input until the user types q for "quit". It also needs to capitalize the last four letters of the users input and, with input under four letters, to capitalize all letters.
It only works for input over four letters, and, when I type "quit", it gets a nil error.
See the code below.
I am using Eclipse with Ruby 2.0.
puts ("\n" * 10)
loop do
puts "Please enter a word. (To quit type q.)" # Gets the users input
puts ("\n" * 3) #Scroll the screen 3 times
str = gets.chomp #Collect the player's response
puts ("\n" * 3) #Scroll the screen 3 times
length = str.length # Counts length of string
str = str[0..(length-5)] + str[(length-4)..length].upcase # Only makes last four letters of user input capitalized
puts str # Shows on screen the user input with capitalized last four letters
puts ("\n" * 3) #Scroll the screen 3 times
break if str == "q"
end
You need to pay attention to [] when you write code like this:
str = str[0..(length-5)] + str[(length-4)..length].upcase
If an index is negative, it is counted from the end of string. For example:
str = "abcde"
str[-1] # => "e"
str[-2] #=> "d"
See String.[] for more details.
With regard to your question, here is my logic:
break if str == "q"
if str.length < 4
str = str.upcase
else
str = str[0...-4] + str[-4..-1].upcase
end
p str
You need to do some checks on your length. If length is less than 4, than length - 5 will return a negative number and your
str[0..(length-5)] + ...
line will be upset. For example. If you type "str", then your code will try to do:
length = 3
str[0..-2] + str[-1..3]
which doesn't make sense. Also, since you check for str == "q" at the end, this is likely also happening for "q". Move your check and break up in the block, and make sure you don't treat all strings as if they're going to be longer than 4 characters.

Checking string with minimum 8 digits using regex

I have regex as follows:
/^(\d|-|\(|\)|\+|\s){12,}$/
This will allow digits, (, ), space. But I want to ensure string contains atleast 8 digits.
Some allowed strings are as follows:
(1323 ++24)233
24243434 43
++++43435++4554345 434
It should not allow strings like:
((((((1213)))
++++232+++
Use Look ahead within your regex at the start..
/^(?=(.*\d){8,})[\d\(\)\s+-]{8,}$/
---------------
|
|->this would check for 8 or more digits
(?=(.*\d){8,}) is zero width look ahead that checks for 0 to many character (i.e .*) followed by a digit (i.e \d) 8 to many times (i.e.{8,0})
(?=) is called zero width because it doesnt consume the characters..it just checks
To restict it to 14 digits you can do
/^(?=([^\d]*\d){8,14}[^\d]*$)[\d\(\)\s+-]{8,}$/
try it here
Here's a non regular expression solution
numbers = ["(1323 ++24)233", "24243434 43" , "++++43435++4554345 434", "123 456_7"]
numbers.each do |number|
count = 0
number.each_char do |char|
count += 1 if char.to_i.to_s == char
break if count > 7
end
puts "#{count > 7}"
end
No need to mention ^, $, or the "or more" part of {8,}, or {12,}, which is unclear where it comes from.
The following makes the intention transparent.
r = /
(?=(?:.*\d){8}) # First condition: Eight digits
(?!.*[^-\d()+\s]) # Second condition: Characters other than `[-\d()+\s]` should not be included.
/x
resulting in:
"(1323 ++24)233" =~ r #=> 0
"24243434 43" =~ r #=> 0
"++++43435++4554345 434" =~ r #=> 0
"((((((1213)))" =~ r #=> nil
"++++232+++" =~ r #=> nil

Resources