4

I want to decrement lowercase letters to lowercase letters only. I do this by taking the ASCII value of the character and decrement it. But for example if I decrement a by 2, the answer should be y. Not a symbol or a uppercase letter.

int charValue = temps.charAt(i);
String increment = String.valueOf( (char) (charValue - (m) ));  
if((charValue - m) < 65){
    int diff = 65 - (charValue - m);
    increment = String.valueOf((char) (91 - diff));
}else if((charValue - m) < 97 && (charValue - m) >= 91){
    int diff = 97 - (charValue - m);
    increment = String.valueOf((char) (123 - diff));    
}
System.out.print(increment);

This is the code I have so far. The problem with this is if I decrement a by 8, it shows an upper case letter. EX:- if i input 'a' and m value as 8, the expected output should be 's'. But im getting 'Y'

manuka_m
  • 331
  • 2
  • 12

5 Answers5

1

Here charToBeChanged is the lowercase character that you want to shift. And decrementValue is the value by how much you want to shift. In the main post you said:

if i input 'a' and m value as 8, the expected output should be 's'

So, here charToBeChanged is a and decrementValue is 8.

System.out.println((char) ((charToBeChanged - 'a' + 26 - decrementValue) % 26 + 'a'));
denvercoder9
  • 2,979
  • 3
  • 28
  • 41
1

For a moment forget about the ASCII code table (or any other) and suppose that the letters are numbered sequentially from 1 (for a) to 26 (for z). The problem is now a simple matter of arithmetic modulo 26. In pseudocode, decrementing a by 2 translates into something like

Mod[(1-2),26]

which is 25, the codepoint for y in the sequential code outlined above.

My Java is laughable so I'll leave it to OP to take care of the translation between ASCII code values and sequential code values, and the implementation of a function to perform the operation.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
  • For an implementation of this, see @RafiduzzamanSonnet's answer. – High Performance Mark Nov 26 '16 at 10:12
  • @Mark thank you for your explanation. I couldn't have explained it more clearly :) – denvercoder9 Nov 26 '16 at 10:13
  • The ASCII code table is not well suited for the problem. The Java code shall define its own set of considered 'lowercase letters' and of their ordering. An array would do. And then calculate the position of the wanted char, of course using the modulo algorithm. – Michal Nov 26 '16 at 10:19
1

It pretty much depends on your definition of 'lowercase letter'. Is ö lowercase letter? For me, it is. Or č? I have it in my name, so definitely I consider it lowercase letter.

Therefore the program needs to define its own sequence of considered lowercase letters. Note that for the example I only included the characters a to g and x to z, but anything (including \u010D for č or \u00f6 for ö) could be included in the list.

public class DecrementChars {

List<Character> validLowercaseChars 
    = Arrays.asList('a', 'b', 'c', 'd', 'e', 'f', 'g', 'x','y', 'z');

boolean isLowercaseletter(char letter) {
    return validLowercaseChars.contains(letter);
}

char decrement(char input, int decrement) {
    if(!isLowercaseletter(input)) {
        throw new IllegalArgumentException();
    }
    int inputIndex = validLowercaseChars.indexOf(input);
    int size = validLowercaseChars.size();
    int outputIndex = (size + inputIndex - decrement) % size;
    return validLowercaseChars.get(outputIndex);
}

@Test(expected=IllegalArgumentException.class)
public void thatDecrementOfInvalidInputThrows() {
    decrement('9', 1);
}


@Test
public void thatDecrementOfbByOneGetsa() {
    Assert.assertEquals('a', decrement('b', 1));
}

@Test
public void thatDecrementOfaByTwoGetsy() {
    Assert.assertEquals('y', decrement('a', 2));
}
}
Michal
  • 2,353
  • 1
  • 15
  • 18
  • Good points. These academic exercises that use arithmetic on UTF-16 code units promote narrow thinking. A defined "alphabet" is a more general solution. – Tom Blodget Nov 26 '16 at 15:39
0

You could use the equals() and to...Case methods to check what the input was and then convert the output to the same case.

if(charValue.equals("[a-z; A-z]")){

    if(charValue.equals(increment)){
        System.out.println(increment);
    }
    if(!charValue.equals(increment)){
        System.out.println(increment.toUpperCase());
    }
    if(!charValue.equals(increment)){
        System.out.println(increment.toLowerCase());
    }
}else{
    System.out.println("Not a letter");
}

Note that I haven't tested this and I am a bit rusty with Regex.

0

Try with this:

int charValue = 'a';
int m = 8;
String increment = null;
//if a-z
if(charValue>96 && charValue<123){
    int difference = charValue - m;
    if(difference < 97)
        difference+=26;
    increment = String.valueOf((char) difference); 
}
System.out.println(increment);
user6904265
  • 1,938
  • 1
  • 16
  • 21