Numbers counting function - java

I have this assignment in school; we are to write a simple program/method/algorithm in java that has us take two numerical inputs and output count of all the numbers in the range between two inputs which are dividable by 2 or 3 or 5.
The assignment is fairly simple, since you can just iterate through all the numbers in range and increment the counter whenever all the criteria is met.
But we also get 10 test inputs and a timer that evaluates the efficiency of our algorithm. First eight fell through, since the eight values were < 10^6. But the last two test input vales were < 10^18 and my algorithm failed.
So I started thinking in the direction of prime number counting function and sieve Eratosthenes, but my head started to hurt. Any ideas on a faster but still simple enough algorithm?

I came up with something like that
public static void main(String[] args) {
long a = 123456789012345678L, b = 876543210987654321L;
long score = getCount(b) - getCount(a - 1);
System.out.println("Divisible by 2 or 3 or 5: " + score);
}
public static long getCount(long end) {
return (end / 2) + (end / 3) + (end / 5) - ((end / 6) + (end / 10) + (end / 15)) + (end / 30);
}
The solution:
It counts how many numbers are divisible by 2 or 3 or 5 separately and sums that.
Now we need to discard numbers that where counted twice: for 2 and 3 it will be every 6th number, for 2 and 5 every 10th number, for 3 and 5 every 15th number
At the end we need to include numbers that are divisible by 2 and 3 and 5 that where discarded in step 2 so we add every 30th number.

Related

print random characters without repeat in square?

I'm generating random characters via my code below:
static void printRandomWhatEver(int NUMBER_OF_CHARACTER,
int NUMBER_OF_LINES,
char char1, char char2) {
int DIFFERENCE_SQUARE = 4;
char oldChar, newChar, random;
for (int i = 0; i < NUMBER_OF_CHARACTER; i++) {
random = getRandomCharacter(char1, char2);
if ((i + 1) % NUMBER_OF_LINES == 0) { // new line each new NUMBER_OF_LINE
System.out.println(random);
} else {
System.out.print(random);
}
}
}
My getReandomCharacter:-
private static char getRandomCharacter(char ch1, char ch2) {
return (char) (ch1 + Math.random() * (ch2 - ch1 + 1));
}
All working fine, what i need is the chars inside square 2*2 numbers to not be equal, here is image to explain what i need.
The digit 4 is in the same square:-
**
**
How i can prevent digits to be equal in a part of square?
Thanks in advance.
Just store the last line of your output, and compare the digit at position N to the digits last_line[N-1], last_line[N] and last_line[N+1]. Take care of the array boundaries for N-1 and N+1.
But you should be aware that you reduce the strength of your random number generator this way. To a human it will most likely look "more random", though.
But there may be even more patterns a human may recognize as "not random", e.g. sequential digits:
154
298
364
To avoid repeats you are better off shuffling rather than picking randomly. You will have to repeatedly select different groups of digits to shuffle to avoid repeats.
To start, pick four digits from [0..9] and shuffle them:
0 1
2 3
Working from left to right, the next two digits come from [0, 2, 4..9] with 1 and 3 omitted:
0 1 7
2 3 8
Repeat the process, adding two from the eight possible digits at a time.
Use a similar "pick two from seven" process to add digits in the next row. You only have seven digits to pick from because it is dangerous to pick an '8' in the given configuration:
0 1 7
2 3 8
1 8
Would be an error, so the '8' cannot be picked:
0 1 7
2 3 8
1 5
Is safe.
Once you move away from the left hand edge, you will be picking from six, as there will be four digits in the row above that you must avoid.
ETA: Working with two rows is overly complex. Generate one row at a time, with any existing adjacent digits cut out of the pre-shuffle selection. That will be 3 digits in the row above, plus the previous digit in the current row, with appropriate adjustments for left and right boundaries.

Analyzing runtime of a short algorithm

I got the following code given:
public class alg
{
public static int hmm (int x)
{
if (x == 1)
{
return 2;
}
return 2*x + hmm(x-1);
}
public static void main (String[] args)
{
int x = Integer.parseInt(args[0]);
System.out.println(hmm(x));
}
}
So first question is, what does this algorithm count?
I have just typed and runned it in eclipse
so I can see better what it does (it was pseudocode before, I couldn't type it here so I typed the code). I have realized that this algorithm does following: It will take the input and multiply it by its following number.
So as examples:
input = 3, output = 12 because 3*4 = 12.
Or Input = 6, output 42 because 6*7 = 42.
Alright, the next question is my problem. I'm asked to analyze the runtime of this algorithm but I have no idea where to start.
I would say, at the beginning, when we define x, we have already got time = 1
The if loop gives time = 1 too I believe.
Last part, return 2x + alg(x-1) should give "something^x" or..?
So in the end we got something like "something^x" + 2, I doubt thats right : /
edit, managed to type pseudocode too :)
Input: Integer x with x > 1
if x = 1 then
return 2;
end if
return 2x + hmm(x-1);
When you have trouble, try to walk through the code with a (small) number.
What does this calculate?
Let's take hmm(3) as an example:
3 != 1, so we calculate 2 * 3 + hmm(3-1). Down a recursion level.
2 != 1, so we calculate 2 * 2 + hmm(2-1). Down a recursion level.
1 == 1, so we return 2. No more recursions, thus hmm(2-1) == hmm(1) == 2.
Back up one recursion level, we get 2 * 2 + hmm(1) = 2 * 2 + 2 = 4 + 2 = 6. Thus hmm(2) = 6
Another level back up, we get 2 * 3 + hmm(2) = 6 + 6 = 12
If you look closely, the algorithm calculates:
2*x + ... + 4 + 2
We can reverse this and factor out 2 and get
2 * (1 + 2 + ... + x).
Which is an arithmetic progression, for which we have a well-known formula (namely x² + x)
How long does it take?
The asymptotic running time is O(n).
There are no loops, so we only have to count the number of recursions. One might be tempted to count the individual steps of calculation, but those a are constant with every step, so we usually combine them into a constant factor k.
What does O(n) mean?
Well ... we make x - 1 recursion steps, decreasing x by 1 in every step until we reach x == 1. From x = n to x = 1 there are n - 1 such steps. We thus need k * (n - 1) operations.
If you think n to be very large, - 1 becomes negligible, so we drop it. We also drop the constant factor, because for large n, O(nk) and O(n) aren't that much different, either.
The function calculates
f(x) = 2(x + x-1 + x-2 + ... + 1)
it will run in O(x), i.e. x times will be called for constant time O(1).

how a splitting number to a separate digits algorithm works

i'm getting back to software development and i was playing around with algorithms in java,and today i'm doing the algorithm the splits a number to a separate digits, I've found it here i wrote it in java ..it works but honestly i don't how ?? there is the code just i didn't understand a part of it :
public static void main(String[] args) {
Integer test = 0, i, N;
ArrayList array_one= new ArrayList<Integer>();
Scanner sc = new Scanner(System.in);
System.out.print("Write An Integer :");
test = sc.nextInt();
while (test > 0){
int mod = test % 10; // <= DON'T UNDERSTAND THE WORK OF THAT PART
// (i know it's the modulo of the entered value)
test = test / 10;
array_one.add(mod);
}
System.out.print(array_one);
}
i know it's a newbie question i'm just passionate about software engineering and algorithms just want to know how it exactly works and thks in advance.
test % 10; gives you the last (least significant) digit of the number, which is the remainder when dividing the number by 10.
test = test / 10 reduces the number by one digit (123456 becomes 12345), making the former 2nd least significant digit the new least significant digit. Therefore, in the next iteration, test % 10; would return the 2nd digit.
And so on...
test % 10; --> Always gives you the last digit.
test / 10; --> divides the existing number by 10.
while loop --> executes until test > 0
So, if your number is 234,
234%10 would be 4
234/10 would be 23.4 which will be converted to 23.
Apply 23 % 10 and 23/10 and so on..
By using %10 you'll get only the last digit.
/10 will give what is before your last digit.
And so you can construct your array.
124%10 --> 4
124/10 --> 12 % 10 --> 2
12 / 10 --> 1
The logic used here is to separate the units place first by dividing the number by 10 and getting the reminder value.
e.g x=153
"% " is the modulus operator that gives the remainder of the division
"/" is the division operator that gives only the quotient
then 153%10= 3 //this is the remainder that separates the first digit.
The number is then divided by 10 so as to get the quotient
i.e 153/10 =15 // Only the quotient
Progressing with the loop, now 15 is taken as the new original number and is again divided by 10 to get the remainder and hence the next digit.
i.e 15%10 =5 //next digit
15/10=1;
1%10=1 //digit
1/10=0 //The loop ends here
You can understand it by an example
Your number to divide it's digits is 345
If you divide it by 10 your remaining and first digit is 5

From 5 dice rolls, generate a random number in the range [1 - 100]

I was going through some coding exercises, and had some trouble with this question:
From 5 dice (6-sided) rolls, generate a random number in the range [1 - 100].
I implemented the following method, but the returned number is not random (called the function 1,000,000 times and several numbers never show up in 1 - 100).
public static int generator() {
Random rand = new Random();
int dices = 0;
for(int i = 0; i < 5; i++) {
dices += rand.nextInt(6) + 1;
}
int originalStart = 5;
int originalEnd = 30;
int newStart = 1;
int newEnd = 100;
double scale = (double) (newEnd - newStart) / (originalEnd - originalStart);
return (int) (newStart + ((dices - originalStart) * scale));
}
Ok, so 5 dice rolls, each with 6 options. if they are un-ordered you have a range of 5-30 as mentioned above - never sufficient for 1-100.
You need to assume an order, this gives you a scale of 1,1,1,1,1 - 6,6,6,6,6 (base 6) assuming 1 --> 0 value, you have a 5 digit base 6 number generated. As we all know 6^5 = 7776 unique possibilities. ;)
For this I am going to give you a biased random solution.
int total = 0;
int[] diceRolls;
for (int roll : diceRolls) {
total = total*6 + roll - 1;
}
return total % 100 + 1;
thanks to JosEdu for clarifying bracket requirement
Also if you wanted to un-bias this, you could divide range by the maxval given in my description above, and subsequently multiply by your total (then add offset), but you would still need to determine what rounding rules you used.
Rolling a 6 sided die 5 times results in 6^5 = 7776 possible sequences, all equally probable. Ideally you'd want to partition those sequences into 100 groups of equal size and you'd have your [1 - 100] rng, but since 7776 isn't evenly divisible by 100 this isn't possible. The best you can do to minimize the bias is 76 groups mapped to by 78 sequences each and 24 groups mapped to by 77 sequences each. Encode the (ordered) dice rolls as a base 6 number n, and return 1 + (n % 100).
Not only is there no way to remove the bias with 5 dice rolls, there is no number of dice rolls that will remove the bias entirely. There is no value of k for which 6^k is evenly divisible by 100 (consider the prime factorizations). That doesn't mean there's no way to remove the bias, it just means you can't remove the bias using a procedure that is guaranteed to terminate after any specific number of dice rolls. But you could for example do 3 dice rolls producing 6^3 = 216 sequences encoded as the base 6 number n, and return 1 + (n % 100) if n < 200. The catch is that if n >= 200 you have to repeat the procedure, and keep repeating until you get n < 200. That way there's no bias but there's also no limit to how long you might be stuck in the loop. But since the probability of having to repeat is only 16/216 each time, from a practical standpoint it's not really much of a problem.
The problem is there aren't enough random values in 5-30 to map one to one to 1-100 interval. This means certain values are destined to never show up; the amount of these "lost" values depends on the size ratio of the two intervals.
You can leverage the power of your dice in a way more efficient way, however. Here's how I'd do it:
Approach 1
Use the result of the first dice to choose one subinterval from the
6 equal subintervals with size 16.5 (99/6).
Use the result of the second dice to choose one subinterval from the 6 equal sub-subintervals of the subinterval you chose in step one.
Use... I guess you know what follows next.
Approach 2
Construct your random number using digits in a base-6 system. I.E. The first dice will be the first digit of the base-6 number, the second dice - the second digit, etc.
Then convert to base-10, and divide by (46656/99). You should have your random number. You could in fact only use 3 dice, of course, the rest two are just redundant.

Calculate the number of ways to roll a certain number

I'm a high school Computer Science student, and today I was given a problem to:
Program Description: There is a belief among dice players that in
throwing three dice a ten is easier to get than a nine. Can you write
a program that proves or disproves this belief?
Have the computer compute all the possible ways three dice can be
thrown: 1 + 1 + 1, 1 + 1 + 2, 1 + 1 + 3, etc. Add up each of these
possibilities and see how many give nine as the result and how many
give ten. If more give ten, then the belief is proven.
I quickly worked out a brute force solution, as such
int sum,tens,nines;
tens=nines=0;
for(int i=1;i<=6;i++){
for(int j=1;j<=6;j++){
for(int k=1;k<=6;k++){
sum=i+j+k;
//Ternary operators are fun!
tens+=((sum==10)?1:0);
nines+=((sum==9)?1:0);
}
}
}
System.out.println("There are "+tens+" ways to roll a 10");
System.out.println("There are "+nines+" ways to roll a 9");
Which works just fine, and a brute force solution is what the teacher wanted us to do. However, it doesn't scale, and I am trying to find a way to make an algorithm that can calculate the number of ways to roll n dice to get a specific number. Therefore, I started generating the number of ways to get each sum with n dice. With 1 die, there is obviously 1 solution for each. I then calculated, through brute force, the combinations with 2 and 3 dice. These are for two:
There are 1 ways to roll a 2 There are 2 ways to roll a 3
There are 3 ways to roll a 4 There are 4 ways to roll a 5
There are 5 ways to roll a 6 There are 6 ways to roll a 7
There are 5 ways to roll a 8 There are 4 ways to roll a 9
There are 3 ways to roll a 10 There are 2 ways to roll a 11
There are 1 ways to roll a 12
Which looks straightforward enough; it can be calculated with a simple linear absolute value function. But then things start getting trickier. With 3:
There are 1 ways to roll a 3 There are 3 ways to roll a 4
There are 6 ways to roll a 5 There are 10 ways to roll a 6
There are 15 ways to roll a 7 There are 21 ways to roll a 8
There are 25 ways to roll a 9 There are 27 ways to roll a 10
There are 27 ways to roll a 11 There are 25 ways to roll a 12
There are 21 ways to roll a 13 There are 15 ways to roll a 14
There are 10 ways to roll a 15 There are 6 ways to roll a 16
There are 3 ways to roll a 17 There are 1 ways to roll a 18
So I look at that, and I think: Cool, Triangular numbers! However, then I notice those pesky 25s and 27s. So it's obviously not triangular numbers, but still some polynomial expansion, since it's symmetric.
So I take to Google, and I come across this page that goes into some detail about how to do this with math. It is fairly easy(albeit long) to find this using repeated derivatives or expansion, but it would be much harder to program that for me. I didn't quite understand the second and third answers, since I have never encountered that notation or those concepts in my math studies before. Could someone please explain how I could write a program to do this, or explain the solutions given on that page, for my own understanding of combinatorics?
EDIT: I'm looking for a mathematical way to solve this, that gives an exact theoretical number, not by simulating dice
The solution using the generating-function method with N(d, s) is probably the easiest to program. You can use recursion to model the problem nicely:
public int numPossibilities(int numDice, int sum) {
if (numDice == sum)
return 1;
else if (numDice == 0 || sum < numDice)
return 0;
else
return numPossibilities(numDice, sum - 1) +
numPossibilities(numDice - 1, sum - 1) -
numPossibilities(numDice - 1, sum - 7);
}
At first glance this seems like a fairly straightforward and efficient solution. However you will notice that many calculations of the same values of numDice and sum may be repeated and recalculated over and over, making this solution probably even less efficient than your original brute-force method. For example, in calculating all the counts for 3 dice, my program ran the numPossibilities function a total of 15106 times, as opposed to your loop which only takes 6^3 = 216 executions.
To make this solution viable, you need to add one more technique - memoization (caching) of previously calculated results. Using a HashMap object, for example, you can store combinations that have already been calculated and refer to those first before running the recursion. When I implemented a cache, the numPossibilities function only runs 151 times total to calculate the results for 3 dice.
The efficiency improvement grows larger as you increase the number of dice (results are based on simulation with my own implemented solution):
# Dice | Brute Force Loop Count | Generating-Function Exec Count
3 | 216 (6^3) | 151
4 | 1296 (6^4) | 261
5 | 7776 (6^5) | 401
6 | 46656 (6^6) | 571
7 | 279936 (6^7) | 771
...
20 | 3656158440062976 | 6101
You don't need to brute force since your first roll determines what values can be used in the second roll, and both first and second roll determine the third roll. Let's take the tens example, suppose you roll a 6, so 10-6=4 meaning you still need 4. For the second roll you need at least 3, because your third roll should at least count for 1. So the second roll goes from 1 to 3. Suppose your second roll is 2, you have 10-6-2=2, meaning your third roll IS a 2, there is no other way.
Pseudo code for tens:
tens = 0
for i = [1..6] // first roll can freely go from 1 to 6
from_j = max(1, 10 - i - 6) // We have the first roll, best case is we roll a 6 in the third roll
top_j = min(6, 10 - i - 1) // we need to sum 10, minus i, minus at least 1 for the third roll
for j = [from_j..to_j]
tens++
Note that each loop adds 1, so at the end you know this code loops exactly 27 times.
Here is the Ruby code for all 18 values (sorry it's not Java, but it can be easily followed). Note the min and max, that determine what values can have each of the dice rolls.
counts = [0] * 18
1.upto(18) do |n|
from_i = [1, n - 6 - 6].max # best case is we roll 6 in 2nd and 3rd roll
top_i = [6, n - 1 -1].min # at least 1 for 2nd and 3rd roll
from_i.upto(top_i) do |i|
from_j = [1, n - i - 6].max # again we have the 2nd roll defined, best case for 3rd roll is 6
top_j = [6, n - i -1].min # at least 1 for 3rd roll
from_j.upto(top_j) do
# no need to calculate k since it's already defined being n - first roll - second roll
counts[n-1] += 1
end
end
end
print counts
For a mathematical approach, take a look at https://math.stackexchange.com/questions/4632/how-can-i-algorithmically-count-the-number-of-ways-n-m-sided-dice-can-add-up-t
Mathematical description is just a 'trick' to make same counting. It uses polynomial to express dice, 1*x^6 + 1*x^5 + 1*x^4 + 1*x^3 + 1*x^2 + 1*x means that each value 1-6 is counted once, and it uses polynomial multiplication P_1*P_2 for a counting of different combinations. That is done since coefficient at some exponent (k) is calculated by summing all coefficient in P_1 and P_2 which exponent sum to k.
E.g. for two dices we have:
(1*x^6 + 1*x^5 + 1*x^4 + 1*x^3 + 1*x^2 + 1*x) * (x^6 + x^5 + x^4 + x^3 + x^2 + x) =
(1*1)*x^12 + (1*1 + 1*1)*x^11 + (1*1 + 1*1 + 1*1)*x^11 + ... + (1*1 + 1*1)*x^3 + (1*1)*x^2
Calculation by this method has same complexity as 'counting' one.
Since function (x^6 + x^5 + x^4 + x^3 + x^2 + x)^n has simpler expression (x(x-1)^6/(x-1))^n, it is possible to use derivation approach. (x(x-1)^6/(x-1))^n is a polynomial, and we are looking for coefficient at x^s (a_s). Free coefficient (at x^0) of s'th derivation is s! * a_k. So, s'th derivation in 0 is s! * a_k.
So, we have to derive this function s times. It can be done using derivation rules, but I think that it will have even worse complexity than counting approach since each derivation produces 'more complex' function. Here are first three derivations from Wolfram Alpha: first, second and third.
In general, I prefer counting solution, and mellamokb gave nice approach and explanation.
Check out Monte Carlo Methods they usually scale linearly with inputsize. In this case the example is easy, we assume that since once throw of the dice doesn't affect the other instead of counting combinations we can simply count the sum of the faces of dices thrown randomly (many times enough).
public class MonteCarloDice {
private Map<Integer, Integer> histogram;
private Random rnd;
private int nDice;
private int n;
public MonteCarloDice(int nDice, int simulations) {
this.nDice = nDice;
this.n = simulations;
this.rnd = new Random();
this.histogram = new HashMap<>(1000);
start();
}
private void start() {
for (int simulation = 0; simulation < n; simulation++) {
int sum = 0;
for (int i = 0; i < nDice; i++) {
sum += rnd.nextInt(6) + 1;
}
if (histogram.get(sum) == null)
histogram.put(sum, 0);
histogram.put(sum, histogram.get(sum) + 1);
}
System.out.println(histogram);
}
public static void main(String[] args) {
new MonteCarloDice(3, 100000);
new MonteCarloDice(10, 1000000);
}
}
The error decreases with number of simulations but at the cost of cputime but the above values were pretty fast.
3 dice
{3=498, 4=1392, 5=2702, 6=4549, 7=7041, 8=9844, 9=11583, 10=12310, 11=12469, 12=11594, 13=9697, 14=6999, 15=4677, 17=1395, 16=2790, 18=460}
10 dice
{13=3, 14=13, 15=40, 17=192, 16=81, 19=769, 18=396, 21=2453, 20=1426, 23=6331, 22=4068, 25=13673, 24=9564, 27=25136, 26=19044, 29=40683, 28=32686, 31=56406, 30=48458, 34=71215, 35=72174, 32=62624, 33=68027, 38=63230, 39=56008, 36=71738, 37=68577, 42=32636, 43=25318, 40=48676, 41=40362, 46=9627, 47=6329, 44=19086, 45=13701, 51=772, 50=1383, 49=2416, 48=3996, 55=31, 54=86, 53=150, 52=406, 59=1, 57=2, 56=7}

Categories

Resources