Puzzled over palindromic product problem
You are testing 999* (999...100), then 998 * (999...100)
Hence you will be testing 999 * 500 before you test 997 * 996.
So, how you we find that right number?
First note the multiplication is reflective, a * b == b * a, so b need not go from 999...0 every time, just a ...0.
When you find a palindrone, add the two factors together and save the sum (save the two factors also)
Inside the loop, if (a+b) is ever less than the saved sum, abandon the inner loop and move to the next a. When a falls below sum/2, no future value you could find would be higher than the one you've already found, so you're done.
Project Euler #4 with C#
Because once you do find a palindrome you are looping forever inside your while loop. Change the while to and if and it should work.
EDIT:
Yes, you will need to keep track of the largest product found so far, not simply assume the last product found is the largest.
Palindrome product
Try and think about what you are telling your code to do in plain english:
"Until x is a palindrome, do this doubly nested loop to completion"
The until loop is never breaking because it is FULLY running both loops BEFORE checking if x is a palindrome. The solution would be to instead break when you find a palindrome Try this:
999.downto(100) do |i|
i.downto(100) do |j|
x = i * j
break if x == x.to_s.reverse.to_i
puts "#{i} * #{j} = #{x}"
end
break if x == x.to_s.reverse.to_i
end
puts x
Ah but now we have arrived at another problem - looping in this way does not guarantee that the product will be the highest product. We can modify slightly to achieve this:palindromes = []
999.downto(100) do |i|
i.downto(100) do |j|
x = i * j
palindromes << x if x == x.to_s.reverse.to_i
end
end
puts palindromes.max
This probably isn't the best solution, but it works. All possible products
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(", ")
Haskell-Project Euler 4
The first big error is that you're calling
reverse (x * y)
Since x * y
is a number, and reverse
only works on lists, this won't compile. You can convert the number to a String
(which is a list) with show
:reverse $ show $ x * y
However, reversing the string is not what you really want to do, you want to filter find all the palindromes, so you need to filter your list of (x * y)
s by a predicate. Instead you could writepalindromeList = [z | x <- [1..999], y <- [1..999], let z = x * y, if show z == reverse (show z)]
But since this marches off the side of the screen, I would recommend breaking it up into smaller functions-- Generates all products
products :: [Integer] -> [Integer] -> [Integer]
products ns ms = [x * y | x <- ns, y <- ms]
-- Checks if a number is a palindrome
isPalindrome :: Integer -> Bool
isPalindrome n = let s = show n in s == reverse s
-- Generates problem-specific palindromes
palindromes :: [Integer]
palindromes = ??? -- Implementation here. Hint: filter
The next big problem is because you're using the max
function, which has the typemax :: Ord a => a -> a -> a
But we really want to find the max of a list, so we turn to maximum
, which has the typemaximum :: Ord a => [a] -> a
So you can finalize your program asprojectEuler4 :: Integer
projectEuler4 = maximum palindromes
One final thought: the problem says that you need to find the largest palindrome that is a multiple of 2 three-digit numbers, but your range that you're looking over is [1..999]
, which includes 1 and 2 digit numbers. What could you do to not check those? Conveniently, it'll make the program faster. Solving palindromic 'Triangle Quest' puzzle in Python
I ended up doing the following (thanks @raina77ow for the idea):
for i in range(1, N+1):
print((111111111//(10**(9-i)))**2)
Related Topics
Automatically Run Rspec When Plain-Old Ruby (Not Rails) Files Change
Ruby a Clever Way to Execute a Function on a Condition
Using Rails as a Framework for a Large Website
How to Use Rspec to Test That a Model Using Paperclip Is Validating The Size of an Uploaded File
Activestorage Issue to Set Record_Type on Active_Storage_Attachments
Where Is Ruby's Erb Format "Officially" Defined
How to Resize Image Only If Width Exceeds with Graphics/Image Magick
How to Get All Message History from Hipchat for a Room via The API
Why Use Gemspec + Gemfile When Checking for Dependencies
Ruby: Start Reading at Arbitrary Point in Large File
Capybara-Webkit: Automatically Save a Screenshot on an Rspec Test Failure
Running "Bundle Install" Fails and Asks Me to Run "Bundle Install"
How to Open File in Default Application. Ruby