I try to write a short solution for a Google Kick Start question in 2020 Round B and always get a WA. I tried to figure out where was wrong but nothing found. I even download other's passed code and wrote a dataset creator to let two programs run and compare the result, but after running more than 100,000 groups of data, nothing different has been found. I'm kind of crazy now, could you help me to check out what's wrong in my code, please?
Here is the question:
Jemma is competing in a robotics competition. The challenge for today
is to build a robot that can navigate around a hole in the arena.
The arena is a grid of squares containing W columns (numbered 1 to W
from left to right) and H rows (numbered 1 to H from top to bottom).
The square in the x-th column and y-th row is denoted (x, y). The
robot begins in the top left square (1,1) and must navigate to the
bottom right square (W, H).
A rectangular subgrid of squares has been cut out of the grid. More
specifically, all the squares that are in the rectangle with top-left
square (L, U) and bottom-right square (R, D) have been removed.
Jemma did not have much time to program her robot, so it follows a
very simple algorithm: If the robot is in the rightmost column, it
will always move to the square directly below it. Otherwise, If the
robot is in the bottommost row, it will always move to the square
directly right of it. Otherwise, The robot will randomly choose to
either move to the square directly to the right, or to the square
directly below it with equal probability.
Jemma passes the challenge if her robot avoids falling into the hole
and makes it to the square (W, H). What is the probability she passes
the challenge?
Input
The first line of the input gives the number of test cases, T. T
test cases follow. Each test case consists of a single line containing
W, H, L, U, R, and D.
Output
For each test case, output one line containing Case #x: y,
where x is the test case number (starting from 1) and y is a real
number between 0 and 1 inclusive, the probability that Jemma passes
the challenge.
y will be considered correct if it is within an absolute or relative
error of 10-5 of the correct answer. See the FAQ for an explanation of
what that means, and what formats of real numbers we accept.
Limits Time limit:
15 seconds per test set. Memory limit: 1GB. 1 ≤ T ≤
100. 1 ≤ U ≤ D ≤ H. 1 ≤ L ≤ R ≤ W. Neither the top-left nor bottom-right squares will be missing.
Test set 1 1 ≤ W ≤ 300. 1 ≤ H ≤ 300.
Test set 2 1 ≤ W ≤ 105. 1 ≤ H ≤ 105.
Here is my code:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int sets = scan.nextInt();
for(int q = 0; q < sets; q++){
int rows = scan.nextInt();
int cols = scan.nextInt();
double[][] board = new double[rows + 1][cols + 1];
int leftx = scan.nextInt();
int lefty = scan.nextInt();
int rightx = scan.nextInt();
int righty = scan.nextInt();
if((rightx == rows && righty == cols) || (leftx == 1 && rightx == 1)){
System.out.println("Case #" + (q + 1) + ": " + 0.0);
continue;
}
board[1][1] = 1;
for(int i = 1; i < rows; i++){
for(int j = 1; j < cols; j++){
if((i == rightx && j >= lefty && j <= righty) || (j == righty && i >= leftx && i <= rightx)){
continue;
}
board[i + 1][j] += board[i][j] / 2;
board[i][j + 1] += board[i][j] / 2;
}
}
for(int i = 1; i < rows; i++){
if(cols == righty && i >= leftx && i <= rightx){
continue;
}
board[i + 1][cols] += board[i][cols];
}
for(int i = 1; i < cols; i++){
if(rows == rightx && i >= lefty && i <= righty){
continue;
}
board[rows][i + 1] += board[rows][i];
}
System.out.printf("Case #%d: %.10f\n", q + 1, board[rows][cols]);
}
}
}
Thanks!!
The problem asks to find the probability, y is a real number between 0 and 1 inclusive. Your code computes the number of paths safely leading to the bottom-right corner, an integer. No wonders it is a wrong answer.
Related
For this formula:
I had to make a method to automate it, and I've received 4 examples to try it out.
x = 1 > p = 2
x = 3 > p = -226
x = 4 > p = 9854
however, when I insert 11 the answer should be 3.0198773447 and I receive -1.78316945E8 instead :/
here is my code:
System.out.println("Insira o numero: ");
int x = input.nextInt();
int fat = 1;
int contador = 0;
int contador1 = 0;
double p = 0;
for(double i = 1; i <=x; i++){
fat = 1;
contador++;
contador1 = contador* 2;
for(double j = 1; j <= contador1; j++){
fat *=j;
}
if(contador <=1){
p += fat / contador;
}
if(contador % 2 ==0 && contador > 1){
p += fat / contador;
}else if( contador % 2 != 0 && contador > 1){
p -= fat / contador;
}
}
System.out.println(p);
If you type in 11, that means contador1 will become as high as 22 (you will loop 11 times, every loop you first increment contador, and contador1 is twice that, so, 22. In other words, you'll end up having to calculate 22!.
The int type does not hold any arbitrary integer. It can only hold integers between -2^31 and +2^31-1. If you try to go beyond those bounds, it just loops around. Witness it in action:
int x = Integer.MAX_VALUE; // a constant representing 2^31-1.
int y = x + 1;
System.out.println(x);
System.out.println(y);
// Prints: 2147483647
// -2147483648
Where'd that minus come from? That's that whole 'loops around' thing. 22! is much lager than than this upper bound. Hence, your code doesn't work and it also explains why your algorithm tosses a negative number in there.
You could choose to use long instead which can hold it, but long, too, has limits - 2^63-1 to be precise. You could use double which goes ever further (up to about 1e308 which is a lot more than 2^63), but doubles are not accurate and the lack of accuracy gets worse as you move further away from 0. Past 2^53 or so, the distance between 2 representable numbers in the double range is more than 1, meaning, +1 no longer does anything (all operations on double values are rounded to the nearest representable double after every operation).
More generally trying to do 'math' on really large numbers is a non-trivial affair, and your basic + and / can no longer get the job done. Look up the API of BigDecimal which guarantees you perfect accuracy at the cost of, naturally, performance. You could use that, and get perfect answers. Though it'll take a while.
Recently, I had encountered an interesting programming puzzle which had some good twist and turn mentioned in the puzzle. Below the question which amazed me, I simply eager to know if any relevant solution probably in java is feasible for below scenario.
Problem statement:
There is a grid of dimension m*n, initially, a bacterium is present at the bottom left cell(m-1,0) of the grid with all the other cells empty. After every second, each bacteria in the grid divides itself and increases the bacteria count int the adjacent(horizontal,vertical and diagonal) cells by 1 and dies.
How many bacteria are present at the bottom right cell(m-1,n-1) after n-1 seconds?
I had taken references from
https://www.codechef.com/problems/BGH17
but failed to submit the solution
Below is the image for more insite of problem
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class BacteriaProblem {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Number of Rows: ");
int m = sc.nextInt();
System.out.println("Number of Columns: ");
int n = sc.nextInt();
int[][] input = new int[m][n];
input[m - 1][0] = 1;
Stack<String> stack = new Stack<>();
stack.push(m - 1 + "~" + 0);
reproduce(stack, input, n - 1);
System.out.println("Value at Bottom Right corner after n-1 secs: " + input[m - 1][n - 1]);
}
private static void reproduce(Stack<String> stack, int[][] input, int times) {
//exit condition
if (times < 1) {
return;
}
//bacteria after splitting
List<String> children = new ArrayList<>();
//reproduce all existing bacteria
while (!stack.isEmpty()) {
String[] coordinates = stack.pop().split("~");
int x = Integer.parseInt(coordinates[0]);
int y = Integer.parseInt(coordinates[1]);
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue;
split(input, x + i, y + j, children);
}
}
input[x][y]--;
}
//add all children to stack
for (String coord : children) {
stack.push(coord);
}
//reduce times by 1
reproduce(stack, input, times - 1);
}
private static void split(int[][] input, int x, int y, List<String> children) {
int m = input.length;
int n = input[0].length;
if (x >= 0 && x < m && y >= 0 && y < n) {
input[x][y]++;
children.add(x + "~" + y);
}
}
}
Well, I was asked this question in an Online Hackerrank test and couldn't solve it at that time.
I did later try to code it and here's the soln in C++,
long countBacteriasAtBottomRight(int m, int n){
long grid[m][n];
// Set all to 0, and only bottom left to 1
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
grid[i][j] = 0;
}
}
grid[m-1][0] = 1;
// Start the cycle, do it for (n-1) times
int time = n-1;
vector<long> toBeUpdated;
while (time--){
cout << "\n\nTime: " << time;
for (int i=0; i<m; i++){
for (int j=0; j<n; j++){
while (grid[i][j] > 0){
grid[i][j]--;
// upper left
if (i > 0 && j > 0){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j-1);
}
// upper
if (i > 0){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j);
}
// upper right
if (i > 0 && j < n-1){
toBeUpdated.push_back(i-1);
toBeUpdated.push_back(j+1);
}
// left
if (j > 0){
toBeUpdated.push_back(i);
toBeUpdated.push_back(j-1);
}
// bottom left
if (i < m-1 && j > 0){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j-1);
}
// bottom
if (i < m-1){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j);
}
// bottom right
if (i < m-1 && j < n-1){
toBeUpdated.push_back(i+1);
toBeUpdated.push_back(j+1);
}
// right
if (j < n-1){
toBeUpdated.push_back(i);
toBeUpdated.push_back(j+1);
}
};
}
}
// Update all other cells
for (int k=0; k<toBeUpdated.size(); k+=2){
grid[toBeUpdated[k]][toBeUpdated[k+1]]++;
}
for (int i=0; i<m; i++){
cout << endl;
for (int j=0; j<n; j++)
cout << grid[i][j] << " ";
}
// Clear the temp vector
toBeUpdated.clear();
};
return grid[m-1][n-1];
}
The starting situation only has a value in the left-most column 0. We need to know the situation in the right-most column n-1 after time n-1. This means that we only have to look at each column once: column x at time x. What happens to column x after time x is no longer important. So we go from left to right, adding up the cells from the previous column:
1
1 8
1 7 35
1 6 27 104
1 5 20 70 230
1 4 14 44 133 392
1 3 9 25 69 189 518
1 2 5 12 30 76 196 512
1 1 2 4 9 21 51 127 323 ...
You will also notice that the result for the last cell is only influenced by two cells in the previous column, and three in the one before that, so to calculate the end result for e.g. the case n=9, you only need to calculate the values in this triangle:
1
1 4 14
1 3 9 25 69
1 2 5 12 30 76 196
1 1 2 4 9 21 51 127 323
However high the grid is, we only ever have to go up n/2 (rounded up) rows. So the total number of sums we have to calculate is n2/4, or n×m if m < n/2.
Also note that we don't have to store all these values at once, because we go column by column from left to right. So we only need a one-dimensional array of size n/2, and the current values in it are transformed like this (e.g. going from column 4 to 5 in the example above):
[4, 5, 3, 1] (0) -> 0 + 5 - 0 = 5
[9, 5, 3, 1] (5) -> 9 + 3 - 5 = 7
[9,12, 3, 1] (7) -> 12 + 1 - 7 = 6
[9,12, 9, 1] (6) -> 9 + 0 - 6 = 3
[9,12, 9, 4] (3) -> 4 + 0 - 3 = 1
[9,12, 9, 4, 1] (1) (additional value is always 1)
where we iterate over the values from left to right, add up the value to the left and right of the current element, subtract a temporary variable which is initialized to 0, store the result in a temporary variable, and add it to the current element.
So the theoretical time complexity is O(n2) or O(n.m) and the space complexity is O(n) or O(m), whichever is smaller. In real terms, the number of steps is n2/4 and the required space is n/2.
I don't speak Java, but here's a simple JavaScript code snippet which should easily translate:
function bacteria(m, n) {
var sum = [1];
for (var col = 1; col < n; col++) {
var temp = 0;
var height = Math.min(col + 1, n - col, m);
if (height > sum.length) sum.push(0);
for (var row = 0; row < height; row++) {
var left = row > 0 ? sum[row - 1] : 0;
var right = row < sum.length - 1 ? sum[row + 1] : 0;
temp = left + right - temp;
sum[row] += temp;
}
}
return sum[0];
}
document.write(bacteria(9, 9));
Today I practiced for my coding test using projecteulers problems. While doing the prime factor division I stumbled across something I found weird. Here is the relevant code (res is an ArrayList):
for (int x = 2; x <= n; x++){
if (n % x == 0){
System.out.println("Prime found: " + x);
res.add(x);
n = n / x;
}
}
Which divided 1000 into [2, 4, 5, 25].
After a while I tried replacing the if-statement with a while-loop and it printed me the correct answer [2, 2, 2, 5, 5, 5].
Obviously there is somthing I didn't understand, could someone explain this to me, please?
Edit:
The newer code:
for (int x = 2; x <= n; x++){
while (n % x == 0){
System.out.println("Prime found: " + x);
res.add(x);
n = n / x;
}
}
The difference is:
If you use if, every number is tested only once. So if you are able to pull out the 2, you try so only once. The next number you can pull out is the 4, although it is not a prime.
The same holds for the 5 resp. 25.
If you use while, you test each number until you know it's no longer in the number to test.
You could also change it into
for (int x = 2 ; x <= n/x ; ) {
if (n % x == 0) {
System.out.println("Prime factor: " + x);
res.add(x);
n = n / x;
}
else {
x++; // increment moved here
}
}
if (n > 1) {
System.out.println("Prime factor: " + n);
res.add(n);
}
I've also changed the termination condition, to make it much more efficient in cases where n's largest prime factor is itself large, because if n = a*b and a <= b, then a*a <= a*b = n, i.e. a <= n/a.
This repeats the test for a prime factor, because as you've found out, some numbers have multiple prime factors of same magnitude (like 1000 = 2*2*2*5*5*5). It is equivalent to your while loop, because the increment is now conditional, performed only when the tested candidate was not n's factor.
The algorithm is suppose to ask the middle letter of the English alphabet, in my program its N. At this point it asks the user whether:
The guess is correct
The letter is earlier in the alphabet.
The letter is later in the alphabet
When trying to guess Jose, it will first ask about N. I choose option 2 which then gives me G. I then choose option 3 which then gives me Q. I then choose option 2 which then gives me I. I then choose option 3 which then gives me R. If I choose option 2, it gives me R again, and basically I'm stuck between R and I. How can I fix my algorithm to properly provide all letters available?
My code is the following:
int let = 26/2;
if(n != 0) {
//Correct guess
if(n == 3) {
aLetter = alphabet[let];
actualLetter = Character.toString(aLetter);
aName.add(actualLetter);
}
//earlier in alphabetical order
else if(n == 2) {
let /= 2;
}
//later in alphabetical order
else if(n == 1) {
for(int i = let; i < 27; i++){
r += 1;
}
r /= 2;
let += r;
r=0;
}
} //done guessing
else if (n == 0) {
for(String str: aName) {
result3 += str;
}
}
Any help and or advice would be great. Thanks!
Problem 1
Say the letter of the alphabet (represented by --- etc.) being guessed is "s" (represented by +). The computer will first guess in the middle (let = 13, represented by |).
-------------|---+--------
You tell the computer to guess higher.
With the code
for(int i = let; i < 27; i++) {
r += 1;
}
r /= 2;
let += r;
r=0;
which can be shortened to
let += (26 - let) / 2;
the computer will guess halfway to the end (let = 19):
-------------|---+-|------
So far so good.
Now, you tell it to guess lower. The computer knows it's higher than 13 and lower than 19, so it should guess halfway in between. However, the code you have does not do that.
let /= 2;
makes let be (int)(19 / 2), i.e., 9.
---------|---|---+-|------
What you want is let = 16
-------------|--|-+|------
Problem 2
Let's say you successfully got to
-------------|--|-+|------
with the most recent guess being 16. You tell the computer to guess higher. With the code
let += (26 - let) / 2;
let will become 21.
-------------|--|-+|-|----
What you want is let = 18 or 19;
Solution
In general, a good algorithm should make let go up or down by "13 / 2n" each iteration, where "n" is the iteration number (starting at 0).
You should therefore use the code
int let = 0;
int iteration = 0;
//start loop
//take input
int delta = 13 / Math.pow(2, iteration) + 1;
if(n != 0) {
//if n == 3
else if(n == 2)
{
let -= delta;
}
else if(n == 1)
{
let += delta;
}
}
iteration++;
//end loop
and replace the comments with the code you are already using.
DISCLAIMER: THIS IS PART OF A HOMEWORK ASSIGNMENT
So i have created an array with the the count of each letter. It would look something like this:
Array charCount
charCount[0] = 10
charCount[1] = 6
charCount[2] = 4
I know that 0 = a, 1 = b etc.
Now I want to print these results to a graphic representation using asteriks. For example:
*
*
*
*
*
**
**
**
***
***
***
ABC
I found this rather difficult and don't really understand how to do this.
- I've made a function to check the max value of my array.
for (int i = 0; i < charCount.length; i++) {
if (letterCount[i] > maxInt) {
maxInt = charCount[i];
}
}
Then I've made a for loop to check if there are any matches.
My next part of code is:
for (int i = 0; i < letterCount.length; i++ ) {
for (int j = 0; j <= maxInt; j++) {
if (letterCount[i] == maxInt) {
System.out.println("*");
} if (letterCount[i] == maxInt - j ) {
System.out.println("*");
} if (letterCount[i] != maxInt ) {
System.out.println(" ");
}
}
But here it where I got stuck.
How do i print asteriks all the way down and next to each other? Should I work with spaces?
How do i know when to stop printing? Does my maxInt - j makes sense?
Can someone point my in the right direction?
I have to come up with a solution using for loops and arrays, So i cant use any fancy methods yet :)
Thank you :)
Imagine you wanna draw this like a bar graph to a grid, which has coordinates, similar to what you did in school with x and y coordinates.
To stay with your example, each y coordinate represents the index of your array, e.g. the specific letter, where the x - coordinate the amount.
Since those numbers may get quite large, it's, like you saw, not best practice to map +1 on the x-coordinate to +1 letter.
Therefore you need to determine the size of your diagram, let's say it shall be 10 letters wide:
y <- 10
^
a|**********
b|**********
c|**********
-------------> x
12345 ...10
Now it's important that the occurences of the letters relative to each other are represented correctly by those *-bars, that means the letter which occurs the most could be shown with a bar exactly as long as you draw the x-coordinate, in this case 10.
Lets use this as an example dataset
0 := 10
1 := 6
2 := 4
3 := 14
If the x-coordinate is 10 * long, the amount from entry 3 (highest in the array) is 14 and needs to be 10 * long. With this information you can calculate the factor by dividing 10(x-length) / 14(biggest amount) ~= 0.71 (the factor)
This factor you apply to all the numbers to get number of stars to draw.
Here as an example in java:
int xLength = 10;
int[] charCount = new int[5];
charCount[0] = 10;
charCount[1] = 4;
charCount[2] = 7;
charCount[3] = 14;
charCount[4] = 1;
// determine the biggest value:
int biggest = 0;
for(int n:charCount) {
if(n>biggest)
biggest = n;
}
System.out.println("Biggest no: " + biggest);
double factor = (double)xLength / (double)biggest;
System.out.println("Using factor: " + factor);
for(int i = 0; i < charCount.length; i++) {
System.out.print("no " + i + ":");
for(int j = 0; j < charCount[i] * factor; j++) {
System.out.print("*");
}
System.out.println();
}
This will output:
Biggest no: 14
Using factor: 0.7142857142857143
no 0:********
no 1:***
no 2:*****
no 3:**********
no 4:*
EDIT:
If you want to print the bars vertically (on the y-choordinate), or turn it any other way, store the bars in a grid, for example with a String[][] array, where arr[2][3] would be y-coordinate 2 and x-coordinate 3. Then you can calculate with the factor above and the maximum height of the chart whether or not a specific point / coordinate should be filled with a "*" or a " " (nothing):
// make a grid to draw the chart
// the height is the the number we defined as maximum height (xLength)
// and the width is one column for every char (charCount.length):
String[][] grid = new String[charCount.length][xLength];
// initialize the grid with spaces:
for(int x = 0; x < grid.length; x++) {
for(int y = 0; y < grid[x].length; y++) {
grid[x][y] = " ";
}
}
// We will go through the grid column by column:
for(int x = 0; x < grid.length; x++) {
// this will be called once for every char
// so just replace spaces in the grid in this column
// by "*" if it's a row (value of y) <= the amount
// of chars times the factor
for(int y = 0; y < grid[x].length; y++) {
if(y <= charCount[x] * factor) {
grid[x][y] = "*";
}
}
}
// print the grid row by row (think of it upside down, (0,0) is the upper left point
// so we start with the last (the no of elements in the array minus 1, counting from 0)
System.out.println("^");
for(int y = grid[0].length - 1; y >= 0; y--) {
System.out.print("|");
for(int x = 0; x < grid.length; x++) {
System.out.print(grid[x][y]);
}
// finish the line:
System.out.println();
}
// draw the bottom line:
System.out.println("------->");
System.out.println(" abcde");
Added this code just below the code from above, the output will be:
Biggest no: 14
Using factor: 0.7142857142857143
no 0:********
no 1:***
no 2:*****
no 3:**********
no 4:*
^
| *
| *
|* *
|* *
|* **
|* **
|* **
|****
|****
|*****
------->
abcde
If you want to put the amounts left to the y-bar, divide the row number by the factor.
If you want to use the absolute values without scaling up or down (which would fill the screen pretty fast for big numbers), just set the 'xLength' (height of the grid) to the biggest number in the input array.