Odds of rolling two dice with equal outcomes seem more common than I pictured - probability

After running this program several times i noticed that my y value is somewhere between 60-80 every single time.
I thought because 70^2 is 4900 that i would end up with my y value ending up around 1 each run through, but actually its about a 1 in 70 chance of the dice equaling each other.
So why is it that rolling 2 70 sided dice and having the results equal each other is not a 1/4900 chance, but rather a 1/70 chance? Heres the program...
x=0
y=0
while x < 4900
random = rand(70)
random2 = rand(70)
puts " "
puts random
puts random2
if random == random2
puts "the numbers matched"
y+=1
end
x+=1
if x == 4900
puts " "
puts y
end
end

There are 4900 possible outcomes (1,1), (1,2), (1,3) .. ,(70, 70)
There are 70 outcomes that are suitable for your condition - (1,1), (2,2) .. (70,70)
So, the probability is needed_outcomes/all_outcomes = 70/4900 = 1/70 ~= 0.0142858
In test program number of tests is not connected to number of outcomes. Larger number of tests tends to show more accurate results (through in this case we don't program at all, but there is ruby tag in the question).
So, we can try this:
x=0
total_matches = 0.0
N = 1000000
while x < N
random = rand(1..70)
random2 = rand(1..70)
total_matches += 1 if random == random2
x += 1
end
puts total_matches/N
It gives something around 0.0142.

If you wish to estimate the probability of two thrown 70-sided dice showing the same value (which we know to be (1.0/70).round(6) #=> 0.014286) by simulating throws, you can assume one die always shows the same given value and repeatedly throw the second die only, counting the number of times it shows the assumed value of the first die, and then divide the count by the number of throws. (See my comment on the question.)
Suppose each die has sides labelled 0, 1,...,69 and we assume the first die always shows a 0. We can then simulate as follows:
def simulate(nbr_throws)
nbr_throws.times.sum { rand(70) == 0 ? 1 : 0 }.fdiv(nbr_throws).round(6)
end
simulate( 100) #=> 0.01
simulate( 1_000) #=> 0.016
simulate( 10_000) #=> 0.0151
simulate( 100_000) #=> 0.01358
simulate( 1_000_000) #=> 0.014305
simulate( 10_000_000) #=> 0.014282
simulate(100_000_000) #=> 0.014284
See Kernel#rand and Integer#fdiv. More generally, if each die had n sides, change rand(70) to rand(n).

Related

ruby weird behavior with integer#times and modulo

If I run this
100.times do |i|
unless i == 0 || i.modulo(2) == 0
p "odd number #{i}"
end
end
I only get back odd numbers, which is the way it should work.
if I run this though
100.times do |i|
unless i == 0 || i.modulo(3) == 0
p "even number #{i}"
end
end
then I get back a mixture of numbers, some of which are even.
Maybe it's me, or 'unless' isn't the best control to use here. Kind of weird though that one gives me the result I want, the other not.
i.modulo(3) == 0 is not a test for odd; it is a is a test of numbers divisible by 3.
Recall the definition of even is divisible by two (or x % 2 == 0) and odd is !even. Therefore only modulo test for even vs odd is mod 2 with a result of 0 or 1.
Example:
100.times { |i|
p "even number #{i}" unless i % 2==1 # better as if i % 2==0
p "odd number #{i}" unless i % 2==0 # better as if i % 2==1
}
To keep it straight, you can also use .even? and .odd?

Comparing two Integers by their divisibility

For instance:
8 > 10 = true, since 8 is divisible by 2 three times and 10 only once.
How can I compare two integers from any range of numbers? Are the modulo and divide operator capable of doing this task?
Use binary caculate to judge it
def devided_by_two(i)
return i.to_s(2).match(/0*$/).to_s.count('0')
end
To make integer divisibility by 2, just transcode it to binary and judge how many zero from end of banary number. The code I provide can be more simple I think.
Yes, they are capable. A number is even if, when you divide it by two, the remainder is zero.
Hence, you can use a loop to continuously divide by two until you get an odd number, keeping a count of how many times you did it.
The (pseudo-code) function for assigning a "divisibility by two, continuously" value to a number would be something like:
def howManyDivByTwo(x):
count = 0
while x % 2 == 0:
count = count + 1
x = x / 2 # make sure integer division
return count
That shouldn't be too hard to turn into Ruby (or any procedural-type language, really), such as:
def howManyDivByTwo(x)
count = 0
while x % 2 == 0
count = count + 1
x = x / 2
end
return count
end
print howManyDivByTwo(4), "\n"
print howManyDivByTwo(10), "\n"
print howManyDivByTwo(11), "\n"
print howManyDivByTwo(65536), "\n"
This outputs the correct:
2
1
0
16
Astute readers will have noticed there's an edge case in that function, you probably don't want to try passing zero to it. If it was production code, you'd need to catch that and act intelligently since you can divide zero by two until the cows come home, without ever reaching an odd number.
What value you return for zero depends on needs you haven't specified in detail. Theoretically (mathematically), you should return infinity but I'll leave that up to you.
Notice that you will likely mess up much of your code if you redefine such basic method. Knowing that, this is how it's done:
class Integer
def <=> other
me = self
return 0 if me.zero? and other.zero?
return -1 if other.zero?
return 1 if me.zero?
while me.even? and other.even?
me /= 2
other /= 2
end
return 0 if me.odd? and other.odd?
return -1 if me.odd?
return 1 if other.odd? # This condition is redundant, but is here for symmetry.
end
end

Ruby Project Euler # 12 Efficiency

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.

The 'upto' method in Ruby

I'm learning Ruby, and there has been a bit of talk about the upto method in the book from which I am learning. I'm confused. What exactly does it do?
Example:
grades = [88,99,73,56,87,64]
sum = 0
0.upto(grades.length - 1) do |loop_index|
sum += grades[loop_index]
end
average = sum/grades.length
puts average
Let's try an explanation:
You define an array
grades = [88,99,73,56,87,64]
and prepare a variable to store the sum:
sum = 0
grades.length is 6 (there are 6 elements in the array), (grades.length - 1) is 5.
with 0.upto(5) you loop from 0 to 5, loop_index will be 0, then 1...
The first element of the array is grades[0] (the index in the array starts with 0).
That's why you have to subtract 1 from the number of elements.
0.upto(grades.length - 1) do |loop_index|
Add the loop_index's value to sum.
sum += grades[loop_index]
end
Now you looped on each element and have the sum of all elements of the array.
You can calculate the average:
average = sum/grades.length
Now you write the result to stdout:
puts average
This was a non-ruby-like syntax. Ruby-like you would do it like this:
grades = [88,99,73,56,87,64]
sum = 0
grades.each do |value|
sum += value
end
average = sum/grades.length
puts average
Addendum based on Marc-Andrés comment:
You may use also inject to avoid to define the initial sum:
grades = [88,99,73,56,87,64]
sum = grades.inject do |sum, value|
sum + value
end
average = sum / grades.length
puts average
Or even shorter:
grades = [88,99,73,56,87,64]
average = grades.inject(:+) / grades.length
puts average
From http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_c_integer.html#upto:
upto int.upto( anInteger ) {| i | block }
Iterates block, passing in integer values from int up to and
including anInteger.
5.upto(10) { |i| print i, " " }
produces:
5 6 7 8 9 10
Upto executes the block given once for each number from the original number "upto" the argument passed. For example:
1.upto(10) {|x| puts x}
will print out the numbers 1 through 10.
It is just another way to do a loop/iterator in Ruby. It says do this action n times based on i being the first number the the number in parens as the limit.
My example would have been this:
1.upto(5) { |i| puts "Countup: #{i}" }
So what you're actually doing here is saying, I want to count up from 1 to the number 5, that's specifically what this part is saying:
1.upto(5)
The latter part of code (a block) is just outputting the iteration of going through the count from 1 up to 5. This is the output you might expect to see:
Countup: 1
Countup: 2
Countup: 3
Countup: 4
Countup: 5
Note: This can be written is another way if you're using multilines:
1.upto(5) do |i|
puts "Countup: #{i}"
end
Hope this helps.
An alternative that looks more like Ruby to me is
require 'descriptive_statistics'
grades=[88,99,73,56,87,64]
sum = grades.sum
average = grades.mean
sd = grades.standard_deviation
Of course it depends what you're doing.

Simple recursion problem

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 :)

Resources