How to shift characters in an array left in Java? [duplicate] - java

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');

Related

(char) (i + 'a') JAVA: what's happening here? [duplicate]

This question already has answers here:
Adding and subtracting chars, why does this work? [duplicate]
(4 answers)
Parentheses around data type?
(5 answers)
What does a 'int' in parenthesis mean when giving a value to an int?
(7 answers)
What is the purpose and meaning of (char)i or (int)i in java?
(3 answers)
Closed 2 years ago.
I encountered a similar piece of code:
public class print {
public static void main(String[] args) {
for (int i = 0; i < 6; i++) {
System.out.print((char) (i + 'a'));
}
}
}
If I run it, I get "abcdef".
My question regards this expression: (char) (i + 'a').
I kind of intuitively get what's going on, but I want a rigorous step-by-step explanation of how the computer translates it. As indicated in some answers, the char is simply a number displayed as a character. Fine, but what does this syntax with parentheses actually do? Is it a conversion? Can I use it for other types as well?
The ASCII value of a is 97.
When i = 0, i + 'a' = 0 + 97 => When cast into char, it will be a
When i = 1, i + 'a' = 1 + 97 => When cast into char, it will be b
When i = 2, i + 'a' = 2 + 97 => When cast into char, it will be c
...and so on
Java char is a 16-bit integral type. 'a' is the same as 97, which you can see with System.out.println((int) 'a'); - it follows that 98 is 'b' and so on across the entire ASCII table.
You can use char as an integer value and vise versa
Below code may help:
char aChar = 'a'; // a char
int aCharAscii = aChar; // 97
char bChar = 'a' + 1; // b char
int bCharAscii = aChar + 1; // 98

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?

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.

Specific digit detector issue

I have written a small piece of code where you enter a 3 digit number via the command line, and then it detects how many 5's are in the code.
public class fivedet {
public static void main (String[] args) {
String input = args[0];
int[] a = {0,0,0};
int x = 0;
int y = 0;
int z = 0;
for(int i = 0; i<input.length();i++) {
a[i] = input.charAt(i) - 48;
}
if(a[0]==5) {
x=5;
}
if(a[1]==5) {
y=5;
}
if(a[2]==5) {
z=5;
}
System.out.println("5 digits here:" + x + y + z);
}
}
My main question is why I require the -48 term after the input.charAt(i) method in order for each value in a[] to be equal to the actual number I input.
For example I enter
java fivedet 505
and without the -48 the array a[]={53,48,53} instead of a[]={5,0,5} and I unfortunately am not experienced enough with coding java (began learning 3 months ago) to understand why this is happening.
I also do want to develop it to be able to detect different digits and for different lengths of input numbers.
I would appreciate any insight as to why this happens.
Subtracting 48 is a quick but slightly confusing way of converting from a character to an integer. It so happens that the character code for each digit is 48 away from its numeric value.
See this table of ASCII values. (Java uses unicode, not ascii - strings are UTF-16 internally - but the values are valid in this specific case). So the character '0' has the value 48; the character '9' has the value 57.
Another way of doing this would be to take 1-character substrings of input, then call Integer.parseInt() on that string, converting "1" to 1, "2" to 2, etc.
You don’t need to convert to int in order to detect character 5. Just count them as chars.
for (char i : args[0].toCharArray()) {
System.out.print(i == '5' ? i : '0');
}
Also this question has good answers to count occurrences of a char in string

How would I loop around the alphabet? [closed]

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.

Conversion from ASCII values to Char

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);
}
}
}

Categories

Resources