问题
I'm trying to solve the problem http://www.codechef.com/APRIL12/problems/DUMPLING/
I'm getting runtime error NZEC on codechef. I searched on the Internet but did not manage to make my code succeed.
This is my code :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
public class Main {
public BigInteger gcd(BigInteger a,BigInteger b){
if(b.compareTo(BigInteger.valueOf(0)) == 0)
return a;
return gcd(b,a.mod(b));
}
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
int t = 1;
Main obj = new Main();
try{
str = br.readLine();
t = Integer.parseInt(str);
}
catch(IOException e){
System.out.println("error");
}
for(int w = 0; w < t; w++){
BigInteger a = BigInteger.valueOf(1);
BigInteger b = BigInteger.valueOf(1);
BigInteger c = BigInteger.valueOf(1);
BigInteger d = BigInteger.valueOf(1);
BigInteger k = BigInteger.valueOf(1);
try{
str = br.readLine();
String s[] = str.split(" ");
a = new BigInteger(s[0]);
b = new BigInteger(s[1]);
c = new BigInteger(s[2]);
d = new BigInteger(s[3]);
k = new BigInteger(s[4]);
}
catch(IOException e){
System.out.println("error");
}
BigInteger g1,g2,num;
if(a.compareTo(b) < 0){
num = a;
a = b;
b = num;
}
if(c.compareTo(d) < 0){
num = c;
c = d;
d = num;
}
g1 = obj.gcd(a,b);
g2 = obj.gcd(c,d);
if(g1.compareTo(g2) < 0){
num = g1;
g1 = g2;
g2 = num;
}
BigInteger g3 = obj.gcd(g1,g2);
BigInteger l = g1.divide(g3);
l = l.multiply(g2);
BigInteger res = k.divide(l);
BigInteger fin = res.multiply(BigInteger.valueOf(2));
fin = fin.add(BigInteger.valueOf(1));
System.out.println(fin);
}
}
}
can anyone please tell me where am I doing wrong?
回答1:
Barring unlikely scenarios, the only possibilities for getting a nonzero exit code with that programme that I see are
- division by zero, but that can't happen if the input conforms to the specifications
- unexpected input format resulting in a
NumberFormatException
So I'm working off the latter hypothesis. An easy way to check would be to replace the two catch(IOException e)
with catch(Exception e)
, if the input is indeed not in the format you expect, you would get a 'Wrong Answer' then (but getting a WA after the change doesn't prove the hypothesis correct).
Any additional whitespace on the first line would cause a NumberFormatException
in Integer.parseInt(str)
. Additional whitespace on any later line would cause the String[]
created by str.split(" ")
to have more than five elements, if any such occurs before the fifth number on that line, the programme would try to create BigInteger.valueOf("")
, which again causes a NumberFormatException
. So I would recommend a more robust input method, for example a java.util.Scanner
that can deal with additional whitespace without problems. The methods to use here are nextInt()
for the number of test cases and nextLong()
for the rest.
Scanner scn = new Scanner(System.in);
int t = scn.nextInt();
for(int w = 0; w < t; w++){
BigInteger a = BigInteger.valueOf(scn.nextLong());
BigInteger b = BigInteger.valueOf(scn.nextLong());
BigInteger c = BigInteger.valueOf(scn.nextLong());
BigInteger d = BigInteger.valueOf(scn.nextLong());
BigInteger k = BigInteger.valueOf(scn.nextLong());
BigInteger g1,g2,num;
...
If that change leads to an accept, the cause for the NZEC was likely an unexpected input format.
You ask
can anyone please tell me where am I doing wrong ?
so I'll point out some more things that are not strictly incorrect, but bad practice/pointless.
public BigInteger gcd(BigInteger a,BigInteger b){
if(b.compareTo(BigInteger.valueOf(0)) == 0)
return a;
return gcd(b,a.mod(b));
}
That method should be static
. It involves no state whatsoever, so having to create an object just to call it is bad.
Another point, not pertinent for small numbers like those that may appear in the problem, but relevant if you deal with large numbers, is that you made it recursive. Java usually (if ever) doesn't perform tail call optimisation, and the call stack can usually only handle a few thousand calls, so you risk a StackOverflowError
with the recursive implementation. (But since the call depth is logarithmic for the Euclidean algorithm, that only concerns larger numbers.)
catch(IOException e){
System.out.println("error");
}
Catching an exception just to print "error" to stdout is bad. If you can't do something more meaningful to handle it, don't catch it at all.
for(int w = 0; w < t; w++){
BigInteger a = BigInteger.valueOf(1);
BigInteger b = BigInteger.valueOf(1);
BigInteger c = BigInteger.valueOf(1);
BigInteger d = BigInteger.valueOf(1);
BigInteger k = BigInteger.valueOf(1);
Assigning a dummy value to the variables is pointless, they will be immediately set to their real values (or the programme should die if that fails).
try{
str = br.readLine();
String s[] = str.split(" ");
a = new BigInteger(s[0]);
b = new BigInteger(s[1]);
c = new BigInteger(s[2]);
d = new BigInteger(s[3]);
k = new BigInteger(s[4]);
}
catch(IOException e){
System.out.println("error");
}
Pointless catch
again.
if(a.compareTo(b) < 0){
num = a;
a = b;
b = num;
}
if(c.compareTo(d) < 0){
num = c;
c = d;
d = num;
}
I suspect you swap to avoid a mod
operation where the dividend is smaller than the divisor. There are places where such micro-optimisations are important, but this is not one of them. If you had reason to care about small things like that, there'd be much more to do. For example, the problem at hand can be solved using long
(there's one place where the algorithm would need to be adapted to avoid possible overflow), and the much faster arithmetic of that primitive type would dwarf the small gain you might get from the swap here.
回答2:
NZEC means “Non zero exit code”. Its essentially saying that your program ran into some error during execution. NZEC is a runtime error.
In Java, NZEC can occur even while taking Input using Scanner like…
import java.util.*;
import java.lang.*;
import java.io.*;
class Codechef
{
public static void main (String[] args) throws java.lang.Exception
{
Scanner sc = new Scanner(system.in);
int cases = sc.nextInt();
}
}
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at Codechef.main(Main.java:11)
Solution:
- Use exception handling (Easiest Way)
try
{
// code which you think might throw an exception or whole main class code
}
catch(Exception t){
// you got the exception.
}
Take Input from Scanner like this
int x; if(sc.hasNextInt()) x=sc.nextInt();
I encountered this problem in CodeChef
回答3:
Try using BufferedReader instead of Scanner class and instead of using try-catch use throws NumberFormatException and throws IOException. This is beacuse if you use try-catch, you might get a wrong answer.
回答4:
int takingInput = sc.nextInt();
SO, I was getting NZEC error exactly at this line of code, but to avoid this runtime error you have to verify that if scanner does contain a valid integer input value, so try replacing the above line of code with following :
int takingInput=0;
if(sc.hasNextInt()){
takingInput= sc.nextInt();
}
It worked for me!
来源:https://stackoverflow.com/questions/9997539/getting-nzec-in-java-code