Map rand5 to number in range - algorithm

I Have a function called Rand5, that gives a random number between 1..5.
I call Rand5 three time in a row, so i have three numbers between 1-5. For example: (1,1,1),(1,2,5), etc.
There are 125 possible options, and I want to map the 125 options to numbers between 1 to 125.
So:
(1,1,1) map to 1.
(1,1,5) map to 5.
(1,2,2) map to 7.
(5,5,5) map to 125.
Can you help me with pseudo-code.
Thanks!

Given that you have your three numbers (a,b,c), you can use this equation:
result = (a-1) * 5^2 + (b-1) * 5 + c
= 25*a + 5*b + c - 30
This is based on Rand5 returning number in [1,..,5], not [0,..4] as some random functions do...
To add a little background explanation, this equation treats the three random numbers as a three digit number in base 5:
abc(base 5) = (5^2 * a) + (5 * b) + c

Related

Advanced Algorithms Problems ("Nice Triangle"): Prime number Pyramid where every number depends on numbers above it

I'm currently studying for an advanced algorithms and datastructures exam, and I simply can't seem to solve one of the practice-problems which is the following:
1.14) "Nice Triangle"
A "nice" triangle is defined in the following way:
There are three different numbers which the triangle consists of, namely the first three prime numbers (2, 3 and 5).
Every number depends on the two numbers below it in the following way.
Numbers are the same, resulting number is also the same. (2, 2 => 2)
Numbers are different, resulting number is the remaining number. (2, 3 => 5)
Given an integer N with length L, corresponding to the base of the triangle, determine the last element at the top
For example:
Given N = 25555 (and thus L = 5), the triangle looks like this:
2
3 5
2 5 5
3 5 5 5
2 5 5 5 5
=> 2 is the result of this example
What does the fact that every number is prime have to do with the problem?
By using a naive approach (simply calculating every single row), one obtains a time-complexity of O(L^2).
However, the professor said, it's possible with O(L), but I simply can't find any pattern!!!
I'm not sure why this problem would be used in an advanced algorithms course, but yes, you can do this in O(l) = O(log n) time.
There are a couple ways you can do it, but they both rely on recognizing that:
For the problem statement, it doesn't matter what digits you use. Lets use 0, 1, and 2 instead of 2, 3, and 5. Then
If a and b are the input numbers and c is the output, then c = -(a+b) mod 3
You can build the whole triangle using c = a+b mod 3 instead, and then just negate every second row.
Now the two ways you can do this in O(log n) time are:
For each digit d in the input, calculate the number of times (call it k) that it gets added into the final sum, add up all the kd mod 3, and then negate the result if you started with an even number of digits. That takes constant time per digit. Alternatively:
recognize that you can do arithmetic on n-sized values in constant time. Make a value that is a bit mask of all the digits in n. That takes 2 bits each. Then by using bitwise operations you can calculate each row from the previous one in constant time, for O(log n) time altogether.
Here's an implementation of the 2nd way in python:
def niceTriangle(n):
# a vector of 3-bit integers mod 3
rowvec = 0
# a vector of 1 for each number in the row
onevec = 0
# number of rows remaining
rows = 0
# mapping for digits 0-9
digitmap = [0, 0, 0, 1, 1, 2, 2, 2, 2, 2]
# first convert n into the first row
while n > 0:
digit = digitmap[n % 10]
n = n//10
rows += 1
onevec = (onevec << 3) + 1
rowvec = (rowvec << 3) + digit
if rows%2 == 0:
# we have an even number of rows -- negate everything
rowvec = ((rowvec&onevec)<<1) | ((rowvec>>1)&onevec)
while rows > 1:
# add each number to its neighbor
rowvec += (rowvec >> 3)
# isolate the entries >= 3, by adding 1 to each number and
# getting the 2^2 bit
gt3 = ((rowvec + onevec) >> 2) & onevec
# subtract 3 from all the greater entries
rowvec -= gt3*3
rows -= 1
return [2,3,5][rowvec%4]

Last non-zero digits of a very large factorial

How can one calculate the last few non-zero digits of a factorial of a large number?
By large, i mean like n=10^100 or something
(EDIT : 10^100 is the magnitude of 'n' in n! )
By few, i mean till 7-8...
I tried googling it and found this -
Last non-zero digit of a factorial
I tried to expand this to last 2 non-zero digits or more, but failed...
I found other websites on google that showed how to calculate last x number of digits but it wasn't clear and i wasn't able to understand it...
Can anyone help me with this?
Also, am not able to get this, the last two non-zero digits of 99! are 64, so i figured that the last two non-zero digits of (199! / 99!) should also be 64, but they turn out to be 24, i know i am making an extremely big logical mistake in this one, am just not able to put my finger on it!
The trick to do your calculations is that you want to find 3 numbers.
The number of factors of 5 in the answer.
The number of factors of 2 in the answer.
The last few digits of all of the products of all of the other primes in the answer.
The number of factors of 5 give you the number of factors of 10. Then subtract the number of factors of 2 from the number of factors of 5. Figure out the last few digits of 2 to that power. Multiply that by the last few digits found in step 3, and you're done.
The number of factors of 5 can be worked out as follows. Take n/5 (round down). That's how many have a first factor of 5. Then n/25 (round down). That how many have a second factor of 5. Continue until you're done.
The number of factors of 2 can be worked out similarly only with the sequence 2, 4, 8, 16 instead.
The third part is tricky.
But what is easier is to do is figure out the product of all of the numbers up to and including n which are relatively prime to 2 and 5. Call that function f(n). You can calculating it by multiplying the relatively prime numbers mod 10^k. And take advantage of the fact that f(i * 10^k + j) = f(j) mod(10^k).
Then you want the last few digits of f(n)*f(n/2)*f(n/4)*f(n/5)*f(n/8)*f(n/10)*f(n/16)*.... Producing that sequence efficiently is a version of the Hamming Numbers problem. See https://rosettacode.org/wiki/Hamming_numbers for how to do that. For 10^100 there will still only be tens of thousands in this sequence - it is well under control.
For your second question about ratios, you'll need to take advantage of the following two facts. Fact 1 is that you know the right number of factors of 2 and 5 just through subtraction. The second is that if m is relatively prime to 10 then m * m^(4 * 10^(k-1) - 1) is 1 mod 10^k. So you can now "divide" mod 10^k, and figure out the last few terms of every factor of the answer that doesn't involve a 2 or a 5, then figure out the number of 0s, and the number of leftover factors of 2 or 5 that you have.
Here is a significant optimization. If you know f(n) mod 2^8 and 5^8, it isn't hard to figure it out mod 10^8. But its value mod those two can be reduced to a lookup table of modest size. The larger one you only need to store it for odd n up to 4*390625, but there are less than 800k of those. (At that point you've multiplied by all elements of the group of things not divisible by 5 mod 5^8, and that product is 1. Then the pattern repeats.) If you're using 4 byte integers, that's few MB lookup table that can be precalculated fairly easily.
I should probably explain why this trick works, because it isn't obvious and I got it wrong a couple of times. The trick is that the numbers relatively prime to 5^k form a group. Meaning each has an inverse. So if you multiply them all out, and rearrange, each has an inverse EXCEPT 5^k-1. So multiply by another copy and they pair up again including that pesky one and the product comes out to 1. Now for our f we are only interested in odd numbers not divisible by 5, but the odd ones not divisible by 5 out to 2*5^k are, mod 5^k, just a rearrangement of the ones divisible by 5 out to 5^k. We need 2 copies, hence out to 4*5^k. But we only need the odds because the even right after always has the same value as the previous odd.
Per request, here is how this works for a single example. I'll do the last 3 digits of 15!
15! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15
= (1*3*7*9*11*13) * (2*6*14) * (4*12) * (5*15) * (8) * (10)
= (1*3*7*9*11*13) * 2^3*(1*3*7) * 2^4*(1*3) * 5^2*(1*3) * 2^3*(1) * 10*(1)
= 2^11 * 5^3 * f(15) * f(15/2) * f(15/4) * f(15/5) * f(15/8) * f(15/10)
= 2^11 * 5^3 * f(15) * f(15/2) * f(15/4) * f(15/5) * f(15/8) * f(15/10)
= 10^3 * 2^8 * f(15) * f(7) * f(3) * f(3) * f(1) * f(1)
Which leads to the calculation...
256 * 27 * 21 * 3 * 3 * 1 * 1 (mod 1000)
= 368 (mod 1000)
This is correct because 15! = 1307674368000.

Algorithm for converting decimal fractions to negadecimal?

I would like to know, how to convert fractional values (say, -.06), into negadecimal or a negative base. I know -.06 is .14 in negadecimal, because I can do it the other way around, but the regular algorithm used for converting fractions into other bases doesn't work with a negative base. Dont give a code example, just explain the steps required.
The regular algorithm works like this:
You times the value by the base you're converting into. Record whole numbers, then keep going with the remaining fraction part until there is no more fraction:
0.337 in binary:
0.337*2 = 0.674 "0"
0.674*2 = 1.348 "1"
0.348*2 = 0.696 "0"
0.696*2 = 1.392 "1"
0.392*2 = 0.784 "0"
0.784*2 = 1.568 "1"
0.568*2 = 1.136 "1"
Approximately .0101011
I have a two-step algorithm for doing the conversion. I'm not sure if this is the optimal algorithm, but it works pretty well.
The basic idea is to start off by getting a decimal representation of the number, then converting that decimal representation into a negadecimal representation by handling the even powers and odd powers separately.
Here's an example that motivates the idea behind the algorithm. This is going to go into a lot of detail, but ultimately will arrive at the algorithm and at the same time show where it comes from.
Suppose we want to convert the number 0.523598734 to negadecimal (notice that I'm presupposing you can convert to decimal). Notice that
0.523598734 = 5 * 10^-1
+ 2 * 10^-2
+ 3 * 10^-3
+ 5 * 10^-4
+ 9 * 10^-5
+ 8 * 10^-6
+ 7 * 10^-7
+ 3 * 10^-8
+ 4 * 10^-9
Since 10^-n = (-10)^-n when n is even, we can rewrite this as
0.523598734 = 5 * 10^-1
+ 2 * (-10)^-2
+ 3 * 10^-3
+ 5 * (-10)^-4
+ 9 * 10^-5
+ 8 * (-10)^-6
+ 7 * 10^-7
+ 3 * (-10)^-8
+ 4 * 10^-9
Rearranging and regrouping terms gives us this:
0.523598734 = 2 * (-10)^-2
+ 5 * (-10)^-4
+ 8 * (-10)^-6
+ 3 * (-10)^-8
+ 5 * 10^-1
+ 3 * 10^-3
+ 9 * 10^-5
+ 7 * 10^-7
+ 4 * 10^-9
If we could rewrite those negative terms as powers of -10 rather than powers of 10, we'd be done. Fortunately, we can make a nice observation: if d is a nonzero digit (1, 2, ..., or 9), then
d * 10^-n + (10 - d) * 10^-n
= 10^-n (d + 10 - d)
= 10^-n (10)
= 10^{-n+1}
Restated in a different way:
d * 10^-n + (10 - d) * 10^-n = 10^{-n+1}
Therefore, we get this useful fact:
d * 10^-n = 10^{-n+1} - (10 - d) * 10^-n
If we assume that n is odd, then -10^-n = (-10)^-n and 10^{-n+1} = (-10)^{-n+1}. Therefore, for odd n, we see that
d * 10^-n = 10^{-n+1} - (10 - d) * 10^-n
= (-10)^{-n+1} + (10 - d) * (-10)^-n
Think about what this means in a negadecimal setting. We've turned a power of ten into a sum of two powers of minus ten.
Applying this to our summation gives this:
0.523598734 = 2 * (-10)^-2
+ 5 * (-10)^-4
+ 8 * (-10)^-6
+ 3 * (-10)^-8
+ 5 * 10^-1
+ 3 * 10^-3
+ 9 * 10^-5
+ 7 * 10^-7
+ 4 * 10^-9
= 2 * (-10)^-2
+ 5 * (-10)^-4
+ 8 * (-10)^-6
+ 3 * (-10)^-8
+ (-10)^0 + 5 * (-10)^-1
+ (-10)^-2 + 7 * (-10)^-3
+ (-10)^-4 + 1 * (-10)^-5
+ (-10)^-6 + 3 * (-10)^-7
+ (-10)^-8 + 6 * (-10)^-9
Regrouping gives this:
0.523598734 = (-10)^0
+ 5 * (-10)^-1
+ 2 * (-10)^-2 + (-10)^-2
+ 7 * (-10)^-3
+ 5 * (-10)^-4 + (-10)^-4
+ 1 * (-10)^-5
+ 8 * (-10)^-6 + (-10)^-6
+ 3 * (-10)^-7
+ 3 * (-10)^-8 + (-10)^-8
+ 6 * (-10)^-9
Overall, this gives a negadecimal representation of 1.537619346ND
Now, let's think about this at a negadigit level. Notice that
Digits in even-numbered positions are mostly preserved.
Digits in odd-numbered positions are flipped: any nonzero, odd-numbered digit is replaced by 10 minus that digit.
Each time an odd-numbered digit is flipped, the preceding digit is incremented.
Let's look at 0.523598734 and apply this algorithm directly. We start by flipping all of the odd-numbered digits to give their 10's complement:
0.523598734 --> 0.527518336
Next, we increment the even-numbered digits preceding all flipped odd-numbered digits:
0.523598734 --> 0.527518336 --> 1.537619346ND
This matches our earlier number, so it looks like we have the makings of an algorithm!
Things get a bit trickier, unfortunately, when we start working with decimal values involving the number 9. For example, let's take the number 0.999. Applying our algorithm, we start by flipping all the odd-numbered digits:
0.999 --> 0.191
Now, we increment all the even-numbered digits preceding a column that had a value flipped:
0.999 --> 0.191 --> 1.1(10)1
Here, the (10) indicates that the column containing a 9 overflowed to a 10. Clearly this isn't allowed, so we have to fix it.
To figure out how to fix this, it's instructive to look at how to count in negabinary. Here's how to count from 0 to 110:
000
001
002
003
...
008
009
190
191
192
193
194
...
198
199
180
181
...
188
189
170
...
118
119
100
101
102
...
108
109
290
Fortunately, there's a really nice pattern here. The basic mechanism works like normal base-10 incrementing: increment the last digit, and if it overflows, carry a 1 into the next column, continuing to carry until everything stabilizes. The difference here is that the odd-numbered columns work in reverse. If you increment the -10s digit, for example, you actually subtract one rather than adding one, since increasing the value in that column by 10 corresponds to having one fewer -10 included in your sum. If that number underflows at 0, you reset it back to 9 (subtracting 90), then increment the next column (adding 100). In other words, the general algorithm for incrementing a negadecimal number works like this:
Start at the 1's column.
If the current column is at an even-numbered position:
Add one.
If the value reaches 10, set it to zero, then apply this procedure to the preceding column.
If the current column is at an odd-numbered position:
Subtract one.
If the values reaches -1, set it to 9, then apply this procedure to the preceding column.
You can confirm that this math works by generalizing the above reasoning about -10s digits and 100s digits and realizing that overflowing an even-numbered column corresponding to 10k means that you need to add in 10k+1, which means that you need to decrement the previous column by one, and that underflowing an odd-numbered column works by subtracting out 9 ยท 10k, then adding in 10k+1.
Let's go back to our example at hand. We're trying to convert 0.999 into negadecimal, and we've gotten to
0.999 --> 0.191 --> 1.1(10)1
To fix this, we'll take the 10's column and reset it back to 0, then carry the 1 into the previous column. That's an odd-numbered column, so we decrement it. This gives the final result:
0.999 --> 0.191 --> 1.1(10)1 --> 1.001ND
Overall, for positive numbers, we have the following algorithm for doing the conversion:
Processing digits from left to right:
If you're at an odd-numbered digit that isn't zero:
Replace the digit d with the digit 10 - d.
Using the standard negadecimal addition algorithm, increment the value in the previous column.
Of course, negative numbers are a whole other story. With negative numbers, the odd columns are correct and the even columns need to be flipped, since the parity of the (-10)k terms in the summation flip. Consequently, for negative numbers, you apply the above algorithm, but preserve the odd columns and flip the even columns. Similarly, instead of incrementing the preceding digit when doing a flip, you decrement the preceding digit.
As an example, suppose we want to convert -0.523598734 into negadecimal. Applying the algorithm gives this:
-0.523598734 --> 0.583592774 --> 0.6845(10)2874 --> 0.684402874ND
This is indeed the correct representation.
Hope this helps!
For your question i thought about this object-oriented code. I am not sure although. This class takes two negadecimals numbers with an operator and creates an equation, then converts those numbers to decimals.
public class NegadecimalNumber {
private int number1;
private char operator;
private int number2;
public NegadecimalNumber(int a, char op, int b) {
this.number1 = a;
this.operator = op;
this.number2 = b;
}
public int ConvertNumber1(int a) {
int i = 1;
int nega, temp;
temp = a;
int n = a & (-10);
while (n > 0) {
temp = a / (-10);
n = temp % (-10);
n = n * i;
i = i * 10;
}
nega = n;
return nega;
}
public int ConvertNumber2(int b) {
int i = 1;
int negb, temp;
temp = b;
int n = b & (-10);
while (n > 0) {
temp = b / (-10);
n = temp % (-10);
n = n * i;
i = i * 10;
}
negb = n;
return negb;
}
public double Equation() {
double ans = 0;
if (this.operator == '+') {
ans = this.number1 + this.number2;
} else if (this.operator == '-') {
ans = this.number1 - this.number2;
} else if (this.operator == '*') {
ans = this.number1 * this.number2;
} else if (this.operator == '/') {
ans = this.number1 / this.number2;
}
return ans;
}
}
Note that https://en.wikipedia.org/wiki/Negative_base#To_Negative_Base tells you how to convert whole numbers to a negative base. So one way to solve the problem is simply to multiply the fraction by a high enough power of 100 to turn it into a whole number, convert, and then divide again: -0.06 = -6 / 100 => 14/100 = 0.14.
Another way is to realise that you are trying to create a sum of the form -a/10 + b/100 -c/1000 + d/10000... to approximate the target number so you want to reduce the error as much as possible at each stage, but you need to leave an error in the direction that you can correct at the next stage. Note that this also means that a fraction might not start with 0. when converted. 0.5 => 1.5 = 1 - 5/10.
So to convert -0.06. This is negative and the first digit after the decimal point is in the range [0.0, -0.1 .. -0.9] so we start with 0. to leave us -0.06 to convert. Now if the first digit after the decimal point is 0 then I have -0.06 left, which is in the wrong direction to convert with 0.0d so I need to chose the first digit after the decimal point to produce an approximation below my target -0.06. So I chose 0.1, which is actually -0.1 and leaves me with an error of 0.04, which I can convert exactly leaving me the conversion of 0.14.
So at each point output the digit which gives you either
1) The exact result, in which case you are finished
2) An approximation which is slightly larger than the target number, if the next digit will be negative.
3) An approximation which is slightly smaller than the target number, if the next digit will be positive.
And if you start off trying to approximate a number in the range (-1.0, 0.0] at each point you can choose a digit which keeps the remaining error small enough and in the right direction, so this always works.

Looping through all combinations of two sets of numbers such that the total of their multiplication goes in decreasing order

For example. Loop through all combinations of 1-99 and 1-99 such that the total of their multiplication goes in descending order.
99 * 99 = 9801
99 * 98 = 9702
98 * 98 = 9604
99 * 97 = 9603
98 * 97 = 9506
99 * 96 = 9504
...
5 * 1 = 5
2 * 2 = 4
4 * 1 = 4
3 * 1 = 3
2 * 1 = 2
1 * 1 = 1
I've tried for a few days to come up with a pattern. At this point I think it's pretty much impossible to do without performing the multiplications first. Has anyone done this?
Here's a merge-sort style divide-and-conquer approach that uses O(log n) memory and O(n log n) time. It cuts the range of the first number in the product in half, and then lazily merges the results of lazily generating the products. I've used a trick of making the products negative in the generator so that the results come out in descending rather than ascending order.
import heapq
def inorder(a0, a1):
if a1 - a0 == 1:
return ((-a0*b, a0, b) for b in xrange(a0, 0, -1))
am = (a0 + a1) // 2
return heapq.merge(inorder(a0, am), inorder(am, a1))
for r, a, b in inorder(1, 100):
print a, '*', b, '=', -r
This question is essentially a duplicate of Order (a,b) pairs by result of a*b
I've looked through all answers for the question and still believe mine is the best, although it's not the one that was accepted. :)
The key point is this:
assume a * b = c such that c is currently the biggest product that you can get
then is the next biggest product (a - 1) * b or a * (b - 1)?
we don't know unless we compare them, hence we need to maintain a priority queue
so in each iteration, we take the biggest product from the priority queue, then add to the priority queue (a - 1) * b and a * (b - 1)
But if you need to loop through ALL combinations anyway, by far the simplest solution would be to generate all products then sort. It's only 10000 items, so any efficiency gain by using the above method will be minimal.

How can I take the modulus of two very large numbers?

I need an algorithm for A mod B with
A is a very big integer and it contains digit 1 only (ex: 1111, 1111111111111111)
B is a very big integer (ex: 1231, 1231231823127312918923)
Big, I mean 1000 digits.
To compute a number mod n, given a function to get quotient and remainder when dividing by (n+1), start by adding one to the number. Then, as long as the number is bigger than 'n', iterate:number = (number div (n+1)) + (number mod (n+1))Finally at the end, subtract one. An alternative to adding one at the beginning and subtracting one at the end is checking whether the result equals n and returning zero if so.
For example, given a function to divide by ten, one can compute 12345678 mod 9 thusly:
12345679 -> 1234567 + 9
1234576 -> 123457 + 6
123463 -> 12346 + 3
12349 -> 1234 + 9
1243 -> 124 + 3
127 -> 12 + 7
19 -> 1 + 9
10 -> 1
Subtract 1, and the result is zero.
1000 digits isn't really big, use any big integer library to get rather fast results.
If you really worry about performance, A can be written as 1111...1=(10n-1)/9 for some n, so computing A mod B can be reduced to computing ((10^n-1) mod (9*B)) / 9, and you can do that faster.
Try Montgomery reduction on how to find modulo on large numbers - http://en.wikipedia.org/wiki/Montgomery_reduction
1) Just find a language or package that does arbitrary precision arithmetic - in my case I'd try java.math.BigDecimal.
2) If you are doing this yourself, you can avoid having to do division by using doubling and subtraction. E.g. 10 mod 3 = 10 - 3 - 3 - 3 = 1 (repeatedly subtracting 3 until you can't any more) - which is incredibly slow, so double 3 until it is just smaller than 10 (e.g. to 6), subtract to leave 4, and repeat.

Resources