Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
This is a bit more trickier than I thought..
I am creating a java program that is encrypted:
the input is 'a' and shift the letter by 5 which goes to 'f'
which is simple in ASCII but when I get to the letter z i want the program to loop back around to 'a' and start over if that makes sense just i have no idea where to start!
The key is modulus division:
char c;
c = (char)((c - 'a' + 5) % 26 + 'a');
c - 'a' gives you the number of the letter 0-25, which is then shifted up by 5 and the remainder after dividing by 26 is then added to 'a' to give up back the character for the letter.
Use mod % operator.
char translated = (char) ('a' + (charOriginal -'a' + 5) % ('z' - 'a' + 1));
Here it is :
public char encrypt(char c)
{
return Character.isLowerCase(c) ? (char)((c - 'a' + 5) % 26 + 'a') : (char)((c - 'A' + 5) % 26 + 'A');
}
I've edited my post, now it checks lower/upper case.
If you don't and minus 'a' for uppercase, it won't work. For example, encrypt('Y') would have returned '^' instead of 'D'.
You could try something like this:
/**
* Shifts a letter 5 letters, if the char is a letter,
* other wise (if a number or symbol) just returns the char.
* Jumps back to 'a' or 'A' when it goes past 'z' or 'Z'.
*/
public char shift5(char letter) {
char letterToReturn = letter;
if(letterToReturn >= 'a' && letter <= 'z') {
// letter is lowercase
letterToReturn = shiftLetter(letterToReturn , 5);
} else if(letter >= 'A' && letter <= 'Z') {
// letter is uppercase
letterToReturn = shiftLetter(letterToReturn , 5);
}
return letterToReturn;
}
/**
* Shifts a letter to the next letter the specified amount of times.
* Jumps back to 'a' or 'A' when it goes past 'z' or 'Z'.
*/
public char shiftLetter(char letter, int amountToShift) {
char letterToReturn = letter;
for (int i = 1; i <= amountToShift; i++) {
letterToReturn ++;
if(letterToReturn == (char)((int)'z' + 1) {
// letter has gone past 'z', so change to 'a'
letterToReturn = 'a'
} else if(letterToReturn == (char)((int)'Z' + 1) {
// letter has gone past 'Z', so change to 'A'
letterToReturn = 'A'
}
}
return letterToReturn;
}
This code handles lowercase, uppercase, and characters that aren't letters.
Related
I was exploring this code which gives a count of vowels and consonants, but didn't understand this else if (ch >= 'a' && ch <= 'z') line of code. Please tell me what's the logic behind it.
import java.util.Scanner;
public class Vowels {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
System.out.println("Enter string");
String str = sc.nextLine();
int vowl = 0;
int conso = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
vowl++;
} else if (ch >= 'a' && ch <= 'z') {
conso++;
}
}
System.out.println(vowl);
System.out.println(conso);
}
}
A benefit of chars is that you can operate with them like if they were integers.
For example, you can do you this as well 'a' + 3 = 'd'
Meaning that 'a' < 'd' = true.
notice the if statement catches all vowels
whats ever is not a vowel will either be a capital letter, a number, a special character or consonants
else if (ch >= 'a' && ch <= 'z')
this checks if its not a vowel does it atleast fall in the range of small letter 'a'-'z' and is not a special charecter or a number.( we knonw its not a vowel but is it in the ascii range 26=a -51=z)
refer to the ASCII table to understand the range comparison
The comparison of characters the way it is done can create confusion, as you can see from Java: Character comparison.
Basically #TDG is correct by saying that ch is checked to be between 'a' and 'z', and thus the check might be translated as "is ch a lower case character?"
The tricky part is that depending on the language people use the expectation can be different, especially since language specific characters are not taken into account. In German language, 'รถ' would definitely qualify as lower case character but is not in the range of the check. The complexity may get evident by studying the Unicode code charts.
The best check is to use Character.isLowerCase().
char is a character that represented by a number which is the index of the character in the ASCII/unicode table, since the the alphabet characters are arranged in order in the ASCII table, the following code checks if the ch is in the range of the lowercase alphabet characters representation which is 97 to 122 in the table.
using (int) ch you can see the decimal value of the character and can compare it with the index in the ASCII table.
you can see the ASCII table here:https://www.asciitable.com/
This code is the first one I've seen. I am curious as to how it changes all character from a to z into uppercase when the last line of code was only written with (ch[i] - 'a' + 'A').
if (ch[i] >= 'a' && ch[i] <= 'z') {
// Convert into Upper-case
ch[i] = (char)(ch[i] - 'a' + 'A');
}
The line:
ch[i] = (char)(ch[i] - 'a' + 'A');
Sets ch[i] to its associated uppercase due to a constant difference between an uppercase letter and its lowercase form.
For means of communication, the line can be re-written as:
ch[i] = (char)(ch[i] + ('A' - 'a'));
By adding this constant difference the line yields the lowercase letter's uppercase character.
This question already has answers here:
How do I shift array characters to the right in Java?
(2 answers)
Closed 5 years ago.
This is what I have right now:
class encoded{
public static void main(String[] args){
int shift = In.getInt();
String s1 = "bool";
char[] ch=s1.toCharArray();
for(int i=0;i<ch.length;i++){
char c = (char) (((ch[i] - 'a' - shift) % 26) + 'a');
System.out.print(c);
}
}
}
This code works to shift all characters in the string left by however much I want it to shift. The problem arises when, for example, I shift 'abc' 1 left, it returns '`ab'. What I want is for the characters to wrap back around to 'z' instead, so that the shifted 'abc' becomes 'zab' instead. How would I go about doing this? The characters need to always wrap back around to z when they're shifted left of 'a', and need to wrap back around to a when they're shifted right of 'z' (this would be done by changing "'a' - shift" to "'a' + shift".
Thanks so much in advance!
Not doing your homework for you, but giving you some hints:
char c = (char) (((ch[i] - 'a' - shift) % 26) + 'a');
You see, you are doing the shift operation unconditionally. Instead, read about using the if statement. You want to do your program different things, compared on the value of ch[i]. For some cases, just "shift", for others to replace values.
The problem is that the modulo operation can yield negative results.
In Java8 you can use Math.floorMod as an alternative:
class Main{
public static void main(String[] args){
int shift = 1;
String s1 = "abool";
char[] ch=s1.toCharArray();
for(int i=0;i<ch.length;i++){
char c = (char) ((Math.floorMod((ch[i] - 'a' - shift), 26)) + 'a');
System.out.print(c);
}
}
}
An alternative would be to use char c = (char) ( (((ch[i] - 'a' - shift) % 26) + 26) % 26 + 'a');
How do I get the numerical value/position of a character in the alphabet (1-26) in constant time (O(1)) without using any built in method or function and without caring about the case of the character?
If your compiler supports binary literals you can use
int value = 0b00011111 & character;
If it does not, you can use 31 instead of 0b00011111 since they are equivalent.
int value = 31 & character;
or if you want to use hex
int value = 0x1F & character;
or in octal
int value = 037 & character;
You can use any way to represent the value 31.
This works because in ASCII, undercase values are prefixed with 011, and uppercase 010 and then the binary equivalent of 1-26.
By using the bitmask of 00011111 and the AND operand, we covert the 3 most significant bits to zeros. This leaves us with 00001 to 11010, 1 to 26.
Adding to the very good (self) answer of Charles Staal.
Assuming ascii encoding following will work. Updated from the kind comment of Yves Daoust
int Get1BasedIndex(char ch) {
return ( ch | ('a' ^ 'A') ) - 'a' + 1;
}
This will make the character uppercase and change the index.
However a more readable solution (O(1)) is:
int Get1BasedIndex(char ch) {
return ('a' <= ch && ch <= 'z') ? ch - 'a' + 1 : ch - 'A' + 1;
}
One more solution that is constant time but requires some extra memory is:
static int cha[256];
static void init() {
int code = -1;
fill_n (&cha[0], &cha[256], code);
code = 1;
for(char s = 'a', l = 'A'; s <= 'z'; ++s, ++l) {
cha[s] = cha[l] = code++;
}
}
int Get1BasedIndex(char ch) {
return cha[ch];
}
We can get their ASCII values and then subtract from the starting character ASCII(a - 97, A - 65)
char ch = 'a';
if(ch >=65 && ch <= 90)//if capital letter
System.out.println((int)ch - 65);
else if(ch >=97 && ch <= 122)//if small letters
System.out.println((int)ch - 97);
Strictly speaking it is not possible to do it portably in C/C++ because there is no guarantee on the ordering of the characters.
This said, with a contiguous sequence, Char - 'a' and Char - 'A' obviously give you the position of a lowercase or uppercase letter, and you could write
Ord= 'a' <= Char && Char <= 'z' ? Char - 'a' :
('A' <= Char && Char <= 'Z' ? Char - 'A' : -1);
If you want to favor efficiency over safety, exploit the binary representation of ASCII codes and use the branchless
#define ToUpper(Char) (Char | 0x20)
Ord= ToUpper(Char) - 'a';
(the output for non-letter character is considered unspecified).
Contrary to the specs, these snippets return the position in range [0, 25], more natural with zero-based indexing languages.
String source = "WEDGEZ"
char letter = source.charAt(i);
shift=5;
for (int i=0;i<source.length();i++){
if (source.charAt(i) >=65 && source.charAt(i) <=90 )
letterMix =(char)(('D' + (letter - 'D' + shift) % 26));
}
Ok what I'm trying to do is take the string WEDGEZ, and shift each letter by 5, so W becomes B and E becomes J, etc. However I feel like there is some inconsistency with the numbers I'm using.
For the if statement, I'm using ASCII values, and for the
letterMix= statement, I'm using the numbers from 1-26 (I think). Well actually, the question is about that too:
What does
(char)(('D' + (letter - 'D' + shift) % 26)); return anyway? It returns a char right, but converted from an int. I found that statement online somewhere I didn't compose it entirely myself so what exactly does that statement return.
The general problem with this code is that for W it returns '/' and for Z it returns _, which I'm guessing means it's using the ASCII values. I really dont know how to approach this.
Edit: New code
for (int i=0;i<source.length();i++)
{
char letter = source.charAt(i);
letterMix=source.charAt(i);
if (source.charAt(i) >=65 && source.charAt(i) <=90 ){
letterMix=(char)('A' + ( ( (letter - 'A') + input ) % 26));
}
}
Well I'm not sure if this homework, so i'll be stingy with the Code.
You're Writing a Caesar Cipher with a shift of 5.
To address your Z -> _ problem...I'm Assuming you want all the letters to be changed into encoded letters (and not weird Symbols). The problem is ASCII values of A-Z lie between 65 and 90.
When coding Z (for eg), you end up adding 5 to it, which gives u the value 95 (_).
What you need to do is Wrap around the available alphabets. First isolate, the relative position of the character in the alphabets (ie A = 0, B = 1 ...) You Need to subtract 65 (which is ASCII of A. Add your Shift and then apply modulus 26. This will cause your value to wrap around.
eg, it your encoding Z, (ASCII=90), so relative position is 25 (= 90 - 65).
now, 25 + 5 = 30, but you need the value to be within 26. so you take modulus 26
so 30 % 26 is 4 which is E.
So here it is
char letter = message(i);
int relativePosition = letter - 'A'; // 0-25
int encode = (relativePosition + shift) % 26
char encodedChar = encode + 'A' // convert it back to ASCII.
So in one line,
char encodedChar = 'A' + ( ( (letter - 'A') + shift ) % 26)
Note, This will work only for upper case, if your planning to use lower case, you'll need some extra processing.
You can use Character.isUpperCase() to check for upper case.
You can try this code for convert ASCII values to Char
class Ascii {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
char ch=sc.next().charAt(0);
if(ch==' ') {
int in=ch;
System.out.println(in);
}
}
}