I should make a programm to control the number of an isbn 10 number. Therefore I'm not allowed to use arrays andd the input of the number has to be a char. The In method is similar to java scanner.
public class ISBN {
public static void main(String[] args) {
System.out.println("ISBN - Pruefung");
System.out.println("=================");
System.out.print("ISBN-Nummer: ");
char isbn = In.read();
int check = 0;
int d=0;
for (d=0; d<10; d++) {
if ('0' <= isbn && isbn <= '9' ) {
check = (int) ((isbn-48)*d)+check;
if(d ==9) {
int lastDigit = check%11;
if(lastDigit ==10) {
System.out.println("x");
}else {
System.out.println(lastDigit);
}
}else {
System.out.print(isbn);
}
}else {
System.out.println(isbn + "Falsche Eingabe");
System.exit(0);
}
isbn = In.read();
}
if (d == 10 && check%11 ==0) {
System.out.println("wahr");
}else {
System.out.println("falsch");
}
}
}
I googled some isbn 10 numbers but my programs says they are wrong (example 2123456802). Now my question where is my mistake and/or understood I the function of the last number wrong?
the sum of all the ten digits, each multiplied by its (integer) weight, descending from 10 to 1, is a multiple of 11.
So you just need to sum that digit value time the weight :
int check = 0;
for(int weight = 10; weight > 0; weigth--){
char c = In.read(); //get the next character
int i;
if( c == 'x' || c == 'X' ){
i = 10;
} else {
if(! Character.isDigit(c)) //Because, just in case...
throw new IllegalArgumentException("Not a numeric value");
i = Character.getNumericValue( c );
}
check += i * weight;
}
Just need to check if it is a multiple of 11
if ( check % 11 == 0 )
System.out.println( "VALID" );
else
System.out.println( "INVALID" );
Related
How do I make the loop check if there is 16 digits in a string and reset the string if there is not enough. I am trying to make a credit card program that will calculate the check digit. I have everything else working I just cant get the program to check the number of digits in the user inputted string.Thanks for any and all help!
import java.util.Scanner;
public class LuhnAlgorithm {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter a number credit card number (Enter a blank line to quit: ");
String nums = input.nextLine();
int i = 0;
char chk = nums.charAt(15);
while(!nums .equals("") ) {
if (nums.length()<16 || nums.length() > 15){ //How do I get this line to reset the while loop?
System.out.println("ERROR! Number MUST have exactly 16 digits.");
}
int sum = 0;
for( i = 0; i < 15; i++) {
char numc = nums.charAt(i);
int num = Character.getNumericValue(numc);
if ( i % 2 == 0 ) {
num = num * 2;
if ( num >= 10) {
num = num - 9;
}
}
sum = num + sum;
}
int sum2 = sum % 10;
if (sum2 > 0) {
sum2 = 10 - sum2;
}
int chk2 = Character.getNumericValue(chk);
System.out.println("The check digit should be: " + sum2);
System.out.println("The check digit is: " + chk);
if ( sum2 == chk2) {
System.out.println("Number is valid.");
}
else {
System.out.println("Number is not valid. ");
}
System.out.print("Enter a number credit card number (Enter a blank line to quit:) ");
nums = input.nextLine();
}
System.out.println("Goodbye!");
input.close();
}
}
You can include your code that you only want done if the length ==16 in an if statement.
Meaning, instead of:
if (nums.length != 16) {
//code if there is an error
}
//code if there is no error
you can do:
if (nums.length == 16) {
//code if there is no error
} else {
//code if there is an error
}
(I also want to point out that you set chk = nums.charAt(15) before your while loop, but you don't reset it in the while loop for the next time the user inputs a new credit card number.)
You can bring the prompts and all your initialization except the scanner itself into the while loop. Then if they say "", break to exit the loop. If they say a number that is too short or too long, say continue to go back to the prompting.
Thus:
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
while (true) {
System.out.print("Enter a number credit card number (Enter a blank line to quit: ");
String nums = input.nextLine().trim();
if (nums.length() == 0) {
break; //exits while loop
}
if (nums.length() != 16) { //How do I get this line to reset the while loop?
System.out.println("ERROR! Number MUST have exactly 16 digits.");
continue; //goes back to the beginning right away
}
//still here, process the number
char chk = nums.charAt(15);
int sum = 0;
for (int i = 0; i < 15; i++) {
char numc = nums.charAt(i);
int num = Character.getNumericValue(numc);
if (i % 2 == 0) {
num = num * 2;
if (num >= 10) {
num = num - 9;
}
}
sum = num + sum;
}
int sum2 = sum % 10;
if (sum2 > 0) {
sum2 = 10 - sum2;
}
int chk2 = Character.getNumericValue(chk);
System.out.println("The check digit should be: " + sum2);
System.out.println("The check digit is: " + chk);
if (sum2 == chk2) {
System.out.println("Number is valid.");
} else {
System.out.println("Number is not valid. ");
}
}
System.out.println("Goodbye!");
input.close();
}
}
I am currently working on a simple code that will check if an user inputted String contains character(s) that are specified in the for loop.
My current code
import java.util.Scanner;
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.contains("G")) {
G++;
} else {
if (S.contains("R")) {
R++;
} else {
if (S.contains("Y")) {
Y++;
} else {
if (S.contains("B")) {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G/total);
System.out.println(R/total);
System.out.println(Y/total);
System.out.println(B/total);
}
}
As you can see, it checks if the string contains such characters and it will increase the counter of the character by one. However when I run it, I don't receive the results I predicted.
If I input GGRY, it outputs 1 0 0 0. When the desired out put is
0.5
0.25
0.25
0.0
Any help would be appreciated!
The problem is that S.contains returns true if the whole string contains the given character. S.charAt should solve your problem:
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') G++;
else if (S.charAt(i) == 'R') R++;
else if (S.charAt(i) == 'Y') Y++;
else if (S.charAt(i) == 'B') B++;
}
Also, dividing integers will return an integer (rounded down). As such your output would always be 0 unless all the characters are the same. Just cast them to double before printing:
System.out.println((double) G/total);
System.out.println((double) R/total);
System.out.println((double) Y/total);
System.out.println((double) B/total);
Edit: As pointed out by Sumit Gulati in a comment, a switch statement will have better performance in Java 7. Also, as David Conrad pointed out using only ifs in the for loop would work too as the conditions are mutually exclusive.
Your earlier code S.contains("some character") was finding the index of the character in the entire string. Use S.charAt(i) to specifically find the index at ith location in the string.
Finally, you need to convert the integer to floating point in order to print output as floating values.
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') {
G++;
} else {
if (S.charAt(i) == 'R') {
R++;
} else {
if (S.charAt(i) == 'Y') {
Y++;
} else {
if (S.charAt(i) == 'B') {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G * 1.0 / total);
System.out.println(R * 1.0 / total);
System.out.println(Y * 1.0 / total);
System.out.println(B * 1.0 / total);
}
}
Its supose to tell me if a card is valid or invalid using luhn check
4388576018402626 invalid
4388576018410707 valid
but it keeps telling me that everything is invalid :/
Any tips on what to do, or where to look, would be amazing. I have been stuck for a few hours.
It would also help if people tell me any tips on how to find why a code is not working as intended.
im using eclipse and java
public class Task11 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter a credit card number as a long integer: ");
long number = input.nextLong();
if (isValid(number)) {
System.out.println(number + " is valid");
} else {
System.out.println(number + " is invalid");
}
}
public static boolean isValid(long number) {
return (getSize(number) >= 13) && (getSize(number) <= 16)
&& (prefixMatched(number, 4) || prefixMatched(number, 5) || prefixMatched(number, 6) || prefixMatched(number, 37))
&& (sumOfDoubleEvenPlace(number) + sumOfOddPlace(number)) % 10 == 0;
}
public static int sumOfDoubleEvenPlace(long number) {
int result = 0;
long start = 0;
String digits = Long.toString(number);
if ((digits.length() % 2) == 0) {
start = digits.length() - 1;
} else {
start = digits.length() - 2;
}
while (start != 0) {
result += (int) ((((start % 10) * 2) % 10) + (((start % 10) * 2) / 2));
start = start / 100;
}
return result;
}
public static int getDigit(int number) {
return number % 10 + (number / 10);
}
public static int sumOfOddPlace(long number) {
int result = 0;
while (number != 0) {
result += (int) (number % 10);
number = number / 100;
}
return result;
}
public static boolean prefixMatched(long number, int d) {
return getPrefix(number, getSize(d)) == d;
}
public static int getSize(long d) {
int numberOfDigits = 0;
String sizeString = Long.toString(d);
numberOfDigits = sizeString.length();
return numberOfDigits;
}
public static long getPrefix(long number, int k) {
String size = Long.toString(number);
if (size.length() <= k) {
return number;
} else {
return Long.parseLong(size.substring(0, k));
}
}
}
You should modiffy your isValid() method to write down when it doesn't work, like this:
public static boolean isValid(long number) {
System.err.println();
if(getSize(number) < 13){
System.out.println("Err: Number "+number+" is too short");
return false;
} else if (getSize(number) > 16){
public static boolean isValid(long number) {
System.err.println();
if(getSize(number) < 13){
System.out.println("Err: Number "+number+" is too short");
return false;
} else if (getSize(number) > 16){
System.out.println("Err: Number "+number+" is too long");
return false;
} else if (! (prefixMatched(number, 4) || prefixMatched(number, 5) || prefixMatched(number, 6) || prefixMatched(number, 37)) ){
System.out.println("Err: Number "+number+" prefix doesn't match");
return false;
} else if( (sumOfDoubleEvenPlace(number) + sumOfOddPlace(number)) % 10 != 0){
System.out.println("Err: Number "+number+" doesn't have sum of odd and evens % 10. ");
return false;
}
return true;
}
My guess for your problem is on the getPrefix() method, you should add some logs here too.
EDIT: so, got more time to help you (don't know if it's still necessary but anyway). Also, I corrected the method I wrote, there were some errors (like, the opposite of getSize(number) >= 13 is getSize(number) < 13)...
First it will be faster to test with a set of data instead of entering the values each time yourself (add the values you want to check):
public static void main(String[] args) {
long[] luhnCheckSet = {
0, // too short
1111111111111111111L, // too long (19)
222222222222222l // prefix doesn't match
4388576018402626l, // should work ?
};
//System.out.print("Enter a credit card number as a long integer: ");
//long number = input.nextLong();
for(long number : luhnCheckSet){
System.out.println("Checking number: "+number);
if (isValid(number)) {
System.out.println(number + " is valid");
} else {
System.out.println(number + " is invalid");
}
System.out.println("-");
}
}
I don't know the details of this, but I think you should work with String all along, and parse to long only if needed (if number is more than 19 characters, it might not parse it long).
Still, going with longs.
I detailed your getPrefix() with more logs AND put the d in parameter in long (it's good habit to be carefull what primitive types you compare):
public static boolean prefixMatched(long number, long d) {
int prefixSize = getSize(d);
long numberPrefix = getPrefix(number, prefixSize);
System.out.println("Testing prefix of size "+prefixSize+" from number: "+number+". Prefix is: "+numberPrefix+", should be:"+d+", are they equals ? "+(numberPrefix == d));
return numberPrefix == d;
}
Still don't know what's wrong with this code, but it looks like it comes from the last test:
I didn't do it but you should make one method from sumOfDoubleEvenPlace(number) + sumOfOddPlace(number)) % 10 and log both numbers and the sum (like i did in prefixMatched() ). Add logs in both method to be sure it gets the result you want/ works like it should.
Have you used a debugger ? if you can, do it, it can be faster than adding a lot of logs !
Good luck
EDIT:
Here are the working functions and below I provided a shorter, more efficient solution too:
public class CreditCardValidation {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = 0;
long array[] = new long [16];
do
{
count = 0;
array = new long [16];
System.out.print("Enter your Credit Card Number : ");
long number = in.nextLong();
for (int i = 0; number != 0; i++) {
array[i] = number % 10;
number = number / 10;
count++;
}
}
while(count < 13);
if ((array[count - 1] == 4) || (array[count - 1] == 5) || (array[count- 1] == 3 && array[count - 2] == 7)){
if (isValid(array) == true) {
System.out.println("\n The Credit Card Number is Valid. ");
} else {
System.out.println("\n The Credit Card Number is Invalid. ");
}
} else{
System.out.println("\n The Credit Card Number is Invalid. ");
}
in.close();
}
public static boolean isValid(long[] array) {
int total = sumOfDoubleEvenPlace(array) + sumOfOddPlace(array);
if ((total % 10 == 0)) {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return true;
} else {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return false;
}
}
public static int getDigit(int number) {
if (number <= 9) {
return number;
} else {
int firstDigit = number % 10;
int secondDigit = (int) (number / 10);
return firstDigit + secondDigit;
}
}
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i=0; i< array.length; i++)
{
while (array[i] > 0) {
result += (int) (array[i] % 10);
array[i] = array[i] / 100;
}
}
System.out.println("\n The sum of odd place is " + result);
return result;
}
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
long temp = 0;
for (int i=0; i< array.length; i++){
while (array[i] > 0) {
temp = array[i] % 100;
result += getDigit((int) (temp / 10) * 2);
array[i] = array[i] / 100;
}
}
System.out.println("\n The sum of double even place is " + result);
return result;
}
}
I also found a solution with less lines of logic. I know you're probably searching for an OO approach with functions, building from this could be of some help.
Similar question regarding error in Luhn algorithm logic:
Check Credit Card Validity using Luhn Algorithm
Link to shorter solution:
https://code.google.com/p/gnuc-credit-card-checker/source/browse/trunk/CCCheckerPro/src/com/gnuc/java/ccc/Luhn.java
And here I tested the solution with real CC numbers:
public class CreditCardValidation{
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);
}
public static void main(String[] args){
//String num = "REPLACE WITH VALID NUMBER"; //Valid
String num = REPLACE WITH INVALID NUMBER; //Invalid
num = num.trim();
if(Check(num)){
System.out.println("Valid");
}
else
System.out.println("Invalid");
//Check();
}
}
I had an interview in which I did terribly. So, now I'm trying to find the solution to the question. Here is the interview question:
"We have the following mapping:
M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1.
And we have the following rules:
Each letter maps to a positive integer value
You add the values together, except...
...when a value (or runs of the same values) is followed by a greater value, you subtract the total of that run of values.
Examples:
IIX -> 8
MCCMIIX -> 1808
We are given this Java method: int valueOfRoman(char roman).
We have implement the Java method: int romanToInt(String s)"
I know it is not a proper roman number system, but that is the actual question.
I was able to code a working solution to a proper Roman system. But I'm unable to change it so that it adapts to these new rules, particularly Rule 3. I have tried, but with no success. The way my solution is right now, for IIX, it prints 10, instead of the correct answer of 8. Here is my code (I also implemented valueOf for my testing):
static int romanToInt(String s) {
char curr;
int currVal;
char prev;
int prevVal;
int total = valueOfRoman(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
curr = s.charAt(i);
currVal = valueOfRoman(curr);
prev = s.charAt(i-1);
prevVal = valueOfRoman(prev);
total += currVal;
if(currVal > prevVal) {
total = total - (2*prevVal);
}
}
return total;
}
static int valueOfRoman(char c) {
if (c == 'M') {
return 1000;
} else if (c == 'D') {
return 500;
} else if (c == 'C') {
return 100;
} else if (c == 'L') {
return 50;
} else if (c == 'X') {
return 10;
} else if (c == 'V') {
return 5;
} else if (c == 'I') {
return 1;
}
return -1;
}
Any help is really appreciated. Specially useful would be if you can tell me how to modify my code. Thanks!
EDIT: I edited the names of the methods so they are clearer.
My take - works with the admittedly small tests you supplied.
static int rom2int(String s) {
if (s == null || s.length() == 0) {
return 0;
}
// Total value.
int total = 0;
// The most recent.
char current = s.charAt(0);
// Total for the current run.
int run = valueOf(current);
for (int i = 1; i < s.length(); i++) {
char next = s.charAt(i);
int value = valueOf(next);
if (next == current) {
// We're in a run - just keep track of its value.
run += value;
} else {
// Up or down?
if (value < valueOf(current)) {
// Gone down! Add.
total += run;
} else {
// Gone UP! Subtract.
total -= run;
}
// Run ended.
run = valueOf(next);
}
// Kee track of most recent.
current = next;
}
return total + run;
}
private void test(String s) {
System.out.println("Value of " + s + " = " + rom2int(s));
}
public void test() {
test("IVX");
test("IIVVL");
test("IIX");
test("MCCMIIX");
test("MVVV");
}
prints
Value of IVX = 4 - Odd!!!
Value of IIVVL = 38
Value of IIX = 8
Value of MCCMIIX = 1808
Value of MVVV = 1015
Here's how I'd approach the problem:
Read the string character by character and during every step note the current character and the previous character.
If the current character is the same as the previous, increase the run length by 1.
If the current character has a smaller value than the previous, add run length * value of previous character to the total, and reset run length to 1.
If the current character has a greater value than the previous, subtract run length * value of previous character from the total, and reset run length to 1.
So, nobody caught my hint. Then I'll give it a try, too. I won't go into the "IVX"- thing because I consider that a syntax error.
int romanToInt( String s ){
int total = 0;
int pivot = 0;
for( int i = s.length()-1; i >= 0; i--){ // We start at the **end**
int current = valueOfRoman((s.charAt(i));
if( current >= pivot ){ // We will have at least "I", so it **will** be > pivot for 1st char.
pivot = current;
total += pivot;
}else{
total -= current;
}
}
return total;
}
Let's see: IIX
i char value total pivot -> total pivot
2 X 10 0 0 > 10 10
1 I 1 10 10 < 9 10
0 I 1 9 10 < 8 10
MCCMIIX
i char value total pivot -> total pivot
6 X 10 0 0 > 10 10
5 I 1 10 10 < 9 10
4 I 1 9 10 < 8 10
3 M 1000 8 10 > 1008 1000
2 C 100 1008 1000 < 908 1000
1 C 100 908 1000 < 808 1000
0 M 1000 808 1000 = 1808 1000
The method leaves out input validation for brevity. I am assuming all input has been checked and consists only of allowed characters according to "the rules".
My take on it.
EDIT CHANGE #2
public class Romans {
private int valueOf(char c) {
if (c == 'M') {
return 1000;
} else if (c == 'D') {
return 500;
} else if (c == 'C') {
return 100;
} else if (c == 'L') {
return 50;
} else if (c == 'X') {
return 10;
} else if (c == 'V') {
return 5;
} else if (c == 'I') {
return 1;
}
return 0;
}
public int rom2int(String s) {
int currVal;
int runValue = 0;
int repetition = 0;
int total = 0;
boolean alreadyAdded = false;
for (int i = 0; i < s.length(); i++) {
currVal = valueOf(s.charAt(i));
if (runValue == 0) {
runValue = currVal;
repetition = 1;
alreadyAdded = false;
} else if (currVal > runValue) {
total = total + (currVal - (runValue * repetition));
repetition = 1;
runValue = currVal;
alreadyAdded = true;
} else if (currVal < runValue) {
if(!alreadyAdded) {
total += (runValue * repetition);
}
repetition = 1;
runValue = currVal;
alreadyAdded = false;
} else {
repetition++;
alreadyAdded = false;
}
}
if (!alreadyAdded) {
total += (runValue * repetition);
}
return total;
}
}
And the main I'm running:
public static void main(String[] args) {
Romans r = new Romans();
String[] inputs = {"MVVV", "IIX","MCCMIIX", "IVX"};
for(String input : inputs) {
System.out.println("Value of " + input + " is: " + r.rom2int(input));
}
}
Outputs:
Value of MVVV is: 1015
Value of IIX is: 8
Value of MCCMIIX is: 1808
Value of IVX is: 9
That's how I did.
It works for those 2 values you mentioned (IIX = 8 and MCCMIIX = 1808):
public static int rom2int(String s)
{
int currVal = 0, prevVal = 0, subTotal = 0, total = 0;
for (int i = 0; i < s.length(); i++) {
currVal = valueOf(s.charAt(i));
if (currVal > 0) {
if (prevVal == 0) {
subTotal = currVal;
}
else if (currVal > prevVal) {
total += (currVal - subTotal);
subTotal = 0;
}
else if (currVal < prevVal) {
total += subTotal;
subTotal = currVal;
}
else if (currVal == prevVal) {
subTotal += currVal;
}
prevVal = currVal;
}
}
total += subTotal;
return total;
}
public static int valueOf(char c)
{
if (c == 'M')
return 1000;
if (c == 'D')
return 500;
if (c == 'C')
return 100;
if (c == 'L')
return 50;
if (c == 'X')
return 10;
if (c == 'V')
return 5;
if (c == 'I')
return 1;
return 0;
}
EDIT 1:
Explanation for "IVX" value:
"...add values together except when a value (or runs of the SAME
values) is followed by a greater value, you subtract the total of that
run of values."
IVX = 1 5 10
if 5 > 1 then 5 - 1 = 4
if 10 > 5 then 10 - 0(*) = 10 (*) we already have used V(5) before, so we discard it.
So the answer for IVX is 14!
My approach would be to break the problem into the following steps:
Create a map of the symbols and values (a roman map).
Create a store to keep your result.
Loop through all the strings from RTL.
For each symbol, check that the value of the current symbol is greater than its previous value.
If the current symbol is greater than its previous value (e.g IV, where V is the current symbol), then do subtraction (current value minus previous value) and add that to the result; then skip the previous value in the loop.
Else; add the value of the current symbol to the result.
Note:
An important rule to note is that there can only be 1 prev value in the roman numerals to indicate a reduction.
IV = 4
IIV = invalid
...same with the rest of the numerals (IXCVDM...).
Hope this helps someone in the future.
class Solution(object):
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
romanMap = { "I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000 }
result = 0;
index = len(s) - 1;
while (index >= 0):
romanValue = s[index];
prevValue = s[index - 1];
if ((index > 0) and (romanMap[romanValue] > romanMap[prevValue])):
result += romanMap[romanValue] - romanMap[prevValue];
index-= 1;
else:
result += romanMap[romanValue];
index-= 1;
return result;
You can run the code with the following:
print(Solution().romanToInt("LVIII"));
this kind of problematics are usually really easy to solve using recursive way of thinking. The solution could look like :
public int rom2int(String s)
{
if(s.length() == 0)
// no string --> 0
return 0;
else if(s.length() == 1)
// One Character --> Value of Character
return valueOf(s.charAt(0));
else if((valueOf(s.charAt(0)) > valueOf(s.charAt(1))) )
// The value is NOT followed by a greater value --> We had the value
return rom2int(s.substring(1, s.length())) + valueOf(s.charAt(0));
else if(valueOf(s.charAt(0)) <= valueOf(s.charAt(1)) )
// The value is followed by a greater (or same) value --> We substract the value
return rom2int(s.substring(1, s.length())) - valueOf(s.charAt(0));
else
// Shouldn't Happen. 0 as neutral element in in a Sum.
return 0;
}
Even if recursive solution is forbidden, to my mind it is simpler to un-recursive this algorithm than find the procedural one at first try =)
Edit :
MY Results :
Value of MCCMIIX is : 1808
Value of IIX is : 8
Value of IVX is : 4
Value of IIVVL is : 38
I tried to check the validation of credit card using Luhn algorithm, which works as the following steps:
Double every second digit from right to left. If doubling of a digit results in a two-digit number, add up the two digits to get a single-digit number.
2 * 2 = 4
2 * 2 = 4
4 * 2 = 8
1 * 2 = 2
6 * 2 = 12 (1 + 2 = 3)
5 * 2 = 10 (1 + 0 = 1)
8 * 2 = 16 (1 + 6 = 7)
4 * 2 = 8
Now add all single-digit numbers from Step 1.
4 + 4 + 8 + 2 + 3 + 1 + 7 + 8 = 37
Add all digits in the odd places from right to left in the card number.
6 + 6 + 0 + 8 + 0 + 7 + 8 + 3 = 38
Sum the results from Step 2 and Step 3.
37 + 38 = 75
If the result from Step 4 is divisible by 10, the card number is valid; otherwise, it is invalid. For example, the number 4388576018402626 is invalid, but the number 4388576018410707 is valid.
Simply, my program always displays valid for everything that I input. Even if it's a valid number and the result of sumOfOddPlace and sumOfDoubleEvenPlace methods are equal to zero. Any help is appreciated.
import java.util.Scanner;
public class CreditCardValidation {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = 0;
long array[] = new long [16];
do
{
count = 0;
array = new long [16];
System.out.print("Enter your Credit Card Number : ");
long number = in.nextLong();
for (int i = 0; number != 0; i++) {
array[i] = number % 10;
number = number / 10;
count++;
}
}
while(count < 13);
if ((array[count - 1] == 4) || (array[count - 1] == 5) || (array[count - 1] == 3 && array[count - 2] == 7)){
if (isValid(array) == true) {
System.out.println("\n The Credit Card Number is Valid. ");
} else {
System.out.println("\n The Credit Card Number is Invalid. ");
}
} else{
System.out.println("\n The Credit Card Number is Invalid. ");
}
}
public static boolean isValid(long[] array) {
int total = sumOfDoubleEvenPlace(array) + sumOfOddPlace(array);
if ((total % 10 == 0)) {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return true;
} else {
for (int i=0; i< array.length; i++){
System.out.println(array[i]);}
return false;
}
}
public static int getDigit(int number) {
if (number <= 9) {
return number;
} else {
int firstDigit = number % 10;
int secondDigit = (int) (number / 10);
return firstDigit + secondDigit;
}
}
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i=0; i< array.length; i++)
{
while (array[i] > 0) {
result += (int) (array[i] % 10);
array[i] = array[i] / 100;
}}
System.out.println("\n The sum of odd place is " + result);
return result;
}
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
long temp = 0;
for (int i=0; i< array.length; i++){
while (array[i] > 0) {
temp = array[i] % 100;
result += getDigit((int) (temp / 10) * 2);
array[i] = array[i] / 100;
}
}
System.out.println("\n The sum of double even place is " + result);
return result;
}
}
You can freely import the following code:
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);
}
}
Link reference: https://github.com/jduke32/gnuc-credit-card-checker/blob/master/CCCheckerPro/src/com/gnuc/java/ccc/Luhn.java
Google and Wikipedia are your friends. Instead of long-array I would use int-array. On Wikipedia following java code is published (together with detailed explanation of Luhn algorithm):
public static boolean check(int[] digits) {
int sum = 0;
int length = digits.length;
for (int i = 0; i < length; i++) {
// get digits in reverse order
int digit = digits[length - i - 1];
// every 2nd number multiply with 2
if (i % 2 == 1) {
digit *= 2;
}
sum += digit > 9 ? digit - 9 : digit;
}
return sum % 10 == 0;
}
You should work on your input processing code. I suggest you to study following solution:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
boolean repeat;
List<Integer> digits = new ArrayList<Integer>();
do {
repeat = false;
System.out.print("Enter your Credit Card Number : ");
String input = in.next();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c < '0' || c > '9') {
repeat = true;
digits.clear();
break;
} else {
digits.add(Integer.valueOf(c - '0'));
}
}
} while (repeat);
int[] array = new int[digits.size()];
for (int i = 0; i < array.length; i++) {
array[i] = Integer.valueOf(digits.get(i));
}
boolean valid = check(array);
System.out.println("Valid: " + valid);
}
I took a stab at this with Java 8:
public static boolean luhn(String cc) {
final boolean[] dbl = {false};
return cc
.chars()
.map(c -> Character.digit((char) c, 10))
.map(i -> ((dbl[0] = !dbl[0])) ? (((i*2)>9) ? (i*2)-9 : i*2) : i)
.sum() % 10 == 0;
}
Add the line
.replaceAll("\\s+", "")
Before
.chars()
If you want to handle whitespace.
Seems to produce identical results to
return LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(cc);
From Apache's commons-validator.
There are two ways to split up your int into List<Integer>
Use %10 as you are using and store it into a List
Convert to a String and then take the numeric values
Here are a couple of quick examples
public static void main(String[] args) throws Exception {
final int num = 12345;
final List<Integer> nums1 = splitInt(num);
final List<Integer> nums2 = splitString(num);
System.out.println(nums1);
System.out.println(nums2);
}
private static List<Integer> splitInt(int num) {
final List<Integer> ints = new ArrayList<>();
while (num > 0) {
ints.add(0, num % 10);
num /= 10;
}
return ints;
}
private static List<Integer> splitString(int num) {
final List<Integer> ints = new ArrayList<>();
for (final char c : Integer.toString(num).toCharArray()) {
ints.add(Character.getNumericValue(c));
}
return ints;
}
I'll use 5 digit card numbers for simplicity. Let's say your card number is 12345; if I read the code correctly, you store in array the individual digits:
array[] = {1, 2, 3, 4, 5}
Since you already have the digits, in sumOfOddPlace you should do something like
public static int sumOfOddPlace(long[] array) {
int result = 0;
for (int i = 1; i < array.length; i += 2) {
result += array[i];
}
return result;
}
And in sumOfDoubleEvenPlace:
public static int sumOfDoubleEvenPlace(long[] array) {
int result = 0;
for (int i = 0; i < array.length; i += 2) {
result += getDigit(2 * array[i]);
}
return result;
}
this is the luhn algorithm implementation which I use for only 16 digit Credit Card Number
if(ccnum.length()==16){
char[] c = ccnum.toCharArray();
int[] cint = new int[16];
for(int i=0;i<16;i++){
if(i%2==1){
cint[i] = Integer.parseInt(String.valueOf(c[i]))*2;
if(cint[i] >9)
cint[i]=1+cint[i]%10;
}
else
cint[i] = Integer.parseInt(String.valueOf(c[i]));
}
int sum=0;
for(int i=0;i<16;i++){
sum+=cint[i];
}
if(sum%10==0)
result.setText("Card is Valid");
else
result.setText("Card is Invalid");
}else
result.setText("Card is Invalid");
If you want to make it use on any number replace all 16 with your input number length.
It will work for Visa number given in the question.(I tested it)
Here's my implementation of the Luhn Formula.
/**
* Runs the Luhn Equation on a user inputed CCN, which in turn
* determines if it is a valid card number.
* #param c A user inputed CCN.
* #param cn The check number for the card.
* #return If the card is valid based on the Luhn Equation.
*/
public boolean luhn (String c, char cn)
{
String card = c;
String checkString = "" + cn;
int check = Integer.valueOf(checkString);
//Drop the last digit.
card = card.substring(0, ( card.length() - 1 ) );
//Reverse the digits.
String cardrev = new StringBuilder(card).reverse().toString();
//Store it in an int array.
char[] cardArray = cardrev.toCharArray();
int[] cardWorking = new int[cardArray.length];
int addedNumbers = 0;
for (int i = 0; i < cardArray.length; i++)
{
cardWorking[i] = Character.getNumericValue( cardArray[i] );
}
//Double odd positioned digits (which are really even in our case, since index starts at 0).
for (int j = 0; j < cardWorking.length; j++)
{
if ( (j % 2) == 0)
{
cardWorking[j] = cardWorking[j] * 2;
}
}
//Subtract 9 from digits larger than 9.
for (int k = 0; k < cardWorking.length; k++)
{
if (cardWorking[k] > 9)
{
cardWorking[k] = cardWorking[k] - 9;
}
}
//Add all the numbers together.
for (int l = 0; l < cardWorking.length; l++)
{
addedNumbers += cardWorking[l];
}
//Finally, check if the number we got from adding all the other numbers
//when divided by ten has a remainder equal to the check number.
if (addedNumbers % 10 == check)
{
return true;
}
else
{
return false;
}
}
I pass in the card as c which I get from a Scanner and store in card, and for cn I pass in checkNumber = card.charAt( (card.length() - 1) );.
Okay, this can be solved with a type conversions to string and some Java 8
stuff. Don't forget numbers and the characters representing numbers are not the same. '1' != 1
public static int[] longToIntArray(long cardNumber){
return Long.toString(cardNumber).chars()
.map(x -> x - '0') //converts char to int
.toArray(); //converts to int array
}
You can now use this method to perform the luhn algorithm:
public static int luhnCardValidator(int cardNumbers[]) {
int sum = 0, nxtDigit;
for (int i = 0; i<cardNumbers.length; i++) {
if (i % 2 == 0)
nxtDigit = (nxtDigit > 4) ? (nxtDigit * 2 - 10) + 1 : nxtDigit * 2;
sum += nxtDigit;
}
return (sum % 10);
}
private static int luhnAlgorithm(String number){
int n=0;
for(int i = 0; i<number.length(); i++){
int x = Integer.parseInt(""+number.charAt(i));
n += (x*Math.pow(2, i%2))%10;
if (x>=5 && i%2==1) n++;
}
return n%10;
}
public class Creditcard {
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
String cardno = sc.nextLine();
if(checkType(cardno).equals("U")) //checking for unknown type
System.out.println("UNKNOWN");
else
checkValid(cardno); //validation
}
private static String checkType(String S)
{
int AM=Integer.parseInt(S.substring(0,2));
int D=Integer.parseInt(S.substring(0,4)),d=0;
for(int i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
d++;
}
if((AM==34 || AM==37) && d==15)
System.out.println("AMEX");
else if(D==6011 && d==16)
System.out.println("Discover");
else if(AM>=51 && AM<=55 && d==16)
System.out.println("MasterCard");
else if(((S.charAt(0)-'0')==4)&&(d==13 || d==16))
System.out.println("Visa");
else
return "U";
return "";
}
private static void checkValid(String S) // S--> cardno
{
int i,d=0,sum=0,card[]=new int[S.length()];
for(i=S.length()-1;i>=0;i--)
{
if(S.charAt(i)==' ')
continue;
else
card[d++]=S.charAt(i)-'0';
}
for(i=0;i<d;i++)
{
if(i%2!=0)
{
card[i]=card[i]*2;
if(card[i]>9)
sum+=digSum(card[i]);
else
sum+=card[i];
}
else
sum+=card[i];
}
if(sum%10==0)
System.out.println("Valid");
else
System.out.println("Invalid");
}
public static int digSum(int n)
{
int sum=0;
while(n>0)
{
sum+=n%10;
n/=10;
}
return sum;
}
}
Here is the implementation of Luhn algorithm.
public class LuhnAlgorithm {
/**
* Returns true if given card number is valid
*
* #param cardNum Card number
* #return true if card number is valid else false
*/
private static boolean checkLuhn(String cardNum) {
int cardlength = cardNum.length();
int evenSum = 0, oddSum = 0, sum;
for (int i = cardlength - 1; i >= 0; i--) {
System.out.println(cardNum.charAt(i));
int digit = Character.getNumericValue(cardNum.charAt(i));
if (i % 2 == 0) {
int multiplyByTwo = digit * 2;
if (multiplyByTwo > 9) {
/* Add two digits to handle cases that make two digits after doubling */
String mul = String.valueOf(multiplyByTwo);
multiplyByTwo = Character.getNumericValue(mul.charAt(0)) + Character.getNumericValue(mul.charAt(1));
}
evenSum += multiplyByTwo;
} else {
oddSum += digit;
}
}
sum = evenSum + oddSum;
if (sum % 10 == 0) {
System.out.println("valid card");
return true;
} else {
System.out.println("invalid card");
return false;
}
}
public static void main(String[] args) {
String cardNum = "4071690065031703";
System.out.println(checkLuhn(cardNum));
}
}
public class LuhnAlgorithm {
/**
* Returns true if given card number is valid
*
* #param cardNum Card number
* #return true if card number is valid else false
*/
private static boolean checkLuhn(String cardNum) {
int cardlength = cardNum.length();
int evenSum = 0, oddSum = 0, sum;
for (int i = cardlength - 1; i >= 0; i--) {
System.out.println(cardNum.charAt(i));
int digit = Character.getNumericValue(cardNum.charAt(i));
if (i % 2 == 0) {
int multiplyByTwo = digit * 2;
if (multiplyByTwo > 9) {
/* Add two digits to handle cases that make two digits after doubling */
String mul = String.valueOf(multiplyByTwo);
multiplyByTwo = Character.getNumericValue(mul.charAt(0)) + Character.getNumericValue(mul.charAt(1));
}
evenSum += multiplyByTwo;
} else {
oddSum += digit;
}
}
sum = evenSum + oddSum;
if (sum % 10 == 0) {
System.out.println("valid card");
return true;
} else {
System.out.println("invalid card");
return false;
}
}
public static void main(String[] args) {
String cardNum = "8112189875";
System.out.println(checkLuhn(cardNum));
}
}
Hope it may works.
const options = {
method: 'GET',
headers: {Accept: 'application/json', 'X-Api-Key': '[APIkey]'}
};
fetch('https://api.epaytools.com/Tools/luhn?number=[CardNumber]&metaData=true', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));