Get the maximum possible value after doing an addition - java

My program takes a number and checks each digit, adds a 5 to it and generates a modified number. Now find the maximum modified value as result.
Example:
Input:
555
Output:
5510
Explanation:
All possible combinations are :
1055
5105
5510
Maximum in these is 5510.
Example:
Input : 444, output : 944.
Constraints: input number can range from 0 to 100000.
This is my code which is working for this example.
public static int process(int number) {
int n = number;
List<Integer> list = new ArrayList<>();
if (n == 0)
return 5;
while (n > 0) {
list.add(n % 10);
n /= 10;
}
int out = -1;
for (int i = list.size() - 1; i >= 0; i--) {
StringBuilder sb = new StringBuilder();
for (int j = list.size() - 1; j >= 0; j--) {
int e = list.get(j);
if (i == j) {
e += 5;
}
sb.append(e);
}
out = Math.max(out, Integer.parseInt(sb.toString()));
}
return out;
}
How to improve this code by reducing time complexity.

If the number has any digits >= 5, choose the right-most such digit. Otherwise choose the left-most digit.
We must choose a digit >= 5 if such exists because that buys us an extra digit and grows the number by more vs any digit < 5 which doesn't get us an extra digit. We choose the right-most because our new number will be 1x and we want that 1 as far to the right as possible.
If all digits are < 5 then +5 will just increase whichever digit it's applied do, which we want done to our left-most digit.
So linear time in the number of digits: scan the digits for ones >= 5, and either modify the last such you find, or the first digit if you find none.

A solution without char/String/StringBuilder may look like this:
use a flag found5 to detect the first occurrence of a digit >= 5
when a first digit >= 5 is detected, add 5, reset the flag, and use additional shift of a power
in the main loop body, calculate the result by adding power * digit, divide n by 10, multiply power by 10 * shift
when the loop is done, check for the flag and add 5 to the leftmost digit
private static int numAnd5(int n) {
boolean found5 = false;
int result = 0;
int power = 1;
while (n > 0) {
int shift = 1;
int digit = n % 10;
if (!found5 && digit >= 5) {
found5 = true;
digit += 5;
shift = 10;
}
result += power * digit;
power *= 10 * shift;
n /= 10;
}
if (!found5) {
result += 5 * Math.max(1, power / 10);
}
return result;
}
Tests:
for (int x : new int[]{0, 1, 2, 7, 10, 14, 16, 61, 125, 153, 111, 145071, 4321023 }) {
System.out.println(x + " -> " + numAnd5(x));
}
Output:
0 -> 5
1 -> 6
2 -> 7
7 -> 12
10 -> 60
14 -> 64
16 -> 111
61 -> 111
125 -> 1210
153 -> 1103
111 -> 611
145071 -> 1450121
4321023 -> 9321023

The following should reduce it from O(n^2) to O(n) where n is the number of characters in the input.
Note that I do not know Java and do not have access to an IDE at the moment, so the following is untested C#/Java-like pseudocode:
public static int process(int number) {
int n = number;
List<Integer> list = new ArrayList<>();
if (n == 0)
return 5;
while (n > 0) {
list.add(n % 10);
n /= 10;
}
// convenient list of powers of 10
List<Integer> powers = new ArrayList<>(list.size);
n = 1;
for (int i = powers.size() - 1; i >= 0; i--) {
powers[i] = n;
n *= 10;
}
int out = -1;
int top = 0;
int bottom = number;
for (int i = list.size() - 1; i >= 0; i--) {
//StringBuilder sb = new StringBuilder();
int curr = list[i] * power[i];
bottom -= curr;
int newTop = top;
int newCurr = (list[i]+5) * power[i];
if (list[i]+5 > 9) {
newTop *= 10;
}
out = Math.max(out, newTop + newCurr + bottom);
top += curr;
}
return out;
}

Related

Count maximum consecutives 1's in binary number

How can I count in Java the maximum consecutive 1's from a binary number?
For instance, the user enters an integer like 13 this would be in binary 1101.
The binary number 1101 has 2 consecutive one's, so the output should be 2.
Another example the number 5 would be in binary 0101, so the output should be 1. My program doesn't work correctly if I type the number 439.
Scanner scanner = new Scanner(System.in);
int numb = scanner.nextInt();
int tempCount = 0;
int count = 0;
// numb = 439 -> output 3
// numb = 13 -> output 2
// numb = 1 -> output 1
while (numb >= 1) {
if (numb % 2 != 0) {
tempCount++;
numb /= 2;
count = tempCount;
if (numb % 2 != 0) {
tempCount++;
count = tempCount;
numb /= 2;
}
}
else {
numb /= 2;
tempCount = 0;
}
}
System.out.println(count);
I figured it out, here is the solution.
I have forgotten an nested if statement.
Scanner scanner = new Scanner(System.in);
int numb = scanner.nextInt();
int tempCount = 0; //save temporarily the longest sequence of one's in this variable
int count = 0; // before the sequence of one's gets interrupted, I save the value from tempCount in count
// numb = 439 -> output 3
// numb = 13 -> output 2
// numb = 1 -> output 1
while (numb >= 1) {
if (numb % 2 != 0) {
tempCount++;
numb /= 2;
if(count < tempCount){
count = tempCount;
}
}
else {
numb /= 2;
tempCount = 0;
}
}
System.out.println(count);
I believe you intended count to be the length of the longest sequence of 1s, while tempCount is the number of 1s in the sequence your currently counting. So you should only assign tempCount to count if it is greater than count. For 439, I believe you are correctly counting three 1s. Then comes a 0, and you correctly reset tempCount to zero. Next time you count a 1, you correctly increment tempCount to one, then assign this one to count too, and your count of three gets lost.
We can identify two consecutive binary ones in the least significant positions like this:
(value & 0b11) == 0b11
We can move the bits in value to the right like so:
value >>>= 1;
It's important to use tripple >>> over double >> because we don't care about the sign bit.
Then all we have to do is keep track of the maximum number of consecutive 1s:
int countMax1Streak(int value) { // value could also be a long if required
int max = 0;
int count = 1;
while (value != 0) {
if ((value & 0b11) == 0b11) {
count++;
} else {
count = 1;
}
value >>>= 1;
if (count > max) {
max = count;
}
}
return max;
}
Test cases:
assertEquals(0, countMax1Streak(0b0));
assertEquals(1, countMax1Streak(0b1));
assertEquals(1, countMax1Streak(0b10));
assertEquals(2, countMax1Streak(0b11));
assertEquals(3, countMax1Streak(0b1110011));
assertEquals(3, countMax1Streak(0b1100111));
assertEquals(3, countMax1Streak(0b1110111));
assertEquals(7, countMax1Streak(0b1111111));
assertEquals(32, countMax1Streak(-1));
You can also use to count the maximum 0 streak like so:
public int countMax0Streak(int value) {
return countMax1Streak(~value);
}
This is an interesting problem. Here is a solution that is generic and also considers all the long values possible (your solution may not work for negative number if you check for the value of n) in Java:
public class LongestBitStreak {
/**
* Returns the longest <i>streak</i> of the given bit b in
given number n.
* A bit streak is defined as a consecutive sequence of the given bit.
* #param n the number to find streak in
* #param b the bit whose streak is to be found
* #return the <i>longest</i> bit streak
*/
static int get(long n, int b) {
if (b != 0 && b != 1)
throw new IllegalArgumentException("second arg: (" + b + ") must be 0 or 1");
int streak = 0, maxStreak = 0;
for (int i = 0; i < 64; i++) {
if ((n & 1) == b) {
streak += 1;
maxStreak = Math.max(streak, maxStreak);
} else {
streak = 0;
}
n >>= 1;
}
return maxStreak;
}
}
Here's an interesting unit test:
#Test
public void foolProof() {
long n = 0b11111000001111100110101010;
long nc = ~n; // One's complement of n
System.out.println(get(n, 1));
System.out.println(get(nc, 0));
assertEquals(get(n, 1), get(nc, 0));
assertEquals(get(n, 0), get(nc, 1));
}
Note that some optimizations are possible based on the values of number and bit, but this should be a decent solution for starters.

java - Instead sum of the number then connect the number [duplicate]

Can anyone explain to me how to reverse an integer without using array or String. I got this code from online, but not really understand why + input % 10 and divide again.
while (input != 0) {
reversedNum = reversedNum * 10 + input % 10;
input = input / 10;
}
And how to do use this sample code to reverse only odd number. Example I got this input 12345, then it will reverse the odd number to output 531.
Java reverse an int value - Principles
Modding (%) the input int by 10 will extract off the rightmost digit. example: (1234 % 10) = 4
Multiplying an integer by 10 will "push it left" exposing a zero to the right of that number, example: (5 * 10) = 50
Dividing an integer by 10 will remove the rightmost digit. (75 / 10) = 7
Java reverse an int value - Pseudocode:
a. Extract off the rightmost digit of your input number. (1234 % 10) = 4
b. Take that digit (4) and add it into a new reversedNum.
c. Multiply reversedNum by 10 (4 * 10) = 40, this exposes a zero to the right of your (4).
d. Divide the input by 10, (removing the rightmost digit). (1234 / 10) = 123
e. Repeat at step a with 123
Java reverse an int value - Working code
public int reverseInt(int input) {
long reversedNum = 0;
long input_long = input;
while (input_long != 0) {
reversedNum = reversedNum * 10 + input_long % 10;
input_long = input_long / 10;
}
if (reversedNum > Integer.MAX_VALUE || reversedNum < Integer.MIN_VALUE) {
throw new IllegalArgumentException();
}
return (int) reversedNum;
}
You will never do anything like this in the real work-world. However, the process by which you use to solve it without help is what separates people who can solve problems from the ones who want to, but can't unless they are spoon fed by nice people on the blogoblags.
I am not clear about your Odd number.
The way this code works is (it is not a Java specific algorithm)
Eg.
input =2345
first time in the while loop
rev=5 input=234
second time
rev=5*10+4=54 input=23
third time
rev=54*10+3 input=2
fourth time
rev=543*10+2 input=0
So the reversed number is 5432.
If you just want only the odd numbers in the reversed number then.
The code is:
while (input != 0) {
last_digit = input % 10;
if (last_digit % 2 != 0) {
reversedNum = reversedNum * 10 + last_digit;
}
input = input / 10;
}
Simply you can use this
public int getReverseInt(int value) {
int resultNumber = 0;
for (int i = value; i !=0; i /= 10) {
resultNumber = resultNumber * 10 + i % 10;
}
return resultNumber;
}
You can use this method with the given value which you want revers.
while (num != 0) {
rev = rev * 10 + num % 10;
num /= 10;
}
That is the solution I used for this problem, and it works fine.
More details:
num % 10
This statement will get you the last digit from the original number.
num /= 10
This statement will eliminate the last digit from the original number, and hence we are sure that while loop will terminate.
rev = rev * 10 + num % 10
Here rev*10 will shift the value by left and then add the last digit from the original.
If the original number was 1258, and in the middle of the run time we have rev = 85, num = 12 so:
num%10 = 2
rev*10 = 850
rev*10 + num%10 = 852
int aa=456;
int rev=Integer.parseInt(new StringBuilder(aa+"").reverse());
import java.util.Scanner;
public class Reverse_order_integer {
private static Scanner scan;
public static void main(String[] args) {
System.out.println("\t\t\tEnter Number which you want to reverse.\n");
scan = new Scanner(System.in);
int number = scan.nextInt();
int rev_number = reverse(number);
System.out.println("\t\t\tYour reverse Number is = \"" + rev_number
+ "\".\n");
}
private static int reverse(int number) {
int backup = number;
int count = 0;
while (number != 0) {
number = number / 10;
count++;
}
number = backup;
int sum = 0;
for (int i = count; i > 0; i--) {
int sum10 = 1;
int last = number % 10;
for (int j = 1; j < i; j++) {
sum10 = sum10 * 10;
}
sum = sum + (last * sum10);
number = number / 10;
}
return sum;
}
}
See to get the last digit of any number we divide it by 10 so we either achieve zero or a digit which is placed on last and when we do this continuously we get the whole number as an integer reversed.
int number=8989,last_num,sum=0;
while(number>0){
last_num=number%10; // this will give 8989%10=9
number/=10; // now we have 9 in last and now num/ by 10= 898
sum=sum*10+last_number; // sum=0*10+9=9;
}
// last_num=9. number= 898. sum=9
// last_num=8. number =89. sum=9*10+8= 98
// last_num=9. number=8. sum=98*10+9=989
// last_num=8. number=0. sum=989*10+8=9898
// hence completed
System.out.println("Reverse is"+sum);
public static void main(String args[]) {
int n = 0, res = 0, n1 = 0, rev = 0;
int sum = 0;
Scanner scan = new Scanner(System.in);
System.out.println("Please Enter No.: ");
n1 = scan.nextInt(); // String s1=String.valueOf(n1);
int len = (n1 == 0) ? 1 : (int) Math.log10(n1) + 1;
while (n1 > 0) {
rev = res * ((int) Math.pow(10, len));
res = n1 % 10;
n1 = n1 / 10;
// sum+=res; //sum=sum+res;
sum += rev;
len--;
}
// System.out.println("sum No: " + sum);
System.out.println("sum No: " + (sum + res));
}
This will return reverse of integer
Just to add on, in the hope to make the solution more complete.
The logic by #sheki already gave the correct way of reversing an integer in Java. If you assume the input you use and the result you get always fall within the range [-2147483648, 2147483647], you should be safe to use the codes by #sheki. Otherwise, it'll be a good practice to catch the exception.
Java 8 introduced the methods addExact, subtractExact, multiplyExact and toIntExact. These methods will throw ArithmeticException upon overflow. Therefore, you can use the below implementation to implement a clean and a bit safer method to reverse an integer. Generally we can use the mentioned methods to do mathematical calculation and explicitly handle overflow issue, which is always recommended if there's a possibility of overflow in the actual usage.
public int reverse(int x) {
int result = 0;
while (x != 0){
try {
result = Math.multiplyExact(result, 10);
result = Math.addExact(result, x % 10);
x /= 10;
} catch (ArithmeticException e) {
result = 0; // Exception handling
break;
}
}
return result;
}
Java solution without the loop. Faster response.
int numberToReverse;//your number
StringBuilder sb=new StringBuilder();
sb.append(numberToReverse);
sb=sb.reverse();
String intermediateString=sb.toString();
int reversedNumber=Integer.parseInt(intermediateString);
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class intreverse
{
public static void main(String...a)throws Exception
{
int no;
int rev = 0;
System.out.println("Enter The no to be reversed");
InputStreamReader str=new InputStreamReader(System.in);
BufferedReader br =new BufferedReader(str);
no=Integer.parseInt(br.readLine().toString());
while(no!=0)
{
rev=rev*10+no%10;
no=no/10;
}
System.out.println(rev);
}
}
public static int reverse(int x) {
boolean negetive = false;
if (x < 0) {
x = Math.abs(x);
negative = true;
}
int y = 0, i = 0;
while (x > 0) {
if (i > 0) {
y *= 10;
}
y += x % 10;
x = x / 10;
i++;
}
return negative ? -y : y;
}
Here is a complete solution(returns 0 if number is overflown):
public int reverse(int x) {
boolean flag = false;
// Helpful to check if int is within range of "int"
long num = x;
// if the number is negative then turn the flag on.
if(x < 0) {
flag = true;
num = 0 - num;
}
// used for the result.
long result = 0;
// continue dividing till number is greater than 0
while(num > 0) {
result = result*10 + num%10;
num= num/10;
}
if(flag) {
result = 0 - result;
}
if(result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
return 0;
}
return (int) result;
}
Scanner input = new Scanner(System.in);
System.out.print("Enter number :");
int num = input.nextInt();
System.out.print("Reverse number :");
int value;
while( num > 0){
value = num % 10;
num /= 10;
System.out.print(value); //value = Reverse
}
int convert (int n)
{
long val = 0;
if(n==0)
return 0;
for(int i = 1; n > exponent(10, (i-1)); i++)
{
int mod = n%( (exponent(10, i))) ;
int index = mod / (exponent(10, i-1));
val *= 10;
val += index;
}
if (val < Integer.MIN_VALUE || val > Integer.MAX_VALUE)
{
throw new IllegalArgumentException
(val + " cannot be cast to int without changing its value.");
}
return (int) val;
}
static int exponent(int m, int n)
{
if(n < 0)
return 0;
if(0 == n)
return 1;
return (m * exponent(m, n-1));
}
It's good that you wrote out your original code. I have another way to code this concept of reversing an integer. I'm only going to allow up to 10 digits. However, I am going to make the assumption that the user will not enter a zero.
if((inputNum <= 999999999)&&(inputNum > 0 ))
{
System.out.print("Your number reversed is: ");
do
{
endInt = inputNum % 10; //to get the last digit of the number
inputNum /= 10;
system.out.print(endInt);
}
While(inputNum != 0);
System.out.println("");
}
else
System.out.println("You used an incorrect number of integers.\n");
System.out.println("Program end");
Even if negative integer is passed then it will give the negative integer
Try This...
public int reverse(int result) {
long newNum=0,old=result;
result=(result>0) ? result:(0-result);
while(result!=0){
newNum*=10;
newNum+=result%10;
result/=10;
if(newNum>Integer.MAX_VALUE||newNum<Integer.MIN_VALUE)
return 0;
}
if(old > 0)
return (int)newNum;
else if(old < 0)
return (int)(newNum*-1);
else
return 0;
}
This is the shortest code to reverse an integer
int i=5263;
System.out.println(Integer.parseInt(new StringBuffer(String.valueOf(i) ).reverse().toString()));
123 maps to 321, which can be calculated as 3*(10^2)+2*(10^1)+1
Two functions are used to calculate (10^N). The first function calculates the value of N. The second function calculates the value for ten to power N.
Function<Integer, Integer> powerN = x -> Double.valueOf(Math.log10(x)).intValue();
Function<Integer, Integer> ten2powerN = y -> Double.valueOf(Math.pow(10, y)).intValue();
// 123 => 321= 3*10^2 + 2*10 + 1
public int reverse(int number) {
if (number < 10) {
return number;
} else {
return (number % 10) * powerN.andThen(ten2powerN).apply(number) + reverse(number / 10);
}
}
If the idea is not to use arrays or string, reversing an integer has to be done by reading the digits of a number from the end one at a time. Below explanation is provided in detail to help the novice.
pseudocode :
lets start with reversed_number = 0 and some value for original_number which needs to be reversed.
the_last_digit = original_number % 10 (i.e, the reminder after dividing by 10)
original_number = original_number/10 (since we already have the last digit, remove the last digit from the original_number)
reversed_number = reversed_number * 10 + last_digit (multiply the reversed_number with 10, so as to add the last_digit to it)
repeat steps 2 to 4, till the original_number becomes 0. When original_number = 0, reversed_number would have the reverse of the original_number.
More info on step 4: If you are provided with a digit at a time, and asked to append it at the end of a number, how would you do it - by moving the original number one place to the left so as to accommodate the new digit. If number 23 has to become 234, you multiply 23 with 10 and then add 4.
234 = 23x10 + 4;
Code:
public static int reverseInt(int original_number) {
int reversed_number = 0;
while (original_number > 0) {
int last_digit = original_number % 10;
original_number = original_number / 10;
reversed_number = reversed_number * 10 + last_digit;
}
return reversed_number;
}
It is an outdated question, but as a reference for others
First of all reversedNum must be initialized to 0;
input%10 is used to get the last digit from input
input/10 is used to get rid of the last digit from input, which you have added to the reversedNum
Let's say input was 135
135 % 10 is 5
Since reversed number was initialized to 0
now reversedNum will be 5
Then we get rid of 5 by dividing 135 by 10
Now input will be just 13
Your code loops through these steps until all digits are added to the reversed number or in other words untill input becomes 0.
while (input != 0) {
reversedNum = reversedNum * 10 + input % 10;
input = input / 10;
}
let a number be 168,
+ input % 10 returns last digit as reminder i.e. 8 but next time it should return 6,hence number must be reduced to 16 from 168, as divide 168 by 10 that results to 16 instead of 16.8 as variable input is supposed to be integer type in the above program.
If you wanna reverse any number like 1234 and you want to revers this number to let it looks like 4321. First of all, initialize 3 variables int org ; int reverse = 0; and int reminder ;
then put your logic like
Scanner input = new Scanner (System.in);
System.out.println("Enter number to reverse ");
int org = input.nextInt();
int getReminder;
int r = 0;
int count = 0;
while (org !=0){
getReminder = org%10;
r = 10 * r + getReminder;
org = org/10;
}
System.out.println(r);
}
A method to get the greatest power of ten smaller or equal to an integer: (in recursion)
public static int powerOfTen(int n) {
if ( n < 10)
return 1;
else
return 10 * powerOfTen(n/10);
}
The method to reverse the actual integer:(in recursion)
public static int reverseInteger(int i) {
if (i / 10 < 1)
return i ;
else
return i%10*powerOfTen(i) + reverseInteger(i/10);
}
You can use recursion to solve this.
first get the length of an integer number by using following recursive function.
int Length(int num,int count){
if(num==0){
return count;
}
else{
count++;
return Lenght(num/10,count);
}
}
and then you can simply multiply remainder of a number by 10^(Length of integer - 1).
int ReturnReverse(int num,int Length,int reverse){
if(Length!=0){
reverse = reverse + ((num%10) * (int)(Math.pow(10,Length-1)));
return ReturnReverse(num/10,Length-1,reverse);
}
return reverse;
}
The whole Source Code :
import java.util.Scanner;
public class ReverseNumbers {
int Length(int num, int count) {
if (num == 0) {
return count;
} else {
return Length(num / 10, count + 1);
}
}
int ReturnReverse(int num, int Length, int reverse) {
if (Length != 0) {
reverse = reverse + ((num % 10) * (int) (Math.pow(10, Length - 1)));
return ReturnReverse(num / 10, Length - 1, reverse);
}
return reverse;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
ReverseNumbers reverseNumbers = new ReverseNumbers();
reverseNumbers.ReturnReverse(N, reverseNumbers.Length(N, 0), reverseNumbers.ReturnReverse(N, reverseNumbers.Length(N, 0), 0));
scanner.close();
}
}
public int getReverseNumber(int number)
{
int reminder = 0, result = 0;
while (number !=0)
{
if (number >= 10 || number <= -10)
{
reminder = number % 10;
result = result + reminder;
result = result * 10;
number = number / 10;
}
else
{
result = result + number;
number /= 10;
}
}
return result;
}
// The above code will work for negative numbers also
Reversing integer
int n, reverse = 0;
Scanner in = new Scanner(System.in);
n = in.nextInt();
while(n != 0)
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
System.out.println("Reverse of the number is " + reverse);
public static int reverseInt(int i) {
int reservedInt = 0;
try{
String s = String.valueOf(i);
String reversed = reverseWithStringBuilder(s);
reservedInt = Integer.parseInt(reversed);
}catch (NumberFormatException e){
System.out.println("exception caught was " + e.getMessage());
}
return reservedInt;
}
public static String reverseWithStringBuilder(String str) {
System.out.println(str);
StringBuilder sb = new StringBuilder(str);
StringBuilder reversed = sb.reverse();
return reversed.toString();
}
public static int reverse(int x) {
int tmp = x;
int oct = 0;
int res = 0;
while (true) {
oct = tmp % 10;
tmp = tmp / 10;
res = (res+oct)*10;
if ((tmp/10) == 0) {
res = res+tmp;
return res;
}
}
}
public static double reverse(int num)
{
double num1 = num;
double ret = 0;
double counter = 0;
while (num1 > 1)
{
counter++;
num1 = num1/10;
}
while(counter >= 0)
{
int lastdigit = num%10;
ret += Math.pow(10, counter-1) * lastdigit;
num = num/10;
counter--;
}
return ret;
}

How do I generate Primes Using 6*k +- 1 rule

We know that all primes above 3 can be generated using:
6 * k + 1
6 * k - 1
However we all numbers generated from the above formulas are not prime.
For Example:
6 * 6 - 1 = 35 which is clearly divisible by 5.
To Eliminate such conditions, I used a Sieve Method and removing the numbers which are factors of the numbers generated from the above formula.
Using the facts:
A number is said to be prime if it has no prime factors.
As we can generate all the prime numbers using the above formulas.
If we can remove all the multiples of the above numbers we are left with only prime numbers.
To generate primes below 1000.
ArrayList<Integer> primes = new ArrayList<>();
primes.add(2);//explicitly add
primes.add(3);//2 and 3
int n = 1000;
for (int i = 1; i <= (n / 6) ; i++) {
//get all the numbers which can be generated by the formula
int prod6k = 6 * i;
primes.add(prod6k - 1);
primes.add(prod6k + 1);
}
for (int i = 0; i < primes.size(); i++) {
int k = primes.get(i);
//remove all the factors of the numbers generated by the formula
for(int j = k * k; j <= n; j += k)//changed to k * k from 2 * k, Thanks to DTing
{
int index = primes.indexOf(j);
if(index != -1)
primes.remove(index);
}
}
System.out.println(primes);
However, this method does generate the prime numbers correctly. This runs in a much faster way as we need not check for all the numbers which we do check in a Sieve.
My question is that am I missing any edge case? This would be a lot better but I never saw someone using this. Am I doing something wrong?
Can this approach be much more optimized?
Taking a boolean[] instead of an ArrayList is much faster.
int n = 100000000;
boolean[] primes = new boolean[n + 1];
for (int i = 0; i <= n; i++)
primes[i] = false;
primes[2] = primes[3] = true;
for (int i = 1; i <= n / 6; i++) {
int prod6k = 6 * i;
primes[prod6k + 1] = true;
primes[prod6k - 1] = true;
}
for (int i = 0; i <= n; i++) {
if (primes[i]) {
int k = i;
for (int j = k * k; j <= n && j > 0; j += k) {
primes[j] = false;
}
}
}
for (int i = 0; i <= n; i++)
if (primes[i])
System.out.print(i + " ");
5 is the first number generated by your criteria. Let's take a look at the numbers generated up to 25:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
Now, let's look at these same numbers, when we use the Sieve of Eratosthenes algorithm:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
After removing 2:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
After removing 3:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
This is the same as the first set! Notice they both include 25, which is not prime. If we think about it, this is an obvious result. Consider any group of 6 consecutive numbers:
6k - 3, 6k - 2, 6k - 1, 6k, 6k + 1, 6k + 2
If we factor a little, we get:
3*(2k - 1), 2*(3k - 1), 6k - 1, 6*(k), 6k + 1, 2*(3k + 1)
In any group of 6 consecutive numbers, three of them will be divisible by two, and two of them will be divisible by three. These are exactly the numbers we have removed so far! Therefore:
Your algorithm to only use 6k - 1 and 6k + 1 is exactly the same as the first two rounds of the Sieve of Erathosthenes.
It's a pretty nice speed improvement over the Sieve, too, because we don't have to add all those extra elements just to remove them. This explains why your algorithm works and why it doesn't miss any cases; because it's exactly the same as the Sieve.
Anyway, I agree that once you've generated primes, your boolean way is by far the fastest. I have set up a benchmark using your ArrayList way, your boolean[] way, and my own way using LinkedList and iterator.remove() (because removals are fast in a LinkedList. Here's the code for my test harness. Note that I run the test 12 times to ensure that the JVM is warmed up, and I print the size of the list and change the size of n to attempt to prevent too much branch prediction optimization. You can also get faster in all three methods by using += 6 in the initial seed, instead of prod6k:
import java.util.*;
public class PrimeGenerator {
public static List<Integer> generatePrimesArrayList(int n) {
List<Integer> primes = new ArrayList<>(getApproximateSize(n));
primes.add(2);// explicitly add
primes.add(3);// 2 and 3
for (int i = 6; i <= n; i+=6) {
// get all the numbers which can be generated by the formula
primes.add(i - 1);
primes.add(i + 1);
}
for (int i = 0; i < primes.size(); i++) {
int k = primes.get(i);
// remove all the factors of the numbers generated by the formula
for (int j = k * k; j <= n; j += k)// changed to k * k from 2 * k, Thanks
// to DTing
{
int index = primes.indexOf(j);
if (index != -1)
primes.remove(index);
}
}
return primes;
}
public static List<Integer> generatePrimesBoolean(int n) {
boolean[] primes = new boolean[n + 5];
for (int i = 0; i <= n; i++)
primes[i] = false;
primes[2] = primes[3] = true;
for (int i = 6; i <= n; i+=6) {
primes[i + 1] = true;
primes[i - 1] = true;
}
for (int i = 0; i <= n; i++) {
if (primes[i]) {
int k = i;
for (int j = k * k; j <= n && j > 0; j += k) {
primes[j] = false;
}
}
}
int approximateSize = getApproximateSize(n);
List<Integer> primesList = new ArrayList<>(approximateSize);
for (int i = 0; i <= n; i++)
if (primes[i])
primesList.add(i);
return primesList;
}
private static int getApproximateSize(int n) {
// Prime Number Theorem. Round up
int approximateSize = (int) Math.ceil(((double) n) / (Math.log(n)));
return approximateSize;
}
public static List<Integer> generatePrimesLinkedList(int n) {
List<Integer> primes = new LinkedList<>();
primes.add(2);// explicitly add
primes.add(3);// 2 and 3
for (int i = 6; i <= n; i+=6) {
// get all the numbers which can be generated by the formula
primes.add(i - 1);
primes.add(i + 1);
}
for (int i = 0; i < primes.size(); i++) {
int k = primes.get(i);
for (Iterator<Integer> iterator = primes.iterator(); iterator.hasNext();) {
int primeCandidate = iterator.next();
if (primeCandidate == k)
continue; // Always skip yourself
if (primeCandidate == (primeCandidate / k) * k)
iterator.remove();
}
}
return primes;
}
public static void main(String... args) {
int initial = 4000;
for (int i = 0; i < 12; i++) {
int n = initial * i;
long start = System.currentTimeMillis();
List<Integer> result = generatePrimesArrayList(n);
long seconds = System.currentTimeMillis() - start;
System.out.println(result.size() + "\tArrayList Seconds: " + seconds);
start = System.currentTimeMillis();
result = generatePrimesBoolean(n);
seconds = System.currentTimeMillis() - start;
System.out.println(result.size() + "\tBoolean Seconds: " + seconds);
start = System.currentTimeMillis();
result = generatePrimesLinkedList(n);
seconds = System.currentTimeMillis() - start;
System.out.println(result.size() + "\tLinkedList Seconds: " + seconds);
}
}
}
And the results of the last few trials:
3432 ArrayList Seconds: 430
3432 Boolean Seconds: 0
3432 LinkedList Seconds: 90
3825 ArrayList Seconds: 538
3824 Boolean Seconds: 0
3824 LinkedList Seconds: 81
4203 ArrayList Seconds: 681
4203 Boolean Seconds: 0
4203 LinkedList Seconds: 100
4579 ArrayList Seconds: 840
4579 Boolean Seconds: 0
4579 LinkedList Seconds: 111
You don't need to add all possible candidates to the array. You can create a Set to store all non primes.
Also you can start checking at k * k, rather than 2 * k
public void primesTo1000() {
Set<Integer> notPrimes = new HashSet<>();
ArrayList<Integer> primes = new ArrayList<>();
primes.add(2);//explicitly add
primes.add(3);//2 and 3
for (int i = 1; i < (1000 / 6); i++) {
handlePossiblePrime(6 * i - 1, primes, notPrimes);
handlePossiblePrime(6 * i + 1, primes, notPrimes);
}
System.out.println(primes);
}
public void handlePossiblePrime(
int k, List<Integer> primes, Set<Integer> notPrimes) {
if (!notPrimes.contains(k)) {
primes.add(k);
for (int j = k * k; j <= 1000; j += k) {
notPrimes.add(j);
}
}
}
untested code, check corners
Here is a bit packing version of the sieve as suggested in the answer referenced by #Will Ness. Rather than return the nth prime, this version returns a list of primes to n:
public List<Integer> primesTo(int n) {
List<Integer> primes = new ArrayList<>();
if (n > 1) {
int limit = (n - 3) >> 1;
int[] sieve = new int[(limit >> 5) + 1];
for (int i = 0; i <= (int) (Math.sqrt(n) - 3) >> 1; i++)
if ((sieve[i >> 5] & (1 << (i & 31))) == 0) {
int p = i + i + 3;
for (int j = (p * p - 3) >> 1; j <= limit; j += p)
sieve[j >> 5] |= 1 << (j & 31);
}
primes.add(2);
for (int i = 0; i <= limit; i++)
if ((sieve[i >> 5] & (1 << (i & 31))) == 0)
primes.add(i + i + 3);
}
return primes;
}
There seems to be a bug in your updated code that uses a boolean array (it is not returning all the primes).
public static List<Integer> booleanSieve(int n) {
boolean[] primes = new boolean[n + 5];
for (int i = 0; i <= n; i++)
primes[i] = false;
primes[2] = primes[3] = true;
for (int i = 1; i <= n / 6; i++) {
int prod6k = 6 * i;
primes[prod6k + 1] = true;
primes[prod6k - 1] = true;
}
for (int i = 0; i <= n; i++) {
if (primes[i]) {
int k = i;
for (int j = k * k; j <= n && j > 0; j += k) {
primes[j] = false;
}
}
}
List<Integer> primesList = new ArrayList<>();
for (int i = 0; i <= n; i++)
if (primes[i])
primesList.add(i);
return primesList;
}
public static List<Integer> bitPacking(int n) {
List<Integer> primes = new ArrayList<>();
if (n > 1) {
int limit = (n - 3) >> 1;
int[] sieve = new int[(limit >> 5) + 1];
for (int i = 0; i <= (int) (Math.sqrt(n) - 3) >> 1; i++)
if ((sieve[i >> 5] & (1 << (i & 31))) == 0) {
int p = i + i + 3;
for (int j = (p * p - 3) >> 1; j <= limit; j += p)
sieve[j >> 5] |= 1 << (j & 31);
}
primes.add(2);
for (int i = 0; i <= limit; i++)
if ((sieve[i >> 5] & (1 << (i & 31))) == 0)
primes.add(i + i + 3);
}
return primes;
}
public static void main(String... args) {
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
for (int i = 0; i < 10; i++) {
int n = (int) Math.pow(10, i);
Stopwatch timer = Stopwatch.createUnstarted();
timer.start();
List<Integer> result = booleanSieve(n);
timer.stop();
System.out.println(result.size() + "\tBoolean: " + timer);
}
for (int i = 0; i < 10; i++) {
int n = (int) Math.pow(10, i);
Stopwatch timer = Stopwatch.createUnstarted();
timer.start();
List<Integer> result = bitPacking(n);
timer.stop();
System.out.println(result.size() + "\tBitPacking: " + timer);
}
});
}
0 Boolean: 38.51 μs
4 Boolean: 45.77 μs
25 Boolean: 31.56 μs
168 Boolean: 227.1 μs
1229 Boolean: 1.395 ms
9592 Boolean: 4.289 ms
78491 Boolean: 25.96 ms
664116 Boolean: 133.5 ms
5717622 Boolean: 3.216 s
46707218 Boolean: 32.18 s
0 BitPacking: 117.0 μs
4 BitPacking: 11.25 μs
25 BitPacking: 11.53 μs
168 BitPacking: 70.03 μs
1229 BitPacking: 471.8 μs
9592 BitPacking: 3.701 ms
78498 BitPacking: 9.651 ms
664579 BitPacking: 43.43 ms
5761455 BitPacking: 1.483 s
50847534 BitPacking: 17.71 s
There are several things that could be optimized.
For starters, the "contains" and "removeAll" operations on an ArrayList are rather expensive operations (linear for the former, worst case quadratic for the latter) so you might not want to use the ArrayList for this. A Hash- or TreeSet has better complexities for this, being nearly constant (Hashing complexities are weird) and logarithmic I think
You could look into the sieve of sieve of Eratosthenes if you want a more efficient sieve altogeter, but that would be besides the point of your question about the 6k +-1 trick. It is slightly but not noticably more memory expensive than your solution, but way faster.
Can this approach be much more optimized?
The answer is yes.
I'll start by saying that it is a good idea to use the sieve on a subset of number within a certain range, and your suggesting is doing exactly that.
Reading about generating Primes:
...Furthermore, based on the sieve formalisms, some integer sequences
(sequence A240673 in OEIS) are constructed which they also could be used for generating primes in certain intervals.
The meaning of this paragraph is that your approach of starting with a reduced list of integers was indeed adopted by the academy, but their techniques are more efficient (but also, naturally, more complex).
You can generate your trial numbers with a wheel, adding 2 and 4 alternately, that eliminates the multiplication in 6 * k +/- 1.
public void primesTo1000() {
Set<Integer> notPrimes = new HashSet<>();
ArrayList<Integer> primes = new ArrayList<>();
primes.add(2); //explicitly add
primes.add(3); //2 and 3
int step = 2;
int num = 5 // 2 and 3 already handled.
while (num < 1000) {
handlePossiblePrime(num, primes, notPrimes);
num += step; // Step to next number.
step = 6 - step; // Step by 2, 4 alternately.
}
System.out.println(primes);
}
Probably the most suitable standard datastructure for Sieve of Eratosthenes is the BitSet. Here's my solution:
static BitSet genPrimes(int n) {
BitSet primes = new BitSet(n);
primes.set(2); // add 2 explicitly
primes.set(3); // add 3 explicitly
for (int i = 6; i <= n ; i += 6) { // step by 6 instead of multiplication
primes.set(i - 1);
primes.set(i + 1);
}
int max = (int) Math.sqrt(n); // don't need to filter multiples of primes bigger than max
// this for loop enumerates all set bits starting from 5 till the max
// sieving 2 and 3 is meaningless: n*6+1 and n*6-1 are never divisible by 2 or 3
for (int i = primes.nextSetBit(5); i >= 0 && i <= max; i = primes.nextSetBit(i+1)) {
// The actual sieve algorithm like in your code
for(int j = i * i; j <= n; j += i)
primes.clear(j);
}
return primes;
}
Usage:
BitSet primes = genPrimes(1000); // generate primes up to 1000
System.out.println(primes.cardinality()); // print number of primes
// print all primes like {2, 3, 5, ...}
System.out.println(primes);
// print all primes one per line
for(int prime = primes.nextSetBit(0); prime >= 0; prime = primes.nextSetBit(prime+1))
System.out.println(prime);
// print all primes one per line using java 8:
primes.stream().forEach(System.out::println);
The boolean-based version may work faster for small n values, but if you need, for example, a million of prime numbers, BitSet will outperform it in several times and actually works correctly. Here's lame benchmark:
public static void main(String... args) {
long start = System.nanoTime();
BitSet res = genPrimes(10000000);
long diff = System.nanoTime() - start;
System.out.println(res.cardinality() + "\tBitSet Seconds: " + diff / 1e9);
start = System.nanoTime();
List<Integer> result = generatePrimesBoolean(10000000); // from durron597 answer
diff = System.nanoTime() - start;
System.out.println(result.size() + "\tBoolean Seconds: " + diff / 1e9);
}
Output:
664579 BitSet Seconds: 0.065987717
664116 Boolean Seconds: 0.167620323
664579 is the correct number of primes below 10000000.
This method below shows how to find prime nos using 6k+/-1 logic
this was written in python 3.6
def isPrime(n):
if(n<=1):
return 0
elif(n<4): #2 , 3 are prime
return 1
elif(n%2==0): #already excluded no.2 ,so any no. div. by 2 cant be prime
return 0
elif(n<9): #5, 7 are prime and 6,8 are excl. in the above step
return 1
elif(n%3==0):
return 1
f=5 #Till now we have checked the div. of n with 2,3 which means with 4,6,8 also now that is why f=5
r=int(n**.5) #rounding of root n, i.e: floor(sqrt(n)) r*r<=n
while(f<=r):
if(n%f==0): #checking if n has any primefactor lessthan sqrt(n), refer LINE 1
return 0
if(n%(f+2)==0): #remember her we are not incrementing f, see the 6k+1 rule to understand this while loop steps ,you will see that most values of f are prime
return 0
f=f+6
return 1
def prime_nos():
counter=2 #we know 2,3 are prime
print(2)
print(3) #we know 2,3 are prime
i=1
s=5 #sum 2+3
t=0
n=int(input("Enter the upper limit( should be > 3: "))
n=(n-1)//6 #finding max. limit(n=6*i+1) upto which I(here n on left hand side) should run
while(i<n):#2*(10**6)):
if (isPrime(6*i-1)):
counter=counter+1
print(6*i-1) #prime no
if(isPrime(6*i+1)):
counter=counter+1
print(6*i+1) #prime no
i+=1
prime_nos() #fn. call
Your prime number formula mathematically incorrect ex. take 96 it dividable to 6 96/6=16 so by this logic 97 and 95 must be prime if square root passed but square root of 95 is 9.7467... (passed) so its "prime". But 95 clearly dividable by 5 fast algorithm in c#
int n=100000000;
bool [] falseprimes = new bool[n + 2];
int ed=n/6;
ed = ed * 6;
int md = (int)Math.Sqrt((double)ed);
for (int i = ed; i > md; i-=6)
{
falseprimes[i + 1] = true;
falseprimes[i - 1] = true;
}
md = md / 6;
md = md * 5;
for (int i = md; i > 5; i -= 6)
{
falseprimes[i + 1] = true;
falseprimes[i - 1] = true;
falseprimes[(i + 1)* (i + 1)] = false;
falseprimes[(i-1) * (i-1)] = false;
}
falseprimes[2] = true;
falseprimes[3] = true;
To generate prime numbers using 6 * k + - 1 rule use this algorithm:
int n = 100000000;
int j,jmax=n/6;
boolean[] primes5m6 = new boolean[jmax+1];
boolean[] primes1m6 = new boolean[jmax+1];
for (int i = 0; i <= jmax; i++){
primes5m6[i] = false;
primes1m6[i] = false;
}
for (int i = 1; i <= (int)((Math.sqrt(n)+1)/6)+1; i++){
if (!primes5m6[i]){
for (j = 6*i*i; j <= jmax; j+=6*i-1){
primes5m6[j]=true;
primes1m6[j-2*i]=true;
}
for (; j <= jmax+2*i; j+=6*i-1)
primes1m6[j-2*i]=true;
}
if (!primes1m6[i]){
for (j = 6*i*i; j <= jmax-2*i; j+=6*i+1){
primes5m6[j]=true;
primes1m6[j+2*i]=true;
}
for (; j <= jmax; j+=6*i+1)
primes5m6[j]=true;
}
}
System.out.print(2 + " ");
System.out.print(3 + " ");
for (int i = 1; i <= jmax; i++){
if (!primes5m6[i])
System.out.print((6*i-1) + " ");
if (!primes1m6[i])
System.out.print((6*i+1) + " ");
}

How do I implement the Luhn algorithm?

I am trying to create a program to validate 10 to 12 digit long number sequences based on the luhn algorithm, but my program keeps on telling me that every number is invalid even though they're not.
This number should be valid, but my code doesn't think so: 8112189876
This number should not be valid, which my program agrees with, as it thinks every number is invalid: 8112189875
Here is my code:
static void luhn(){
System.out.print("Enter number to validate:\n");
String pnr = input.nextLine();
int length = pnr.length();
int sum = 0;
for (int i = 1, pos = length - 1; i < 10; i++, pos--){
char tmp = pnr.charAt(pos);
int num = tmp - 0
int product;
if (i % 2 != 0){
product = num * 1;
}
else{
product = num * 2;
}
if (product > 9)
product -= 9;
sum+= product;
boolean valid = (sum % 10 == 0);
if (valid){
System.out.print("Valid!\r");
}
else{
System.out.print("Invalid!");
}
}
}
use org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(number)
Maven Dependency:
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.5.1</version>
</dependency>
The first thing I see is that you have:
int num = tmp - 0
You should instead have:
int num = tmp - '0';
Secondly, you should be validating your sum outside of the for loop, because you only care about the sum after processing all the digits.
Thirdly, you are starting from the end of the number, and you are not including the first number of your string. Why not use i for both tasks?
Resulting (working) method:
static void luhn(){
System.out.print("Enter number to validate:\n");
String pnr = input.nextLine();
// this only works if you are certain all input will be at least 10 characters
int extraChars = pnr.length() - 10;
if (extraChars < 0) {
throw new IllegalArgumentException("Number length must be at least 10 characters!");
}
pnr = pnr.substring(extraChars, 10 + extraChars);
int sum = 0;
// #3: removed pos
for (int i = 0; i < pnr.length(); i++){
char tmp = pnr.charAt(i);
// #1: fixed the '0' problem
int num = tmp - '0';
int product;
if (i % 2 != 0){
product = num * 1;
}
else{
product = num * 2;
}
if (product > 9)
product -= 9;
sum+= product;
}
// #2: moved check outside for loop
boolean valid = (sum % 10 == 0);
if (valid){
System.out.print("Valid!\r");
}
else{
System.out.print("Invalid!");
}
}
Stylistically, this method would be more useful if, instead of method signature
static void luhn() {
it instead had method signature
static boolean luhn(String input) {
This easily allows your code to get the String from ANY source (a file, hardcoded, etc.) and do anything with the result (print a message as yours does, or do something else). Obviously you would move the System.out.print, input.nextLine(), and if(valid) bits of code outside of this method.
Full refactored program:
import java.util.Scanner;
public class Luhn {
private static Scanner input;
public static void main(String... args) {
input = new Scanner(System.in);
System.out.print("Enter number to validate:\n");
String pnr = input.nextLine();
boolean result = luhn(pnr);
printMessage(result);
input.close();
}
static boolean luhn(String pnr){
// this only works if you are certain all input will be at least 10 characters
int extraChars = pnr.length() - 10;
if (extraChars < 0) {
throw new IllegalArgumentException("Number length must be at least 10 characters!");
}
pnr = pnr.substring(extraChars, 10 + extraChars);
int sum = 0;
for (int i = 0; i < pnr.length(); i++){
char tmp = pnr.charAt(i);
int num = tmp - '0';
int product;
if (i % 2 != 0){
product = num * 1;
}
else{
product = num * 2;
}
if (product > 9)
product -= 9;
sum+= product;
}
return (sum % 10 == 0);
}
private static void printMessage(boolean valid) {
if (valid){
System.out.print("Valid!\r");
}
else{
System.out.print("Invalid!");
}
}
}
I use this function in an app for checking card number validity :
public static boolean Check(String ccNumber)
{
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--)
{
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate)
{
n *= 2;
if (n > 9)
{
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
Hope it helps,
If you use Java 10 or higher, you can use the following code:
public static boolean luhn(String s) {
IntUnaryOperator sumDigits = n -> n / 10 + n % 10;
var digits = s.chars()
.map(Character::getNumericValue)
.toArray();
return IntStream.rangeClosed(1, digits.length)
.map(i -> digits.length - i)
.map(i -> i % 2 == 0 ? digits[i] : sumDigits.applyAsInt(digits[i] * 2))
.sum() % 10 == 0;
}
It's the functional approach to this algorithm.
You should be subtracting '0' from tmp, not 0. Subtracting 0 returns the ASCII value, which you don't want.
Here's some functions I wrote to both calculate the check digit for a given number and to verify a given number sequence and extract the number from it.
To calculate the check digit for a given number:
/**
* Generates the check digit for a number using Luhn's algorithm described in detail at the following link:
* https://en.wikipedia.org/wiki/Luhn_algorithm
*
* In short the digit is calculated like so:
* 1. From the rightmost digit moving left, double the value of every second digit. If that value is greater than 9,
* subtract 9 from it.
* 2. Sum all of the digits together
* 3. Multiply the sum by 9 and the check digit will be that value modulo 10.
*
* #param number the number to get the Luhn's check digit for
* #return the check digit for the given number
*/
public static int calculateLuhnsCheckDigit(final long number) {
int sum = 0;
boolean alternate = false;
String digits = Long.toString(number);
for (int i = digits.length() - 1; i >= 0; --i) {
int digit = Character.getNumericValue(digits.charAt(i)); // get the digit at the given index
digit = (alternate = !alternate) ? (digit * 2) : digit; // double every other digit
digit = (digit > 9) ? (digit - 9) : digit; // subtract 9 if the value is greater than 9
sum += digit; // add the digit to the sum
}
return (sum * 9) % 10;
}
To verify a sequence of digits using Luhn's algorithm and extract the number:
/**
* Verifies that a given number string is valid according to Luhn's algorithm, which is described in detail here:
* https://en.wikipedia.org/wiki/Luhn_algorithm
*
* In short, validity of the number is determined like so:
* 1. From the rightmost digit (the check digit) moving left, double the value of every second digit. The check
* digit is not doubled; the first digit doubled is the one immediately to the left of the check digit. If that
* value is greater than 9, subtract 9 from it.
* 2. Sum all of the digits together
* 3. If the sum modulo 10 is equal to 0, then the number is valid according to Luhn's algorithm
*
* #param luhnsNumber the number string to verify and extract the number from
* #return an empty Optional if the given string was not valid according to Luhn's algorithm
* an Optional containing the number verified by Luhn's algorithm if the given string passed the check
*/
public static Optional<Long> extractLuhnsNumber(final String luhnsNumber) {
int sum = 0;
boolean alternate = true;
Long number = Long.parseLong(luhnsNumber.substring(0, luhnsNumber.length() - 1));
for (int i = luhnsNumber.length() - 1; i >= 0; --i) {
int digit = Character.getNumericValue(luhnsNumber.charAt(i)); // get the digit at the given index
digit = (alternate = !alternate) ? (digit * 2) : digit; // double every other digit
digit = (digit > 9) ? (digit - 9) : digit; // subtract 9 if the value is greater than 9
sum += digit; // add the digit to the sum
}
return (sum % 10 == 0) ? Optional.of(number) : Optional.empty();
}
Newcomers to this post/question can check appropriate Wikipedia page for solution. Below is the Java code copy-pasted from there.
public class Luhn
{
public static boolean check(String ccNumber)
{
int sum = 0;
boolean alternate = false;
for (int i = ccNumber.length() - 1; i >= 0; i--)
{
int n = Integer.parseInt(ccNumber.substring(i, i + 1));
if (alternate)
{
n *= 2;
if (n > 9)
{
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
}
package randomNumGen;
public class JavaLuhnAlgorithm {
public static void main(String[] args) {
// TODO Auto-generated method stub
validateCreditCardNumber("8112189876");
String imei = "012850003580200";
validateCreditCardNumber(imei);
}
private static void validateCreditCardNumber(String str) {
int[] ints = new int[str.length()];
for (int i = 0; i < str.length(); i++) {
ints[i] = Integer.parseInt(str.substring(i, i + 1));
}
for (int i = ints.length - 2; i >= 0; i = i - 2) {
int j = ints[i];
j = j * 2;
if (j > 9) {
j = j % 10 + 1;
}
ints[i] = j;
}
int sum = 0;
for (int i = 0; i < ints.length; i++) {
sum += ints[i];
}
if (sum % 10 == 0) {
System.out.println(str + " is a valid credit card number");
} else {
System.out.println(str + " is an invalid credit card number");
}
}
}

Sum of odd integers

I need to complete a method which is passed an int(max) as a parameter and returns the sum of the odd integers from 1 to max (inclusive).
For example, sumOfOddIntegers(5) must return 9. i.e. 1 + 3 + 5 = 9
My attempt was this:
int sumOfOddIntegers(int max) {
int sumOdd = 0;
int digit;
while (max >= 1) {
digit = max%10;
if (digit%2 == 1)
sumOdd += digit;
max /= 10;
}
return sumOdd;
}
But it does not work with some inputs such as 5, 9, etc. What do I need to change in my code?
why not just do this the easy way. Find the number of odd numbers in the range from 1 to max and then square it. This might help you http://www.wikihow.com/Add-a-Sequence-of-Consecutive-Odd-Numbers
If you are trying to get s sum of odd number, you are not required to do digit = max%10; or max/= 10;
See the comments in your code, let say max = 98
/****FIRST RUN****/
// digit = 98%10 = 8
digit = max%10;
// 8 % 2 == 0
if( digit % 2 == 1 )
sumOdd += digit;
// max = 98/10 = 9
max/= 10;
/****SECOND RUN****/
// digit = 9%10 = 9
digit = max%10;
// 9 % 2 == 1
if( digit % 2 == 1 )
// sumOdd = 1
sumOdd += digit;
// max = 9/10 = 0
max/= 10;
Your output is 1, which is not what you expect.
Hence, in order to compute sum of odd number you can proceed via:
for(int i = 1; i <= max; i+= 2)
{
oddSum += i; // assuming oddSum = 0, and max is > 0
}
here is some code
void calculateOdd(int max) {
int total = 0;
for (int i=max; i>0; i--) {
if ( (i % 2) != 0 ) total+=i;
}
}
or
void calculateOdd(int max) {
int total = 0;
if ( (max % 2) == 0 ) max--;
for (int i=max; i>0; i--) {
total+=i;
i--;
}
}
Write a method that will take a number as input, and will check whether or not it's odd. If the number is odd, it may return true, otherwise it may return false (HINT: odd numbers aren't divisible by 2).
From your current method, loop from 1 to max. Pass each number to this method to check if it's odd or not. If it is, add it to the sum.
Might be this helps :
import java.util.*;
class oddsum {
public static void main(String args[]) {
int sumOdd = 0;
int digit;
System.out.println("Please Enter Number.");
Scanner in = new Scanner(System.in);
int i = Integer.parseInt(in.nextLine());
int j;
for(j =1; j<=i; j+=2) {
sumOdd += j;
}
System.out.println(sumOdd);
}
}
To make the sum of odd integers from 1 to max, you can use the Java 8 Streams
public static int sumOddIntegers(int max){
if(max<1) return 0;
return IntStream.rangeClosed(1, max).filter(i -> i%2 != 0).sum();
}
The following method calls are used:
IntStream.rangeClosed(1, max) to generate a stream of int from 1 to max.
filter(i->i%2!=0) to keep only odd int
sum() to make the sum.
You then find the right values.

Categories