Optimize Collatz Conjecture in Java - java

I'm working on a program that determines the number of steps it takes for a number to become 1 using the Collatz Conjecture (if n is odd, 3n+1; if n is even, n/2). The program increases the number being calculated by one each time it completes a calculation, and tests how many numbers it can calculate in seconds. Here is the working program I currently have:
public class Collatz {
static long numSteps = 0;
public static long calculate(long c){
if(c == 1){
return numSteps;
}
else if(c % 2 == 0){
numSteps++;
calculate(c / 2);
}
else if(c % 2 != 0){
numSteps++;
calculate(c * 3 + 1);
}
return numSteps;
}
public static void main(String args[]){
int n = 1;
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() < startTime + 60000){
calculate(n);
n++;
numSteps = 0;
}
System.out.println("The highest number was: " + n);
}
}
It can currently calculate about 100 million numbers in a minute, but I'm looking for advice on how to further optimize the program so that it can calculate more numbers in a minute. Any and all advice would be appreciated :).

You can
optimise the calculate method by assuming that is c % 2 == 0 is false than c % 2 != 0 must be true. You can also assume that c * 3 + 1 must be an even number so you can calculate (c * 3 + 1)/2 and add two to the numSteps. You can use a loop instead of recursion as Java doesn't have tail-call optimisation.
get a bigger improvement by using memorisation. For each each number you can memorise the result you get and if the number has been calculated before just return that value. You might want to place an upper bound on memorization e.g. no higher than the last number you want to calculate. If you don't do this some of the value will be many times the largest value.
For your interest
public class Collatz {
static final int[] CALC_CACHE = new int[2_000_000_000];
static int calculate(long n) {
int numSteps = 0;
long c = n;
while (c != 1) {
if (c < CALC_CACHE.length) {
int steps = CALC_CACHE[(int) c];
if (steps > 0) {
numSteps += steps;
break;
}
}
if (c % 2 == 0) {
numSteps++;
c /= 2;
} else {
numSteps += 2;
if (c > Long.MAX_VALUE / 3)
throw new IllegalStateException("c is too large " + c);
c = (c * 3 + 1) / 2;
}
}
if (n < CALC_CACHE.length) {
CALC_CACHE[(int) n] = numSteps;
}
return numSteps;
}
public static void main(String args[]) {
long n = 1, maxN = 0, maxSteps = 0;
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() < startTime + 60000) {
for (int i = 0; i < 10; i++) {
int steps = calculate(n);
if (steps > maxSteps) {
maxSteps = steps;
maxN = n;
}
n++;
}
if (n % 10000000 == 1)
System.out.printf("%,d%n", n);
}
System.out.printf("The highest number was: %,d, maxSteps: %,d for: %,d%n", n, maxSteps, maxN);
}
}
prints
The highest number was: 1,672,915,631, maxSteps: 1,000 for: 1,412,987,847
A more advanced answer would be to use multiple threads. In this case using recursion with memorisation was easier to implement.
import java.util.stream.LongStream;
public class Collatz {
static final short[] CALC_CACHE = new short[Integer.MAX_VALUE-8];
public static int calculate(long c) {
if (c == 1) {
return 0;
}
int steps;
if (c < CALC_CACHE.length) {
steps = CALC_CACHE[(int) c];
if (steps > 0)
return steps;
}
if (c % 2 == 0) {
steps = calculate(c / 2) + 1;
} else {
steps = calculate((c * 3 + 1) / 2) + 2;
}
if (c < CALC_CACHE.length) {
if (steps > Short.MAX_VALUE)
throw new AssertionError();
CALC_CACHE[(int) c] = (short) steps;
}
return steps;
}
static int calculate2(long n) {
int numSteps = 0;
long c = n;
while (c != 1) {
if (c < CALC_CACHE.length) {
int steps = CALC_CACHE[(int) c];
if (steps > 0) {
numSteps += steps;
break;
}
}
if (c % 2 == 0) {
numSteps++;
c /= 2;
} else {
numSteps += 2;
if (c > Long.MAX_VALUE / 3)
throw new IllegalStateException("c is too large " + c);
c = (c * 3 + 1) / 2;
}
}
if (n < CALC_CACHE.length) {
CALC_CACHE[(int) n] = (short) numSteps;
}
return numSteps;
}
public static void main(String args[]) {
long maxN = 0, maxSteps = 0;
long startTime = System.currentTimeMillis();
long[] res = LongStream.range(1, 6_000_000_000L).parallel().collect(
() -> new long[2],
(long[] arr, long n) -> {
int steps = calculate(n);
if (steps > arr[0]) {
arr[0] = steps;
arr[1] = n;
}
},
(a, b) -> {
if (a[0] < b[0]) {
a[0] = b[0];
a[1] = b[1];
}
});
maxN = res[1];
maxSteps = res[0];
long time = System.currentTimeMillis() - startTime;
System.out.printf("After %.3f seconds, maxSteps: %,d for: %,d%n", time / 1e3, maxSteps, maxN);
}
}
prints
After 52.461 seconds, maxSteps: 1,131 for: 4,890,328,815
Note: If I change the second calculate call to
steps = calculate((c * 3 + 1) ) + 1;
it prints
After 63.065 seconds, maxSteps: 1,131 for: 4,890,328,815

Related

Dead code warning in the i--

I'm going to try to define function which return greatest common divisor.
Now I'm just meeting some obstacle.
Why do dead code warning appear in the i--?
I can feel nothing so please let me know what is wrong.
public class Main {
public static int function(int a, int b, int c) {
int min;
if (a > b) {
if (b > c) {
min = c;
} else {
min = b;
}
} else {
if (a > c) {
min = c;
} else {
min = a;
}
}
for (int i = min; i > 0; i--) {
if (a % i == 0 && b % i == 0 && c % i == 0) {
return i;
}
return -1;
}
return 0;
}
public static void main(String[] args) {
System.out.println("(400, 300, 750)의 최대 공약수 : " + function(400, 300, 750));
}
}
The for loop has an if block where you are returning the greatest common divisor if found. If not you are returning -1. So the loop will never continue and "i--" will never be executed. That is why it's a dead code. Remove "return -1", it should work properly.
Stepping through the code in your debugger is often the quickest way to find these bugs. However, you could make the code much faster by only checking values which are a factor of the min value. This reduces the number of iterations dramatically.
public class Main {
public static int function(int a, int b, int c) {
int min;
if (a > b) {
if (b > c) {
min = c;
} else {
min = b;
}
} else {
if (a > c) {
min = c;
} else {
min = a;
}
}
for (int i = min; i > 0; i--) {
if (a % i == 0 && b % i == 0 && c % i == 0) {
System.err.println("Iterations " + (min + 1 - i));
return i;
}
}
return 0;
}
public static long gcd(long a, long b, long c) {
long min = Math.min(a, Math.min(b, c));
for (int j = 1, max = (int) Math.sqrt(min); j <= max; j++) {
long i = min / j;
if (a % i == 0 && b % i == 0 && c % i == 0) {
System.err.println("Iterations: " + j);
return i;
}
}
return 1;
}
public static void main(String[] args) {
System.out.println("(400, 300, 750)의 최대 공약수 : " + function(400, 300, 750));
System.out.println("(400, 300, 750)의 최대 공약수 : " + gcd(400, 300, 750));
}
}
prints
(400, 300, 750)의 최대 공약수 : 50
(400, 300, 750)의 최대 공약수 : 50
Iterations 251
Iterations: 6
In your approach, it has to consider all the factors from 300 to 50 (251 values). But considering only the factors of 300 i.e. 300/1, 300/2, 300/3, 300/4, 300/5, 300/6 (6 values) it is much faster.

Recursive method for Amicable numbers between 1 - 10000 Java

I have a problem with creating a recursive method for finding Amicable numbers between 1 - 10000. I created a method to find out if two numbers are Amicable, but I don't know how to run it against every possible number combination. Here are both methods which I wrote.
public void amicable(int n, int m) {
int sumM = 0;
int sumN = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumN += i;
}
}
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumM += j;
}
}
if (sumN == m && sumM == n) {
System.out.println(n + " and " + m + " are amicable numbers");
}
}
public static void amicableBetween(int n, int m) {
int sumaM = 0;
int sumaN = 0;
if (m >= 1) {
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumaM += j;
}
}
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumaN += i;
}
}
if (sumaN == m && sumaM == n) {
System.out.println(n + " and " + m + " are amicable numbers");
amicableBetween(n + 1, m - 1);
} else {
System.out.println(n + " i " + m + " aren't amicable numbers");
amicableBetween(n + 1, m - 1);
}
}
}
}
Minor disclaimer, this method might take forever and you might run out of stack space so I'm not 100% sure that calculating all the amicable numbers from 1-10000 recursively is the way to go. If this is just for fun or practice then I guess is ok.
One approach will be to sweep n until we reach m - 1 and call amicable(n,m) in each step. Once n has reached m - 1, we can decrease m by 1 and repeat the process until n is equal to m - 1 then we have checked all possible combinations. To do this, you can break your two methods into three methods.
The first method is the amicable method you already have, just changed the return type so that we can reuse it while we are going down the recursion chain:
public static boolean amicable(int n, int m) {
int sumM = 0;
int sumN = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumN += i;
}
}
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumM += j;
}
}
return sumN == m && sumM == n;
}
The second will be the public method amicableBetween(int n, int m)
public static void amicableBetween(int n, int m) {
amicableBetween(n, m, true);
}
Which will call a third private helper method amicableBetween(int n, int m, boolean start) that has a third parameter start that it can use to identify if n has reached m. Then we need to decrease m by 1 and repeat the process:
private static void amicableBetween(int n, int m, boolean start) {
if(n == m) {
return;
}
if (m >= 1) {
if (amicable(n, m)) {
System.out.println(n + " and " + m + " are amicable numbers");
} else {
System.out.println(n + " and " + m + " aren't amicable numbers");
}
amicableBetween(n + 1, m, false);
}
if(start) {
amicableBetween(n, m - 1, true);
}
}
I wonder why do you want a recursive algorithm. Don't you warry about StackOvervlowException?! It is pretty easy to find with simple Map within O(n) time:
public static void amicable(int lo, int hi) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = lo; i <= hi; i++) {
int j = map.computeIfAbsent(i, DIV_SUM);
if (j > i && j <= hi && map.computeIfAbsent(j, DIV_SUM) == i)
System.out.format("[%d : %d]\n", i, j);
}
}
private static final Function<Integer, Integer> DIV_SUM = val -> {
int sum = 0;
for (int i = 1, max = val / 2; i <= max; i++)
if (val % i == 0)
sum += i;
return sum;
};
Demo: time ~150ms
amicable(1, 10000);
[220 : 284]
[1184 : 1210]
[2620 : 2924]
[5020 : 5564]
[6232 : 6368]
So, you wrote a method that can tell if two numbers are amicable. That's the hard part out of the way. All you have to do is call that from inside two loops, one for the upper bound, one for the lower bound.
for(lowerNumber = 1; lowerNumber < 10000; lowerNumber++){
for(upperNumber = lowerNumber + 1; upperNumber <= 10000; upperNumber++){
amicable(lowerNumber, upperNumber);
}
}
I'm not sure why you need two parameters in the amicable function. An amicable number has a repeating aliquot sequence of period 2, which means
s(s(n)) == n
We can find the number's complement by retrieving the sum of its proper divisors and checking the assertion above.
This means to find the amicable numbers for n between 1 and 10,000 we only need n, and would also make trivial the part of the process you seem to want as a recursion.
JavaScript code:
function s(n){
let s = n > 1 ? 1 : 0;
let sqrt_n = Math.sqrt(n);
let d1=Math.floor(n/2);
for (; d1>=sqrt_n; d1--){
let d2 = n / d1;
if (d2 == Math.floor(d2))
s += d1 + d2;
}
if (d1 == sqrt_n)
s += d1;
return s;
}
let n = 220;
let s_n = s(n);
if (s(s_n) == n)
console.log('Amicable!', n, s_n);

Miller-Rabin Primality Test Often Returns Composite for Prime Numbers

I have been trying to implement a Miller-Rabin primality test from scratch (only primitives and Strings) that works for 64 bit integers (longs). I've tried the Java and pseudocode from Wikipedia, as well as various other websites. So far, only very small numbers have worked correctly. Most numbers are incorrectly marked composite, such as 53 or 101. I have tried tracking various sections of the code to see where the problem is. It seems to be in the innermost loop. I don't know what the specific issue is. Any help is appreciated. Thanks!
Here is my code:
public class PrimeTest
{
public static void main(String[] args)
{
PrimeTest app = new PrimeTest();
}
private PrimeTest()
{
long n = 53; // Change to any number. 53 is prime, but is reported as composite
if (checkPrime(n, 10))
{
System.out.println(n + " is prime.");
}
else
{
System.out.println(n + " is not prime.");
}
}
// Check if n is prime with 4^(-k) change of error
private boolean checkPrime(long n, int k)
{
// Factor n-1 as d*2^s
long d = n - 1;
int s = 0;
while (d % 2 == 0)
{
d /= 2;
s++;
}
// Repeat k times for 4^-k accuracy
for (int i = 0; i < k; i++)
{
long a = (long) ((Math.random() * (n - 3)) + 2);
long x = modPow(a, d, n);
if (x == 1 || x == (n - 1))
{
continue;
}
int r;
for (r = 0; r < s; r++)
{
x = modPow(x, 2, n);
if (x == 1)
{
return false;
}
if (x == (n - 1))
{
break;
}
}
if (r == s)
{
return false;
}
}
return true;
}
// Return (base^exp) % mod
private long modPow(long base, long exp, long mod)
{
if (mod == 1)
{
return 0;
}
long result = 1;
base = base % mod;
while (exp > 0)
{
if ((exp & 1) == 0)
{
result = (result * base) % mod;
}
exp = exp >> 1;
base = (base * base) % mod;
if (base == 1)
{
break;
}
}
return result;
}
}
This line in modPow:
if ((exp & 1) == 0)
is wrong and should instead be
if ((exp & 1) == 1)

How to print the middle digit of a number if so?

I tried a program but it shows the first digit. I want a mid digit program by using while loop.
I used the following-
public class MID {
public static void Indra(int n) {
int a = 0, c = 0, m = 0, r = 0;
a = n;
while (n != 0) {
c++;
n = n / 10;
}
n = a;
if (c % 2 == 0) {
System.out.println("No mid digit exsist!!");
} else {
m = (c + 1) / 2;
c = 0;
while (n != 0) {
c++;
r = n % 10;
if (c == r) {
System.out.println(r);
}
n = n / 10;
}
}
}
}
But it keeps on giving the same output-
The mid digit of 345 is 3
Please,help me!
If you dont mind using a different logic, you can try this..
int x = 354;
String num = Integer.toString(x);
if(num.length() % 2 != 0){
System.out.println("The mid digit of " + x + " is " + num.charAt(num.length()/2));
}else {
System.out.println("No middle number.");
}
You calculate m for the position middle digit, but you don't use it.
m = (c + 1) / 2;
for (int i = 0; i < m; i++)
n /= 10;
System.out.println(n % 10);
If you want to stick to int then use this
if (c == 1 || c % 2 == 0) {
System.out.println("No mid digit exsist!!");
}
else
{
m = c/2;
int lower = (int)(n % Math.pow(10, m));
int upper = n-((int)(n % Math.pow(10, m+1)));
r = n-(upper+lower);
while (r >= 10)
{
r = r/10;
}
System.out.println(r);
}

Reverse Integer leetcode -- how to handle overflow

The problem is:
Reverse digits of an integer.
Example1: x = 123, return 321
Example2: x = -123, return -321
Did you notice that the reversed integer might overflow? Assume the input is a 32-bit integer, then the reverse of 1000000003 overflows. How should you handle such cases?
Throw an exception? Good, but what if throwing an exception is not an option? You would then have to re-design the function (ie, add an extra parameter).
The solution from the website I search is:
public class Solution {
public static int reverse(int x) {
int ret = 0;
boolean zero = false;
while (!zero) {
ret = ret * 10 + (x % 10);
x /= 10;
if(x == 0){
zero = true;
}
}
return ret;
}
public static void main(String[] args) {
int s = 1000000003;
System.out.println(reverse(s));
}
}
However when s = 1000000003, the console prints -1294967295 instead of 3000000001. So this solution still does not solve the overflow problem if we cannot use exception. Any help here?(Although there is a hint: add an extra parameter, I still cannot figure out what parameter I should add)
There's no need for any data type other than int.
Just make sure when there's an operation that increases a number, reversing the operation should give you the previous number. Otherwise, there's overflow.
public int reverse(int x) {
int y = 0;
while(x != 0) {
int yy = y*10 + x%10;
if ((yy - x%10)/10 != y) return 0;
else y = yy;
x = x/10;
}
return y;
}
Above most of the answers having a trivial problem is that the int variable possibly might overflow. You can try this : x = -2147483648 as parameter.
There has an easy way to solve the problem. Convert x to long, and check if the result >= Integer.MAX_VALUE, otherwise return 0.
The solution passed all test cases on https://leetcode.com/problems/reverse-integer/
This is a java version.
public int reverse(int x) {
long k = x;
boolean isNegtive = false;
if(k < 0){
k = 0 - k;
isNegtive = true;
}
long result = 0;
while(k != 0){
result *= 10;
result += k % 10;
k /= 10;
}
if(result > Integer.MAX_VALUE) return 0;
return isNegtive ? 0 - ((int)result) : (int)result;
}
C# version
public int Reverse(int x)
{
long value = 0;
bool negative = x < 0;
long y = x;
y = Math.Abs(y);
while (y > 0)
{
value *= 10;
value += y % 10;
y /= 10;
}
if(value > int.MaxValue)
{
return int.MaxValue;
}
int ret = (int)value;
if (negative)
{
return 0 - ret;
}
else
{
return ret;
}
}
Python version
def reverse(self, x):
isNegative = x < 0
ret = 0
x = abs(x)
while x > 0:
ret *= 10
ret += x % 10
x /= 10
if ret > 1<<31:
return 0
if isNegative:
return 0 - ret
else:
return ret
This java code handles the overflow condition:
public int reverse(int x) {
long reverse = 0;
while( x != 0 ) {
reverse = reverse * 10 + x % 10;
x = x/10;
}
if(reverse > Integer.MAX_VALUE || reverse < Integer.MIN_VALUE) {
return 0;
} else {
return (int) reverse;
}
}
This is an old question, but anyway let me have a go at it too! I just solved it on leetcode. With this check, you never hit the overflow/ underflow in either direction, and I think the code is more concise than all the listed codes. It passes all test cases.
public int reverse(int x) {
int y = 0;
while(x != 0) {
if(y > Integer.MAX_VALUE/10 || y < Integer.MIN_VALUE/10) return 0;
y *= 10;
y += x % 10;
x /= 10;
}
return y;
}
you can try this code using strings in java
class Solution {
public int reverse(int x) {
int n = Math.abs(x);
String num = Integer.toString(n);
StringBuilder sb = new StringBuilder(num);
sb.reverse();
String sb1;
sb1 = sb.toString();
int foo;
try {
foo = Integer.parseInt(sb1);
}
catch (NumberFormatException e){
foo = 0;
}
if(x < 0){
foo *= -1;
}
return foo;
}
}
My soluton for this problem is to convert integer inputed to c-string, then everthing will be easy.
class Solution {
public:
int reverse(int x) {
char str[11];
bool isNegative = false;
int i;
int ret = 0;
if ( x < 0 ) {
isNegative = true;
x = -x;
}
i = 0;
while ( x != 0 ) {
str[i++] = x % 10 + '0';
x = x / 10;
}
str[i] = '\0';
if ( (isNegative && strlen(str) == 10 && strcmp(str, "2147483648") > 0) || (!isNegative && strlen(str) == 10 && strcmp(str, "2147483647") > 0) ) {
cout << "Out of range!" << endl;
throw new exception();
}
i = 0;
int strLen = (int)strlen(str);
while ( str[i] != '\0' ) {
ret += ((str[i] - '0') * pow(10.0, strLen - 1 - i));
i++;
}
return (isNegative ? -ret : ret);
}
};
This works:
public class Solution {
public int reverse(int x) {
long tmp = Math.abs((long)x);
long res = 0;
while(tmp >= 10){
res += tmp%10;
res*=10;
tmp=tmp/10;
}
res+=tmp;
if(x<0){
res = -res;
}
return (res>Integer.MAX_VALUE||res<Integer.MIN_VALUE)? 0: (int)res;
}
}
I tried to improve the performance a bit but all I could come up with was this:
public class Solution {
public int reverse(int x) {
long tmp = x;
long res = 0;
if(x>0){
while(tmp >= 10){
res += tmp%10;
res*=10;
tmp=tmp/10;
}
}
else{
while(tmp <= -10){
res += tmp%10;
res*=10;
tmp=tmp/10;
}
}
res+=tmp;
return (res>Integer.MAX_VALUE||res<Integer.MIN_VALUE)? 0: (int)res;
}
}
Its C# equivalent runs 5% faster than the 1st version on my machine, but their server says it is slower, which can't be - I got rid of extra function call here, otherwise it is essentially the same. It places me between 60-30% depending on the language (C# or Java). Maybe their benchmarking code is not very good - if you submit several times - resulting times vary a lot.
Solution In Swift 4.0 (in reference to problem from https://leetcode.com/problems/reverse-integer/description/)
func reverse(_ x : Int) -> Int {
var stringConversion = String(x)
var negativeCharacter = false
var finalreversedString = String()
let signedInt = 2147483647 //Max for Int 32
let unSignedInt = -2147483647 // Min for Int 32
if stringConversion.contains("-"){
stringConversion.removeFirst()
negativeCharacter = true
}
var reversedString = String(stringConversion.reversed())
if reversedString.first == "0" {
reversedString.removeFirst()
}
if negativeCharacter {
finalreversedString = "-\(reversedString)"
} else {
finalreversedString = reversedString
}
return (x == 0 || Int(finalreversedString)! > signedInt || Int(finalreversedString)! < unSignedInt) ? 0 : Int(finalreversedString)!
}
Last night, i have tried this same problem and i have found a simple solution in python, which is given below, here after checking the number type positive or negative, though i have tried in different section for both of them, i have convert the negative number into positive and before returning the reverse number, i had converted the number into negative.
For handling overflow, i have just simply checked with the upper limit of our 32-bit signed number and lower limit of the number, and it accepted my answer, thank you.
class Solution:
def reverse(self, x: int):
reverse = 0
if x > 0:
while x != 0:
remainder = x % 10
if reverse > (2147483647/10):
return 0
reverse = reverse * 10 + remainder
x = int(x / 10)
return reverse
elif x < 0:
x = x * (-1)
while x != 0:
remainder = x % 10
if reverse > ((2147483648)/10):
return 0
reverse = reverse * 10 + remainder
x = int(x / 10)
reverse = reverse * (-1)
return reverse
else:
return 0
public static int reverse(int x) {
boolean pos = x >= +0;
int y = (pos) ? x : -x;
StringBuilder sb = new StringBuilder(
String.valueOf(y));
sb.reverse();
int z = Integer.parseInt(sb.toString());
return pos ? z : -z;
}
public static void main(String[] args) {
for (int i = -10; i < 11; i++) {
System.out.printf("%d r= '%d'\n", i, reverse(i));
}
}
Outputs
-10 r= '-1'
-9 r= '-9'
-8 r= '-8'
-7 r= '-7'
-6 r= '-6'
-5 r= '-5'
-4 r= '-4'
-3 r= '-3'
-2 r= '-2'
-1 r= '-1'
0 r= '0'
1 r= '1'
2 r= '2'
3 r= '3'
4 r= '4'
5 r= '5'
6 r= '6'
7 r= '7'
8 r= '8'
9 r= '9'
10 r= '1'
Did you notice the reverse of 10 and -10? Or 20? You could just return a String, for example
public static String reverse(int x) {
boolean pos = x >= +0;
int y = (pos) ? x : -x;
StringBuilder sb = new StringBuilder(
String.valueOf(y));
sb.reverse();
if (!pos) {
sb.insert(0, '-');
}
return sb.toString();
}
public static void main(String[] args) {
for (int i = -10; i < 11; i++) {
System.out.printf("%d r= '%s'\n", i, reverse(i));
}
}
Works as I would expect.
If you are required to return a 32 bit int, and still need to know if there was an overflow perhaps you could use a flag as an extra parameter. If you were using c or c++ you could use pointers to set the flag, or in Java you can use an array (since Java objects pass by value).
Java example:
public class Solution {
public static int reverse(int x, Boolean[] overflowed) {
int ret = 0;
boolean zero = false;
boolean inputIsNegative = x < 0;
while (!zero) {
ret = ret * 10 + (x % 10);
x /= 10;
if(x == 0){
zero = true;
}
}
//Set the flag
if ( (inputIsNegative && (ret > 0)) || ((!inputIsNegative) && (ret < 0)))
overflowed[0] = new Boolean(true);
else
overflowed[0] = new Boolean(false);
return ret;
}
public static void main(String[] args) {
int s = 1000000004;
Boolean[] flag = {null};
System.out.println(s);
int n = reverse(s,flag); //reverse() will set the flag.
System.out.println(flag[0].booleanValue() ? "Error: Overflow": n );
}
}
Notice if the reversed number is too large for a 32 bit integer the flag will be set.
Hope this helps.
Use string to store the reverse and then print or use long or BigInt
public class Solution {
/**
* OVERFLOW
* #param x
* #return
*/
public int reverse(int x) {
int sign = x>0? 1: -1;
x *= sign;
int ret = 0;
while(x>0) {
ret *= 10;
if(ret<0 || x>10&&ret*10/10!=ret) // overflow
return 0;
ret += x%10;
x /= 10;
}
return ret*sign;
}
public static void main(String[] args) {
assert new Solution().reverse(-2147483412)==-2147483412;
}
}
public class Solution {
public int Reverse(int x) {
var sign = x < 0 ? -1 : 1;
var reverse = 0;
if (x == int.MinValue)
{
return 0;
}
x = Math.Abs(x);
while(x > 0)
{
var remainder = x % 10;
if (reverse > ((int.MaxValue - remainder)/10))
{
return 0;
}
reverse = (reverse*10) + remainder;
x = x/10;
}
return sign * Convert.ToInt32(reverse);
}
}
Here we will use long to handle the the over flow:
public class Solution {
public int reverse(int A) {
// use long to monitor Overflow
long result = 0;
while (A != 0) {
result = result * 10 + (A % 10);
A = A / 10;
}
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
return 0;
} else {
return (int) result;
}
}
}
Well This Suitable Code in Java Can be:-
public class Solution {
public int reverse(int x) {
int r;
long s = 0;
while(x != 0)
{
r = x % 10;
s = (s * 10) + r;
x = x/10;
}
if(s >= Integer.MAX_VALUE || s <= Integer.MIN_VALUE) return 0;
else
return (int)s;
}
}
My solution without using long:
public class ReverseInteger {
public static void main(String[] args) {
int input = Integer.MAX_VALUE;
int output = reverse(input);
System.out.println(output);
}
public static int reverse(int x) {
int remainder = 0;
int result = 0;
if (x < 10 && x > -10) {
return x;
}
while (x != 0) {
remainder = x % 10;
int absResult = Math.abs(result);
int maxResultMultipliedBy10 = Integer.MAX_VALUE / 10;
if (absResult > maxResultMultipliedBy10) {
return 0;
}
int resultMultipliedBy10 = absResult * 10;
int maxRemainder = Integer.MAX_VALUE - resultMultipliedBy10;
if (remainder > maxRemainder) {
return 0;
}
result = result * 10 + remainder;
x = x / 10;
}
return result;
}
}
here is the JavaScript solution.
/**
* #param {number} x
* #return {number}
*/
var reverse = function(x) {
var stop = false;
var res = 0;
while(!stop){
res = res *10 + (x % 10);
x = parseInt(x/10);
if(x==0){
stop = true;
}
}
return (res <= 0x7fffffff && res >= -0x80000000) ? res : 0
};
Taking care if the input is negative
public int reverse(int x)
{
long result = 0;
int res;
int num = Math.abs(x);
while(num!=0)
{
int rem = num%10;
result = result *10 + rem;
num = num / 10;
}
if(result > Integer.MAX_VALUE || result < Integer.MIN_VALUE)
{
return 0;
}
else
{
res = (int)result;
return x < 0 ? -res : res;
}
}
This solution in Java will work:
class Solution {
public int reverse(int x) {
long rev = 0, remainder = 0;
long number = x;
while (number != 0) {
remainder = number % 10;
rev = rev * 10 + remainder;
number = number / 10;
}
if (rev >= Integer.MAX_VALUE || rev <= Integer.MIN_VALUE || x >= Integer.MAX_VALUE || x <= Integer.MIN_VALUE)
return 0;
else
return (int) rev;
}
}
Much simpler solution. Ensure that intermittent result does not exceed INT_MAX or get below INT_MIN
int reverse(int x) {
int y = 0;
while(x != 0) {
if ( (long)y*10 + x%10 > INT_MAX || (long)y*10 + x%10 < INT_MIN) {
std::cout << "overflow occurred" << '\n'
return 0;
}
y = y*10 + x%10;
x = x/10;
}
return y;
}
Here is the solution coded in JS(Javascript, it has passed all the 1032 test cases successfully in Leetcode for the problem (https://leetcode.com/problems/reverse-integer), also as asked in the question about the same.
/**
* #param {number} x
* #return {number}
*/
var reverse = function(x) {
let oldNum = x, newNum = 0, digits = 0, negativeNum = false;
if(oldNum < 0){
negativeNum = true;
}
let absVal = Math.abs(x);
while(absVal != 0){
let r = Math.trunc(absVal % 10);
newNum = (newNum*10) + r; digits++;
absVal = Math.floor(absVal/10);
}
if( !(newNum < Number.MAX_VALUE && newNum >= -2147483648 && newNum <= 2147483647)){
return 0;
}
return negativeNum ? -newNum :newNum;
};
Here is the solution coded in JS(Javascript, it has passed all the 1032 test cases successfully in Leetcode for the problem (https://leetcode.com/problems/reverse-integer), also as asked in the question about the same.
/**
* #param {number} x
* #return {number}
*/
var reverse = function(x) {
let oldNum = x, newNum = 0, digits = 0, negativeNum = false;
if(oldNum < 0){
negativeNum = true;
}
let absVal = Math.abs(x);
while(absVal != 0){
let r = Math.trunc(absVal % 10);
newNum = (newNum*10) + r; digits++;
absVal = Math.floor(absVal/10);
}
if( !(newNum < Number.MAX_VALUE && newNum >= -2147483648 && newNum <= 2147483647)){
return 0;
}
return negativeNum ? -newNum :newNum;
};
The earlier answer was posted by the same user (unregistered). Consider this one.
There are several good solutions posted. Here is my JS solution:
const reverse = function (x) {
const strReversed = x.toString().split("").reverse().join("");
rv =
parseInt(strReversed) > Math.pow(2, 31)
? 0
: Math.sign(x) * parseInt(strReversed);
return rv;
};
I got all 1032 cases to work in python, I don't know how to remove multiple 0's such as 100, 1000, 10000 etc thus I used my if statement multiple times lol.
class Solution:
def reverse(self, x: int) -> int:
string = ""
y = str(x)
ab = list(reversed(y))
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if len(ab) > 1 and ab[0] == "0":
ab.remove("0")
if ab[-1] == "-":
ab.remove("-")
ab.insert(0, "-")
for i in ab:
string += i
if int(string) > 2**31 - 1 or int(string) < -2**31:
return 0
return string
public static int reverse(int x) {
if (x == 0) return 0;
int sum = 0;
int y = 0;
while (x != 0) {
int value = (x % 10);
x = x - value;
y = sum;
sum = (sum * 10) + value;
if(sum / 10 != y) return 0;
x = x / 10;
}
return sum;
}
Extracting the first digit and dividing x to ten until x will be equal to 0. Therefore integer will be tokenized its digits.
Every extracted value will be adding the sum value after multiplying the sum by 10. Because adding a new digit means that adding a new 10th to the sum value. Also added if block to check any corruption of data because after 9th digit data will be corrupted.
1032 / 1032 test cases passed.
Status: Accepted
Runtime: 3 ms
Memory Usage: 38 MB
Public int reverse(int A) {
int N, sum = 0;
int rem = 0;
boolean flag = false;
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
if (A < 0) {
flag = true;
A = A * -1;} // 123 // 10 1
while (A > 0) {
rem = A % 10;
if (flag == true) {
if ((min + rem) / 10 > -sum) {
return 0;}}else{
if ((max - rem) / 10 < sum) {
return 0;}}
sum = (sum * 10) + rem;
A = A / 10;}
return (flag == true) ? —sum : sum;}}
#java #Algo
def reverse(self, x: int) -> int:
if x<=-2**31 or x>=2**31-1:
return 0
else:
result = 0
number = x
number = abs(number)
while (number) > 0:
newNumber = number % 10
result = result * 10 + newNumber
number = (number // 10)
if x<0:
result = "-"+str(result)
if int(result)<=-2**31:
return 0
return result
else:
if result>=2**31-1:
return 0
return result
if __name__ == '__main__':
obj = Solution()
print(obj.reverse(1534236469))
Note that there are previous solutions that do not work for input: 1000000045
try this:
public int reverse(int A) {
int reverse=0;
int num=A;
boolean flag=false;
if(A<0)
{
num=(-1)*A;
flag=true;
}
int prevnum=0;
while(num>0)
{
int currDigit=num%10;
reverse=reverse*10+currDigit;
if((reverse-currDigit)/10!=prevnum)
return 0;
num=num/10;
prevnum=reverse;
}
if(flag==true)
reverse= reverse*-1;
return reverse;
}

Categories

Resources