Project Euler: Riddle 4 - What is my Ruby code doing? - ruby

I'm NOT asking for a solution to this riddle.
So, I'm working through the Project Euler problems using Ruby.
I made a palindrome checker with the following method:
def is_palindrome(n)
if n.to_s == n.to_s.reverse
true
else
false
end
end
Using this, I use the next method to try and find the largest palindrome made with two 3 digit numbers.
x = 999
y = 998
while y > 100
if is_palindrome(x * y) == true
puts (x * y)
else
x-=1
y-=1
end
end
The result is the terminal throws a complete fit and gets stuck on 289982 and has to be Ctrl+C'd for it to stop.
As I said, I'm not looking for a solution to this riddle, but I want to know what it is my code is doing for this to happen. I'm still learning so my code is likely to be rather ugly, so extra karma points to anyone that can help me out with this.

In case a palindrome is found, you don't decrement your variables. Since the variables remain the same, the same palindrome is found again. And so it goes...

Amadan's solved your problem, so I'll go for the extra karma points :)
First thing, you can just do if something instead of if something == true.
Also, you don't need to do
if something == something_else
true
else
false
end
because the == operator returns either true or false already, so your is_palindrome method could be as simple as
def is_palindrome(n)
n.to_s == n.to_s.reverse
end
Also, in Ruby, you will usually see methods like this one (a boolean check) named with a question mark at the end, because it's really like you're asking it a yes/no question! So usually you'd see that called is_palindrome?(n). Similar ones you might see elsewhere are Array#empty? and Hash#has_key?(k).

Not answering your question, but your use of booleans is horrendous. Remember boolean expressions return a boolean itself, you don't need another comparison. i.e.
def is_palindrome(n)
if n.to_s == n.to_s.reverse
true
else
false
end
end
Should be:
def is_palindrome(n)
n.to_s == n.to_s.reverse
end
And
while y > 100
if is_palindrome(x * y) == true
Should be
while y > 100
if is_palindrome(x * y)

Here's my solution:
# Find largest palindrome made from the product of two 3-digit numbers
largest = 0
for i in 100..999
for j in i..999
product = j*i
# Check for palindrome and determine largest
largest = product.to_s == product.to_s.reverse && product > largest ? product : largest
end
end
p largest

Related

Ruby and bignum issue with OSX terminal

I'm learning Ruby and am working through this problem on Project Euler. When I try to run my Ruby file through the terminal for the answer, it just stalls (no error message, but just comes up blank like its thinking). I'm assuming it's an issue with calculating such a large number. I tried copying and pasting my code into repl.it, but came up with this error message:
(eval):12: (eval):12: negative allocation size (or too big)
(NoMemoryError)
Is there any way around this through the terminal (or any other suggestions)? Thanks.
Edit (added in my code):
#3. Largest prime factor
#The prime factors of 13195 are 5, 7, 13 and 29.
#What is the largest prime factor of the number 600851475143 ?
def largest_prime(num)
all_primes = []
(2...num).each do |p|
if (num % p == 0) && (is_prime?(p))
all_primes << p
end
end
all_primes.sort!
puts all_primes.last
end
def is_prime?(number)
(2...number).each do |x|
if number % x == 0
return false
else
next
end
end
true
end
puts largest_prime(600851475143)
The idea behind Project Euler is to build effective algorithms, otherwise the execution will just take too much time or resources - this is your case. Take a look at primality_test wiki article and you'll understand, why you shouldn't check (2...number) and why (2..Math.sqrt(num)) is enough. I didn't run your code, but suggest you to improve your is_prime? method first of all(by the way, you shouldn't prefix your method names with is_ when you have question mark in the end):
def prime?(num)
return false if num == 0 || num == 1
(2..Math.sqrt(num).to_i).each do |i|
return false if num % i == 0
end
true
end
It isn't MOST effective way of prime numbers detection, but its one of the simplest and effective enough for your needs.

All possible products

I'm trying to find all possible product of two 3-digit numbers. When I work with small ranges, I'm able to get an output in short amount of time but when the ranges are big, it seems to take really long time. Is there any way to to shorten the time to get the result?
The problem I'm working on is:
"A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers."
a = []
for x in 100..999
for y in 100..999
num = (x * y)
unless a.include? num
a.push num
end
end
end
p a
This is going to compute 100 x 101 and 101 x 100 separately, even though they're not going to be pushed to the array since they're already in it.
I'm bad at math, but maybe every time x goes up, y's minimum range can go up since that one was just used? people who are better at math can tell me if this is going to start missing numbers.
z= 100
for x in 100..999
for y in z..999
num = (x * y)
unless a.include? num
a.push num
end
z = z+1
end
end
I think doing this might make the "unless a.include? num" line unnecessary, too.
Looking at your code a quick optimization you can make is to use a set rather than an array to store the already computed products.
Since a is an array, a.include?(num) will have to iterate through the entire list of elements before returning true / false.
If a were to be a set, a.include?(num) will return in sub linear time.
Example:
require 'set'
a = Set.new
for x in 100..999
for y in 100..999
num = (x * y)
unless a.include? num
a.add(num)
end
end
end
puts a.to_a.join(", ")
Moreover one of the nice properties of a set is that it only stores unique elements so the following would be equivalent:
require 'set'
a = Set.new
for x in 100..999
for y in 100..999
num = (x * y)
a.add(num)
end
end
puts a.to_a.join(", ")
What are you really trying to do, i.e. what is the original problem, and why do you need all of these products?
Are you printing every single one out? Is someone asking you for a concrete list of every single one?
If not, there is likely a better way to deal with this problem. For example, if all you wanted is to check if a number X will be an element in "that list of products", all you'd have to do is:
range = 100..999
range.any? { |i| range.include?(x / i) }

Idiomatic ruby code - simple for each casuing confusing for me [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
Im very new to ruby and cant determin if i am using the ruby language correctly. I want find out if any one of an array of numbers is divisible by another number. If so return that number otherwise, return 0.
def is_divisible(nums, n)
nums.each do |m|
if n % m == 0
return n
end
end
0
end
The function works correctly but there are a few aspects to it which i think are not idiomatic of ruby:
Should i check if nums is of a type that can be looped first or catch an exception (coming from php and python I know these think differently but cant tell with ruby yet)
Is there a more concise way to structure the loop and the 2 separate return values
Anything else that isnt correct with this code?
Here are my thoughts:
Naming: Predicate methods in Ruby are named predicate? and not is_predicate, so the name of your method should be divisible? … except that it isn't actually a predicate. It doesn't test whether a number is divisible by another number, rather it finds the first number in an Enumerable which is divisible by another number. That sentence almost sounds like a descriptive method name, doesn't it?
def find_first_divisible(nums, n)
nums.each do |m|
if n % m == 0
return n
end
end
0
end
Naming cont'd: We don't charge you for your characters. You can use more of them if you want ;-) nums is probably okay, n is on the fence, but what the heck is m? In fact, you have a bug there, which is caused precisely by you confusing n and m.
def find_first_divisible(numbers, divisor)
numbers.each do |n|
if n % divisor == 0
return n
end
end
0
end
Guard clauses: For cases like this, where you want to use return (or next) to break out early, I prefer to use a guard clause style of the form "do this if that":
def find_first_divisible(numbers, divisor)
numbers.each do |n|
return n if n % divisor == 0
end
0
end
One line blocks: In this case, the contents of the block are short enough to fit on one line, so I would do that. Note that there are two competing styles for block formatting: one says to always use do/end for multiline blocks and always use {/} for single line blocks. The other says to always use do/end for blocks which are used primarily for their side-effects ("imperative blocks") and {/} for blocks which are used primarily for their return value ("functional blocks"). I prefer the latter style.
def find_first_divisible(numbers, divisor)
numbers.each do |n| return n if n % divisor == 0 end
0
end
Descriptive methods:
def find_first_divisible(numbers, divisor)
numbers.each do |n| return n if (n % divisor).zero? end
0
end
Know the core and standard libraries: This is very important, you don't want to reinvent the wheel!
def find_first_divisible(numbers, divisor)
numbers.find {|n| (n % divisor).zero? } || 0
end
Note how I changed the block style: now we are interested in the return value, there are no side-effects.
Extract methods with meaningful names:
class Integer
def divisible_by?(n) (self % n).zero? end
end
def find_first_divisible(numbers, divisor)
numbers.find {|n| n.divisible_by?(divisor) } || 0
end
Now, the method reads exactly like your description in the question: "within numbers, find the first n which is divisible_by the divisor, and if there is none, the result is 0".
Respect conventions: Last but not least, you should respect the conventions of the community. Methods that search for something should return nil to indicate the absence of a result:
def find_first_divisible(numbers, divisor)
numbers.find {|n| n.divisible_by?(divisor) }
end
Firstly, you should post questions like that to CodeReview SE page. Now to your questions:
It is typical for ruby not to do this to allow duck typing. Rubbyist assumes that programmers are intelligent enough not to call is_divisible method on strings.
Ruby comes with extended Enumerable module which I strongly reccommend to get familiar with: ruby-doc.org/core-2.0.0/Enumerable.html. There is for example method find which will do exactly what you need:
def is_divisible(num, n)
num.find{|number| number % n == 0} || 0
end
Your code seems all right, however I would reconsider its name - i would expect it to return true or false rather than first divisible number. Also when you use simple conditionals to execute just one line use it like:
return n if n % m == 0
You can use similar rules to do end and {} blocks:
nums.each {|m| return n if n % m == 0 }
0
Ruby core Array class contains many useful features, that query and/or re-structure arrays in generic ways when given a block that defines what you are interested in.
Taking your written description:
I want find out if any one of an array of numbers is divisible by another number.
If so return that number otherwise, return 0.
You could do this:
def is_divisible( nums, n )
nums.find { |x| x % n == 0 } || 0
end
using the built-in Array#find method.
However, it would not usually be idiomatic Ruby to return a 0 when you don't have a match. How would you differentiate between a list which contains 0 and the default? So usually I would structure the code like this:
def find_first_divisible( nums, n )
nums.find { |x| x % n == 0 }
end
# If you really need default 0 for no match:
result = find_first_divisible( my_nums, divisor ) || 0
Also the method has become so trivial, and understanding .find statements is easy (compared to looking up definition of a custom method), that I probably would not create a method here unless it was being called in multiple places. That's a personal choice.
For checking types, I tend to do that defensively in factory methods and/or initialize, and not so much elsewhere. That's a more complex discussion though - whole books could be written on typing systems, approaches to validation and testing, and how different languages lend themselves to different approaches.

How can I test if a value is a prime number in Ruby? Both the easy and the hard way?

I am trying to create a program that will test whether a value is prime, but I don't know how. This is my code:
class DetermineIfPrime
def initialize (nth_value)
#nth_value = nth_value
primetest
end
def primetest
if Prime.prime?(#nth_value)
puts ("#{#nth_value} is prime")
else
puts ("This is not a prime number.")
end
rescue Exception
puts ("#{$!.class}")
puts ("#{$!}")
end
end
And every time I run that it returns this.
NameError
uninitialized constant DetermineIfPrime::Prime
I tried other ways to do the job, but I think this is the closest I can get.
I also tried this:
class DetermineIfPrime
def initialize (nth_value)
#nth_value = nth_value
primetest
end
def primetest
for test_value in [2, 3, 5, 7, 9, 11, 13] do
if (#nth_value % test_value) == 0
puts ("#{#nth_value} is not divisible by #{test_value}")
else
puts ("This is not a prime number since this is divisible by #{test_value}")
break
end
end
end
end
Or am I just doing something wrong?
Ruby has built in method to check if number is prime or not.
require 'prime'
Prime.prime?(2) #=> true
Prime.prime?(4) #=> false
def is_prime?(num)
return false if num <= 1
Math.sqrt(num).to_i.downto(2).each {|i| return false if num % i == 0}
true
end
First, we check for 0 and 1, as they're not prime. Then we basically just check every number less than num to see if it divides. However, as explained here, for every factor greater than the square root of num, there's one that's less, so we only look between 2 and the square root.
Update
def is_prime?(num)
return if num <= 1
(2..Math.sqrt(num)).none? { |i| (num % i).zero? }
end
The error you are getting is because you haven't required Primein your code, You need to do require Prime in your file.
One cool way I found here, to check whether a number is prime or not is following:
class Fixnum
def prime?
('1' * self) !~ /^1?$|^(11+?)\1+$/
end
end
10.prime?
From an algorithmic standpoint, checking if a number is prime can be done by checking all numbers up to and including (rounding down to previous integer) said number's square root.
For example, checking if 100 is prime involves checking everything up to 10.
Checking 99 means only going to 9.
** Another way to think about it **
Each factor has a pair (3 is a factor of 36, and 3's pair is 12).
The pair is on the other side of the square root (square root of 6 is 36, 3 < 6, 12 > 6).
So by checking everything until the square root (and not going over) ensures you check all possible factors.
You can make it quicker by having a list of prime numbers to compare, as you are doing. If you have a maximum limit that's reasonably small, you could just have a list of primes and do a direct lookup to see if that number is prime.
def is_prime?(num)
Math.sqrt(num).floor.downto(2).each {|i| return false if num % i == 0}
true
end
lol sorry for resurrecting a super old questions, but it's the first one that came up in google.
Basically, it loops through possible divisors, using the square root as the max number to check to save time on very large numbers.
In response to your question, while you can approach the problem by using Ruby's Prime I am going to write code to answer it on its own.
Consider that all you need to do is determine a factor that is smaller than the integer's square root. Any number larger than the integer's square root as a factor requires a second factor to render the number as the product. (e.g. square root of 15 is approx 3.8 so if you find 5 as a factor it is only a factor with the factor pair 3 and 5!!)
def isPrime?(num)
(2..Math.sqrt(num)).each { |i| return false if num % i == 0}
true
end
Hope that helps!!
(To first answer the question: yes, you are doing something wrong. As BLUEPIXY mentions, you need to put require 'prime' somewhere above the line that calls Prime.prime?. Typically on line 1.)
Now, a lot of answers have been given that don't use Prime.prime?, and I thought it might be interesting to benchmark some of them, along with a possible improvement of my own that I had in mind.
###TL;DR
I benchmarked several solutions, including a couple of my own; using a while loop and skipping even numbers performs best.
Methods tested
Here are the methods I used from the answers:
require 'prime'
def prime1?(num)
return if num <= 1
(2..Math.sqrt(num)).none? { |i| (num % i).zero? }
end
def prime2?(num)
return false if num <= 1
Math.sqrt(num).to_i.downto(2) {|i| return false if num % i == 0}
true
end
def prime3?(num)
Prime.prime?(num)
end
def prime4?(num)
('1' * num) !~ /^1?$|^(11+?)\1+$/
end
prime1? is AndreiMotinga's updated version. prime2? is his original version (with the superfluous each method removed). prime3? is Reboot's, using prime library. prime4? is Saurabh's regex version (minus the Fixnum monkey-patch).
A couple more methods to test
The improvement I had in mind was to leverage the fact that even numbers can't be prime, and leave them out of the iteration loop. So, this method uses the #step method to iterate over only odd numbers, starting with 3:
def prime5?(num)
return true if num == 2
return false if num <= 1 || num.even?
3.step(Math.sqrt(num).floor, 2) { |i| return false if (num % i).zero? }
true
end
I thought as well that it might be interesting to see how a "primitive" implementation of the same algorithm, using a while loop, might perform. So, here's one:
def prime6?(num)
return true if num == 2
return false if num <= 1 || num.even?
i = 3
top = Math.sqrt(num).floor
loop do
return false if (num % i).zero?
i += 2
break if i > top
end
true
end
Benchmarks
I did a simple benchmark on each of these, timing a call to each method with the prime number 67,280,421,310,721. For example:
start = Time.now
prime1? 67280421310721
puts "prime1? #{Time.now - start}"
start = Time.now
prime2? 67280421310721
puts "prime2? #{Time.now - start}"
# etc.
As I suspected I would have to do, I canceled prime4? after about 60 seconds. Presumably, it takes quite a bit longer than 60 seconds to assign north of 6.7 trillion '1''s to memory, and then apply a regex filter to the result — assuming it's possible on a given machine to allocate the necessary memory in the first place. (On mine, it would seem that there isn't: I went into irb, put in '1' * 67280421310721, made and ate dinner, came back to the computer, and found Killed: 9 as the response. That looks like a SignalException raised when the process got killed.)
The other results are:
prime1? 3.085434
prime2? 1.149405
prime3? 1.236517
prime5? 0.748564
prime6? 0.377235
Some (tentative) conclusions
I suppose that isn't really surprising that the primitive solution with the while loop is fastest, since it's probably closer than the others to what's going on under the hood. It is a bit surprising that it's three times faster than Prime.prime?, though. (After looking at the source code in the doc it is less so. There are lots of bells and whistles in the Prime object.)
AndreiMotinga's updated version is nearly three times as slow as his original, which suggests that the #none? method isn't much of a performer, at least in this context.
Finally, the regex version might be cool, but it certainly doesn't appear to have much practical value, and using it in a monkey-patch of a core class looks like something to avoid entirely.
If you are going to use any Prime functions you must include the Prime library. This problem can be solved without the use of the prime library however.
def isPrime?(num)
(2..Math.sqrt(num)).each { |i|
if num % i == 0 && i < num
return false
end
}
true
end
Something like this would work.
Try this
def prime?(num)
2.upto(Math.sqrt(num).ceil) do |i|
break if num%i==0
return true if i==Math.sqrt(num).ceil
end
return false
end
So most of the answers here are doing the same thing in slightly different ways which is one of the cool things about Ruby, but I'm a pretty new student (which is why I was looking this up in the first place) and so here's my version with comment explanations in the code:
def isprime n # starting with 2 because testing for a prime means you don't want to test division by 1
2.upto(Math.sqrt(n)) do |x| # testing up to the square root of the number because going past there is excessive
if n % x == 0
# n is the number being called from the program
# x is the number we're dividing by, counting from 2 up to the square root of the number
return false # this means the number is not prime
else
return true # this means the number is prime
end
end
end

Ruby -If-Else Statement (Triangle Test)

The question is Create a function that takes three numbers as input and returns true or false depending on whether those three numbers can form a triangle. Three numbers can form a triangle if the sum of any two sides is greater than the third side.
my answer is:
def is_triangle(a,b,c)
if a+b > c
return true
elsif a+c>b
return true
elsif b+c>a
return true
else
return false
end
end
the thing is: my supposed false return keeps returning true. please help!
This logic should work for finding your triangle
def is_triangle?(a,b,c)
sorted = [a,b,c].sort
greatest_side = sorted.pop
greatest_side < sorted.sum
end
Yet another approach:
def is_triangle?(a,b,c)
[a,b,c].max < [a,b,c].sum/2.0
end
Or for Ruby outside of Rails:
def is_triangle?(a,b,c)
[a,b,c].max < [a,b,c].inject(:+)/2.0
end
Your problem is that unless all 3 numbers are 0 one of your ifs will always be true. What you want is something more like
def is_triangle(a,b,c)
a + b > c && a + c > b && b + c > a
end
is_triangle(3,6,8) #=> true
is_triangle(3,6,80) #=> false
Nothing you pass into this is going to return false. Your method is wrong.
You can tell if three sides make a triangle by finding the longest side and then adding the remaining two sides. If they are greater than the longest side, then the sides can make a traingle.
I suggest if you are sure your logic is correct change the method to
def is_triangle?(a, b, c)
a+b > c or b+c > a or c+a > b
end
But according to me it is not so the method should be
def is_triangle?(a, b, c)
a+b>c and b+c>a and c+a>b
end
Some points to note about ruby conventions:
Method which returns boolean ends with '?'
A ruby method returns the last evaluated expression, so writing return is redundant here.
puts " enter a, b and c values"
a=gets.to_i
b=gets.to_i
c=gets.to_i
if a+b > c
print true
elsif a+c>b
print true
elsif b+c>a
print true
else
print false
end
you can also use this code too.. this is much easy
This is also a solution to this problem :
if 2*[a,b,c].max < a + b + c
true
else
false
end
There are a variety of different inequalities theoretically possible:
http://en.wikipedia.org/wiki/Triangle_inequality

Resources