Caesar Cipher Uppercase and Lowercase Wrap Around - java

I am having a problem regarding wrapping around the alphabet with my Caesar Cipher Program.
The program works fine with all lowercase letters. Wraps around perfectly and is able to apply positive and negative shifts. When i try to input an uppercase letter, the uppercase letter does not wrap around.
Here is my code:
public static StringBuilder encode(String str, int numShift)
{
numShift = numShift % 26;
//assign each character of the string to a position in the character array
char[] strChars = str.toCharArray();
for (int i = 0; i < strChars.length; i++)
{
//ignore and continue if the character is not within the alphabet
if((strChars[i] < 'a' || strChars[i] > 'z') && (strChars[i]<'A' || strChars[i] > 'Z'))
continue;
//apply the shift to each character
strChars[i] += numShift;
//wrap around if the shift is beyond Z
**if(strChars[i] > 'z')
{
strChars[i] -= 'z';
strChars[i] += ('a' - 1);
}**
}
StringBuilder encodedStr = new StringBuilder();
encodedStr.append(strChars);
return encodedStr;
}
public static void init(){
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the string that you would like to encode:");
String str = scan.nextLine();
System.out.println("Please enter the number of letters you would like to shift:");
int strShift = scan.nextInt();
scan.close();
StringBuilder result = encode(str, strShift);
System.out.println(result);
}
public static void main(String[] args)
{
init();
}
}
Hints would be much appreciated! Of course, I am not asking anyone to do my work for me but some help would be appreciated! Thank you! :)
Edit: here's the if statement that does the wrap around for lowercase letters only:
if(strChars[i] > 'z')
{
strChars[i] -= 'z';
strChars[i] += ('a' - 1);
}

Let's implement a wrap-around function for a single character. This will be used by the other method. When you separate your tasks and sub-tasks wisely, you will observe that your problem becomes easier to solve. Here I have based my solution on the fact that char variables are represented as numbers, we know the number of letters and we can use that number as a modulo class, to make sure that algebra is aiding us.
private static char wrapChar(char input, int amount) {
//assume for now that we have an upper-case letter
char start = 'A';
//if the assumption is mistaken...
if (('a' <= input) && (input <= 'z')) {
//then, if it is lower-case, then use lower-case
start = 'a';
} else if (!(('A' <= input) && (input <= 'Z'))) {
//target is not letter
return input;
}
//Calculate total offset compared to the first letter of the alphabet
//be it lower or upper
int offset = ((input - start) + amount) % 26;
//If offset happens to be negative, then shift a modulo period of 26
//To get the correct positive offset
if (offset < 0) {
offset += 26;
}
//Add the final offset to start and convert it to char
return ((char)(start + offset));
}
Now, instead of
//apply the shift to each character
strChars[i] += numShift;
//wrap around if the shift is beyond Z
**if(strChars[i] > 'z')
{
strChars[i] -= 'z';
strChars[i] += ('a' - 1);
}**
You need just:
strChars[i] = wrapChar(strChars[i], numShift);

Related

Pangram, Perfect Pangram, Neither

I am supposed to read from a text file and figure if a sentence is a PANGRAM (uses all characters in the alphabet), a PERFECT pangram (uses every character in the alphabet once), or NEITHER.
The guide says that I am supposed to initialize x with '0', then go through each letter in the sentence, and if the letter matches with a character in the alphabet, I increment x by 1; then at the end, if the value x for each sentence has a '0', it's NEITHER, if it's all '1', it's PERFECT ,if there is no '0', it's PANGRAM.
Scanner pangram = new Scanner (
PerfectPangram.class.getResourceAsStream ( "pangram.txt" ));
while (pangram.hasNext())
{
String text = pangram.nextLine().toUpperCase();
char [] alphabet = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
char txt[] = text.toCharArray();
int zero[] = new int [text.length()];
for(int i = 0; i < zero.length; i++)
{
zero[i] = 0;
for (int a = 0; a < text.length(); a++)
{
zero[i] = txt[a];
for (int array = 0; array < alphabet.length; array++)
{
if (alphabet[array] == text.charAt(i))
{
zero[i]++;
}
}
}
if (zero[i] == 1)
{
}
}
}
Output should be like this:
PANGRAM: THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
NEITHER: ALL YOUR BASE ARE BELONG TO US; SOMEONE SET US UP THE BOMB.
PERFECT: NEW JOB: FIX MR GLUCK'S HAZY TV, PDQ.
You got it all wrong I guess. First of all your counter array (zero) is initialized with wrong length. Its fixed length should be 'Z'(90) - 'A'(65) + 1 = 26 as is the count of the letters in the latin alphabet. Then you should increment the index of that counter array representing the characters position in the alphabet (c - 'A'), but only if the character is part of the alphabet (c >= 'A' && c <= 'Z'). Once you do this for each of the symbols in a sentence you should now iterate throughout the members of zero and find if any of them is lower then 1: not a pangram; or any is higher then 1: not a perfect pangram;
I will post some crappy code of mine just to demonstrate it but I will not advise you to go with it as your final homework ;) I hope you get the basics and you are able to do it on your own now.
public static void main(String[] args) {
String test = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\nALL YOUR BASE ARE BELONG TO US; SOMEONE SET US UP THE BOMB.\nNEW JOB: FIX MR GLUCK'S HAZY TV, PDQ.";
Scanner pangram = new Scanner (test);
int zero[] = new int ['Z' - 'A' + 1];
while (pangram.hasNextLine())
{
Arrays.fill(zero, 0);
String text = pangram.nextLine().toUpperCase();
for (char c : text.toCharArray())
{
if (c >= 'A' && c <= 'Z') {
zero[c - 'A']++;
}
}
boolean isPangram = true;
boolean isPerfectPangram = true;
for (int i : zero) {
if (i < 0) {
isPangram = false;
break;
}
if (i > 1) {
isPerfectPangram = false;
}
}
System.out.println(isPerfectPangram ? "Prefect Pangram" : isPangram ? "Pangram" : "Neither");
}
}

Print 10 characters per line

hello i have some trouble doing my coding on this question;
Write a method that prints characters using the following header:
public static void printChars(char ch1, char ch2, int numberPerLine)
This method prints the characters between ch1 and ch2 with the specified numbers per line. Write test program that prints ten characters per line from ā€˜lā€™ and ā€˜Zā€™.
can somebody show me the coding sample to solve my problem? thanks
Here is some code that seems to wok on my end.
public static String alphabet = "abcdefghijklmnopqrstuvwxyz";
public static void printChars(char ch1, char ch2, int numberPerLine){
int currentNumber = numberPerLine;
int beginningIndex = alphabet.indexOf((ch1 + "").toLowerCase()) + 1;
int endingIndex = alphabet.indexOf((ch2 + "").toLowerCase());
for(int i = beginningIndex; i < endingIndex; i++){
System.out.print(alphabet.charAt(i));
if(currentNumber > 1){
currentNumber --;
}else{
System.out.println("");
currentNumber = numberPerLine;
}
}
}
public static void main(String[] args) {
printChars('c', 'z', 2);
}
Characters are encoded in ASCII. Each character has a unique decimal number representation. We can access these characters by their numbers, rather than the actual character.
For example, the character 'A' has an ASCII code of 65. We don't really need to know the integer codes to use their respective character representations though. We can just typecast the integers into chars.
We can also use characters in simple arithmetic. Since 'A' has ASCII code 65, then it makes sense for 65 + 1 = 66 to represent the character 'B'. Indeed it does.
public static void printChars(char ch1, char ch2, int numberPerLine) {
if(ch1 <= 'Z' && ch2 >= 'a')
return;
int count = 0; //count number of characters on a line.
char nextChar = ch1; //initialize our next character
while(nextChar <= ch2) { //test case
System.out.print(nextChar);
count++; //once we print a character, increment our count
if(count == numberPerLine) { //check if we reach our desired amount of characters
System.out.println();
count = 0; //once we print a new line, restart the count
}
nextChar = (char) (nextChar + 1); //get next character
}
}

convert uppercase letter to lowercase letter

Write a program called CaseConverter with a main method that converts a single uppercase letter to a lowercase letter. You have to declare a char variable to hold the lowercase letter.
public class CaseConverter {
public static void main (String [] args){
int offset = 'a' - 'A';
char temp = 'X'; // or any other uppercase alphabet
System.out.println("uppercase: " + temp);
// insert code here
System.out.println("lowercase: " + temp);
}
}
This can be used for case conersion
public char toLowercase(char c) {
int offset = 'a' - 'A';
if (c >= 'A' && c <= 'Z') {
return (char) (c + offset);
}
return c;
}
public char toUppercase(char c) {
int offset = 'a' - 'A';
if (c >= 'a' && c <= 'z') {
return (char) (c - offset);
}
return c;
}
Code of Uppercase alphabet 'A' is 67 and Code of Lowercase alphabet is 'a' is 97. So, the offset is 32. So, to convert any Uppercase alphabet to Lowercase alphabet you have to add 32 i.e. offset to it.
Edit:
public class CaseConverter{
public static void main(String args[]){
int offset = 'a' - 'A';
int temp = 'X'; // or any other uppercase alphabet
System.out.println("uppercase: " + (char)temp);
temp = temp + offset;
System.out.println("lowercase: " + (char)temp);
}
}
Edit: Since your temp data type is char, then this would work
public class CaseConverter{
public static void main(String args[]){
int offset = 'a' - 'A';
char temp = 'X'; // or any other uppercase alphabet
System.out.println("uppercase: " + temp);
temp = (char)((int)temp + offset);
System.out.println("lowercase: " + temp);
}
}
Your question can be easily answered if you look at the ASCII table. When you write a, the int variable will hold the ASCII value of the character a.
Look for example at the ASCII value of the letter P, it is 80. How do you get the ASCII value of p which is 112? I won't give you full solution but this should help you to begin*.
* 'a' - 'A' is 32
import java.io.*;
public CaseConverter{
public static void main(String args[]){
char temp = 'X'; // or any other uppercase alphabet
System.out.println("uppercase: " + temp);
System.out.println(temp.toUpperCase() );
}
}
offset:
lower case letters in ASCII code follows uppercase by 32 as I can remember so if you have an uppercase letter 'X' the you sub its int value by the difference between upper and lower case letters you get the lower.
char ch = 'x'; //x is lower case letter
int diff = (int)'a' - (int)'A'; //Difference between lower and upper
ch = (int)ch - diff; //now you get the lower case
use java Character class static method which convert upper case character to lowercase character :> Character.toLowerCase(c);

In a String, how can I separate & store the characters and integers?

My task is to create a Bubble Breaker type game, I broke my task into several smaller tasks, and I hit a wall.
I created a 2D Array Grid which will, whenever the program starts, be randomized with different coloured Bubbles. Each Line and Each Column is numbered, Lines range in Numbers, Columns range in Letters.
My goal is to have the user input choosing a String (Note I can only use String, as I'm programming in a pre-designed console), for example B10, B9 or 10B.
I'm able to check if the characters are numbers or letters via
command.charAt(i) >= '0' && command.charAt(i) <= '9' // i is a counter in a for
The above allows me to find if it's a digit or a number, the problem is that to select the Exact grid position, I need to, and can't:
Separate the String into Integrers AND character
Join the two Integrers
(note they can be B9, B10 or 10B)
This is an example of the duality B10 and 10B
You only need two lines:
int num = Integer.parseInt(str.replaceAll("\\D", ""));
String letter = str.replaceAll("\\d", "");
The order of letters and digits in the string is irrelevant - this will work either way.
Edited to cater for requirements as per comments below
To process a series of letter-digit pairs in larger string, parsing the letter to an int x (where A=1, B=2, etc) and assigning the digit(s) to int y, you can split the string up on whitespace and use code similar to above:
for (String pair : command.toUpperCase().split("\\s+")) {
int x = pair.replaceAll("\\d", "").charAt(0) - '#';
int y = Integer.parseInt(pair.replaceAll("\\D", ""));
}
Using split() means not having to sully yourself with the tedium of using a loop variable.
The reason for subtracting '#' is that is the character one before 'A', so subtracting that will convert A to 1, B to 2, etc.
Here's some test code:
String command = "A5 B10 11C 20D";
for (String pair : command.split("\\s+")) {
int x = pair.replaceAll("\\d", "").charAt(0) - '#';
int y = Integer.parseInt(pair.replaceAll("\\D", ""));
System.out.format("X = %d, Y = %d\n", x, y);
}
Output:
X = 1, Y = 5
X = 2, Y = 10
X = 3, Y = 11
X = 4, Y = 20
To answer the question, just use an if loop. (If the first char is a digit, parse all but the last as an integer, otherwise parse all starting from the second as an integer.) (use String.substring(start, end) to separate it if that's all you want to know)
Also, you can use Character.isDigit() instead of
command.charAt(i) >= '0' && command.charAt(i) <= '9'
(just for code legibility)
Loop through the String
Check if character is a letter
Save that letter to a variable (char letter)
Replace the original String such that the letter is replace with nothing (String numString)
Now you have them separated: letter and numString
This will work with B10 or 10B. And set that has only one letter and the rest numbers
See code
String code = "10B";
char letter;
for (char c : code.toCharArray()){
if (Character.isLetter(c)){ // if the character is a letter, save if the "letter"
letter = c;
break;
}
}
String numString = code.replace(letter, ""); // replace the original string, letter for ""
// Parse if you need to
int num = Integer.parseInt(numString);
// You have the letter by itself, and the number by itself
System.out.println("Letter: " + letter + ", Number: " + num);
Edit: Try the code below. I had a couple errors in one above
String code = "10B";
char letter = ' '; // <-- initialize
for (char c : code.toCharArray()) {
if (Character.isLetter(c)) { // if the character is a letter, save if the "letter"
letter = c;
break;
}
}
String numString = code.replace(String.valueOf(letter), ""); <-- String valueOf
int num = Integer.parseInt(numString);
System.out.println("Letter: " + letter + ", Number: " + num);
Result : Letter: B, Number: 10
public class StringSpliter {
public static void main(String[] args) {
ArrayList<Character> chars = new ArrayList<>();
ArrayList<Integer> ints = new ArrayList<>();
String str = "T23his i43s a Stin4g Whi12ch C1on3431tains Ch 5ara32cter2343s and Alphabets";
char[] mychars = str.toCharArray();
for (int i = 0; i < mychars.length; i++) {
if (mychars[i] >= 33 && !(mychars[i] <= '9' && mychars[i] >= '0')) {
chars.add(mychars[i]);
} else if (mychars[i] >= '0' && mychars[i] <= '9') {
ints.add((Integer.parseInt(""+mychars[i])));
}
}
for (int i = 0; i < chars.size() + ints.size(); i++) {
if (i < chars.size()) {
System.out.println(chars.get(i));
} else {
System.out.println(ints.get(i - chars.size()));
}
}
}
}
Try the above code

Convert a letter to the corresponding letter on the opposite counting direction in the alphabet

I am self-studying Java and I am very at the beginning learning the basics. With below code I am trying to convert a letter to the corresponding letter on the opposite counting direction in the alphabet(i.e A to Z or Z to A etc.). It works for a single letter but not for a series of letters. How can I make it work with more than one letter? If you can use the simplest way it would be good as I am quite new in Java. I don't(know how to) export any built in classes etc.
Thank you.
class Turner{
int find(int fin, int mi,int ma,char ch[]){
int mid = (ma+mi)/2;
int x;
if(ch[mid]==fin)
return mid;
else if(fin<ch[mid])
return(find(fin, mi,mid-1,ch));
else
return x = find(fin,(mid+1),ma,ch);
}
}
class Turn {
public static void main(String args[]) throws java.io.IOException
{
Turner try1 = new Turner();
char arra[] = new char[26];
char arrb[] = new char[26];
int min = 0;
int max = arra.length;
char a = 'A';
char b = 'Z';
int i;
char letter;
for(i=0;i<26;i++)
{
arra[i]=a;
a++;
arrb[i]=b;
b--;
}
System.out.println("Enter a letter: ");
letter = (char)System.in.read();
System.out.print(arrb[try1.find(letter,min,max,arra)]);
}
}
Have you considered just doing some math?
letter = Character.toUpperCase((char)System.in.read());
System.out.print((char)('Z' - (letter - 'A'));
And it works for only one letter because you are not repeating the conversion procedure. The program reads one char, prints its opposite and then terminates.
All you have to do is to put the read and print code inside some sort of loop, so every time it runs it will promptly wait for the next letter.
while (true) {
letter = Character.toUpperCase((char)System.in.read());
if ((letter > 'Z') || (letter < 'A'))
break; // user inputted an invalid symbol, terminating the program
System.out.print((char)('Z' - (letter - 'A')));
}
If your function (they are called methods in java) works, good. Just put it in a while loop or otherwise call it when you need it.
boolean done = false;
while(!done){
System.out.println("Enter a letter (space to quit): ");
letter = (char)System.in.read();
if(letter == ' ') done = true;
else System.out.print(arrb[try1.find(letter,min,max,arra)]);
}
And Havenard is right, this can be written considerably more simply, with arithmetic on chars. For instance ch -'a' == 1 evaluates to true when ch is 'b'.
One other note: find and Turner aren't very descriptive names for what these things do. Before long it could get messy without simple and to the point naming.
A character has an equivalent numerical value. For "basic characters", this mapping is called ASCII table: http://www.asciitable.com/
Now, in java, you can convert a char into an int by casting. Example: int nValue=(int) 'a'.
Since there is a numerical value associated to 'a' and another one associated with 'z', you could use some simple math to solve your problem.
See:
int aNumericalValue = (int) 'a';
int zNumericalValue = (int) 'z';
char characterToConvert = ...;
int characterToConvertAsNumericalValue = (int) characterToConvert;
int resultCharacterAsNumericalValue = zNumericalValue - (characterToConvertAsNumericalValue - aNumericalValue);
char resultCharacter = (char) resultCharacterAsNumericalValue;
Or, you could write all of this as a single line of code:
char resultCharacter = (char) ((int) 'z' - ((int) characterToConvert - (int) 'a'));
And finally, if you are willing to hardcode some ASCII values:
char resultCharacter = (char) (122 - ((int) characterToConvert - 97));
Note that this is for lowercase letters. For caps, use 'A' (ascii 65), 'Z' (ascii 90).

Categories

Resources