How to get sum of char values produced in a loop? - java

Sorry if the title is misleading or is confusing, but here is my dilemma.
I am inputting a string, and want to assign a value to each capitalized letter in the alphabet (A=1, .. Z=26) and then add the values of each letter in that string.
Example: ABCD = 10 (since 1 + 2 + 3 + 4)
But I don't know how to add all the values in the string
NOTE: This is only for capitalized letters and strings
public class Test {
public static void main(String[] args) {
Scanner scannerTest = new Scanner(System.in);
System.out.println("Enter a name here: ");
String str = scannerTest.nextLine();
char[] ch = str.toCharArray();
int temp_integer = 64;
for (char c : ch) {
int temp = (int) c;
if (temp <= 90 & temp >= 65){
int sum = (temp - temp_integer);
System.out.println(sum);
}
}
}
}
So, as you can see I print out the sum for each time its looped,
meaning: if I input "AB", the output will be 1 and 2.
However, I want to go a step further, and add these two values together, but I'm stumped, any suggestions or help? (NOTE: this is not a assignment or anything, just practising problem sets)

I would prefer to use the character literals. You know that the range is A to Z (1 to 26), so you can subtract 'A' from each char (but you need to add 1 because it doesn't start at 0). I would also call toUpperCase on the input line. Something like,
Scanner scannerTest = new Scanner(System.in);
System.out.println("Enter a name here: ");
String str = scannerTest.nextLine().toUpperCase();
int sum = 0;
for (char ch : str.toCharArray()) {
if (ch >= 'A' && ch <= 'Z') {
sum += 1 + ch - 'A';
}
}
System.out.printf("The sum of %s is %d%n", str, sum);
Which I tested with your example
Enter a name here:
ABCD
The sum of ABCD is 10

Using 64 to represent the character before 'A' in the ascii table is difficult to understand, you can perform substration between characters in Java directly.
So if 'A' represent 1, then just do c - 'A' + 1 will give you the corresponding integer value for each capitalized letter.
To get the sum, just sum up: initialize the sum as 0, and in the for loop, add increment sum by the value you calculated. You can use the incremental assignment operation: +=
Scanner scannerTest = new Scanner(System.in);
System.out.println("Enter a name here: ");
String str = scannerTest.nextLine();
char[] ch = str.toCharArray();
int sum = 0;
for (char c : ch) {
sum += c - 'A' + 1;
}
System.out.println(sum);

Change only your for to these:
int sum = 0;
for(int i = 0; i < ch.length; i++){
sum += (int) ch[i] - 96;
System.out.println(sum);
}
The sum += (int) ch[i] - 96; is because the char a is the value 97, as your say, you want char a corresponde to 1, note that a is different than A
Check the char value here: https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html
This was tested and worked fine! Good Luck

It would look something like this (in C programming language) which you can easily modify for other programming languages:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int i;
char word[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned int sum = 0;
unsigned int charVal;
for (i=0; i < strlen(word); ++i) {
charVal = word[i] - 'A' + 1;
printf("Value of %c is %d\n", word[i], charVal);
sum += charVal;
}
printf("Sum of %s = %d\n", word, sum);
return(0);
}
The trick is to take the character value, subtract the baseline 'A' value and add 1 to arrive at your calculation range:
charVal = word[i] - 'A' + 1;

Achieve the same in a concise way by employing Java 8's lambda functions
String str = "ABCD";
int sum = str.chars()
.filter(c -> c >= 'A' && c <= 'Z')
.map(c -> 1 + c - 'A')
.reduce(0, Integer::sum);

Related

Caesar cipher by comparing char array with two arrays

I need to build a Caesar cipher that only encrypts letters, but no special characters. My concept was, to compare the input char[] with two alphabet char[]. If there is no match in a char, the char should be added to the String without being changed. The problem is that the not-changed char will be added to the String until the the for-loop ends. How do I fix this?
public static String encrypt(String text, int number) {
String str = "";
char[] chars = text.toCharArray();
char[] al = "abcdefghijklmnopqrstuvwxyz".toCharArray();
char[] ab = "abcdefghijklmnopqrstuvwxyz".toUpperCase().toCharArray();
for (char c : chars) {
boolean match = false;
for (int i = 1; i < chars.length - 1; i++) {
for (int k = 0; (k < al.length || k < ab.length) && !match; k++) {
match = (c == al[k] || c == ab[k]);
if (match) {
c += number;
str += c;
}
}
if (!match) {
str += c;
}
}
}
return str;
}
I already tried to put the case for not changing the string within the other for-loop, but it will be added until the for-loop has reached it's end.
I would tackle the problem by iterating through the String and considering the possible cases for each letter
Uppercase Letter
Lowercase Letter
Special Character
public static String encrypt(String text, int number) {
//String to hold our return value
String toReturn = "";
//Iterate across the string at each character
for (char c : text.toCharArray()){
if (Character.isUpperCase(c)){
/* If uppercase, add number to the character
If the character plus number is more than 90,
subtract 25 [uppercase letters have ASCII 65 to 90] */
toReturn += c + number > 90 ? (char)(c + number - 25) : (char)(c + number);
} else if (Character.isLowerCase(c)){
/* If lowercase, add number to the character
If the character plus number is more than 122,
subtract 25 [uppercase letters have ASCII 97 to 122] */
toReturn += c + number > 122 ? (char)(c + number - 25) : (char)(c + number);
} else {
// For other characters, just add it onto the return string
toReturn += c;
}
}
return toReturn;
}
Explanation of Code
You might be wondering what the following code does
toReturn += c + number > 90 ? (char)(c + number - 25) : (char)(c + number)
The structure is
toReturn += CONDITION ? A : B
It basically reads as
IF CONDITION IS TRUE, toReturn += A, ELSE toReturn += B
The CONDITION is simply c + number > 90 since we want to make sure that we are sticking with uppercase letters only
When this is true (A), we subtract 25 from c + number, otherwise (B) we just keep it as c + number (B)
We then cast this value into a char since it is initially an int

Error with multiplying char with a number and add with char ( Big Java Ex 6.2)

Currently going through an exercise in my book, but i'm stuck ( I havent learned arrays yet, this chapter is on loops nested loops and for loops)
The first part of the problem is to take a credit card number and then sum every other number backwards
Consider 4358 9795, which should output the sum 5+7+8 + 3 = 23.
Heres my solution which isn't working
class Checkit{
private String creditNum;
private int sum;
public Checkit(String creditNum)
{
this.creditNum = creditNum;
sum = 0;
}
public int getSum()
{
for (int i = creditNum.length() ; i > 0 ; i--)
{
char ch = creditNum.charAt(i-1);
if(i%2 == 1 )
{
sum+=ch;
}
}
return sum;
}
}
public class test{
public static void main(String [] args)
{
Checkit sampleNumber = new Checkit("4358 9795");
System.out.println(sampleNumber.getSum());
}
}
I'm not exactly sure whats wrong with my logic. ch is taking all of the values of my credit card number 5,7,8,3. But for some reason the sum is messing up.
BONUS PART
Take Each number that wasn't added and double it, so 9+9 + 5 + 4, double each of those terms ( that becomes 18 + 18 + 10 + 8), and then get the sum of 1 + 8 + 1 + 8 + 1 + 0 + 8.
I tried the bonus part, but for some reason every time I get 9, 9, 5,4 and times that char value by 2, I get letters. I don't think I can multiply chars by integers, so should I do conversions? Note I didn't learn arrays yet
NEW CODE
class Checkit {
private String creditCardNum;
private int sum;
public Checkit(String creditCardNum) {
sum = 0;
this.creditCardNum = creditCardNum;
}
public int getSum() {
creditCardNum = creditCardNum.replaceAll("\\s+", "");
for (int i = creditCardNum.length(); i > 0; i--) {
char ch = creditCardNum.charAt(i - 1);
if (i % 2 == 0) {
sum += Character.getNumericValue(ch);
}
}
return sum;
}
public int doubleDigitSum() {
sum = 0;
creditCardNum = creditCardNum.replaceAll("\\s", "");
for (int i = creditCardNum.length(); i > 0; i--) {
char ch = creditCardNum.charAt(i - 1);
if (i % 2 == 1) {
int newChar = Character.getNumericValue(ch) * 2;
String newCharString = Integer.toString(newChar);
for (int j = 0; j < newCharString.length(); j++) {
char sumThis = newCharString.charAt(j);
sum += Character.getNumericValue(sumThis);
}
}
}
return sum;
}
}
public class DataSet{
public static void main(String [] args) {
Checkit data = new Checkit("4358 9795");
System.out.println(data.getSum());
System.out.println(data.doubleDigitSum());
}
}
You're adding char values rather than int values. Replace sum+=ch; with
sum += ch - '0';
The reason why this works as opposed to the original solution is that when you're adding char values to an int value, the char is converted to a decimal via its ASCII value. For example, '5' has a ASCII dec value of 53. However, '5' - '0' equals 5. More on these ASCII values can be found here, http://www.asciitable.com/
Your issue is that you are not converting the char to an integer:
public int getSum()
{
for (int i = creditNum.length() ; i > 0 ; i--)
{
char ch = creditNum.charAt(i-1);
if(i%2 == 1 )
{
sum+=ch;
}
}
return sum;
}
Fun fact that's causing your error - chars are numbers! They're simply a number that represents the ascii character code of the letter. So when you add them to a sum, Java is OK with that and just adds the corresponding number for the char '8' for example, which is 56.
To make your code work, you need to properly convert to an integer:
public int getSum()
{
for (int i = creditNum.length() ; i > 0 ; i--)
{
char ch = creditNum.charAt(i-1);
if(i%2 == 1)
{
sum+=Character.getNumericValue(ch);
}
}
return sum;
}
for (int i = creditNum.length() ; i > 0 ; i--) {
char ch = creditNum.charAt(i-1);
First iteration thru loop gets IndexOutOfBounds exception. And then you never check the initial character of the credit card number, since your termination criterion is ( i > 0 ), not (i >= 0)
And why not just use i -= 2 for the increment instead of the if-check?

Converting String number to integer array

I want to read a number as a String, and split its characters to an integer array, and find the sum of it's digits by looping through that integers array.
This is my code so far:
public static void main(String[] args) {
Scanner S = new Scanner(System.in);
String Number = S.next();
int counterEnd = Number.length();
int sum = 0 ;
for ( int i = 0 ; i < counterEnd ; i++) {
sum += sum + (Number.charAt(i));
}
System.out.println(sum);
}
Unfortunately, this code prints the sum of ASCII not the digits.
You can subtract the '0' character (i.e. '1' - '0' is 49 - 48 = 1):
sum += Number.charAt(i) - '0';
You could, has #August suggested, substract the character '0' to obtain the numeric value of the character (I find this approach kind of hackish). Or you can use Character.getNumericValue to achieve this:
sum += Character.getNumericValue(Number.charAt(i)); //note it's sum += theDigit; not sum += sum + theDigit
You might also want to look at the enhanced for loop, as you basically don't need the index here:
for(char c : Number.toCharArray()) {
sum += Character.getNumericValue(c);
}
As of Java 8 you could also do it like this:
int sum = Number.chars().map(Character::getNumericValue).sum();
It basically gets a Stream of the characters in the String, map each character to its corresponding numeric value and sum them.
sum+= Integer.parseInt(String.valueOf(Number.charAt(i)));
You can do it like this:
public static void main(String[] args) {
Scanner S = new Scanner(System.in);
String n = S.next();
int sum = 0;
for (int i = 0; i < n.length(); i++) {
sum += Integer.parseInt(n.substring(i, i+1));
}
System.out.println(sum);
}
Note: Replacing the body of the for loop with:
int offset = (n.substring(i, i+1).equals("-")) ? 1 : 0;
sum += Integer.parseInt(n.substring(i, i+1+offset));
i+=offset;
Will allow the program to take negative numbers. Ex: Inputting
-24
Would return a positive 2.

Bitwise operations - get the next char in ASCII table

How can I write a program that will use bitwise operation to take the next value in the ASCII table?
Input: char from ASCII table
Output: the next char from the ASCII table.
For example, if I get 'a' as input, the program should return 'b'.
If I get '7' as input, the program should return '8'. and so on...
Just add 1 (character can be treated as being int16):
char value = 'a';
char next = (char) (value + 1); // <- next == 'b'
Just Increment by 1.
Input = 'a';
Output = ++Input;
Very simple. Just cast your char as an int.
char character = 'a';
int ascii = (int) character;
and then you need to add 1 in ascii
++ascii;
and convert it back...
char c=(char)ascii ;
System.out.println(c);
Here's a method that will add 1 to its argument using only bit-wise functions.
public void test() {
String s = "Hello";
StringBuilder t = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
t.append((char) inc(s.charAt(i)));
}
System.out.println(s);
System.out.println(t.toString());
}
private int inc(int x) {
// Check each bit
for (int i = 0; i < Integer.SIZE; i++) {
// Examine that bit
int bit = 1 << i;
// If it is zero
if ((x & bit) == 0) {
// Set it to 1
x |= bit;
// And stop the loop - we have added one.
break;
} else {
// Clear it.
x &= ~bit;
}
}
return x;
}
prints
Hello
Ifmmp

algorithm to create a char array from permutations list in java

I'm sorry for the slightly confusing title, I'm unsure of how to phrase it.
I need to create a char array allowing for every possible permutation of a character set.
If I were to give you:
char[] charSet = {"a", "b", "c"};
BigInteger value = n; //where n is a number >= 0
char[] charArray = createCharArray(value, charSet);
How can I create charArray from value and charSet such that if I ran:
createCharArray(new BigInteger("6"), {"a", "b", "c"});
it would return {"a", "c"}
because
a=1
b=2
c=3
aa=4
ab=5
ac=6
Here's what I have so far:
private char[] createCharArray(BigInteger value, char[] charSet){
List<Character> charArray = new ArrayList<Character>();
if (value.compareTo(this.max) == 0)
System.out.println("");
BigInteger csSize = new BigInteger(String.valueOf(charSet.length));
if(this.powers.isEmpty())
this.powers.add(0, csSize.pow(0));
if(this.sumPowers.isEmpty())
this.sumPowers.add(0, csSize.pow(0));
BigInteger curPow;
int i = 1;
while((curPow = csSize.pow(i)).compareTo(value) <= -1){
if(this.powers.size() <= i)
this.powers.add(i, curPow);
if(this.sumPowers.size() <= i)
this.sumPowers.add(i, this.sumPowers.get(i-1).add(curPow));
i += 1;
}
i -= 1;
while (i >= 0 && value.compareTo(BigInteger.ZERO) >= 0){
if (i <= 1){
int charNum = value.divide(this.sumPowers.get(0)).intValue() - 1;
charArray.add(charSet[charNum]);
}
else{
int charNum = value.divide(this.sumPowers.get(i-1).subtract(BigInteger.ONE)).intValue() - 1;
charArray.add(charSet[charNum]);
}
value = value.subtract(this.powers.get(i));
i -= 1;
}
char[] returnArray = new char[charArray.size()];
int j = 0;
while(j<charArray.size()){
returnArray[j] = charArray.get(j);
j += 1;
}
return returnArray;
}
It certainly could use some help, as a value of 0 fails, values of 1 and 2 succeed, 3-8 fail, 9, 10 succeed, etc.
EDIT: To be clear, the value parameter must be able to be ANY number n > 0. This is why I've chosen BigInteger
Make a class that has two fields:
private char letter;
private int value;
public <classname>(char letter){
this.letter = letter;
value = 0;
}
//Setters and getters
Then in your main when initializing an array (via for loop) set the value to i + 1 (getting rid of 0)
for(int i = 0; i < <yourarray>.length; i ++){
//Assuming you initialized your objects before
<yourarray>[i].<setterforvalue>(i + 1);
}
And then to calculate them together:
for(int i = 0; i < <yourarray>.length; i ++){
for(int j = 0; j < <yourarray>.length; j ++){
if(<yourarray>[i] + <yourarray>[j] == <needednumber>){
//Do what you need to do with the value
}
}
}
Okay after much thinking and eventually breaking it down to using numbers 0-9 instead of characters. Here's the breakdown: Think about how regular base 10 numerals are created.
The number 194 is made up of a 4 in the ones column, a 9 in the tens, and a 1 in the hundreds. The difference between ones, tens, and hundreds is multiplication/division by 10, which is the base.
So I figured that I could mod the 194 by the base (10) to get 4, the ones. then divide by 10 to remove the ones column. mod again to get 9, then divide by 10, mod again to get 1, divide by 10. once the division creates a number that is exactly 0, we are done. This is because we cannot make a number 000194.
For my function, My base is the length of the character set, and the value is like 194 in the example above.
private static void createCharArray(BigInteger value, char[] charSet){
List<Character> charArray = new ArrayList<Character>();
BigInteger csSize = BigInteger.valueOf(charSet.length);
if (value.compareTo(BigInteger.ZERO) == 0)
charArray.add(0, charSet [0]);
else{
BigInteger modded = value.mod(csSize);
BigInteger digit = value.divide(csSize);
while (modded.compareTo(BigInteger.ZERO) != 0 || digit.compareTo(BigInteger.ZERO) != 0){
if(modded.compareTo(BigInteger.ZERO) == 0){
charArray.add(0, charSet[csSize.subtract(BigInteger.ONE).intValue()]);
value = value.subtract(BigInteger.ONE);
}
else
charArray.add(0, charSet[modded.subtract(BigInteger.ONE).intValue()]);
value = value.divide(csSize);
modded = value.mod(csSize);
digit = value.divide(csSize);
}
}
for(char c : charArray)
System.out.print(c);
System.out.println();
}
public static void main(String[] args) {
long start = System.nanoTime();
String characters = "";
characters += "0123456789";
characters += "abcdefghijklmnopqrstuvwxyz";
characters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
characters += " !\"#$%&'()*+,-./:;<=>?#[\\]^_`{|}~";
char[] cs = characters.toCharArray();
Arrays.sort(cs);
createCharArray(new BigInteger("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"), cs);
long total = System.nanoTime() - start;
System.out.println("Completed in: " + total + " billionths of a second");
System.out.println("Completed in: " + total/1000000 + " thousandth(s) of a second");
}
If you run this, note that that BigInteger 4 lines from the bottom is 100 characters long. On my machine, it takes only 1/1000 th of a second (1 Millisecond).

Categories