The task is to count all the possible paths from top left to bottom right of a mXn matrix with the constraints that from each cell you can either move only to right or down.
int[][] count = new int[n][m];
int i,j;
for (i = 0; i < n; i++)
count[i][0] = 1;
for (i = 0; i < m; i++)
count[0][i] = 1;
for (i = 1; i < n; i++)
for (j = 1; j < m; j++)
count[i][j] = (count[i - 1][j] + count[i][j - 1]);
System.out.println(count[n - 1][m - 1]);
The above code shows the wrong answers for large values of m and n.
Using long arrays is also not working.
In one of the correct solutions, the formula
`count[i][j]=(count[i-1][j]+count[i][j-1])%((int)Math.pow(10,9)+7);
is used!
I cannot understand the reason for the same.
Testing with a square size and using int, you can calculate up to 17x17. With 18x18 you get numeric overflow.
To detect the numeric overflow, change the following line:
count[i][j] = (count[i - 1][j] + count[i][j - 1]);
To:
count[i][j] = Math.addExact(count[i - 1][j], count[i][j - 1]);
Running with 18x18 you then get java.lang.ArithmeticException: integer overflow, while 17x17 prints 601080390.
Changing to long raises the limit to 34x34 = 7219428434016265740, and 35x35 fails.
To go beyond that, use BigInteger:
private static void count(int n, int m) {
BigInteger[][] count = new BigInteger[n][m];
for (int i = 0; i < n; i++)
count[i][0] = BigInteger.ONE;
for (int i = 0; i < m; i++)
count[0][i] = BigInteger.ONE;
for (int i = 1; i < n; i++)
for (int j = 1; j < m; j++)
count[i][j] = count[i - 1][j].add(count[i][j - 1]);
System.out.println(n + "x" + m + ": " + count[n - 1][m - 1]);
}
You can now calculate for very large sizes:
public static void main(String[] args) {
for (int i = 10; i < 150; i+=10)
count(i,i);
}
Output
10x10: 48620
20x20: 35345263800
30x30: 30067266499541040
40x40: 27217014869199032015600
50x50: 25477612258980856902730428600
60x60: 24356699707654619143838606602026720
70x70: 23623985175715118288974865541854103729000
80x80: 23156006494021191956342707682359261381151378400
90x90: 22880174247360071687155809670095748237789263482394000
100x100: 22750883079422934966181954039568885395604168260154104734000
110x110: 22738029575969641265497648088901902565550598643635116137437818400
120x120: 22820983692956015651850538861400483591556161461874723704379950728024000
130x130: 22985198722890636106807214387141205118592781510195606858610359655612113472140
140x140: 23220197341838572012462842682887166477737842005968501197039194284526789533662125200
It takes m + n - 2 steps to travel from top left to bottom right of an m x n grid via only right and down steps: m - 1 steps right, and n - 1 steps down. Each distinct path is characterized by a particular choice of which of those steps is down (equivalently: which of those steps is right). There is an analytic solution for that:
factorial(m + n - 2) / (factorial(m - 1) * factorial(n - 1))
You may recognize that as the m-1th binomial coefficient of order m + n - 2.
You don't need to compute it that way, of course, and in fact, you need to exercise great care if you want to do so, because the factorial grows extremely rapidly. And that's why I bring it up: by whatever means you compute it, the result grows rapidly for m close to n, exceeding the range of long pretty quickly -- albeit exponentially, not factorially.
In one of the correct solutions, the formula `count[i][j]=(count[i-1][j]+count[i][j-1])%((int)Math.pow(10,9)+7); is used! I cannot understand the reason for the same.
That would not be used in a correct solution to the problem you have presented, but I have seen a modified version of this problem where it would make sense: one where you are asked to compute the result modulo 1000000007, which is exactly what the bit that has confused you does. I think I've seen that on Project Euler, but it may be other places, too. That variation on the problem allows one to completely avoid the issue of unrepresentable integers on any system that has a 32-bit integer type.
Related
Given a binary string, that is it contains only 0s and 1s (number of zeros equals the number of ones) We need to make this string a sequence of alternate characters by swapping some of the bits, our goal is to minimize the number swaps.
For example, for the string "00011011" the minimum number of swaps is 2, one way to do it is:
1) swap the bits : 00011011 --->> 00010111
2) swap the bits(after the first swap) : 00010111 --->> 01010101
Note that if we are given the string "00101011" we can turn it into an alternate string starting with 0 (that requires 3 swaps) and also into alternate string starting with 1 ( that requires one swap - the first and the last bits ).
So the minimum in this case is one swap.
The end goal is to return the minimum number of swaps for a given string of ones and zeros. What is the most efficient way to solve it?
What you are looking for is called the Levenshtein distance. It is a bit more complex since it works on all type of String not just bitstrings but based on the implementation you should be able to develop your own fitting solution. Here is an java implementation I found on Wikibooks:
public static int computeLevenshteinDistance(CharSequence lhs, CharSequence rhs) {
int[][] distance = new int[lhs.length() + 1][rhs.length() + 1];
for (int i = 0; i <= lhs.length(); i++)
distance[i][0] = i;
for (int j = 1; j <= rhs.length(); j++)
distance[0][j] = j;
for (int i = 1; i <= lhs.length(); i++)
for (int j = 1; j <= rhs.length(); j++)
distance[i][j] = minimum(
distance[i - 1][j] + 1,
distance[i][j - 1] + 1,
distance[i - 1][j - 1] + ((lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1));
return distance[lhs.length()][rhs.length()];
}
Ice-Cream:
The beach stretches along the seacoast like a narrow strip. At some points of the beach the ice cream stalls are located. One day not all the ice cream sellers come to work. Distribute the sellers among the ice-cream stalls so that the minimum distance between them is as much as possible. So they will interfere less with each other.
Input:
The first line contains the number of stalls n (2 < n < 10001) and the number of ice cream sellers k (1 < k < n) at work. The second line contains n positive integers in increasing order - the coordinates of the stalls (the coordinates are not greater than 109).
Output:
Print one number - the minimum distance between the adjacent stalls in the optimal arrangement.
Input example:
5 3
1 2 3 100 1000
Output example:
99
This is what I have come up with so far. It is working not fast enough and I need other idea.
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int[] n = new int[s.nextInt()];
int k = s.nextInt();
for(int i = 0; i < n.length; i++)
{n[i] = s.nextInt();}
int c = -1;
int[] cA = new int[k + 3]; //control array
for(int j = 1; j < cA.length; j++)
{cA[j] = j - 1;}
cA[k+1] = n.length;
cA[k+2] = 0;
while(true)
{
int currentCoordinate = -1, previousCoordinate = -1, minDist = -1;
for(int i = 1; i <= k; i++)
{
if(currentCoordinate == -1)
{currentCoordinate = n[cA[i]];}
else
{
previousCoordinate = currentCoordinate;
currentCoordinate = n[cA[i]];
int currentDistance = currentCoordinate - previousCoordinate;
if(minDist == -1 || minDist > currentDistance)
{minDist = currentDistance;}
}
}
if(minDist > c)
{c = minDist;}
int j = 1;
while(cA[j] + 1 == cA[j + 1])
{cA[j] = j - 1; j++;}
if(j > k)
{break;}
cA[j] = cA[j] + 1;
}
System.out.println(c);
}
}
This problem is solvable using binary search. First assume the answer is x. It means the minimum distance between two stalls is x. A greedy approach can verify this assumption. It is obvious that in the best configuration we have to use the leftmost stall (Can be easily proven by contradiction). Now traverse the points from left to right until the distance between the leftmost point and the rightmost point is less than x. Upon reaching to the first point (pi) that its distance to the leftmost point is bigger than x increment your counter. From now on your leftmost is px. Repeat this process until you reach the end of the points. Now if your counter is bigger than k it means that you can increase the value of x and vice versa.
So you can binary search to find the minimum value for x. This approach is in O(nLogn).
My assignment is to convert binary to decimal in a JLabel array without using pre-written methods (there's no user input). I have the right idea but for some reason the output is always a little bit off. I've gone through it countless times but I can't find anything wrong with my algorithm and I'm very confused as to why it doesn't produce the correct answer. I'd be very grateful if someone could help me out. Thanks!
Side note: I've read similar discussion threads regarding binary to decimal conversions but I don't understand how to do it with arrays.
Here is a snippet of my code:
private void convert()
{
int[] digit = new int[8]; //temporary storage array
int count = 0;
for(int x = 0; x < digit.length; x++)
{
digit[x] = Integer.parseInt(bits[x].getText()); //bits is the original array
count= count + digit[digit.length - 1 - x] * (int)(Math.pow(2, x));
}
label.setText("" + count);
}
You are following the binary number from left to right but are grabbing the wrong digit. You want the same digit but to multiply by the right power of two - first index being +n*128 and not +n*1
int count = 0;
for(int i = 0; i < bits.length; i++) {
count += Integer.parseInt(bits[i].getText()) * Math.pow(2, bits.length - i - 1);
}
Obviously there is a bug in your snippet.
You set the digit[x], but not set the digit[length - 1 - x].
for example, x = 0, you set the digit[0], but not set digit[7].
So there will be an error when you want use the digit[length - 1 -x] here :
count= count + digit[digit.length - 1 - x] * (int)(Math.pow(2, x));
This the correct code here:
private void convert()
{
int count = 0, length = 8;
for(int i = 0; i < length; count += Integer.parseInt(bits[i].getText()) * (1 << (length - 1 - i)), i++);
label.setText("" + count);
}
Have not test the code. But I think it will work.
I'm having a problem with average distance in this exercise. It should be close to the sqrt of N steps, but it's lower. Can you help me to find out where is my mistake?
2D random walk.
A two dimensional random walk simulates the behavior of a particle moving in a grid of points.
At each step, the random walker moves north, south, east, or west with probability 1/4,
independently of previous moves. Determine how far away (on average) the random walker is from the starting point after N steps.
(Theoretical answer: on the order of sqrt(N).)
public class RandomWalk{
public static void main(String[] args){
int N = Integer.parseInt(args[0]);
double nextStep = 0;
double averageDistance = 0;
int COUNT = 1000;
for (int j = 0; j < COUNT; j++){
int moveWest = 0;
int moveEast = 0;
int moveSouth = 0;
int moveNorth = 0;
double distance = 0;
for (int i = 0; i < N; i++){
nextStep = Math.random()*4;
if (nextStep <= 1) ++moveWest;
else if (nextStep <= 2) ++moveEast;
else if (nextStep <= 3) ++moveSouth;
else if (nextStep <= 4)++moveNorth;
}
moveEast = moveEast - moveWest;
moveNorth = moveNorth - moveSouth;
distance = Math.sqrt((moveEast * moveEast) + (moveNorth * moveNorth));
averageDistance += distance;
System.out.println("Walker is " + distance + "\t steps away of from the starting point");
//System.out.println("Sqrt of N is " + Math.sqrt(N));
}
System.out.println("Average distance is " + averageDistance/COUNT + " steps away of from the starting point");
}
}
I ran a few tests on your code with aforementioned change of ranges <0,1),<1,2),<2,3), <3,4) making them even.
And you do it like that:
if (nextStep < 1) ++moveWest;
else if (nextStep < 2) ++moveEast;
else if (nextStep < 3) ++moveSouth;
else if (nextStep < 4)++moveNorth;
Notice <= becoming <.
100000 trials of 100 steps each gave those resutls:
Average distance is 8.873435509749317 steps away of from the starting point
W=2498906
E=2501447
N=2500022
S=2499625
,
where W,E,N,S are summed steps for given direction during all the trials.
They look fine.
Running such a test case for a couple of times reveals that there is no preferable direction. You might use other methods to get random numbers, but that would be testing generators, not your case. Your code looks ok from my point of view.
Sentence from the problem statement also gives you a clue:Theoretical answer: on the order of sqrt(N).
I think this line won't work :
nextStep = Math.random()*4;
the explanation is a logical one. I think it would be better to use Integers for your purpose because you want to calculate with steps, wich is a static unit. Well thats opinion based, but I recommend to count the full number of steps instead of tracking partial steps.
try this instead:
Random rand = new Random();
nextStep = rand.nextInt(4)+1; //random numbers {1,2,3,4}
Furthermore since nextInt() generates random Integer values you need to use the == operator instead of <= in your if/else statements.
if (nextStep == 1) ++moveWest;
else if (nextStep == 2) ++moveEast;
else if (nextStep == 3) ++moveSouth;
else if (nextStep == 4)++moveNorth;
regards to Tom (not me, the one in the comments!)
Write a program that computes the following equation.
100/1+99/2+98/3+97/4+96/5...3/98+2/99+1/100
I am not asking for a solution. Yes this is a homework problem, but I am not here to copy paste the answers. I asked my professor to explain the problem or how should I approach this problem? She said "I can't tell you anything."
public static void main(String[] args){
int i;
for(i = 100; i >= 1; i--)
{
int result = i/j;
j = j+1;
System.out.println(result);
}
}
You can try to observe a "trend" or "pattern" when solving questions of this type.
Given: 100/1+99/2+98/3+97/4+96/5...3/98+2/99+1/100
We derived: Numerator/Denominator, let's call it n divide by d (n/d)
Pattern Observed:
n - 1 after every loop
d + 1 after every loop
So, if you have 100 numbers, you need to loop 100 times. Thus using a for-loop which loops 100 times will seemed appropriate:
for(int n=0; n<100; n++) //A loop which loops 100 times from 0 - 100
To let n start with 100, we change the loop a little to let n start from 100 instead of 0:
for(int n=100; n>0; n--) //A loop which loops 100 times from 100 - 0
You settled n, now d needs to start from 1.
int d = 1; //declare outside the loop
Putting everything together, you get:
int d = 1;
double result = 0.0;
for (int n=100; n>0; x--)
{
result += (double)n/d; //Cast either n or d to double, to prevent loss of precision
d ++; //add 1 to d after every loop
}
You are on the right track. You need to loop like you've done, but then you need to SUM up all the results. In your example you can try:
result = result + i/j;
or
result += i/j;
Note that the declaration of result needs to be outside the loop otherwise you are always initializing it.
Also think about the division (hint), you are dividing integers...
What you have is a series.
There is more than one way to define a series, but all things being the same it's more intuitive to have the index of a series increase rather than decrease.
In this case, you could use i from 0 to 99.
Which in java can be:
double sum = 0;
for (int i = 0; i < 100; i++) {
sum += (100 - i) / (double) (1 + i);
}
if you want the result in the same format then do :
int j = 100;
double sum=0;
for (int i = 1; i <= 100; i++) {
sum += ((double) j / i); // typecast as least one of i or j to double.
System.out.print(j + "/" + i+"+");
j--;
}
// here print the sum