Java: Adding Digits Of A String - java

I have the correct code, I found an answer long ago, however I still don't understand why it works.
class Main {
public static void main(String[] args) {
System.out.println(D5PSum(10));
}
private static int D5PSum(int number) {
String n = Integer.toString(number);
int sum = 0;
for (int i = 0; i < n.length(); i++) {
// (1) WHY DOES THIS NOT WORK
//sum += Integer.parseInt(number.charAt(i));
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
char c = n.charAt(i);
sum += (c-'0');
// (3) WHAT IN THE WORLD IS c-'0'
}
return sum;
}
}

// (1) WHY DOES THIS NOT WORK
because Integer.parseInt(...); is expecting a string as parameter not a char
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
char c = n.charAt(i);
any char is nothing else as an integer mapped to a table of symbols...(ASCII table for example) so this (c - '0') is just another valid mathematical operation

charAt is not a valid method of the primitive type int.
'0' is the character 0, and the character encoding set that Java uses has 0 to 9 in a consecutive block. Therefore c - '0' yields the position of c in that consecutive block which is therefore the value of the digit. (Actually this sort of thing is idiomatic C - goes right back to the 1960s).

You should first convert String to Int.. Please check the below code:
class MainClass {
public static void main(String[] args) {
System.out.println(D5PSum(11));
}
private static int D5PSum(int number) {
String n = Integer.toString(number);
System.out.println(n);
int sum = 0;
for (int i = 0; i < n.length(); i++) {
// (1) WHY DOES THIS NOT WORK
String str = String.valueOf(n.charAt(i));
sum += Integer.parseInt(str);
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
// char c = n.charAt(i);
// sum += (c-'0');
// (3) WHAT IN THE WORLD IS c-'0'
}
return sum;
}
}

1
It doesnt work because Integer.parseInt takes a String and String.charAt returns a char(actar). Integer.parseInt (Character.toString(n.charAt(i))) would Work.
2/3
A char represents a number between 0 and 65535. EACH digit-characters (0-9) has a number in that range which depends on the charset. All digits are typically in a row, for example the character 0 has the value 48, 1 49 and 9 57. So ich you want to know the digit value of a char you simply subtract the character value of 0 from your character. That is the Line c-'0'

// (1) WHY DOES THIS NOT WORK
//sum += Integer.parseInt(number.charAt(i));
number is a variable of primitive data type "int" so number.charAt(i) won't work.
// (2) MORE IMPORTANTLY WHY DOES THIS WORK
char c = n.charAt(i);
n is an instance of String and we are getting the character at i th position in the n string
sum += (c-'0');
// (3) WHAT IN THE WORLD IS c-'0'
for every character there is an ascii code assigned. '0' = 48, 'c' = 99. That's the reason why it works here. when 'c'-'0' is executed, it's equivalent to 99-48

Why convert to a string in the first place? The simplest and fastest way to solve this is without deviation to strings:
private static int D5PSum(int number) {
int v = number, sum = 0;
while (v != 0) {
sum += v % 10;
v /= 10;
}
return sum;
}

If you want your code (the part which does not works to work then do this).
class Main {
public static void main(String[] args) {
System.out.println(D5PSum(10));
}
private static int D5PSum(int number) {
String n = Integer.toString(number);
int sum = 0;
for (int i = 0; i < n.length(); i++) {
sum += Integer.parseInt(n.charAt(i)+"");
}
return sum;
}
}

To get sum of the digits of a string str:
int sum = str.chars().map(Character::getNumericValue).sum();

Related

Credit card validator , calling method doesn't work

I'm relatively new to java and am trying to break my code down as much as possible. This question is really on how to organize methods to work together
My credit card validator works if checkSum() code is written in the validateCreditCard() method. I think it's weird 'cause it works when called by the checkDigitControl() method
I used these sources for the program's logic:
To Check ~ https://www.creditcardvalidator.org/articles/luhn-algorithm
To Generate ~ https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm
Here's my code(I apologize in advance if it's rather clumsy)
public class CreditCards {
public static void main(String[] args) {
long num;
num = genCreditCard();
boolean bool = validateCreditCard(num);
}
// Validity Check
public static boolean validateCreditCard(long card) {
String number = card+"";
String string=null;
int i;
for(i=0; i<number.length()-1; i++) {//Populate new string, leaving out last digit.
string += number.charAt(i)+"";
}
String checkDigit = number.charAt(i)+"";// Stores check digit.
long sum = checkSum(string);// Program works if this line is swapped for the code below(from checkSum)
//**********************************************************************
// int[] digits = new int[number.length()];
// int lastIndex = digits.length-1;
// int position=2; int mod=10;
// int sum=0;
//
// for(int j=lastIndex; j>=0; j--) {// Populate array in REVERSE
// digits[j] = Integer.parseInt(number.charAt(j)+"");
// digits[j] *= ( (position%2 == 0) ? 2: 1 );// x2 every other digit FROM BEHIND
// position++;
//
// digits[j] = ( (digits[j] > 9) ? (digits[j] / mod)+(digits[j] % mod) : digits[j] );//Sums integers of double-digits
// sum += digits[j];
// }
//**********************************************************************
sum *= 9;
string = sum+"";
string = string.charAt(string.length()-1)+"";// Last digit of result.
return (string.equals(checkDigit));
}
public static long genCreditCard() {
String number = "34";// American Express(15 digits) starts with 34 or 37
for(int i=0; i<12; i++)
number += (int)(Math.random() * 10) + "";// Add 12 random digits 4 base.
number += checkDigitControl(number);// Concat the check digit.
System.out.println(number);
return Long.parseLong(number);
}
// Algorithm to calculate the last/checkSum digit.
public static int checkDigitControl(String number) {
int i;
for(i=0; i<5; i++)
++i;
int sum = checkSum(number);
return 10 - sum%10;// Returns number that makes checkSum a multiple of 10.
}
public static int checkSum(String number) {
int[] digits = new int[number.length()];
int lastIndex = digits.length-1;
int position=2; int mod=10;
int sum=0;
for(int j=lastIndex; j>=0; j--) {// Populate array in REVERSE
digits[j] = Integer.parseInt(number.charAt(j)+"");
digits[j] *= ( (position%2 == 0) ? 2: 1 );// x2 every other digit FROM BEHIND
position++;
digits[j] = ( (digits[j] > 9) ? (digits[j] / mod)+(digits[j] % mod) : digits[j] );//Sums integers of double-digits
sum += digits[j];
}
return sum;
}
}
Thx in advance, sorry if this isn't the right format; it's also my 1st Stackoverflow post ¯\_(ツ)_/¯
You are initializing the variable string with null value:
String string=null;
And in the following for you are adding every char of the card number to this string.
for(i=0; i<number.length()-1; i++) {
string += number.charAt(i)+"";
}
But this will result in the variable string to be null + cardnumbers, because you didn't initialize the String string, and the value null is converted to the string "null" (Concatenating null strings in Java)
This will fix you code:
String string = new String();
Note, this code:
for(i=0; i<number.length()-1; i++) {
string += number.charAt(i)+"";
}
can be easily replace by this line that does the same thing:
number = number.substring(0, number.length() -1);
If you switch to this code just pass number to checkSum method

How to swap digits in number?

I need to write function that gets 3 params(int num, int k, int nDigit).
The function get number and replace the digit inside the number in k index by nDigit.
for example:
int num = 5498
int k = 2
int nDigit= 3
the result is num = 5398
My question is how can I implement it?I undastand that the best way to convert the num to string and then just replace char on specific index by nDigit char.
But is there any way to implement it?Without
public int changeDigit(int num, int k, int nDigit){
k = pow(10,k);
double saved = num%k; // Save digits after
num = num - (num%(k*10)); //Get what's before k
return ((int) (num + (nDigit*k) + saved));
}
I won't do your homework for you, but here's some hints:
Convert integer to string:
String s = Integer.toString(1234);
Enumerating a string:
for (i = 0; i < s.length; i++)
{
char c = s.charAt(i);
}
String building (a little less efficient without the StringBuilder class)
char c = '1';
String s = "3";
String j = "";
j = j + c;
j = j + s; // j is now equal to "13"
String back to integer:
int val = Integer.parseInt("42");
You can use a StringBuilder. It's easier to see what you're doing and you don't need to perform mathematics, only adjust the characters in their positions. Then convert it back to int.
public class Main {
static int swapParams(int num, int k, int nDigit) {
StringBuilder myName = new StringBuilder(Integer.toString(num));
myName.setCharAt(k-1, Integer.toString(nDigit).charAt(0));
return Integer.parseInt(myName.toString());
}
public static void main(String[] args) {
System.out.println(swapParams(5498, 2, 3));
}
}
http://ideone.com/e4MF6m
You can do it like this:
public int func(int num, int k, int nDigit) {
String number = String.valueOf(num);
return Integer.parseInt(number.substring(0, k - 1) + nDigit + number.substring(k, number.length()));
}
This function takes the first characters of the number without the k'th number and adds the nDigit to it. Then it adds the last part of the number and returns it as an integer number.
This is my javascript solution.
const solution = numbers => { //declare a variable that will hold
the array el that is not strictly ascending let flawedIndex;
//declare a boolean variable to actually check if there is a flawed array el in the given array let flawed = false;
//iterate through the given array for(let i=0; i<numbers.length; i++) {
//check if current array el is greater than the next
if(numbers[i] > numbers[i+1])
{
//check if we already set flawed to true once.
//if flawed==true, then return that this array cannot be sorted
//strictly ascending even if we swap one elements digits
if(flawed) {
return false;
}
//if flawed is false, then set it to true and store the index of the flawed array el
else {
flawed = true;
flawedIndex = i;
}
}
}
//if flawed is still false after the end of the for loop, return true //where true = the array is sctrictly ascending if(flawed ==
false) return true;
//if flawed==true, that is there is an array el that is flawed if(flawed){
//store the result of calling the swap function on the digits of the flawed array el
let swapResult = swap(flawedIndex,numbers);
//if the swapresult is true, then return that it is ascending
if (swapResult == true) return true; }
//else return that its false return false; }
const swap = (flawIndex, numbers) => {
let num = numbers[flawIndex];
//convert the given array el to a string, and split the string based on '' let numToString = num.toString().split('');
//iterate through every digit from index 0 for(let i=0;
i<numToString.length; i++) {
//iterate from every digit from index 1
for(let j=i+1; j<numToString.length; j++) {
//swap the first index digit with every other index digit
let temp = numToString[i];
numToString[i] = numToString[j]
numToString[j] = temp;
console.log(numToString)
//check if the swapped number is lesser than the next number in the main array
//AND if it is greater than the previous el in the array. if yes, return true
let swappedNum = Number(numToString.join(''));
if(swappedNum < numbers[flawIndex + 1] && swappedNum > numbers[flawIndex-])
{
return true;
}
} } //else return false return false; }
console.log("the solution is ",solution([1, 3, 900, 10]))

Accessing characters of a String beyond the range of Integer

I have a String/character sequence that is being repeated infinitesimally... Naturally ,characters will go out of range of Integer and start falling into range of Long, since methods used for accessing characters for both String as well as StringBuilder class all require an int "index" how do I access these characters at say ,Long long>Intger.MAX_VALUE . is there a way to override these methods such as charAt(int index) so that they start "accepting " long arguments ,if not so , how can I access the characters at this index, considered conversion to character array using String.toCharArray() method but then again, array length can only be upto Integer.MAX_VALUE. Is there a method/constructor type that I'm not aware of which accepts long arguments?
You should definitely not construct a string and do measurements on it.
This is a test on how well you are able to abstract things. I will give you some code you may study. You should not copy+paste it for several reasons - including the possibility that I did some mistake.
The idea is, to simply compute the information, which is possible because we have a simple repetition pattern.
class RepeatedString {
private String s;
public RepeatedString(String s) {this.s = s;}
public char charAt(long i) {
return s.charAt((int)(i % s.length()));
}
public long count(char c, long i) {
long n = 0;
// how many complete repetitions?
{
long r = i / s.length();
if (r > 0) {
// count c in s
for (int j = 0 ; j < s.length() ; j++) n += s.charAt(j) == c ? 1 : 0;
n *= r;
}
}
// how many c in last repitition
{
long l = i % s.length();
for (int j = 0 ; j < l ; j++) n += s.charAt(j) == c ? 1 : 0;
}
return n;
}
}
class Kata {
public static void main(String[] args) {
RepeatedString s = new RepeatedString("bla");
System.out.println(s.charAt(1)); // expected 'l'
System.out.println(s.charAt(6)); // expected 'b'
System.out.println(s.count('a', 19)); // expected 6
System.out.println(s.count('a', 21)); // expected 7
}
}

Converting from binary to decimal in Java

I need to write a program that can convert bits into decimal. Whenever I enter a bit, it only outputs 0.0. I cannot figure out why. I know it's incredibly simple but I am just not seeing it. Any help would be appreciated.
import java.lang.Math;
import java.util.Scanner;
public class Lab1 {
static double number = 0;
public static double toDec(String num) {
char[] charArray = num.toCharArray();
for(int i = 0; i<charArray.length;i++) {
if(charArray[i] == 1) {
number = Math.pow(2, charArray.length-i);
}
}
return number;
}
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int bit;
String bitString;
System.out.println("Please enter a bit");
bit = keyboard.nextInt();
bitString = Integer.toString(bit);
System.out.println(toDec(bitString));
}
}
You have compared charArray[i] to 1, but you're comparing apples to oranges, specifically, a char to an int.
Compare to the char '1' instead.
if(charArray[i] == '1') {
Also, you can make number a local variable in toDec; it doesn't need to exist outside that method.
In addition, this will only work if one bit is set. Right now you are working with one bitonly, but if you want to modify this to work with multiple bits, another changes is needed.
You overwrite number each time toDec is called and the condition is true. You will probably want to add to number with += instead of overwriting the previous value with =.
Integer#parseInt(String str, int radix) does the job :
public static Integer toDec(String num) {
return Integer.parseInt(num, 2);
}
So if you want to take the String "110011" which is 51. For big-endian you are going to have to determine how many bits to process. So if you read the string and it is 6 digits long then you know the first bit has to be shifted 6 places to the left.
int l = 6;
long value = 0;
for( int i = 0; i < l; i++ )
{
int bit = ( charArray[i] == "1" ) ? 1 : 0;
l = l + ( bit << l-i );
}
For float you would basically have to build an interpreter to decode the bits based on however the float is represented in binary.

Converting alphanumeric to ascii and incrementing

I'm stumped on how to convert 3 letters and 3 numbers to ascii and increment them by one...it's the old next-license-plate problem. Can anyone give me a nudge in the right direction?
This problem actually have real applications. I wrote an account number generator that works just like this. I modified it to your format. Here you go,
public class LicenseNumber {
int numericSum;
int letterSum;
public LicenseNumber() {
numericSum = letterSum = 0;
}
public LicenseNumber(String number) {
if (!number.matches("^[A-Za-z]{3}[0-9]{3}$"))
throw new IllegalArgumentException("Number doesn't match license format");
numericSum = Integer.valueOf(number.substring(3));
letterSum = value(number, 0) * 26 * 26 + value(number, 1) * 26 +
value(number, 2);
}
public void increment() {
increment(1);
}
public void increment(int inc) {
numericSum += inc;
if (numericSum >= 1000) {
letterSum += numericSum/1000;
numericSum %= 1000;
}
}
public String toString() {
char[] letters = new char[3];
int n = letterSum;
for (int i = 0; i < 3; i++) {
letters[2-i] = (char)('A' + (n%26));
n /= 26;
}
return new String(letters) + String.format("%03d", numericSum);
}
private int value(String s, int index) {
return Character.toUpperCase(s.charAt(index)) - 'A';
}
/**
* Example
*/
public static void main(String[] args) {
LicenseNumber lic = new LicenseNumber("ABC999");
for (int i=0; i < 100; i++) {
lic.increment(500);
System.out.println(lic);
}
}
}
String str = "abc123"
String newstr = "";
for(int i=0; i<str.length(); i++) {
newstr += (char) (str.charAt(i) + 1);
}
// newstr now is "bcd234"
Note that this does not handle the characters 'z','Z' or '9' the way you would want. But it should give you a start.
Also note that using StringBuilder to create newstr would be more efficient.
I guess,
char c='A';
int no=97;
System.out.println( (++c) + " " + (char)++no);
You can do this by converting your String of letters and numbers to a char[]. Once you have done that you can iterate over the array and ++ each.
You're making strings like this: "AAA000", "AAA001", ..., "AAA999", "AAB000", ..., "ZZZ999", right?
Think of it like a number system where the different columns don't use the same number of digits. So where our numbers are 10-10-10-10, your numbers are 26-26-26-10-10-10. Use an underlying integer which you increment, then convert to letters and digits by dividing and taking the modulo successively by 10, 10, 10, 26, 26, 26.
To convert a license plate to its underlying integer, multiply out the letter position (A == 0, B == 1, etc) by the proper power of 26, and the digits by the proper power of 10, and add them all together.
An easy way to generate plate numbers would be to have an integer variable which gets incremented and three integer variables corresponding to the letters, something like this, please modify where appropriate. One trick is to use String.format which seamlessly converts between an integer and its char counterpart (you can also use casts.)
class plateGenerator {
int minLetter = "A".charAt(0);
int maxLetter = "Z".charAt(0);
int curLetter1 = minLetter;
int curLetter2 = minLetter;
int curLetter3 = minLetter;
int number = 0;
public String generatePlate() {
String plate = String.format("%c%c%c-%03d",curLetter1,
curLetter2,curLetter3,number);
increment();
return plate;
}
private void increment() {
number++;
if (number == 1000) {
number = 0;
curLetter1++;
}
if (curLetter1 > maxLetter) {
curLetter1 = minLetter;
curLetter2++;
}
if (curLetter2 > maxLetter) {
curLetter2 = minLetter;
curLetter3++;
}
if (curLetter3 > maxLetter) {
curLetter3 = minLetter;
number++;
}
}
public static void main(String[] args) {
plateGenerator pg = new plateGenerator();
for (int i = 0; i < 50000; i++) {
System.out.println(pg.generatePlate());
}
}
}
I haven't seen any code samples for general solutions for incrementing alphanumeric strings so I though I'd post mine.
This takes a string of any length with any ordering of alpha numeric characters, converts them to upper case and increments it by one (as if it were base 26). It also throws an exception if the numbers wrap. Its really up to you if wrapping makes sense...
private static string IncrementAlphaNumericString(string alphaNumericString)
{
char[] an = alphaNumericString.ToCharArray();
int i = an.Length - 1;
while (true)
{
if (i <= 0)
throw new Exception("Maxed out number!!!");
an[i]++;
if (an[i] - 1 == '9')
{
an[i] = 'A';
}
if (an[i] - 1 == 'Z')
{
an[i] = '0';
i--;
continue;
}
return new string(an);
}
}

Categories