I'm taking my first steps into recursion and dynamic programming and have a question about forming subproblems to model the recursion.
Problem:
How many different ways are there to
flip a fair coin 5 times and not have
three or more heads in a row?
If some could put up some heavily commented code (Ruby preferred but not essential) to help me get there. I am not a student if that matters, this is a modification of a Project Euler problem to make it very simple for me to grasp. I just need to get the hang of writing recursion formulas.
If you would like to abstract the problem into how many different ways are there to flip a fair coin Y times and not have Z or more heads in a row, that may be beneficial as well. Thanks again, this website rocks.
You can simply create a formula for that:
The number of ways to flip a coin 5 times without having 3 heads in a row is equal to the number of combinations of 5 coin flips minus the combinations with at least three heads in a row. In this case:
HHH-- (4 combinations)
THHH- (2 combinations)
TTHHH (1 combination)
The total number of combinations = 2^5 = 32. And 32 - 7 = 25.
If we flip a coin N times without Q heads in a row, the total amount is 2^N and the amount with at least Q heads is 2^(N-Q+1)-1. So the general answer is:
Flip(N,Q) = 2^N - 2^(N-Q+1) +1
Of course you can use recursion to simulate the total amount:
flipme: N x N -> N
flipme(flipsleft, maxhead) = flip(flipsleft, maxhead, 0)
flip: N x N x N -> N
flip(flipsleft, maxhead, headcount) ==
if flipsleft <= 0 then 0
else if maxhead<=headcount then 0
else
flip(flipsleft - 1, maxhead, headcount+1) + // head
flip(flipsleft - 1, maxhead, maxhead) // tail
Here's my solution in Ruby
def combination(length=5)
return [[]] if length == 0
combination(length-1).collect {|c| [:h] + c if c[0..1]!= [:h,:h]}.compact +
combination(length-1).collect {|c| [:t] + c }
end
puts "There are #{combination.length} ways"
All recursive methods start with an early out for the end case.
return [[]] if length == 0
This returns an array of combinations, where the only combination of zero length is []
The next bit (simplified) is...
combination(length-1).collect {|c| [:h] + c } +
combination(length-1).collect {|c| [:t] + c }
So.. this says.. I want all combinations that are one shorter than the desired length with a :head added to each of them... plus all the combinations that are one shorter with a tail added to them.
The way to think about recursion is.. "assuming I had a method to do the n-1 case.. what would I have to add to make it cover the n case". To me it feels like proof by induction.
This code would generate all combinations of heads and tails up to the given length.
We don't want ones that have :h :h :h. That can only happen where we have :h :h and we are adding a :h. So... I put an if c[0..1] != [:h,:h] on the adding of the :h so it will return nil instead of an array when it was about to make an invalid combination.
I then had to compact the result to ignore all results that are just nil
Isn't this a matter of taking all possible 5 bit sequences and removing the cases where there are three sequential 1 bits (assuming 1 = heads, 0 = tails)?
Here's one way to do it in Python:
#This will hold all possible combinations of flipping the coins.
flips = [[]]
for i in range(5):
#Loop through the existing permutations, and add either 'h' or 't'
#to the end.
for j in range(len(flips)):
f = flips[j]
tails = list(f)
tails.append('t')
flips.append(tails)
f.append('h')
#Now count how many of the permutations match our criteria.
fewEnoughHeadsCount = 0
for flip in flips:
hCount = 0
hasTooManyHeads = False
for c in flip:
if c == 'h': hCount += 1
else: hCount = 0
if hCount >= 3: hasTooManyHeads = True
if not hasTooManyHeads: fewEnoughHeadsCount += 1
print 'There are %s ways.' % fewEnoughHeadsCount
This breaks down to:
How many ways are there to flip a fair coin four times when the first flip was heads + when the first flip was tails:
So in python:
HEADS = "1"
TAILS = "0"
def threeOrMoreHeadsInARow(bits):
return "111" in bits
def flip(n = 5, flips = ""):
if threeOrMoreHeadsInARow(flips):
return 0
if n == 0:
return 1
return flip(n - 1, flips + HEADS) + flip(n - 1, flips + TAILS)
Here's a recursive combination function using Ruby yield statements:
def combinations(values, n)
if n.zero?
yield []
else
combinations(values, n - 1) do |combo_tail|
values.each do |value|
yield [value] + combo_tail
end
end
end
end
And you could use regular expressions to parse out three heads in a row:
def three_heads_in_a_row(s)
([/hhh../, /.hhh./, /..hhh/].collect {|pat| pat.match(s)}).any?
end
Finally, you would get the answer using something like this:
total_count = 0
filter_count = 0
combinations(["h", "t"], 5) do |combo|
count += 1
unless three_heads_in_a_row(combo.join)
filter_count += 1
end
end
puts "TOTAL: #{ total_count }"
puts "FILTERED: #{ filter_count }"
So that's how I would do it :)
Related
I'm trying to implement a recursive solution to the largest palindrome product problem
What I'm trying to do is start both numbers at 999 and iterate down to 100 for num1 and then restart num1 at 999 and iterate num2 down by 1.
The goal is basically to mimic a nested for-loop.
def largest_palindrome_prod(num1 = 999, num2 = 999, largest_so_far = 0)
prod = num1 * num2
largest_so_far = prod if prod > largest_so_far && check_pal(prod)
if num2 == 100
return largest_so_far
elsif num1 == 100
largest_palindrome_prod(num1 = 999, num2 -= 1, largest_so_far)
else
largest_palindrome_prod(num1 -= 1, num2, largest_so_far)
end
end
#I know this function works, just here for reference
def check_pal(num)
num = num.to_s if num.is_a? Integer
if num.length < 2
true
else
num[0] == num[-1] ? check_pal(num[1..-2]) : false
end
end
rb:10:inlargest_palindrome_prod': stack level too deep`
I'm getting this error which is referring to the else statement in the largest_palindrome_prod function, but I can't figure out wast could be causing the stack error.
You don't have an infinite recursion bug. The stack is just running out of space because of the size of your input. To prove this, you can run your same function with the range of 2-digit numbers, instead of the 3-digit ones. It returns fine, which shows that there is no flaw with your logic.
How to get around this? Two options.
Option 1: You could simply not use recursion here (just use a regular nested loop instead)
Option 2: Keep your same code and enable tail call optimization:
# run_code.rb
RubyVM::InstructionSequence.compile_option = {
tailcall_optimization: true,
trace_instruction: false
}
require './palindrome_functions.rb'
puts largest_palindrome_prod
# => 906609
Note, for a reason I don't fully understand, the tail call optimization must be enabled in a different file than the code being run. So if you simply moved the compile_option line to the palindrome_functions.rb file, it wouldn't work.
I cant really give you a full explanation of tail call optimization (look it up on Wikipedia) but from my understanding, its a heavy optimization for recursive functions that only works when the recursive call is at the end of the function body. Your function meets this criteria.
#maxpleaner has answered your question and has shown how you can use recursion that avoids the stack level error. He also mentioned the option (which I expect he favours) of simply looping, rather than employing recursion. Below is one looping solution. The following method is used in the search1.
def check_ranges(range1, range2 = range1)
range1.flat_map do |n|
[n].product((range2.first..[n, range2.last].min).to_a)
end.map { |x,y| x*y }.
sort.
reverse_each.
find do |z|
arr = z.digits
arr == arr.reverse
end
end
Let's first find the largest palindrome of the product of two numbers between 960 and 999 (if there are any):
check_ranges(960..999)
#=> nil
There are none. Note that this calculation was very cheap, requiring the examination of only 40*40/2 #=> 800 products. Next, find the largest palindrome that is equal to the product of two numbers between 920 and 999.
check_ranges(920..999)
#=> 888888
Success! Note that this method re-checks the 800 products we checked earlier. It makes more sense to examine only the cases represented by the following two calls to brute_force:
check_ranges(960..999, 920..959)
#=> 888888
check_ranges(920..959)
#=> 861168
The first call computes 40*40 #=> 1600 products; the second, 800 products.
Of course, we have not yet necessarily found the largest product that is a palindrome. We do, however, have a lower bound on the largest product, which we can use to advantage. Since
888888/999
#=> 889
we infer that if the product of two numbers is larger than 888888, both of those numbers must be at least 889. We therefore need only check:
check_ranges(889..999, 889..919)
#=> 906609
check_ranges(889..919)
#=> 824428
We are finished. This tells us that 906609 is the largest product of two 3-digit numbers that is a palindrome.
The question does not ask what are the two numbers whose product is the largest palindrome, but we can easily find them:
(889..999).to_a.product((889..919).to_a).find { |x,y| x*y == 906609 }
#=> [993, 913]
993*913
#=> 906609
Moreover, let:
a = (889..999).to_a.product((889..919).to_a).map { |x,y| x*y }.
sort.
reverse
Then:
a.index { |n| n == 906609 }
#=> 84
tells us that only the largest 84 elements of this sorted group of 111*31 #=> 3441 products had to be examined before a palindrome (906609) was found.
All of this needs to be organized into a method. Though challenging for a newbie, it should be a good learning experience.
1. It would be useful to test which is faster, arr = z.digits; arr == arr.reverse or s = z.to_s; s == s.reverse.
#maxpleaner already answered, #Cary Swoveland already showed one brute force way using ranges and product. I'd like to show another brute force using a nested loop, easier to follow (IMO):
n = 9999
res = [0]
bottom = 10**(n.digits.size - 1)
n.downto(bottom) do |k|
k.downto(bottom) do |j|
# puts "#{k}, #{j}"
res = [k, j, k * j] if check_pal(k * j) && k * j > res.last
end
end
res
#=> [9999, 9901, 99000099]
I guess it can be optimized further, for example, using
n.downto(n*99/100) do |k|
k.downto(k*99/100) do |j|
Returned [99979, 99681, 9966006699] in 0.7 seconds.
Not required, but this increases the speed:
def check_pal(num)
word = num.to_s
word.reverse == word
end
I am trying to take the sum of the n first prime numbers. I found a way of showing the first 100, but I don't know how to get rid of 1 and how to make a sum with the numbers. I was thinking about storing them into an array, but I can not figure it out.
num = 1
last = 100
while (num <= last)
condition = true
x = 2
while (x <= num / 2)
if (num % x == 0)
condition = false
break
end
x = x + 1
end
primes = [] # Here
if condition
puts num.to_s
primes << num.to_s # Here
end
num = num + 1
end
puts primes.inject(:+) # Here
Based on what I understood from what you guys are saying I added these lines (the ones commented # Here). It still does not print the sum of them. What I meant with getting rid of 1 is that I know that 1 is not considered a prime number, and I do not get how to make it without 1. Thank you very much guys for your time and answers, and please understand that I am just starting to study this.
If you want to add a list of numbers together you can use the following:
list_of_prime_numbers.inject(0) {|total,prime| total + prime}
This will take the list of numbers, and add them one by one to an accumulator (total) that was injected into the loop (.inject(0)), add it to the current number (prime) and then return the total which then becomes the value of total in the next iteration.
I'm not quite sure what you mean by:
I don't know how to get rid of 1
but if you mean to not use the first number (which is 1 in a list of primes starting from 0)
then you could do:
list_of_prime_numbers[1...list_of_prime_numbers.length].
inject(0) {|total,prime| total + prime}
Which would only get all the numbers except the first up to but not including the length of the array
and as for getting the number into the array you could push it into the array like so:
list_of_prime_numbers << prime_number
You can make use of Prime Enumerable in ruby
require 'prime'
((1..100).select { |number| Prime.prime?(number) }).inject(:+)
OR
Prime.each(100).inject(:+)
Hope this helps.
I'm working on the problem stated in the question statement. I know my solution is correct (ran the program) but I'm curious as to whether or not I'm analyzing my code (below) correctly.
def parens(num)
return ["()"] if num == 1
paren_arr = []
parens(num-1).each do |paren|
paren_arr << paren + "()" unless "()#{paren}" == "#{paren}()"
paren_arr << "()#{paren}"
paren_arr << "(#{paren})"
end
paren_arr
end
parens(3), as an example, will output the following:
["()()()", "(()())", "(())()", "()(())", "((()))"]
Here's my analysis:
Every f(n) value is roughly 3 times as many elements as f(n-1). So:
f(n) = 3 * f(n-1) = 3 * 3 * f(n-2) ~ (3^n) time cost.
By a similar analysis, the stack will be occupied by f(1)..f(n) and so the space complexity should be 3^n.
I'm not sure if this analysis for either time or space is correct. On the one hand, the stack only holds n function calls, but each of these calls returns an array ~3 times as big as the call before it. Does this factor into space cost? And is my time analysis correct?
As others have mentioned, your solution is not correct.
My favourite solution to this problem generates all the valid combinations by repeatedly incrementing the current string to the lexically next valid combination.
"Lexically next" breaks down into a few rules that make it pretty easy:
The first difference in the string changes a '(' to a ')'. Otherwise the next string would be lexically before the current one.
The first difference is as far to the right as possible. Otherwise there would be smaller increments.
The part after the first difference is lexically minimal, again because otherwise there would be smaller increments. In this case that means that all the '('s come before all the ')'.
So all you have to do is find the rightmost '(' that can be changed to a ')', flip it, and then append the correct number of '('s and ')'s.
I don't know Ruby, but in Python it looks like this:
current="(((())))"
while True:
print(current)
opens=0
closes=0
pos=0
for i in range(len(current)-1,-1,-1):
if current[i]==')':
closes+=1
else:
opens+=1
if closes > opens:
pos=i
break
if pos<1:
break
current = current[:pos]+ ")" + "("*opens + ")"*(closes-1)
Output:
(((())))
((()()))
((())())
((()))()
(()(()))
(()()())
(()())()
(())(())
(())()()
()((()))
()(()())
()(())()
()()(())
()()()()
Solutions like this turn out to be easy and fast for many types of "generate all the combinations" problems.
Recursive reasoning makes a simple solution. If the number of left parens remaining to emit is positive, emit one and recur. If the number of right parens remaining to emit is greater than the number of left, emit and recur. The base case is when all parens, both left and right, have been emitted. Print.
def parens(l, r = l, s = "")
if l > 0 then parens(l - 1, r, s + "(") end
if r > l then parens(l, r - 1, s + ")") end
if l + r == 0 then print "#{s}\n" end
end
As others have said, the Catalan numbers give the number of strings that will be printed.
While this Ruby implementation doesn't achieve it, a lower level language (like C) would make it easy to use a single string buffer: O(n) space. Due to substring copies, this one is O(n^2). But since the run time and output length are O(n!), O(n) space inefficiency doesn't mean much.
I found Tom Davis' article, "Catalan Numbers," very helpful in explaining one recursive method for defining the Catalan Numbers. I'll try to explain it myself (in part, to see how much of it I've understood) as it may be applied to finding the set of all unique arrangements of N matched parentheses (e.g., 1 (); 2 ()(), (()); etc. ).
For N > 1 let (A)B represent one arrangement of N matched parentheses, where A and B each have only balanced sets of parentheses. Then we know that if A contains k matched sets, B must have the other N - k - 1, where 0 <= k <= N - 1.
In the following example, a dot means the group has zero sets of parentheses:
C_0 => .
C_1 => (.)
To enumerate C_2, we arrange C_1 as AB in all ways and place the second parentheses around A:
. () = AB = C_0C_1 => (.)()
() . = AB = C_1C_0 => (()) .
Now for C_3, we have three partitions for N - 1, each with its own combinations: C_0C_2, C_1C_1, C_2C_0
C_0C_2 = AB = . ()() and . (()) => ()()(), ()(())
C_1C_1 = AB = ()() => (())()
C_2C_0 = AB = ()() . and (()) . => (()()), ((()))
We can code this method by keeping a set for each N and iterating over the combinations for each partition. We'll keep the individual arrangements as bits: 0 for left and 1 for right (this appears backwards when cast as a binary string).
def catalan
Enumerator.new do |y|
# the zero here represents none rather than left
s = [[0],[2]]
y << [0]
y << [2]
i = 2
while true
s[i] = []
(0..i - 1).each do |k|
as = s[k]
bs = s[i - k - 1]
as.each do |a|
bs.each do |b|
if a != 0
s[i] << ((b << (2*k + 2)) | (1 << (2*k + 1)) | (a << 1))
else
s[i] << (2 | (b << 2))
end
end # bs
end # as
end # k
y.yield(s[i])
i = i + 1
end # i
end # enumerator
end
catalan.take(4)
# => [[0], [2], [10, 12], [42, 50, 44, 52, 56]]
The yielder is lazy: although the list is infinite, we can generate as little as we like (using .take for example):
catalan.take(4).last.map{|x| x.to_s(2)}
# => ["101010", "110010", "101100", "110100", "111000"]
The former generation obliges us to keep all previous sets in order to issue the next. Alternatively, we can build a requested set through a more organic type, meandering recursion. This next version yields each arrangement to the block, so we can type:
catalan(4){
|x| (0..7).reduce(""){
|y,i| if x[i] == 0 then y + "(" else y + ")" end
}
}.take(14)
# => ["(((())))", "((()()))", "((())())", "((()))()", "(()(()))", "(()()())",
# "(()())()", "(())(())", "(())()()", "()((()))", "()(()())", "()(())()",
# "()()(())", "()()()()"]
Direct generation:
def catalan(n)
Enumerator.new do |y|
s = [[0,0,0]]
until s.empty?
left,right,result = s.pop
if left + right == 2 * n
y << yield(result)
end
if right < left
s << [left, right + 1, result | 1 << (left + right)]
end
if left < n
s << [left + 1, right, result]
end
end
end
end
I am trying to write a code for the following problem:
Input
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.
Sample Input:
2
1 10
3 5
Sample Output:
2
3
5
7
3
5
My code:
def prime?(number)
return false if number == 1
(2..number-1).each do |n|
return false if number % n == 0
end
true
end
t = gets.strip.to_i
for i in 1..t
mi, ni = gets.strip.split(' ')
mi = mi.to_i
ni = ni.to_i
i = mi
while i <= ni
puts i if prime?(i)
i += 1
end
puts "\n"
end
The code is running fine, only problem I am having is that it is taking a lot of time when run against big input ranges as compared to other programming languages.
Am I doing something wrong here? Can this code be further optimized for faster runtime?
I have tried using a for loop, normal loop, creating an array and then printing it.
Any suggestions.
Ruby is slower than some other languages, depending on what language you compare it to; certainly slower than C/C++. But your problem is not the language (although it influences the run-time behavior), but your way of finding primes. There are many better algorithms for finding primes, such as the Sieve of Eratosthenes or the Sieve of Atkin. You might also read the “Generating Primes” page on Wikipedia and follow the links there.
By the way, for the Sieve of Eratosthenes, there is even a ready-to-use piece of code on Stackoverflow. I'm sure a little bit of googling will turn up implementations for other algorithms, too.
Since your problem is finding primes within a certain range, this is the Sieve of Eratosthenes code found at the above link modified to suit your particular problem:
def better_sieve_upto(first, last)
sieve = [nil, nil] + (2..last).to_a
sieve.each do |i|
next unless i
break if i*i > last
(i*i).step(last, i) {|j| sieve[j] = nil }
end
sieve.reject {|i| !i || i < first}
end
Note the change from "sieve.compact" to a complexer "sieve.reject" with a corresponding condition.
Return true if the number is 2, false if the number is evenly divisible by 2.
Start iterating at 3, instead of 2. Use a step of two.
Iterate up to the square root of the number, instead of the number minus one.
def prime?(number)
return true if number == 2
return false if number <= 1 or number % 2 == 0
(3..Math.sqrt(number)).step(2) do |n|
return false if number % n == 0
end
true
end
This will be much faster, but still not very fast, as #Technation explains.
Here's how to do it using the Sieve of Eratosthenes built into Ruby. You'll need to precompute all the primes up to the maximum maximum, which will be very quick, and then select the primes that fall within each range.
require 'prime'
ranges = Array.new(gets.strip.to_i) do
min, max = gets.strip.split.map(&:to_i)
Range.new(min, max)
end
primes = Prime.each(ranges.map(&:max).max, Prime::EratosthenesGenerator.new)
ranges.each do |range|
primes.each do |prime|
next if prime < range.min
break if prime > range.max
puts prime
end
primes.rewind
puts "\n"
end
Here's how the various solutions perform with the range 50000 200000:
Your original prime? function: 1m49.639s
My modified prime? function: 0m0.687s
Prime::EratosthenesGenerator: 0m0.221s
The more ranges being processed, the faster the Prime::EratosthenesGenerator method should be.
Working on Problem 12 of Project Euler:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
Here's what I've got:
require 'reusable'
# The idea here is that 2^n is the smallest number with n factors,
# according to their definition, so it's a good place to start.
# It also happens to be a HUGE number, so I'm worried I'm thinking
# about this wrong. Did 4999 instead of 5000, just to make sure
# I didn't overshoot.
start = 2 * 4999
# The faster way to calculate the nth Triangle number
def nthTriangle(n)
n * (n + 1) / 2
end
def answer(num)
i = startingTriangle(num)
while true
triangle = i*(i+1)/2
puts triangle
factors = numFactors(triangle)
return "#{triangle} is triangle number #{i}, with #{factors} factors." if factors > num
i += 1
end
end
# Basic reversal of the nthTriangle thing to figure
# out which n to start with in the answer function.
def startingTriangle(n)
power = n - 2
sqrt(power * 2).to_i - 1
end
puts answer(5000)
And that required file (where I'm trying to put methods I'll reuse in a bunch of Euler problems):
def primesUpTo(n)
nums = [0, 0] + (2..n).to_a
(2..sqrt(n).to_i+1).each do |i|
if nums[i].nonzero?
(i**2..n).step(i) {|m| nums[m] = 0}
end
end
nums.find_all {|m| m.nonzero?}
end
def prime?(n)
test = primesUpTo(sqrt(n).to_i)
test.each do |i|
if n % i == 0
return false
end
end
true
end
# Just for faster, more intuitive (to me) array summing
def sum(array)
array.inject(0) {|s, n| s + n }
end
# Ditto
def product(array)
array.inject(1) {|p, n| p * n}
end
# I don't like typing the 'Math.'
def sqrt(n)
Math.sqrt(n)
end
# Returns an array of arrays of the prime factors of num
# Form [[factor1, power1],[factor2, power2]]
# Ex: primeFactors(12) == [[2,2],[3,1]]
def primeFactors(n)
array = []
# 2 3
primesUpTo((n/2).to_i+1).select{ |i| n % i == 0 }.each do |p|
pcount = 1
n = n / p
while n % p == 0
pcount += 1
n = n / p
end
array << [p, pcount]
end
array
end
# Returns the number of factors a number has
# INCLUDING both the number itself and 1
# ex: numFactors(28) = 6
def numFactors(n)
return 2 if prime?(n)
product = 1
primeFactors(n).each do |i|
product *= i[1] + 1
end
product
end
My problem is that my code is really super slow. If I start at 1 instead of my start number, it takes a minute + before it gets to like 200000 (nowhere near 2^4999). But apart from scrapping the library prime-number solution and adding all primes to an array I keep referring to -- which I feel would only make it a small amount faster -- I can't think of how to make this much faster. And it needs to be WAY faster.
Am I thinking about this all wrong? Any suggestions?
Also useful would be any suggestions for how to improve the efficiency of any of my library methods, which I'll probably be using again and again. I wanted to make them from scratch so I understood them, but I'm afraid they're very inefficient.
From your code:
The idea here is that 2^n is the smallest number with n factors
From the stated Project Euler task:
We can see that 28 is the first triangle number to have over five divisors.
I'm not sure why you think 2^n is the smallest number with n factors, but the example given in the question clearly proves your assumption wrong, as 2^5 = 32, which is greater than 28.
My solution starts the search at 1 and is reasonably efficient. I don't use primes at all.
Addendum: For the sake of completeness, the other large issue besides starting at a number far too high is searching for greater than 5000 divisors rather than greater than 500, as you noticed and pointed out in the comments.