Solving a Maze Problem without exceeding the Heap Memory - java

Link to the problem on HackerEarth. - The Maze
I have tried this problem and now facing an issue in passing all the test cases.
Here is my code:
import java.util.*;
class SumTarget {
static boolean[][] hole=new boolean[10001][10001];
static boolean[][] temp=new boolean[10001][10001];
public static void main(String args[] ) throws Exception {
int k,t,i,j,n,m,w,count,x1,y1,x2,y2;
Scanner sc=new Scanner(System.in);
t=sc.nextInt();
for(k=0;k<t;k++){
n=sc.nextInt();
m=sc.nextInt();
w=sc.nextInt();
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
hole[i][j]=false;
temp[i][j]=false;
}
}
for(i=0;i<w;i++)
{
x1=sc.nextInt();
y1=sc.nextInt();
x2=sc.nextInt();
y2=sc.nextInt();
for(j=x1;j<=x2;j++)
hole[y1][j]=true;
}
pathtoexit(n-1,m-1);
count=0;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(!hole[i][j]&&!temp[i][j])
count++;
}
}
System.out.println(count);
}
}
static void pathtoexit(int r,int c)
{
if(temp[r][c]||hole[r][c])
return;
if(r-1>=0)
pathtoexit(r-1,c);
if(c-1>=0)
pathtoexit(r,c-1);
temp[r][c]=true;
return;
}
}
Now, this fails when the size of the grid NxM is very large, of the order of 10^5 or more. I get an error of "Java heap overflow".
Can anyone please help me sort this issue out and make the necessary changes in the code as required ?

It's difficult to propose changes to your code because your approach to the problem is not really practical. You are using a brute force approach to find every path but the problem's parameters allow for a 10^6 x 10^6 maze - finding a path from every cell is really not practical as it could require you to check 10^18 cells which would take more time than the current age of the universe!
The solution here is to start with the insight that the only way for a cell to be 'BAD' is if it is caught behind intersecting horizontal and vertical lines of holes (considering the edges to also represent holes). The secret is to look for those groups and calculate how many 'BAD' cells they generate.

Related

On the Codechef aug long challenge, AUG21C >CHFINVNT, this is the code I wrote, but the submit doesn't work. Its showing RE(NZEC) error

On the Codechef August long challenge, AUG21C > CHFINVNT, this is the code that I wrote, but the submit doesn't work. It's showing RE(NZEC) error.
The output still works.... but it won't submit. Please help.
/* package codechef; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Codechef
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
Scanner scr = new Scanner(System.in);
try {
int T = scr.nextInt();
while(T-- > 0)
{
int N = scr.nextInt();
int p = scr.nextInt();
int K = scr.nextInt();
int[] A = new int[N];
for(int i=0; i<N; i++)
{
A[i%K]++;
}
int sum=0;
for(int i=0; i<p%K; i++)
{
sum+=A[i];
}
int add = (p - (p%K)) / K;
add++;
sum = sum + add;
System.out.println(sum);
}
}catch(Exception e){}
}
}
Obviously, you have a flaw in your code. NZEC means non-zero exit code. Your code probably triggered an uncaught exception. Although you have a broad catch statement, there are exceptions outside of your catch clause.
In the question statement, N can be as large as 10^9.
If that happens, int[] A = new int[N]; tries to allocate that memory. That is over the memory constraints. Probably that is causing the problem. Even if you could allocate that memory, you would hit the time limits: even counting to 10^9 shall fail on CodeChef.
Not directly related to the question, but I want to comment on your code from the perspective of software engineering and competitive coding best practices.
Having a broad catch block will hide any exceptions you may have. Even if you get an index-out-of-bounds exception, you shall not be able to see that in your trials. You may avoid catching broad exceptions.
Your code does not have a proper indentation. That makes reading & debugging cumbersome. Especially in competitive programming, speed is important. So, a proper indentation is critical in that regard. You may just use an IDE to format the code.
Your Java code does not follow the general conventions of Java. One of the rules is "local variables start with a lowercase". The local variables A and N violate that rule.
The code you submitted contains many empty lines. While submitting your code to StackOverflow, removing unnecessary lines shall ease the reading and increase the probability of getting a good answer.

Resizing an Array with a Dedicated method for upsize and downsizing

I'm fairly new to coding and am struggling with an assignment for my class. The program takes a user input for the size of an Array and prompts the user to enter each value 1 at a time. The array size starts at 3 and if the array needs to be bigger when the array has filled a new array that's 2x size is created and all info is copied into it. I was able to figure out this part but I just can't see what I'm doing wrong in the downsizing part. After the info is copied I have to remove the trailing zeroes. I think I have the downsize method right but I don't know if I'm calling it right
import java.util.Scanner;
public class Lab6 {
public static void main(String args[]) {
int[] myarray = new int[3];
int count = 0;
int limit, limitcount = 1;
Scanner kbd = new Scanner(System.in);
System.out.print("How many values would you like to enter? ");
limit = kbd.nextInt();
while (limitcount <= limit) {
System.out.println("Enter an integer value ");
int input = kbd.nextInt();
limitcount++;
if (count < myarray.length) {
myarray[count] = input;
}
else {
myarray = upsize(myarray);
myarray[count] = input;
}
count++;
}
myarray = downsize(myarray, count)
printArray(myarray);
System.out.println("The amount of values in the arrays that we care about is: " + count);
}
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
for (int i =0;i<array.length; i++) {
bigger[i] = array[i];
}
return bigger;
}
static void printArray( int[] array ) {
for ( int number : array ) {
System.out.print( number + " ");
}
System.out.println();
}
static int[] downsize(int[] array,int count) {
int[] smaller = new int[count];
for (int i =0; i<count; i++) {
smaller[i] = array[i];
}
return array;
}
}
Giving you a full response rather than a comment since you're new here and I don't want to discourage you with brevity which could be misunderstood.
Not sure what happened to your code when you pasted it in here, you've provided everything but the format is weird (the 'code' bit is missing out a few lines at the top and bottom). Might be one to double-check before posting. After posting, I see that someone else has already edited your code to fix this one.
You're missing a semi-colon. I'm not a fan of handing out answers, so I'll leave you to find it :) If you're running your code in an IDE, it should already be flagging that one up for you. If you're not, why on earth not??? IntelliJ is free, easy to get going with, and incredibly helpful. There are others out there as well which different folk prefer :) An IDE will help you spot all sorts of useful things quickly.
I have now run your code, and you do have a problem! It's in your final method, downsize(). Look very, very carefully at the return statement ;) Your questions suggests you aren't actually sure whether or not this method is right, which makes me wonder: have you actually run this code with different inputs to see what results you get? Please do that.
Style-wise: blank lines between methods would make the code easier to look at, by providing a visual gap between components. Please be consistent with putting your opening { on the same line as the method signature, and with having spaces between items, e.g. for (int i = 0; i < count; i++) rather than for (int i =0; i<count; i++). The compiler couldn't care less, but it is easier for humans to look at and just makes it look like you did care. Always a good thing!
I think it is awesome that you are separating some of the work into smaller methods. Seriously. For extra brownie points, think about how you could move that while() block into its own method, e.g. private int[] getUserData(int numberOfItems, Scanner scanner). Your code is great without this, but the more you learn to write tiny units, the more favours you will be doing your future self.
Has your class looked at unit testing yet? Trust me, if not, when you get to this you will realise just how important point 5 can be. Unit tests will also help a lot with issues such as the one in point 3 above.
Overall, it looks pretty good to me. Keep going!!!
Simple mistake in your downsize method. If you have an IDE like Eclipse, Intellij, etc. you would have seen it flagged right away.
return array; // should return smaller
I have a few suggestions since you mentioned being new to coding.
The "limitcount" variable can be removed and substituted with "count" at every instance. I'll leave it to you to figure that out.
Try using more descriptive and understandable variable names. Other people will read your code (like now) and appreciate it.
Try to use consistent spacing/indentation throughout your code.
Your upsize method can be simplified using a System.arraycopy() call which generally performs better and avoids the need for writing out a for loop. You can rewrite downsize in a similar manner.
static int[] upsize(int[] array) {
int[] bigger = new int[array.length * 2];
System.arraycopy(array, 0, bigger, 0, array.length);
return bigger;
}
Edit: All good points by sunrise above - especially that you've done well given your experience. You should set up an IDE when you have the time, they're simple to use and invaluable. When you do so you should learn to step through a debugger to explore the state of your program over time. In this case you would have noticed that the myarray variable was never reassigned after the downsize() call, quickly leading you to a solution (if you had missed the warning about an unused "smaller" array).

I'm working on Euler 12 , the code i have seems to workes properly but too slow , very very slow. How can i modify it to run faster?

Like i sad , i am working on Euler problem 12 https://projecteuler.net/problem=12 , i believe that this program will give the correct answer but is too slow , i tried to wait it out but even after 9min it still cant finish it. How can i modify it to run faster ?
package highlydivisibletriangularnumber_ep12;
public class HighlyDivisibleTriangularNumber_EP12 {
public static void findTriangular(int triangularNum){
triangularValue = triangularNum * (triangularNum + 1)/2;
}
static long triangularValue = 0l;
public static void main(String[] args) {
long n = 1l;
int counter = 0;
int i = 1;
while(true){
findTriangular(i);
while(n<=triangularValue){
if(triangularValue%n==0){
counter++;
}
n++;
}
if(counter>500){
break;
}else{
counter = 0;
}
n=1;
i++;
}
System.out.println(triangularValue);
}
}
Just two simple tricks:
When x%n == 0, then also x%m == 0 with m = x/n. This way you need to consider only n <= Math.ceil(sqrt(x)), which is a huge speed up. With each divisor smaller than the square root, you get another one for free. Beware of the case of equality. The speed gain is huge.
As your x is a product of two numbers i and i+1, you can generate all its divisors as product of the divisors of i and i+1. What makes it more complicated is the fact that in general, the same product can be created using different factors. Can it happen here? Do you need to generate products or can you just count them? Again, the speed gain is huge.
You could use prime factorization, but I'm sure, these tricks alone are sufficient.
It appears to me that your algorithm is a bit too brute-force, and due to this, will consume an enormous amount of cpu time regardless of how you might rearrange it.
What is needed is an algorithm that implements a formula that calculates at least part of the solution, instead of brute-forcing the whole thing.
If you get stuck, you can use your favorite search engine to find a number of solutions, with varying degrees of efficiency.

10 ×10 multiplication table, but only shows those entries which are greater than a value entered by the user

I have a 10x10 multiplication table. I need to code in so that when a user inputs a certain number, 50 for example, the numbers >50 are replaced by a character and the rest remain the same.
I know how to do this using strings but I have no clue how to do this in this situation. Any help will be appreciated.
public class task4{
public static void main(String args[]){
int Multiples = 10;
System.out.format(" Table");
for(int z = 1; z<=Multiples;z++ ) {
System.out.format("%5d",z);
}
System.out.println();
System.out.println("-------------------------------------------------------------------------------------------------------");
for(int i = 1 ;i<=Multiples;i++) {
System.out.format("%5d |",i);
for(int j=1;j<=Multiples;j++) {
System.out.format("%5d",i*j);
}
System.out.println();
}
}
}
That seems to be simple enough problem, basically you have table drawing code, your for loops, so we function that off into a nice little method public void drawTable(){} which we call to draw the table initially, but we also provide an overloaded version which takes a number public void drawTable(int maxDispNum){} and this method is the same except if i*j >maxDispNum we print a character instead. then in main we can simply while(true){ read val; drawTable(val);}
alternativley if you want to maintain a permanent record of what's been removed stored the table in an array, 10*10 in your case and use some marker, -1 works here to indicate removed, and simply check for that in your draw method,

All possible values of int from the smallest to the largest, using Java

Write a program to print out all possible values of int data type from the smallest to the largest, using Java.
Some notable solutions as of 8th of May 2009, 10:44 GMT:
1) Daniel Lew was the first to post correctly working code.
2) Kris has provided the simplest solution for the given problem.
3) Tom Hawtin - tackline, came up arguably with the most elegant solution.
4) mmyers pointed out that printing is likely to become a bottleneck and can be improved through buffering.
5) Jay's brute force approach is notable since, besides defying the core point of programming, the resulting source code takes about 128 GB and will blow compiler limits.
As a side note I believe that the answers do demonstrate that it could be a good interview question, as long as the emphasis is not on the ability to remember trivia about the data type overflow and its implications (that can be easily spotted during unit testing), or the way of obtaining MAX and MIN limits (can easily be looked up in the documentation) but rather on the analysis of various ways of dealing with the problem.
class Test {
public static void main(String[] args) {
for (int a = Integer.MIN_VALUE; a < Integer.MAX_VALUE; a++) {
System.out.println(a);
}
System.out.println(Integer.MAX_VALUE);
}
}
Am I hired?
Simplest form (minimum code):
for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++) {
System.out.println(i);
}
No integer overflow, no extra checks (just a little more memory usage, but who doesn't have 32 spare bits lying around).
While I suppose
for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
System.out.println(i);
has fewer characters, I can't really say that it is simpler. Shorter isn't necessarily simpler, it does have less code though.
I just have to add an answer...
public class PrintInts {
public static void main(String[] args) {
int i = Integer.MIN_VALUE;
do {
System.out.println(i);
++i;
} while (i != Integer.MIN_VALUE);
}
}
We don't want the body repeated (think of the maintenance!)
It doesn't loop forever.
It uses an appropriate type for the counter.
It doesn't require some wild third-party weirdo library.
Ah, and here I had just started writing
System.out.println(-2147483648);
System.out.println(-2147483647);
System.out.println(-2147483646);
Okay, just give me a few weeks to finish typing this up ...
The instructions didn't say I have to use a loop, and at least this method doesn't have any overflow problems.
Is there something tricky that I'm not catching? There probably is... (edit: yes, there is!)
class AllInts {
public static void main(String[] args) {
// wrong -- i <= Integer.MAX_VALUE will never be false, since
// incrementing Integer.MAX_VALUE overflows to Integer.MIN_VALUE.
for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++) {
System.out.println(i);
}
}
}
Since the printing is the bottleneck, a buffer would improve the speed quite a lot (I know because I just tried it):
class AllInts {
public static void main(String[] args) {
// a rather large cache; I did no calculations to optimize the cache
// size, but adding the first group of numbers will make the buffer
// as large as it will ever need to be.
StringBuilder buffer = new StringBuilder(10000000);
int counter = 0;
// note that termination check is now <
// this means Integer.MAX_VALUE won't be printed in the loop
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; i++) {
buffer.append(i).append('\n');
if (++counter > 5000000) {
System.out.print(buffer);
buffer.delete(0, buffer.length()-1);
counter = 0;
}
}
// take care of the last value (also means we don't have to check
// if the buffer is empty before printing it)
buffer.append(Integer.MAX_VALUE);
System.out.println(buffer);
}
}
Also, this version will actually terminate (thanks to Daniel Lew for pointing out that there was, in fact, something tricky that I wasn't catching).
The total run time for this version (run with -Xmx512m) was 1:53. That's over 600000 numbers/second; not bad at all! But I suspect that it would have been slower if I hadn't run it minimized.
When I first looked at this, my first question was 'how do you define smallest and largest'. For what I thought was the most obvious definition ('smallest' == 'closest to 0') the answer would be
for (int i = 0; i >= 0; i++) {
System.out.println(i);
System.out.println(-i-1);
}
But everyone else seems to read 'smallest' as 'minimum' and 'largest' as 'maximum'
Come on folks, it said using java. It didn't say use an int in the for loop. :-)
public class Silly {
public static void main(String[] args) {
for (long x = Integer.MIN_VALUE; x <= Integer.MAX_VALUE; x++) {
System.out.println(x);
}
}
}
Another way to loop through every value using an int type.
public static void main(String[] args) {
int i = Integer.MIN_VALUE;
do {
System.out.println(i);
} while (i++ < Integer.MAX_VALUE);
}
Given the overview of the best answers, I realized that we're seriously lacking in the brute-force department. Jay's answer is nice, but it won't actually work. In the name of Science, I present - Bozo Range:
import java.util.Random;
import java.util.HashSet;
class Test {
public static void main(String[] args) {
Random rand = new Random();
HashSet<Integer> found = new HashSet<Integer>();
long range = Math.abs(Integer.MAX_VALUE - (long) Integer.MIN_VALUE);
while (found.size() < range) {
int n = rand.nextInt();
if (!found.contains(n)) {
found.add(n);
System.out.println(n);
}
}
}
}
Note that you'll need to set aside at least 4 GB of RAM in order to run this program. (Possibly 8 GB, if you're on a 64-bit machine, which you'll probably require to actually run this program...). This analysis doesn't count the bloat that the Integer class adds to any given int, either, nor the size of the HashSet itself.
The maximum value for int is Integer.MAX_VALUE and the minimum is Integer.MIN_VALUE. Use a loop to print all of them.
Package fj is from here.
import static fj.pre.Show.intShow;
import static fj.pre.Show.unlineShow;
import static fj.data.Stream.range;
import static java.lang.Integer.MIN_VALUE;
import static java.lang.Integer.MAX_VALUE;
public class ShowInts
{public static void main(final String[] args)
{unlineShow(intShow).println(range(MIN_VALUE, MAX_VALUE + 1L));}}
At 1000 lines/sec you'll be done in about 7 weeks. Should we get coffee now?
Just improving the StringBuilder's approach a little:
2 threads + 2 buffers (i.e. StringBuilder): The main idea is that one thread fills one buffer while the other thread dumps the content of the other buffer.
Obviously, the "dumper" thread will always run slower than the "filler" thread.
If the interviewer was looking for all the Integer values possible in Java, You might try giving him a solution using Long:
class AllIntegers{
public static void main(String[] args) {
for (int i = Integer.MIN_VALUE; i < Long.MAX_VALUE; i++) {
System.out.println(i);
}
System.out.println(Long.MAX_VALUE);
}
}
This should print a range from -9223372036854775808 to 9223372036854775807 which is way more than you would achieve using Integer.

Categories