I am trying to solve this problem and I think I am in the right track but for some reason the program does not run in a specific condition.
This is the code:
public class Eight {
public static void main(String[] args) {
String set = "731671765313306249192251196744265747423"
+ "553491949349698352031277450632623957831801698"
+ "480186947885184385861560789112949495459501737958"
+ "331952853208805511125406987471585238630507156932909"
+ "632952274430435576689664895044524452316173185640309871"
+ "112172238311362229893423380308135336276614282806444486645"
+ "238749303589072962904915604407723907138105158593079608"
+ "66701724271218839987979087922749219016997208880937"
+ "7665727333001053367881220235421809751254540594752"
+ "243525849077116705560136048395864467063244157221"
+ "55397536978179778461740649551492908625693219784"
+ "686224828397224137565705605749026140797296865"
+ "241453510047482166370484403199890008895243450"
+ "6585412275886668811642717147992444292823086346567481391912316282458617866458"
+ "3591245665294765456828489128831426076900422421902267105562632111110937054421750694165"
+ "8960408071984038509624554443629812309878799272442849091888458015616609791913387549920052"
+ "4063689912560717606058861164671094050775410022569831552000559357297257163626956188267042"
+ "8252483600823257530420752963450";
int initialIndex = 0;
int lastIndex = 4;
int finale = 0;
for (;last <= set.length() - 1; initialIndex++, lastIndex++)
{
int num = Integer.parseInt(set.substring(initialIndex, lastIndex));
int result = 1;
while (num > 0)
{
int digit = num % 10;
result *= digit;
num /= 10;
}
if (result > finale)
finale = result;
} //end for
System.out.println(finale);
}
}
When lastIndex equals 4, the result I get is 5832, which is the same result as Project Euler gives you as an example. But when Im trying to run this program with 13 numbers instead of 4, I get an exception and the program does not run.
A 13 digit string will exceed the maximum allowable size of an int. Use Long.parseLong and change num from int to long. I did it, and got the following when I used 13 digits: 2091059712
Your issue begins here:
int num = Integer.parseInt(set.substring(initialIndex, lastIndex));
When you set lastIndex as 13, the number you are trying to take out of the string is 7,316,717,653,133. In your code, you are trying to parse that String as an int, which has a maximum value of 2^31 2,147,483,647.
You can fix your problem by making any variable you expect to excede 2^31 a different integral data type, like a long.
Related
I'm trying to take a digit from a string and perform operations on it. This is the relevant code I'm working on (updated):
String cardNumber;
String curNum;
long currentNum;
int firstNum;
int randNum;
int i;
long sum = 0;
while (i <= 15) {
//Delete this line if it doesnt work
currentNum = Long.parseLong(cardNumber.substring(i));
if (i % 2 == 0) {
//currentNum = Integer.parseInt(cardNumber.charAt(i));
currentNum = currentNum * 2;
if (currentNum > 9) {
currentNum = currentNum - 9;
sum = sum + currentNum;
}
else {
//currentNum = Integer.parseInt(cardNumber.charAt(i));
sum = sum + currentNum;
}
i++;
}
long lastVal = 10 - (sum % 10);
char charNum = (char) lastVal;
//add int to char statement here
cardNumber = cardNumber + charNum;
}
System.out.println(cardNumber);
userNum--;
}
The // code is another option I was working on and didn't want to lose, so if there's a way to make it work using that, that's great! The error message this code returns is:
Exception in thread "main" java.lang.NumberFormatException: For input string: "64406849400888"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Long.parseLong(Long.java:692)
at java.base/java.lang.Long.parseLong(Long.java:817)
at MasterCardGenerator.main(MasterCardGenerator.java:54)
You said you're trying to take "a" digit from a string. If that's truly the case, and you are trying to examine cardNumber one digit at a time, then you want cardNumber.substring(i, i+1) instead of cardNumber.substring(i).
Read the javadocs for substring(int) and substring(int, int) to understand why.
The problem is that the domain of integers is between [-2^31,2^31[, indeed between [-2,147,483,648 to +2,147,483,647]. A possible solution is to parse the string using Long.parseLong(arg)
public class Test{
public static void main(String []args){
System.out.println("Integer.MAX_VALUE: " + Integer.MAX_VALUE);
System.out.println("Long.MAX_VALUE: " + Long.MAX_VALUE);
Long var = Long.parseLong("267574698286122");
System.out.println("Printing content of 'var': " + var);
}
}
And the output is:
Integer.MAX_VALUE: 2147483647
Long.MAX_VALUE: 9223372036854775807
Printing content of 'var': 267574698286122
The problem is that the range string you are trying to format is larger than range of int.
To solve this problem, you need to change the line Integer.parseInt(cardNumber.substring(i)); with Long.parseLong(cardNumber.substring(i));.
See the range off different data types here. Also you can see, for int see here the Integer.MIN_VALUE and Integer.MAX_VALUE
and for long see here the Long.MIN_VALUE and Long.MAX_VALUE
UPDATED
As per updated question, String passed is 64406849400888 so valid index for i are 0 <= i <= 13. Apart from that above code looks fine. 64406849400888 can be parsed in long. See it the parsing here
I solved the Project Euler problem #14 https://projecteuler.net/problem=14 on Java, but when I run it in Powershell, it stops iterating at exactly i = 113383 every time. I rewrote the solution on python, and it works perfectly fine, albeit slowly. According to my (identical) python solution, the answer is that the number that produces the longest chain is 837799 and the chain is 524 operations long.
Why does the Java solution not finish the for-loop? Is there some kind of limit in Java on how long it can stay in a loop? I cannot come up with any other explanation. Java code below. I wrote the System.out.println(i) there just to see what is going on.
class ProjectEuler14 {
public static void main(String[] args) {
int largestNumber = 1;
int largestChain = 1;
int currentNumber;
int chainLength;
for (int i = 2; i < 1000000; i++) {
System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
if (currentNumber % 2 == 0) currentNumber /= 2;
else currentNumber = 3 * currentNumber + 1;
chainLength++;
}
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber +
" and the chain's length is " + largestChain);
}
}
It's not the for loop. It's the while loop. The condition currentNumber != 1 is always true; forever.
In java, an int is specifically defined as an integral number between -2^31 and +2^31 -1, inclusive, and operations 'roll over'. try it!
int x = 2^31 -1;
x++;
System.out.println(x);
this prints a large negative number (in fact, precisely -2^31).
It's happening in your algorithm, and that's why it never finishes.
A trivial solution is to 'upgrade' to longs; they are just as fast, really (yay 64-bit processors!) and use 64 bits, thus giving them a range of -2^63 to +2^63-1.
Python sort of scales up its numbers into slowness silently, java makes different choices (and, for crypto and other purposes, that rollover thing is in fact desired).
If you want to go even further, you can always use BigInteger, which grows as much as you need forever (becoming slower and taking more memory as it goes).
To know rollover occurred, the 3* operation would then result in a number that is lower than the original, and you can check for that:
replace:
else currentNumber = 3 * currentNumber + 1;
with:
else {
int newNumber = currentNumber * 3 + 1;
if (newNumber < currentNumber) throw new IllegalStateException("Overflow has occurred; 3 * " + currentNumber + " + 1 exceeds ints capacities.");
currentNumber = newNumber;
}
and rerun it. You'll see your app nicely explain itself.
The currentNumber is exceeding size of int, use long instead.
Do you hava problem overflow int.
Change int to long.
long largestNumber = 1;
long largestChain = 1;
long currentNumber;
long chainLength;
for (int i = 2; i < 1000000; i++) {
//System.out.println(i);
currentNumber = i;
chainLength = 0;
while (currentNumber != 1) {
//System.out.println("# = " + currentNumber);
if (currentNumber % 2 == 0) {
currentNumber /= 2;
} else {
currentNumber = (3 * currentNumber) +1 ;
}
chainLength++;
}
// System.out.println("################################ " + i);
if (chainLength > largestChain) {
largestChain = chainLength;
largestNumber = i;
}
}
System.out.println("\n\nThe number under million that produces the "
+ "longest chain is " + largestNumber
+ " and the chain's length is " + largestChain);
This question already has answers here:
Java reverse an int value without using array
(33 answers)
Closed 3 years ago.
I'm a Java beginner so please pardon me if the question seems silly but I already searched the forums but it seems like no one has my problem.
I need to reverse the digits of an integer, and my class hasn't covered while or if loops yet, so I can't use those. All answers I can find on stackoverflow use those, so I can't use those.
the input I am given is below 10000 and above 0 and the code I have written has no problem reversing the integer if the input is 4 digits (e.g. 1000 - 9999) but once the input is between 1 - 999 it creates zeroes on the right hand side but according to the answer sheets its wrong.
For example: 1534 gets turned into 4351, but
403 becomes 3040 instead of the 304 it should be, and 4 becomes 4000 instead of 4.
I've tried different things in the code but it seems to just keep giving the same answer. Or maybe I'm just missing some key mathematics, I'm not sure.
Scanner scan = new Scanner(System.in);
System.out.println ("Enter an integer:");
int value = scan.nextInt();
int digit = (value % 10);
value = (value / 10);
int digit2 = (value % 10);
value = (value / 10);
int digit3 = (value % 10);
value = (value / 10);
int digit4 = (value % 10);
String reversednum = ("" + digit + digit2 + digit3 + digit4);
System.out.println ( reversednum);
and
Scanner scan = new Scanner(System.in);
System.out.println ("Enter an integer:");
int value = scan.nextInt();
int digit = (value % 10);
int reversednum = (digit);
value = (value /10);
digit = (value % 10);
reversednum = (reversednum * 10 + digit);
value = (value / 10);
digit = (value % 10);
reversednum = (reversednum * 10 + digit);
value = (value / 10);
digit = (value);
reversednum = (reversednum * 10 + digit);
System.out.println (reversednum);
What am I doing wrong?
You can convert from int to String -> reverse String -> convert again in int.
This is a code example.
public int getReverseInt(int value) {
String revertedStr = new StringBuilder(value).reverse().toString();
return Integer.parseInt(revertedStr);
}
Your code assumes that the number can be divided by 1000, which is clearly not the case for numbers below 1000. So add some if statements:
public int reverseNumber(int n) {
// step one: we find the factors using integer maths
int s = n;
int thousands = s / 1000; // this will be 0 if the number is <1000
s = s - thousands*1000;
int hundreds = s / 100; // this will be 0 if the number is <100
s = s - hundreds*100;
int tens = s / 10; // etc.
s = s - tens*10;
int ones = s;
// then: let's start reversing. single digit?
if (n<10) return n;
// two digits?
if (n<100) {
return ones*10 + tens;
}
// etc.
if (n<1000) {
return ones*100 + tens*10 + hundreds;
}
if (n<10000) {
return ones*1000 + tens*100 + hundreds*10 + thousands;
}
// if we get here, we have no idea what to do with this number.
return n;
}
Without spoon-feeding you code (leaving the value of writing your own homework code intact)...
Although you've said you can't use a loop, I don't think there's a sane approach that doesn't use one. Your basic problem is you have hard-coded a solution that works when the number happens to have 4 digits, rather than using code that adapts to a variable length. ie, are not using a loop.
All is not lost with your code however. You have figured out the essence of the solution. You just need to convert it to work processing one digit at a time. Consider using recursion, that divides the number by 10 each time and continues until the number is zero. Of course, you’ll have to capture the end digit before it’s lost by division.
Pseudo code may look like:
pass in the number and the current result
if the number is 0 return result
multiply result by 10 and add remainder of number divided by 10
return the result of calling self with number divided by 10 and result
then call this passing number and zero
Using modulus and division:
int nbr = 123; // reverse to 321 or 3*10*10 + 2*10 + 1
int rev = 0;
while(nbr > 0) {
rev *= 10; // shift left 1 digit
int temp = nbr % 10; // get LO digit
rev += temp; // add in next digit
nbr /= 10; // move to next digit
}
Or a recursive method:
public static int reverseInt(int number, int value) {
switch(number) { // is this conditional statement allowed???
case 0:
return value;
}
value *= 10;
int lod = number % 10;
value += lod;
number /= 10;
return reverseInt(number, value);
}
I am given a non-recursive method, that I need to modify to make recursive.
This is what I have so far:
public class BaseN {
public static final int BASEN_ERRNO = -1;
public static void main(String[] argv) {
Scanner input = new Scanner(System.in);
System.out.print("enter number followed by base (e.g. 237 8): ");
int number = input.nextInt();
int base = input.nextInt();
BigInteger answer = basen(number, base);
System.out.println(number + " base-" + base + " = " + answer);
}
static BigInteger basen(int number, int base ) {
List<Integer> remainder = new ArrayList<>();
int count = 0;
String result = "";
while( number != 0 ) {
remainder.add( count, number % base != 0 ? number % base : 0 );
number /= base;
try {
result += remainder.get( count );
} catch( NumberFormatException e ) {
e.printStackTrace();
}
}
return new BigInteger( new StringBuffer( result ).reverse().toString() );
}
}
It's converting it to base 10 then the given base. I need it to convert to the given base first then base 10.
UPDATE:
I changed around Caetano's code a bit and think I am closer.
static String basen(int number, int base) {
String result = String.valueOf(number % base);
int resultC;
String resultD;
int newNumber = number / base;
if (newNumber != 0)
result += basen(newNumber, base);
if (newNumber == 0)
resultC = Integer.parseInt(result);
resultD = Integer.toString(resultC);
return resultD;
Now when I compile it it gives me an error it says:
BaseN.java:49: error: variable resultC might not have been initialized
resultD = Integer.toString(resultC);
Am I on the right track here? Any help is appreciated
Its hard to tell what you are asking for.
I can only assume that you want to convert from a given base to base 10. The way that you would do this is explained in this page here: MathBits introduction to base 10.
The way explained in this is simple. For each digit in the number you get the base to the power of the position of the digit(reversed) and multiply that by whatever the digit is. Then add all the results. So 237 in base 8 would be
(8^2 * 2) + (8^1 * 3) + (8^0 * 7) = 159
Now you will run in to a problem when you do this with bases higher then 10 since the general notation for digits above 9 is alphabetical letters. However you could get around this by having a list of values such as [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F] and compare the digits with this list and get the index of the location of that digit as the number.
I hope this is what you were asking for.
Now then this is code that does what you want it to do. Get a number in a given base and convert it to base 10. However I don't see why you need to use a recursive method for this. If this is some kind of school task or project then please tell us the details because I don't personally see a reason to use recursion. However the fact that your question asks us to modify the code up top to make it recursive then it makes much more sense. Since that code can be edited to be as such.
public static final int BASEN_ERRNO = -1;
public static void main(String[] argv) {
Scanner input = new Scanner(System.in);
System.out.print("enter number followed by base (e.g. 237 8): ");
String number = input.next();
int base = input.nextInt();
int answer = basen(number, base);
System.out.println(number + " base-" + base + " = " + answer);
}
private static int basen(String number, int base ) {
int result = 0;
for(int i = 0; i < number.length(); i++) {
int num = Integer.parseInt(number.substring(i, i + 1));
result += Math.pow(base, number.length() - i - 1) * num;
}
return result;
}
However what I think that you want is actually this which shows recursion but instead of converting from base given to base 10 it converts from base 10 to base given. Which is exactly what the code you showed does but uses recursion. Which means '512 6' will output '2212'
public static final int BASEN_ERRNO = -1;
public static void main(String[] argv) {
Scanner input = new Scanner(System.in);
System.out.print("enter number followed by base (e.g. 237 8): ");
int number = input.nextInt();
int base = input.nextInt();
String answer = new StringBuffer(basen(number, base)).reverse().toString();
System.out.println(number + " base-" + base + " = " + answer);
}
static String basen(int number, int base) {
String result = String.valueOf(number % base);
int newNumber = number / base;
if (newNumber != 0)
result += basen(newNumber, base);
return result;
}
I figured out a way to do it recursively. Thank you everyone who provided help. I ended up using Math.pow on the base and put the length of the number -1 for how it would be exponentially increased. Math.pow puts the result in double format so I just converted it back to an int. My professor gave me 100% for this answer, so I'd imagine it would work for others too.
public static int basen(int number, int base) {
String numberStr;
int numberL;
char one;
String remainder;
int oneInt;
int remainderInt;
double power;
int powerInt;
numberStr = Integer.toString(number);
numberL = numberStr.length();
if(numberL > 1){
one = numberStr.charAt(0);
remainder = numberStr.substring(1);
oneInt = Character.getNumericValue(one);
remainderInt = Integer.parseInt(remainder);
power = Math.pow(base, (numberL - 1));
powerInt = (int)power;
return ((oneInt * powerInt) + (basen(remainderInt, base)));
}
else{
return number;
}
}
I have incoming bits like, 0, 1, 11, 10 etc. Which I store in a string. Then I convert the string to an Int.
Now, suppose Int A = "011" and Int B = "00". Is it possible in java to know, how many bits was there in the string which I have converted to the Int. Thanks.
Yes, just test each bit in turn using a mask. For integers there are 32 possible bits.
Luckily java provides this for you:
Integer.bitCount(value)
If you wanted to do it yourself:
int value = Integer.parseInt("1000101010", 2);
int bitCounter = 0;
for (int i = 0; i < Integer.SIZE; i++) {
if (((1 << i) & value) > 0) {
bitCounter++;
}
}
System.out.println(value + " has " + bitCounter + " bits");
Output
554 has 4 bits
If alternatively you wanted the "length", i.e. the number of 0s or 1s...
Convert to string and find length
System.out.println(Integer.toString(value, 2).length());
Use some knowledge of maths to take the base(2) log of the value.
double valueUnsigned;
if (value < 0) {
valueUnsigned = (value & 0x7FFFFFF) + 0x80000000l;
} else {
valueUnsigned = value;
}
System.out.println("Maths solution " + Math.floor(1d + Math.log(valueUnsigned) / Math.log(2)));