Pushing numbers onto an array in Ruby - ruby

I'm trying to create a program outputting each number and whether it is divisible by numbers 2-9. I'm doing this by iterating over 2-9 and pushing each number onto an array, however, an error shows up when compiling:
/Users/XXX/XXX/XXX/XXX.rb:3: warning: already initialized constant ArrayOfMultiples
How do I remove this error?
Here is my code:
(1..200).each do |number|
output_str = ""
ArrayOfMultiples = Array.new
(2..9).each do |multiple|
if number%multiple == 0
ArrayOfMultiples.push(multiple)
end
end
output_str = number.to_s + " is divisble by " + ArrayOfMultiples.join(", ")
puts output_str
end

Start your variable with lower case, otherwise it is considered a constant. If you reinitialize a constant, you get that warning.
arrayOfMultiples
A simple program like the following can demonstrate this behaviour:
A = 1
A = 2
When you run the above script, it says:
test.rb:2: warning: already initialized constant A
test.rb:1: warning: previous definition of A was here

You could also make this a lot simpler:
(1..200).each do |x|
divisible_by = (2..9).select {|y| x%y==0}
puts "#{x}: #{divisible_by.join(", ")}"
end

Related

Codility error: Invalid result type, Integer expected, NilClass found

EDIT: SOLVED BY STEFAN
BUT: Now, the only questions left are: Why has the shorter solution such a poor performance (results: 100%, performance: 32%, result: 66%) , while the longer version performs a bit better but seems to produce worse results (60%, 50%, 55%)?
Start of original question:
I'm currently trying the Codility demo test and the problem to solve is to find the lowest integer above 0 that's not included in a given array.
This is my code in two different versions with the same result. The output is right but the compiler throws the abovementioned error, resulting in the test failing. This seems to be a common error on Codility, when looking up this error here on SO.
# you can write to stdout for debugging purposes, e.g.
# puts "this is a debug message"
def solution(a)
# write your code in Ruby 2.2
num = 1
a=a.sort
a.uniq!
a.each do |x|
if x == num then
num += 1
next
else
break
end
end
puts num
end
or
def solution(a)
# write your code in Ruby 2.2
num = 1
while a.include?(num) do
num += 1
end
puts num
end
results in:
Compilation successful.
Example test: [1, 3, 6, 4, 1, 2]
Output (stderr):
Invalid result type, Integer expected, NilClass found
Output:
5
RUNTIME ERROR (tested program terminated with exit code 1)
Example test: [1, 2, 3]
Output (stderr):
Invalid result type, Integer expected, NilClass found
Output:
4
RUNTIME ERROR (tested program terminated with exit code 1)
Example test: [-1, -3]
Output (stderr):
Invalid result type, Integer expected, NilClass found
Output:
1
RUNTIME ERROR (tested program terminated with exit code 1)
Producing output might cause your solution to fail performance tests.
You should remove code that produces output before you submit your solution.
Detected some errors.
I really don't understand what's wrong. The array only contains integers, num is an integer, everything is an integer but the compiler says it's NIL. What can I do?
EDIT: The same code runs without errors in the SoloLearn app and on my local machine.
The output is right but the compiler throws the abovementioned error, resulting in the test failing
Although puts generates output it has a return value of nil:
puts 123
# 123 # <- output
#=> nil # <- return value
I assume that your method is supposed to return the value instead just printing it to standard out.
You can fix this by removing puts in your method's last line:
def solution(a)
num = 1
while a.include?(num)
num += 1
end
num # <- without "puts"
end
To generate debug output you could add puts num on a separate line before the return value, e.g.:
def solution(a)
# ...
puts num # <- prints num
num # <- returns num
end
or you could use p which outputs the object's inspect value and returns the object:
def solution(a)
# ...
p num # <- prints num.inspect and returns num
end
Regarding the performance: try to understand what the code has to do in order to get the result. The "short" solution increments num and checks whether it is included in the array. But an inclusion check has to traverse the array (at least up to the matching element). So for each increment of num, you are traversing the array from the beginning.
You can speed this up significantly by utilizing Set for the lookup:
require 'set'
def solution(a)
set = Set.new(a)
num = 1
num += 1 while set.include?(num)
num
end
def solution(a)
range = (1..a.max).to_a
(range - a).first
end
If you are printing within the code just remove that lines
for Ex in Javascript remove used console.log

How to do a simple test in ruby

I have some code below that gives square numbers. I also wrote a simple test that prints true or false.
numbers = (1..20)
test=numbers.each do |number|
puts number * number
end
puts test == [1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400]
I expect it to print true, but it puts false.
I was wondering if anyone could help to see why.
Try below code to get your answer :
numbers = (1..20)
test = numbers.map{|a| a*a}
puts test == [1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,256,289,324,361,400]
You are using first test which contents 1..20. So you have to modify your code.
In your code numbers.each do |number| .. end returns the range (1..20) and that's the value that test will be assigned to after the loop through numbers is done. So even if you deleted the line puts number* number, test will still have the value (1..20). So using map would be the right choice to keep your values in an array. But you should first delete puts, because it shows the value on the screen but returns nil. So if you used map but didn't delete puts test will be assigned to an array of nils.

How to optimize code removing unwanted characters

This code is designed for a problem where the users computer has a bug where every time he/she hits the backspace button it displays a '<' symbol. The created program should fix this and output the intended string considering that '<' represents a backspace. The input string can be up to 10^6 characters long, and it only will include lowercase letters and '<'.
My code seems to be executing correctly but, when I submit it, the website says it exceeded the time limit for test 5/25. The amount of time given is 1 second. Also, if there are only '<' symbols it should produce no output.
For example,
"hellooo<< my name is matthe<<"
would output
"hello my name is matt"
and
"ssadfas<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
would output nothing, etc.
Here is the code:
input = gets.chomp
while input[/[[:lower:]]</]
input.gsub!(/[[:lower:]]</, "")
end
input.gsub!(/</, "")
puts"#{input}"
In the code above I stay in the while loop if there are any instances where a lowercase letter is in front of a '<'. Anywhere a lowercase letter is followed by a '<' it is replaced with nothing. Once the while loop is exited if there are any '<' symbols left, they are replaced with nothing. Then the final string is displayed.
I created a test which I think is worst case scenario for my code:
input = ("a" + "<" + "a")*10000000
#input = gets.chomp
while input[/[[:lower:]]</]
input.gsub!(/[[:lower:]]</, "")
end
input.gsub!(/</, "")
puts"#{input}"
I made the program stop between the creation of the string and the execution of the while loop and then ran it completely to be able to eyeball if it was taking longer than a second. It seemed to take much longer than 1 second.
How can it be modified to be faster or is there a much better way to do this?
Your approach is good but you get better performance if you adapt the regular expression.
Cary, I hope you don't mind I take your excellent solution also in the benchmark ?
Benchmark done on a MRI ruby 2.3.0p0 (2015-12-25 revision 53290) [x64-mingw32]
I use .dup on my sample string to make sure none of the methods changes the input sample.
require 'benchmark'
input = ""
10_000_000.times{input << ['a','<'].sample}
def original_method inp
while inp[/[[:lower:]]</]
inp.gsub!(/[[:lower:]]</, "")
end
inp.gsub(/</, "")
end
def better_method inp
tuple = /[^<]</
while inp[tuple]
inp.gsub!(inp[tuple], "")
end
inp.gsub(/</, "")
end
def backspace str
bs_count = 0
str.reverse.each_char.with_object([]) do |s, arr|
if s == '<'
bs_count += 1
else
bs_count.zero? ? arr.unshift(s) : bs_count -= 1
end
end.join
end
puts original_method(input.dup).length
puts better_method(input.dup).length
puts backspace(input.dup).length
Benchmark.bm do |x|
x.report("original_method") { original_method(input.dup) }
x.report("backspace ") { backspace(input.dup) }
x.report("better_method ") { better_method(input.dup) }
end
gives
3640
3640
3640
user system total real
original_method 3.494000 0.016000 3.510000 ( 3.510709)
backspace 1.872000 0.000000 1.872000 ( 1.862550)
better_method 1.155000 0.031000 1.186000 ( 1.187495)
def backspace(str)
bs_count = 0
str.reverse.each_char.with_object([]) do |s, arr|
if s == '<'
bs_count += 1
else
bs_count.zero? ? arr.unshift(s) : bs_count -= 1
end
end.join
end
backspace "Now is the<< tim<e fo<<<r every<<<one to chill ou<<<<t"
#=> "Now is t tier evone to chilt"

Simple Ruby Input Scraper

I'm completely new to ruby and wanted to ask for some help with this ruby script.
it's supposed to take in a string and find out which character occurs the most frequently. It does this using a hash, it stores all the characters in a hash and then iterates through it to find the one with greatest value. As of right now it doesn't seem to be working properly and i'm not sure why. It reads the characters in properly as far as i can tell with print statements. Any help is appreciated.
Thanks!
puts "Enter the string you want to search "
input = gets.chomp
charHash = Hash.new
input.split("").each do |i|
if charHash.has_key?(i)
puts "incrementing"
charHash[i]+=1
else
puts"storing"
charHash.store(i, 1)
end
end
goc = ""
max = 0
charHash.each { |key,value| goc = key if value > max }
puts "The character #{goc} occurs the most frequently"
There are two major issues with you code:
As commented by Holger Just, you have to use += 1 instead of ++
charHash.store(:i, 1) stores the symbol :i, you want to store i
Fixing these results in a working code (I'm using snake_case here):
char_hash = Hash.new
input.split("").each do |i|
if char_hash.has_key?(i)
char_hash[i] += 1
else
char_hash.store(i, 1)
end
end
You can omit the condition by using 0 as your default hash value and you can replace split("").each with each_char:
char_hash = Hash.new(0)
input.each_char do |i|
char_hash[i] += 1
end
Finally, you can pass the hash into the loop using Enumerator#with_object:
char_hash = input.each_char.with_object(Hash.new(0)) { |i, h| h[i] += 1 }
I might be missing something but it seems that instead of
charHash.each { |key,value| goc = key if value > max }
you need something like
charHash.each do |key,value|
if value > max then
max = value
goc = key
end
end
Notice the max = value statement. In your current implementation (i.e. without updating the max variable), every character that appears in the text at least once satisfies the condition and you end up getting the last one.

Mysterious error with beginner's ruby code (while loops)

So this is my code. I'm learning while loops and not sure why this doesn't work. I'm getting an error.
i = 0
numbers = []
def while_var(x)
while i < #{x}
print "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
while_var(6)
puts "Want to see all the entries of the numbers array individually (i.e. not in array format)? Here you go!"
for num in numbers
puts num
end
puts "1337"
This is my error
1.rb:5: syntax error, unexpected tSTRING_BEG, expecting keyword_do or '{' or '('
print "Entry #{i}: i is now #{i}."
^
I have no idea what this is all about. Thanks.
EDIT
So I have this revised code
def while_var(x)
i = 0
numbers = []
while i < x
print "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
puts "next part"
for num in numbers
puts num
end
end
while_var(6)
It works when I type it line-by-line into irb, but not when I run the file with ruby. What gives? I'm getting this error:
Entry 0: i is now 0.1.rb:8:in `while_var': undefined method `push' for nil:NilClass (NoMethodError)
from 1.rb:23:in `<main>'
EDIT : Figured it out. All I had to do was change the "print" to "puts" for some reason.
Here is the fixed code :
def while_var(x)
i = 0
numbers = []
while i < x
print "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
end
You did several mistakes :
You forgot to close the while loop.
You used #{x} which is not correct syntax for interpolation,But you don't need interpolation here. make it only x.
Inside the method two local variables i and numbers can't be used,as they have created at the top level. So you need to create those variables locally inside the method.
This code should work:
def while_var(x)
i = 0
numbers = []
while i < x
puts "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
numbers
end
numbers = while_var(6)
puts "Want to see all the entries of the numbers array individually (i.e. not in array format)? Here you go!"
for num in numbers
puts num
end
I hope it does what you wanted to achieve.
You should use puts to print something to console. And move i and numbers variables to while_var method.

Resources