Let x, range, d be integers. We'd like to generate a number y, such that
1 <= y <= range
abs(x-y) >= d
One idea I came up with is to generate some smaller range and then make some adjustments to handle the numbers which too close to x. But that's really tedious.
Is there any better way to do it?
Here is a Python function that you should be able to adapt to the language of your choice:
import random
def distantRand(a,b,x,d):
#returns a random integer in range a ... b
#which is greater than or equal to d units from x
lb = max(a,x-d+1)
ub = min(b,x+d-1)
k = ub-lb+1 #number of numbers ruled out
if b-k < a:
return None
else:
y = random.randint(a,b-k)
if y > x - d:
y = y + k
return y
For example, distantRand(1,10,5,3) should return a number in the range 1 to 10 which is at least units away from 5. This rules out 3,4,5,6,7 as return values, leaving 10-5 = 5 valid numbers. The function picks one such in the range 1 to 5. If the number chosen is >2, 5 is added to it to make it a number which is >7 (but still <= 10). For example:
>>> for i in range(20):
print(distantRand(1,10,5,3))
1
1
1
8
2
9
10
8
1
10
10
2
8
10
8
8
8
2
1
2
I have done it like this in Python.
import random
range=100
d=20
x=115
while(True):
y=random.randint(1,range)
if abs(x-y)>=d:
print abs(x-y)
print y
break
And here it is as a def
import random
r=100
d=20
x=115
def yourandom (x,d,r):
while(True):
y=random.randint(1,r)
if abs(x-y)>=d:
print "abs(x-y)=",abs(x-y)
print "y=",y
break
yourandom(x,d,r)
Related
I have been attempting the test below on codewars. I am relatively new to coding and will look for more appropriate solutions as well as asking you for feedback on my code. I have written the solution at the bottom and for the life of me cannot understand what is missing as the resultant figure is always 0. I'd very much appreciate feedback on my code for the problem and not just giving your best solution to the problem. Although both would be much appreciated. Thank you in advance!
The test posed is:
If we list all the natural numbers below 10 that are multiples of 3 or
5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Finish the solution so that it returns the sum of all the multiples of
3 or 5 below the number passed in. Additionally, if the number is
negative, return 0 (for languages that do have them).
Note: If the number is a multiple of both 3 and 5, only count it once.
My code is as follows:
def solution(number)
array = [1..number]
multiples = []
if number < 0
return 0
else
array.each { |x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
}
end
return multiples.sum
end
In a situation like this, when something in your code produces an unexpected result you should debug it, meaning, run it line by line with the same argument and see what each variable holds. Using some kind of interactive console for running code (like irb) is very helpfull.
Moving to your example, let's start from the beginning:
number = 10
array = [1..number]
puts array.size # => 1 - wait what?
puts array[0].class # => Range
As you can see the array variable doesn't contain numbers but rather a Range object. After you finish filtering the array the result is an empty array that sums to 0.
Regardless of that, Ruby has a lot of built-in methods that can help you accomplish the same problem typing fewer words, for example:
multiples_of_3_and_5 = array.select { |number| number % 3 == 0 || number % 5 == 0 }
When writing a multiline block of code, prefer the do, end syntax, for example:
array.each do |x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
end
I'm not suggesting that this is the best approach per se, but using your specific code, you could fix the MAIN problem by editing the first line of your code in one of 2 ways:
By either converting your range to an array. Something like this would do the trick:
array = (1..number).to_a
or by just using a range INSTEAD of an array like so:
range = 1..number
The latter solution inserted into your code might look like this:
number = 17
range = 1..number
multiples = []
if number < 0
return 0
else range.each{|x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
}
end
multiples.sum
#=> 60
The statement return followed by end suggests that you were writing a method, but the def statement is missing. I believe that should be
def tot_sum(number, array)
multiples = []
if number < 0
return 0
else array.each{|x|
if x % 3 == 0 || x % 5 == 0
multiples << x
end
}
end
return multiples.sum
end
As you point out, however, this double-counts numbers that are multiples of 15.
Let me suggest a more efficient way of writing that. First consider the sum of numbers that are multiples of 3 that do not exceed a given number n.
Suppose
n = 3
m = 16
then the total of numbers that are multiples of three that do not exceed 16 can be computed as follows:
3 * 1 + 3 * 2 + 3 * 3 + 3 * 4 + 3 * 5
= 3 * (1 + 2 + 3 + 4 + 5)
= 3 * 5 * (1 + 5)/2
= 45
This makes use of the fact that 5 * (1 + 5)/2 equals the sum of an algebraic series: (1 + 2 + 3 + 4 + 5).
We may write a helper method to compute this sum for any number n, with m being the number that multiples of n cannot exceed:
def tot_sum(n, m)
p = m/n
n * p * (1 + p)/2
end
For example,
tot_sum(3, 16)
#=> 45
We may now write a method that gives the desired result (remembering that we need to account for the fact that multiples of 15 are multiples of both 3 and 5):
def tot(m)
tot_sum(3, m) + tot_sum(5, m) - tot_sum(15, m)
end
tot( 9) #=> 23
tot( 16) #=> 60
tot(9999) #=> 23331668
I have a task where I need to take a number, e.g. 13002, and print it digit by digit using UART (including non-leading 0's). The UART expects that whatever it prints will go in the $s0 register but I can call it whenever I need using a jal.
This means I need to place a digit in $s0 and jump (the UART code has a jr $ra in it so it will return properly once complete.
My problem is I don't know how to iterate over the digits in the number.
My approach so far is to mod the number by 10 (Because it's a decimal number represented in binary) but that gives me the digits in reverse order.
E.g. 13002 % 10 = 2 (then divide 13002 by 10, integer division will truncate the decimal), 1300 % 10 = 0, divide again by 10, 130 ...so on and so forth.
As mentioned above however, that gives me the digits in reverse order. How would I properly iterate over the number?
I wrote some pseudocode in python but it's having trouble with numbers that have 0's in them:
def iterateOverDigits(n):
while (n >= 10):
x = n
i = 0
while (x >= 10):
x = x // 10
i += 1
print(x)
x = n
x = x % (10 ** i)
n = x
iterateOverDigits(1302) # This prints 132
In [1]: def by_digit(n):
...: for char in str(n):
...: print(char)
...:
In [2]: by_digit(120405)
1
2
0
4
0
5
In [3]:
Change the print statement to the following to remove the newlines between each digit:
print(char, end="")
I need help with the following problem.
Given an integer m, I need to find the number of positive integers n and the integers, such that the factorial of n ends with exactly m zeroes.
I wrote this code it works fine and i get the right output, but it take way too much time as the numbers increase.
a = input()
while a:
x = []
m, n, fact, c, j = input(), 0, 1, 0, 0
z = 10*m
t = 10**m
while z - 1:
fact = 1
n = n + 1
for i in range(1, n + 1):
fact = fact * i
if fact % t == 0 and ((fact / t) % 10) != 0:
x.append(int(n))
c = c + 1
z = z - 1
for p in range(c):
print x[p],
a -= 1
print c
Could someone suggest me a more efficient way to do this. Presently, it takes 30 seconds for a test case asking for numbers with 250 trailing zeros in its factorial.
Thanks
To get number of trailing zeroes of n! efficiently you can put
def zeroes(value):
result = 0;
d = 5;
while (d <= value):
result += value // d; # integer division
d *= 5;
return result;
...
# 305: 1234! has exactly 305 trailing zeroes
print zeroes(1234)
In order to solve the problem (what numbers have n trailing zeroes in n!) you can use these facts:
number of zeroes is a monotonous function: f(x + a) >= f(x) if a >= 0.
if f(x) = y then x <= y * 5 (we count only 5 factors).
if f(x) = y then x >= y * 4 (let me leave this for you to prove)
Then implement binary search (on monotonous function).
E.g. in case of 250 zeroes we have the initial range to test [4*250..5*250] == [1000..1250]. Binary search narrows the range down into [1005..1009].
1005, 1006, 1007, 1008, 1009 are all numbers such that they have exactly 250 trainling zeroes in factorial
Edit I hope I don't spoil the fun if I (after 2 years) prove the last conjecture (see comments below):
Each 5**n within facrtorial when multiplied by 2**n produces 10**n and thus n zeroes; that's why f(x) is
f(x) = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + ...
where [...] stands for floor or integer part (e.g. [3.1415926] == 3). Let's perform easy manipulations:
f(x) = [x / 5] + [x / 25] + [x / 125] + ... + [x / 5**n] + ... <= # removing [...]
x / 5 + x / 25 + x / 125 + ... + x / 5**n + ... =
x * (1/5 + 1/25 + 1/125 + ... + 1/5**n + ...) =
x * (1/5 * 1/(1 - 1/5)) =
x * 1/5 * 5/4 =
x / 4
So far so good
f(x) <= x / 4
Or if y = f(x) then x >= 4 * y Q.E.D.
Focus on the number of 2s and 5s that makes up a number. e.g. 150 is made up of 2*3*5*5, there 1 pair of 2&5 so there's one trailing zero. Each time you increase the tested number, try figuring out how much 2 and 5s are in the number. From that, adding up previous results you can easily know how much zeros its factorial contains.
For example, 15!=15*...*5*4*3*2*1, starting from 2:
Number 2s 5s trailing zeros of factorial
2 1 0 0
3 1 0 0
4 2 0 0
5 2 1 1
6 3 1 1
...
10 5 2 2
...
15 7 3 3
..
24 12 6 6
25 12 8 8 <- 25 counts for two 5-s: 25 == 5 * 5 == 5**2
26 13 8 8
..
Refer to Peter de Rivaz's and Dmitry Bychenko's comments, they have got some good advices.
What I need to achieve is basically x dice rolls = n sum but backwards.
So let's create an example:
The dice has to be rolled 5 times (min. sum 5, max. sum 30) which means:
x = 5
Let's say in this case the sum that was rolled is 23 which means:
n = 23
So what I need is to get the any of the possible single dice roll combinations (e.g. 6, 4, 5, 3, 5)
What I could make up in my mind so far is:
Create 5 random numbers.
Add them up and get the sum.
Now divide every single random number by the sum and multiply by the wanted number 23.
The result is 5 random numbers that equal the wanted number 23.
The problem is that this one returns random values (decimals, values below 1 and above 6) depending on the random numbers. I can not find a way to edit the formula to only return integers >= 1 or <= 6.
If you don't need to scale it up by far the easiest way is to re-randomize it until you get the right sum. It takes milliseconds on any modern cpu. Not pretty tho.
#!/usr/local/bin/lua
math.randomseed(os.time())
function divs(n,x)
local a = {}
repeat
local s = 0
for i=1,x do
a[i] = math.random(6)
s = s + a[i]
end
until s==n
return a
end
a = divs(23,5)
for k,v in pairs(a) do print(k,v) end
This was an interesting problem. Here's my take:
EDIT: I missed the fact that you needed them to be dice rolls. Here's a new take. As a bonus, you can specify the number of sides of the dices in an optional parameter.
local function getDiceRolls(n, num_rolls, num_sides)
num_sides = num_sides or 6
assert(n >= num_rolls, "n must be greater than num_rolls")
assert(n <= num_rolls * num_sides, "n is too big for the number of dices and sides")
local rolls = {}
for i=1, num_rolls do rolls[i] = 1 end
for i=num_rolls+1, n do
local index = math.random(1,num_rolls)
while rolls[index] == num_sides do
index = (index % num_rolls) + 1
end
rolls[index] = rolls[index] + 1
end
return rolls
end
-- tests:
print(unpack(getDiceRolls(21, 4))) -- 6 4 6 5
print(unpack(getDiceRolls(21, 4))) -- 5 5 6 5
print(unpack(getDiceRolls(13, 3))) -- 4 3 6
print(unpack(getDiceRolls(13, 3))) -- 5 5 3
print(unpack(getDiceRolls(30, 3, 20))) -- 9 10 11
print(unpack(getDiceRolls(7, 7))) -- 1 1 1 1 1 1 1
print(unpack(getDiceRolls(7, 8))) -- error
print(unpack(getDiceRolls(13, 2))) -- error
If the # of rolls does not change wildly, but the sum does, then it would be worth creating a lookup table for combinations of a given sum. You would generate every combination, and for each one compute the sum, then add the combination to a list associated to that sum. The lookup table would look like this:
T = {12 = {{1,2,3,4,2},{2,5,3,1,1},{2,2,2,3,3}, ...}, 13=....}
Then when you want to randomly select a combo for n=23, you look in table for key 23, the list has all combos with that sum, now just randomly pick one of them. Same for any other number.
I was doing this question today.
Basically, question asks for the largest 'Decent' Number having N digits where 'Decent' number is:
Only 3 and 5 as its digits.
Number of times 3 appears is divisible by 5.
Number of times 5 appears is divisible by 3.
Input Format
The 1st line will contain an integer T, the number of test cases,
followed by T lines, each line containing an integer N i.e. the number
of digits in the number
Output Format
Largest Decent number having N digits. If no such number exists, tell
Sherlock that he is wrong and print '-1'
Sample Input
4
1
3
5
11
Sample Output
-1
555
33333
55555533333
Explanation
For N=1 , there is no such number. For N=3, 555 is only possible
number. For N=5, 33333 is only possible number. For N=11 , 55555533333
and all of permutations of digits are valid numbers, among them, the
given number is the largest one.
I've solved it using normal method but saw this answer:
t = int(raw_input())
for _ in range(t):
n = int(raw_input())
c3 = 5*(2*n%3)
if c3 > n:
print -1
else:
print '5' * (n-c3) + '3'*c3
Can anyone explain the method please? Especially the line 'c3 = 5*(2*n%3)', thanks
We are looking for integer solutions of n = 5*x + 3*y where 5*x is the number of 3s and 3*y is the number of 5s. Both x and y must be >= 0 and x should be as small as possible since we can build larger numbers if we have more 5s.
Transforming this gives y = (n-5*x)/3. In order for y to be an integer n-5*x must be a multiple of 3 so we can calculate modulo 3 (I write == for is congruent modulo 3 from now on).
n-5*x == 0
n == 5*x == 2*x (because 5 == 2)
multiplying both sides by 2 gives
2*n == 4*x == x (because 4 == 1)
Since we want x small we take x = 2 * n % 3 and y = (n-5*x)/3
There is no solution if y < 0.