Project Euler #35 Solution in Ruby

Categories: Coding, Project Euler

I haven’t done any Project Euler problems in Ruby as of yet, but since I’m spending a majority of my time coding in Ruby for the time being I figured it would be good to give it a try! Conceptually this question wasn’t too hard but my original solution had me turning numbers into strings and arrays multiple times which ended up not working. This solution, below, works though it takes about 21 seconds to complete on my computer. I’m certain that there are better solutions out there but this gets the job done.

Here’s the question:

The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime. There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97. How many circular primes are there below one million?

And here’s my solution:

def is_circular?(num)
	# Create array of all rotations
	num = num.to_s.split('') 
	rotations = [num]
	# Create the rotations of the numbers if more than 1 digit
	(num.length-1).times do
		test = rotations.last.dup
		test = test << test.shift
		rotations << test
	end
	rotations.all?{|num| is_prime?(num.join('').to_i)} ? true : false
end

def is_prime?(num)
	return false if num == 1
	return true if num == 2

	2.upto(Math.sqrt(num).ceil) do |test|
		if num % test == 0
			return false
		end
	end
	true
end

def circular_up_to(limit)
	count = 0
	limit.downto(2) do |num|
		count += 1 if is_circular?(num)
	end
	puts count
end

beginning_time = Time.now
circular_up_to(1_000_000)
end_time = Time.now
puts "Time elapsed #{(end_time - beginning_time)*1000} milliseconds"

What I’m doing here is pretty straightforward: creating three functions which are is_prime?, is_circular?, and circular_up_to. Is_prime? is self-explanatory so I won’t go over that. Is_circular is the interesting one, and the function that broke my original solution. Originally I had integers being stored in the rotations array, then to get the next “rotation” I would turn that number into a string, then split(”) it, then save it as an integer again. This proved to be too heavy, and I couldn’t complete the problem that way. This solution saves each rotation as an array (like [[“1″,”0″,”0”]] and makes rotations a nested array. Then it’s simple to just shift the first item and add it to the end.

Though it still takes 21 seconds to complete, at least it’s able to be completed this time.

Running the above code in your CLI will yield the final answer, which is 55. Onto the next one! Any questions or recommendations would be greatly appreciated.

«
»