How can I make this Java program run faster? - java

I am solving this problem from HackerEarth but I am getting the "Time limit exceeded" error.
Function F(N) is defined as:
F(N) = sum_of_digits(N2)
Given a number N, output if it is possible for it to ultimately become {1 or 4} or not.
Input:
First line contains T which is the number of test cases.
T lines follow each with an integer N.
Output:
For each N output "YES" or "NO" if the number can achieve desired goal or not.
This is the program:
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Stream;
public class MoodyNumbers {
public static boolean is1or4(int x) {
boolean result = false;
Integer digitSum = Stream.of((int) Math.pow(x, 2)).reduce(Integer::sum).get();
StringBuilder sumStringBuilder = new StringBuilder(String.valueOf(digitSum));
for (int i = 0; i < sumStringBuilder.length(); i++) {
result = sumStringBuilder.charAt(i) == '1' || sumStringBuilder.charAt(i) == '4';
if (result) {
break;
}
}
return result;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedOutputStream bos = new BufferedOutputStream(System.out);
int numberOfTest = Integer.parseInt(br.readLine());
for (int i = 0; i < numberOfTest; i++) {
boolean result = is1or4(Integer.parseInt(br.readLine()));
if (result) {
bos.write("YES\n".getBytes());
}
else {
bos.write("NO\n".getBytes());
}
bos.flush();
}
}
}
I ran out of ideas to make this faster, any recommendations?

What takes time is writing to standard output, so if you write the result to standard output for each test case, that will increase the overall time significantly.
You can use StringBuilder and append to it the result of each test case. Then after you have handled all the test cases, print out the entire contents of the StringBuilder.
Also, I think you misunderstood the question. Your code checks whether the sum of the digits of the square of the test case number (i.e. the result of function F(N)) contains a 1 (one) or a 4. As I understand it, you need to check whether the result of F(N) is 1 or 4.
Here is my solution which was accepted on hackerearth, i.e. it produced the correct results in an acceptable time.
import java.util.Scanner;
public class MoodyNumbers {
private static boolean is1or4(int x) {
boolean result = x == 1 || x == 4;
if (!result) {
int newX = sumDigits((long) x * x);
if (newX == 1 || newX == 4) {
return true;
}
if (newX == 9 || newX == 16) {
return false;
}
result = is1or4(newX);
}
return result;
}
private static int sumDigits(long x) {
int sum = 0;
while (x >= 10) {
sum += x % 10;
x /= 10;
}
sum += x;
return sum;
}
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
int numberOfTestCases = stdin.nextInt();
StringBuilder sb = new StringBuilder(numberOfTestCases * 4);
String newLine = System.lineSeparator();
while (numberOfTestCases-- > 0) {
int n = stdin.nextInt();
sb.append((is1or4(n) ? "YES" : "NO"));
sb.append(newLine);
}
System.out.print(sb);
}
}
If the result of F(N) is either 9 or 16, that creates an endless loop. F(9) returns 9. F(16) returns 13 and F(13) returns 16 which also creates an endless loop. Hence for any number for which F(N) eventually returns either 9 or 16, the result is NO.

Related

Find amount of happy numbers in a given range

I need to find all happy numbers in a given range (input)
A happy number is a number which eventually reaches 1 when replaced by the sum of the square of each digit. 13 is a happy number because 1^2 + 3^2 = 10 And 1^2 + 0^2 = 1, thus 13 is a happy number.
So far I have this:
import java.util.HashSet;
import java.util.Set;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String wrd = scan.nextLine().trim();
String wrd2 = scan.nextLine().trim();
int nieuwnummer = Integer.parseInt(wrd);
int nieuwnummer2 = Integer.parseInt(wrd2);
// int count = 0
Set<Integer> numbers = new HashSet<Integer>();
for (int i = nieuwnummer; i <= nieuwnummer2; i++) { while(nieuwnummer>0) {
nieuwnummer2 += (nieuwnummer % 10)*(nieuwnummer % 10);
nieuwnummer /=10; };
}
nieuwnummer = nieuwnummer2;
}
//System.out.println(count)
}
I think the range isn't working yet and I need a way to actually count the happy number. Please help :)
Here is some working example.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String st1 = scan.nextLine().trim();
String st2 = scan.nextLine().trim();
int min = Integer.parseInt(st1);
int max = Integer.parseInt(st2);
Set<Integer> happyNumbers = getHappyNumbers(min, max);
System.out.println(happyNumbers.size());
}
public static Set<Integer> getHappyNumbers(int min, int max) {
Set<Integer> out = new HashSet<>();
for (int i = min; i < max; i++) {
if (isHappy(i)) {
out.add(i);
}
}
return out;
}
private static boolean isHappy(int i) {
int sum = 0;
while (i != 0) {
sum += Math.pow((i % 10), 2);
i /= 10;
}
if (sum == 1) return true;
else if (sum >= 10) {return isHappy(sum);}
else return false;
}
}
I don't know if I understand you correctly but:
You have while(nieuwnummer > 0) which is some number on start but after first loop it is changing to 0 [ eg. if range is from 1 to 16] so it will go one time and then skip.
For that kind of problem I would use something like this:
https://www.geeksforgeeks.org/lucky-numbers/
and iterate over the loop

Recursive function not working java

I am trying to find out 2 to the power n. I used recursive function for this.
My Code:
class TwoPowerN
{
static BigInteger twoPowern(BigInteger x, long y)
{
BigInteger temp = new BigInteger("1");
if( y == 0)
return new BigInteger("1");
temp.equals(twoPowern(x, y/2));
if (y%2 == 0)
return temp.multiply(temp);
else
return x.multiply(temp.multiply(temp));
}
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
int t = Integer.parseInt(br.readLine());
while(t>0)
{
long r = Long.parseLong(br.readLine());
BigInteger a = new BigInteger("2");
BigInteger ans=twoPowern(a,r);
pw.println(ans);
t--;
}
pw.close();
}
}
But I don't get the required result.
For cases 1 2 3 4 5 I am getting 2 1 2 1 2. A similar program(using similar function but with int) in 'C' works fine.
Can anyone explain what is the mistake?
I think that you need to assign the recursive result, rather than test for equality:
temp.equals(twoPowern(x, y/2)); // This is checking for equality
Should be
temp = twoPowern(x, y/2); // This is assigning the value
temp.equals(twoPowern(x, y/2));
is a conditional statement in java, not an assignment, so you aren't
storing the recursive value.
This is a lot simpler:
public class power2 {
public static long power2( int power)
{
if(power <= 0)
return 1;
return 2 * power2(power-1);
}
static BigInteger twoPowern(long y)
{
if( y == 0) {
return BigInteger.ONE;
}
return new BigInteger("2").multiply(twoPowern(y-1));
}
public static void main(String[] args)
{
for(int i = 0; i < 10; i++)
{
System.out.println("2^" + i + "," + power2(i));
System.out.println("2^" + i + "," + twoPowern(i));
}
}
}
Using regular longs, or BigInteger.

Loop in Credit Card Validation in java

I am a high school student in an introductory Computer Science course. Our assignment was the following:
The last digit of a credit card number is the check digit, which protects against transcription errors such as an error in a single digit or switching two digits. the following method is used to verify actual credit card numbers but, for simplicity, we will describe it for numbers with 8 digits instead of 16:
Starting from the rightmost digit, form the sum of every other digit. For example, if the credit card number is 4358 9795, then you form the sum 5+7+8+3 = 23.
Double each of the digits that were not included in the preceding step. Add all the digits of the resulting numbers. For example, with the numbers given above, doubling the digits, starting with the next-to-last one, yields 18 18 10 8. Adding all the digits in these values yields 1+8+1+8+1+0+8=27.
Add the sums of the two preceding steps. If the last digit of the result is 0, the number is valid. In our case, 23 + 27 = 50, so the number is valid.
Write a program that implements this algorithm. The user should supply an 8-digit number, and you should print out whether the number is valid or not. If it is not valid, you should print out the value of the check digit that would make the number valid.
I have everything done except for the part in bold. My code is listed below:
public class CreditCard
{
private String creditCardNumber;
private boolean valid;
private int checkDigit;
int totalSum;
/**
* Constructor for objects of class CreditCard
*/
public CreditCard(String pCreditCardNumber)
{
creditCardNumber = pCreditCardNumber;
checkDigit = Integer.parseInt(pCreditCardNumber.substring(creditCardNumber.length() - 1));
int sumOfDigits = checkDigit + Integer.parseInt(pCreditCardNumber.substring(6,7)) + Integer.parseInt(pCreditCardNumber.substring(3,4)) + Integer.parseInt(pCreditCardNumber.substring(1,2));
int dig7 = Integer.parseInt(pCreditCardNumber.substring(7,8));
int dig5 = Integer.parseInt(pCreditCardNumber.substring(5,6));
int dig3 = Integer.parseInt(pCreditCardNumber.substring(2,3));
int dig1 = Integer.parseInt(pCreditCardNumber.substring(0,1));
String string7 = Integer.toString(dig7);
int doubledDig7a = Integer.parseInt(string7.substring(0));
int doubledDig7b = 0;
if (dig7 * 2 >= 10)
{
doubledDig7a = Integer.parseInt(string7.substring(0));
doubledDig7b = 0;
}
String string5 = Integer.toString(dig5);
int doubledDig5a = Integer.parseInt(string7.substring(0));
int doubledDig5b = 0;
if (dig5 * 2 >= 10)
{
doubledDig5a = Integer.parseInt(string5.substring(0));
doubledDig5b = 0;
}
String string3 = Integer.toString(dig3);
int doubledDig3a = Integer.parseInt(string3.substring(0));
int doubledDig3b = 0;
if (dig3 * 2 >= 10)
{
doubledDig3a = Integer.parseInt(string3.substring(0));
doubledDig3b = 0;
}
String string1 = Integer.toString(dig1);
int doubledDig1a = Integer.parseInt(string1.substring(0));
int doubledDig1b = 0;
if (dig1 * 2 >= 10)
{
doubledDig1a = Integer.parseInt(string1.substring(0));
doubledDig1b = 0;
}
int doubleDigits = doubledDig1a + doubledDig1b + doubledDig3a + doubledDig3b + doubledDig5a + doubledDig5b + doubledDig7a + doubledDig7b;
totalSum = sumOfDigits + doubleDigits;
if (totalSum % 10 == 0)
{
valid = true;
}
else
{
valid = false;
}
}
public void makeItValid()
{
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
}
public boolean isItValid()
{
return valid;
}
}
The loop is what I am having issues with. I always end up in an infinite loop whenever it compiles. It looks like everything should work, though. It's supposed to decrease the value of the check Digit (not increase so I don't end up with a check digit of 10 or higher), and then add that number back into the total sum until the total sum is divisible by 10, and then the loop would end. Is the type of loop I'm using wrong? Any advice would be appreciated.
Your problem is that both of your loop conditions involve totalSum but you only change checkDigit.
while (totalSum % 10 != 0)
{
checkDigit--;
if (totalSum % 10 == 0)
{
break;
}
}
You either need to recalculate totalSum or change the condition to be based on checkDigit. If you want to loop and decrement like you are doing you will need to add a method that performs the algorithm and call it every time. The way you have your class outlined makes this very inconvenient because you don't convert the numbers.
public static int[] cardToNumbers(String cardText) {
// \D is regex for non-digits
cardText = cardText.replaceAll("\\D", "");
int[] cardNumbers = new int[cardText.length()];
// convert unicode to corresponding integers
for (int i = 0; i < cardText.length(); i++)
cardNumbers[i] = cardText.charAt(i) - '0';
return cardNumbers;
}
public static int calcTotalSum(int[] cardNumbers) {
int sum = 0;
/* "every other one" loops
*
* I recommend against the "mod 2 index" scheme
* i % 2 relies on the card number being even
* you can't have your code blow up with unusual inputs
*
*/
for (int i = cardNumbers.length - 1; i >= 0; i -= 2) {
sum += cardNumbers[i];
}
for (int i = cardNumbers.length - 2; i >= 0; i -= 2) {
int dig = cardNumbers[i] * 2;
while (dig > 0) {
sum += dig % 10;
dig /= 10;
}
}
return sum;
}
Now you can do something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
int sum = calcTotalSum(invalidNumbers);
while ((sum = calcTotalSum(invalidNumbers)) % 10 != 0)
invalidNumbers[invalidNumbers.length - 1]--;
totalSum = sum;
checkDigit = invalidNumbers[invalidNumbers.length - 1];
}
But you should be able to just subtract the difference to find the valid check digit:
if (totalSum % 10 != 0) checkDigit -= totalSum % 10;
Or something like:
public void makeItValid() {
int[] invalidNumbers = cardToNumbers(creditCardNumber);
checkDigit = invalidNumbers[invalidNumbers.length - 1] -= totalSum % 10;
totalSum = calcTotalSum(invalidNumbers);
valid = true;
}
Some asides,
I would recommend storing the digits as a field and have checkDigit represent an index in the array. This would simplify some of the operations you are doing.
I would also suggest not to be "silently" changing fields internally IE like in your makeItValid method unless this is a specification of the assignment. I think a better form is to let the "owning" code make the changes itself which is more clear externally. A somewhat complete implementation would look like this:
public class CreditCard {
public static void main(String[] args) {
if (args.length == 0) return;
CreditCard card = new CreditCard(args[0]);
if (!card.isValidNumber()) {
card.setCheckDigit(card.getValidCheckDigit());
}
}
private final String cardText;
private final int[] cardDigits;
private final int cdIndex;
public CreditCard(String ct) {
cardDigits = cardToNumbers(cardText = ct);
if ((cdIndex = cardDigits.length - 1) < 0) {
throw new IllegalArgumentException("# had no digits");
}
}
public boolean isValidNumber() {
return calcTotalSum(cardDigits) % 10 == 0;
}
public void setCheckDigit(int dig) {
cardDigits[cdIndex] = dig;
}
public int getValidCheckDigit() {
int sum = calcTotalSum(cardDigits);
if (sum % 10 != 0) {
return cardNumbers[cdIndex] - sum % 10;
} else {
return cardNumbers[cdIndex];
}
}
// above static methods
}
The best form IMO would be to disallow creation of a credit card object at all unless the check digit is valid. As an OOP principle it should not make sense to create invalid credit cards. The constructor should throw an exception if the card is invalid and have a static method to correct the number.
I would do something like the following (shortened):
public class CreditCard {
public CreditCard(String number) {
if (!validateCheckDigit(number)) {
throw new IllegalArgumentException("check digit failure");
}
}
}
public static void main(String[] args) {
String number = args[0];
CreditCard card = null;
boolean valid = false;
do {
try {
card = new CreditCard(number);
valid = true;
} catch (IllegalArgumentException e) {
number = CreditCard.correctCheckDigit(number);
}
} while (!valid);
}
I guess that's more or less doing your homework for you but I'm sure you can learn from it.
Unless I'm missing something major on how the validation works your makeitvalid method wont work in the way you are approaching it.
It makes more sense (at least to me) to extract everything you have in your constructor into a method ie.
boolean isValid(String cardNumber);
which would do everything that your constructor does except set the valid flag. your constructor then becomes
public CreditCard(String pCreditCardNumber){
valid = isValid(pCreditCardNumber);
}
and then to find what change would make it valid your check valid method does something like
change the value of check digit
if (isValid(Changed String))
return checkdigit
else
continue
repeat until you either find one that works or until you determine that it can't work.
Something along these lines should do. You'll still need to implement a few methods on your own.
public static void main(String[] args) {
String creditCardNumber = readCreditCardNumber();
String correctCreditCardNumber = getCorrectCreditCardNumber(creditCardNumber);
if (creditCardNumber.equals(correctCreditCardNumber)) {
System.out.println("Credit Card Valid");
} else {
System.out.println("Credit Card Invalid. Did you mean " + correctCreditCardNumber + "?");
}
}
public static String getCorrectCreditCardNumber(String creditCardNumber) {
int[] creditCardDigits = getCreditCardDigits(creditCardNumber);
int sum = 0;
for (int i = creditCardDigits.length - 2; i >= 0; i--) {
if (isOdd(i)) {
sum += creditCardDigits[i];
} else {
sum += digitSum(creditCardDigits[i] * 2);
}
}
int last = creditCardDigits.length - 1;
int remainder = sum % 10;
if (remainder != 0) {
creditCardDigits[last] = 10 - remainder;
}
return getCreditCardNumberAsString(creditCardDigits);
}
This program is very dynamic. I did not add too much error handling. You can enter any number that is divisible by 8.
Code in action:
Enter a card number: 4358 9795
Number is valid?: true
Continue? (y/n): y
Enter a card number: 4358 9796
Number is valid?: false
Continue? (y/n): y
Enter a card number: 43-58 97-95
Number is valid?: true
Continue? (y/n): n
Exiting...
CreditCardValidator.java
import java.text.ParseException;
import java.util.Scanner;
public class CreditCardValidator {
Integer[] digits;
public CreditCardValidator(String numberSequence) {
parseNumber(numberSequence);
}
private void parseNumber(String numberSequence) {
try {
String sequence = numberSequence.replaceAll("[\\s-]+", "");
int length = sequence.length();
if (length % 8 != 0) {
throw new IllegalArgumentException("Number length invalid.");
}
digits = new Integer[length];
int pos = 0;
for (Character c : sequence.toCharArray()) {
if (Character.isDigit(c)) {
digits[pos++] = Character.getNumericValue(c);
} else {
throw new ParseException("Invalid digit.", pos);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean validateNumber() {
int sum = 0;
for (int i = digits.length - 1; i >= 0; i--) {
if (i % 2 == 1) {
sum += digits[i];
} else {
sum += NumberUtils.sumDigits(digits[i] * 2);
}
}
return sum % 10 == 0;
}
public static void main(String[] args) {
boolean stop = false;
CreditCardValidator c;
while (!stop) {
System.out.print("Enter a card number: ");
c = new CreditCardValidator(new Scanner(System.in).nextLine());
System.out.println("Number is valid?: " + c.validateNumber());
System.out.print("\nContinue? (y/n): ");
if (new Scanner(System.in).next().charAt(0) == 'n') {
stop = true;
}
System.out.println();
}
System.out.println("Exiting...");
System.exit(0);
}
}
I wrote a separate digit summation utility:
public class NumberUtils {
public static void main(String[] args) {
for(int i = 0; i < 2000; i+=75) {
System.out.printf("%04d: %02d\n", i, sumDigits(i));
}
}
public static int sumDigits(int n) {
if (n < 0)
return 0;
return sumDigitsRecursive(n, 0);
}
private static int sumDigitsRecursive(int n, int total) {
if (n < 10)
return total + n;
else {
return sumDigitsRecursive(n / 10, total + (n % 10));
}
}
}

Java Fitness Function - Scales

I have a fitness function as part of a lab and wish to apply it to a set of 'weights' (ArrayList weights). I have created the array and stored some values in it. I have created random binary strings (which have an 'x' at the end in order to generate random values) which I wish to also apply the fitness function to; however, the problem I am having is that the fitness function always returns a value of 0. Am I missing something here?
The fitness function is as follows:
import java.util.*;
public class ScalesSolution{
private static String scasol;
//Creates a new scales solution based on a string parameter
//The string parameter is checked to see if it contains all zeros and ones
//Otherwise the random binary string generator is used (n = length of parameter)
public ScalesSolution(String s)
{
boolean ok = true;
int n = s.length();
for(int i=0;i<n;++i)
{
char si = s.charAt(i);
if (si != '0' && si != '1') ok = false;
}
if (ok)
{
scasol = s;
}
else
{
scasol = RandomBinaryString(n);
}
}
private static String RandomBinaryString(int n)
{
String s = new String();
//Code goes here
//Create a random binary string of just ones and zeros of length n
for(int i = 0; i < n; i++){
int x = CS2004.UI(0,1);
if(x == 0){
System.out.print(s + '0');
}
else if(x == 1){
System.out.print(s + '1');
}
}
return(s);
}
public ScalesSolution(int n)
{
scasol = RandomBinaryString(n);
}
//This is the fitness function for the Scales problem
//This function returns -1 if the number of weights is less than
//the size of the current solution
//EXERCISE 3
public static double ScalesFitness(ArrayList<Double> weights)
{
int n = scasol.length();
double lhs = 0.0, rhs = 0.0;
if (n > weights.size()) return(-1);
for(int i = 0; i < n; i++){
if(scasol.charAt(i) == 0){
lhs += weights.get(i);
}
else{
rhs += weights.get(i);
}
}
//Code goes here
//Check each element of scasol for a 0 (lhs) and 1 (rhs) add the weight wi
//to variables lhs and rhs as appropriate
return(Math.abs(lhs-rhs));
}
//Display the string without a new line
public void print()
{
System.out.print(scasol);
}
//Display the string with a new line
public void println()
{
print();
System.out.println();
}}
Main method (in separate class):
import java.util.ArrayList;
public class Lab8 {
public static void main(String args[])
{
for(int i = 0; i < 10; i++){
ScalesSolution s = new ScalesSolution("10101x");
s.println();
}
ArrayList<Double> weights = new ArrayList<Double>();
weights.add(1.0);
weights.add(2.0);
weights.add(3.0);
weights.add(4.0);
weights.add(10.0);
System.out.println();
System.out.println(weights);
System.out.print("Fitness: ");
double fitness = ScalesSolution.ScalesFitness(weights);
System.out.println(fitness);
}}
CS2004 class:
import java.util.*;
import java.io.*;
//Some useful code that we will probably reuse in later laboratories...
public class CS2004
{
//Shared random object
static private Random rand;
//Create a uniformly distributed random integer between aa and bb inclusive
static public int UI(int aa,int bb)
{
int a = Math.min(aa,bb);
int b = Math.max(aa,bb);
if (rand == null)
{
rand = new Random();
rand.setSeed(System.nanoTime());
}
int d = b - a + 1;
int x = rand.nextInt(d) + a;
return(x);
}
//Create a uniformly distributed random double between a and b inclusive
static public double UR(double a,double b)
{
if (rand == null)
{
rand = new Random();
rand.setSeed(System.nanoTime());
}
return((b-a)*rand.nextDouble()+a);
}
//This method reads in a text file and parses all of the numbers in it
//This code is not very good and can be improved!
//But it should work!!!
//It takes in as input a string filename and returns an array list of Doubles
static public ArrayList<Double> ReadNumberFile(String filename)
{
ArrayList<Double> res = new ArrayList<Double>();
Reader r;
try
{
r = new BufferedReader(new FileReader(filename));
StreamTokenizer stok = new StreamTokenizer(r);
stok.parseNumbers();
stok.nextToken();
while (stok.ttype != StreamTokenizer.TT_EOF)
{
if (stok.ttype == StreamTokenizer.TT_NUMBER)
{
res.add(stok.nval);
}
stok.nextToken();
}
}
catch(Exception E)
{
System.out.println("+++ReadFile: "+E.getMessage());
}
return(res);
}}
Once run, the random binary strings work perfectly well, yet the fitness function fails to change from 0. Here is a sample output:
011100
111010
001110
111011
001000
010101
001010
100011
110100
011001
[1.0, 2.0, 3.0, 4.0, 10.0]
Fitness: 0.0
Thank you all so much for your time.
Stefanos.
scasol appears to be empty when ScalesFitness is called. In the RandomBinaryString method, you never actually construct s, but rather, just print it out. Instead of System.out.print(s+'0') and the other line, you should have s += '0';.
Since this appears to be an exercise, I'll leave the rest to you, but here is a tip for next time: don't have a function do more than it's supposed to (such as printing out its results), otherwise, it might look like the set of functions is actually working, when in reality it isn't.
In this case, it looked like everything was working fine since it appeared like the s.println() function what actually printing out scasol, but in reality, scasol was empty and the RandomBinaryString method was actually doing the printing.

Uva's 3n+1 problem

I'm solving Uva's 3n+1 problem and I don't get why the judge is rejecting my answer. The time limit hasn't been exceeded and the all test cases I've tried have run correctly so far.
import java.io.*;
public class NewClass{
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
int maxCounter= 0;
int input;
int lowerBound;
int upperBound;
int counter;
int numberOfCycles;
int maxCycles= 0;
int lowerInt;
BufferedReader consoleInput = new BufferedReader(new InputStreamReader(System.in));
String line = consoleInput.readLine();
String [] splitted = line.split(" ");
lowerBound = Integer.parseInt(splitted[0]);
upperBound = Integer.parseInt(splitted[1]);
int [] recentlyused = new int[1000001];
if (lowerBound > upperBound )
{
int h = upperBound;
upperBound = lowerBound;
lowerBound = h;
}
lowerInt = lowerBound;
while (lowerBound <= upperBound)
{
counter = lowerBound;
numberOfCycles = 0;
if (recentlyused[counter] == 0)
{
while ( counter != 1 )
{
if (recentlyused[counter] != 0)
{
numberOfCycles = recentlyused[counter] + numberOfCycles;
counter = 1;
}
else
{
if (counter % 2 == 0)
{
counter = counter /2;
}
else
{
counter = 3*counter + 1;
}
numberOfCycles++;
}
}
}
else
{
numberOfCycles = recentlyused[counter] + numberOfCycles;
counter = 1;
}
recentlyused[lowerBound] = numberOfCycles;
if (numberOfCycles > maxCycles)
{
maxCycles = numberOfCycles;
}
lowerBound++;
}
System.out.println(lowerInt +" "+ upperBound+ " "+ (maxCycles+1));
}
}
Are you making sure to accept the entire input? It looks like your program terminates after reading only one line, and then processing one line. You need to be able to accept the entire sample input at once.
I faced the same problem. The following changes worked for me:
Changed the class name to Main.
Removed the public modifier from the class name.
The following code gave a compilation error:
public class Optimal_Parking_11364 {
public static void main(String[] args) {
...
}
}
Whereas after the changes, the following code was accepted:
class Main {
public static void main(String[] args) {
...
}
}
This was a very very simple program. Hopefully, the same trick will also work for more complex programs.
If I understand correctly you are using a memoizing approach. You create a table where you store full results for all the elements you have already calculated so that you do not need to re-calculate results that you already know (calculated before).
The approach itself is not wrong, but there are a couple of things you must take into account. First, the input consists of a list of pairs, you are only processing the first pair. Then, you must take care of your memoizing table limits. You are assuming that all numbers you will hit fall in the range [1...1000001), but that is not true. For the input number 999999 (first odd number below the upper limit) the first operation will turn it into 3*n+1, which is way beyond the upper limit of the memoization table.
Some other things you may want to consider are halving the memoization table and only memorize odd numbers, since you can implement the divide by two operation almost free with bit operations (and checking for even-ness is also just one bit operation).
Did you make sure that the output was in the same order specified in the input. I see where you are swapping the input if the first input was higher than the second, but you also need to make sure that you don't alter the order it appears in the input when you print the results out.
ex.
Input
10 1
Output
10 1 20
If possible Please use this Java specification : to read input lines
http://online-judge.uva.es/problemset/data/p100.java.html
I think the most important thing in UVA judge is 1) Get the output Exactly same , No Extra Lines at the end or anywhere . 2) I am assuming , Never throw exception just return or break with No output for Outside boundary parameters.
3)Output is case sensitive 4)Output Parameters should Maintain Space as shown in problem
One possible solution based on above patterns is here
https://gist.github.com/4676999
/*
Problem URL: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36
Home>Online Judge > submission Specifications
Sample code to read input is from : http://online-judge.uva.es/problemset/data/p100.java.html
Runtime : 1.068
*/
import java.io.*;
import java.util.*;
class Main
{
static String ReadLn (int maxLg) // utility function to read from stdin
{
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
String line = "";
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static void main (String args[]) // entry point from OS
{
Main myWork = new Main(); // create a dinamic instance
myWork.Begin(); // the true entry point
}
void Begin()
{
String input;
StringTokenizer idata;
int a, b,max;
while ((input = Main.ReadLn (255)) != null)
{
idata = new StringTokenizer (input);
a = Integer.parseInt (idata.nextToken());
b = Integer.parseInt (idata.nextToken());
if (a<b){
max=work(a,b);
}else{
max=work(b,a);
}
System.out.println (a + " " + b + " " +max);
}
}
int work( int a , int b){
int max=0;
for ( int i=a;i<=b;i++){
int temp=process(i);
if (temp>max) max=temp;
}
return max;
}
int process (long n){
int count=1;
while(n!=1){
count++;
if (n%2==1){
n=n*3+1;
}else{
n=n>>1;
}
}
return count;
}
}
Please consider that the integers i and j must appear in the output in the same order in which they appeared in the input, so for:
10 1
You should print
10 1 20
package pandarium.java.preparing2topcoder;/*
* Main.java
* java program model for www.programming-challenges.com
*/
import java.io.*;
import java.util.*;
class Main implements Runnable{
static String ReadLn(int maxLg){ // utility function to read from stdin,
// Provided by Programming-challenges, edit for style only
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
String line = "";
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static void main(String args[]) // entry point from OS
{
Main myWork = new Main(); // Construct the bootloader
myWork.run(); // execute
}
public void run() {
new myStuff().run();
}
}
class myStuff implements Runnable{
private String input;
private StringTokenizer idata;
private List<Integer> maxes;
public void run(){
String input;
StringTokenizer idata;
int a, b,max=Integer.MIN_VALUE;
while ((input = Main.ReadLn (255)) != null)
{
max=Integer.MIN_VALUE;
maxes=new ArrayList<Integer>();
idata = new StringTokenizer (input);
a = Integer.parseInt (idata.nextToken());
b = Integer.parseInt (idata.nextToken());
System.out.println(a + " " + b + " "+max);
}
}
private static int getCyclesCount(long counter){
int cyclesCount=0;
while (counter!=1)
{
if(counter%2==0)
counter=counter>>1;
else
counter=counter*3+1;
cyclesCount++;
}
cyclesCount++;
return cyclesCount;
}
// You can insert more classes here if you want.
}
This solution gets accepted within 0.5s. I had to remove the package modifier.
import java.util.*;
public class Main {
static Map<Integer, Integer> map = new HashMap<>();
private static int f(int N) {
if (N == 1) {
return 1;
}
if (map.containsKey(N)) {
return map.get(N);
}
if (N % 2 == 0) {
N >>= 1;
map.put(N, f(N));
return 1 + map.get(N);
} else {
N = 3*N + 1;
map.put(N, f(N) );
return 1 + map.get(N);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
while(scanner.hasNextLine()) {
int i = scanner.nextInt();
int j = scanner.nextInt();
int maxx = 0;
if (i <= j) {
for(int m = i; m <= j; m++) {
maxx = Math.max(Main.f(m), maxx);
}
} else {
for(int m = j; m <= i; m++) {
maxx = Math.max(Main.f(m), maxx);
}
}
System.out.println(i + " " + j + " " + maxx);
}
System.exit(0);
} catch (Exception e) {
}
}
}

Categories

Resources