In Java how do you randomly select a letter (a-z)? - java

If I want to randomly select a letter between a and z, I assume I have to use the Random class:
Random rand = new Random();
But since this only generates numbers, what do I need to do to apply this to letters?

Random r = new Random();
char c = (char) (r.nextInt(26) + 'a');

Letters, or more exactly, characters, are numbers (from 0 to 255 in extended ascii, 0 to 127 in non-extended). For instance, in ASCII, 'A' (quote means character, as opposed to string) is 65. So 1 + 'A' would give you 66 - 'B'.
So, you can take a random number from 0 to 26, add it to the character 'a', and here you are : random letter.
You could also do it with a string, typing "abcdefghijklmnopqrstuvwxyz" and taking a random position in this chain, but Barker solution is more elegant.

alter version of #Michael Barker
Random r = new Random();
int c = r.nextInt(26) + (byte)'a';
System.out.println((char)c);

char randomLetter = (char) ('a' + Math.random() * ('z'-'a' + 1));

why assume to use Random instead of Math.random? You can even make the code shorter...
public static char genChar(){
return (char)(Math.random()*26 + 'a');
}

import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
...
randomAlphabetic(1).toLowerCase()
this gives you a string with single character

To randomly select a letter from (a- z) I would do the following:
Random rand = new Random();
...
char c = rand.nextInt(26) + 'a';
Since Random.nextInt() generates a value from 0 to 25, you need only add an offset of 'a' to produce the lowercase letters.

use the ascii value of the letters to generate the random number.

Random r = new Random();
char symbel = (char)(r.nextInt(26) + 'a');
if(symbel>='a' && symbel <= 'z') {
System.out.println("Small Letter" + symbel);
} else {
System.out.println("Not a letter" + symbel);
}

Related

Is there a possibility to write a random letter generator as short as in python?

So I want to shorten my code and I asked myself if there is any possibility that a Random Letter generator in Java is as short as in python. In python it's just one a one liner.
The following Code is my Code yet:
int random = (int) Math.random()*25;
String[] letters ={"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"};
String letter = letters[random];
If "short" just means one line, then any of these would do:
char letter = "abcdefghijklmnopqrstuvwxyz".charAt((int) (Math.random() * 26));
char letter = (char) ThreadLocalRandom.current().nextInt('a', 'z'+1);
char letter = (char) ('a' + Math.random() * 26);
Use the ASCII table. 97 = 'a', so just add your random number to that and convert to char.
ASCII Table
public class MyClass {
public static void main(String args[]) {
char z = (char)(97 + Math.random()*26);
System.out.println("z = " + z);
}
}
This is the shortest version to create 100 Characters:
Character[] result = new Random().ints(100,'a','z'+1).mapToObj(ch -> (char)ch).toArray(Character[]::new);

Decrementing lowercase letters to lowercase letters only

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

Decrement only letters

I have to handle some strings, I should put them N positions to left to organize the string.
Here's my code for while:
private String toLeft() {
String word = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Example
byte lpad = 2; // Example
StringBuilder sb = new StringBuilder();
for (int i = 0; i < word.length(); i++) {
sb.append((char) (word.charAt(i) - lpad));
}
return sb.toString();
}
It's working for inputs that don't have to move many times...
So, the problem is that when the number N of positions to move is a little bit large (like 10), it returns me non letters, like in the example below, what can I do to prevent it?
Ex.: ABCDEFGHIJKLMNOPQRSTUVWXYZ if I move each char 10 positions to left it returns 789:;<=>?#ABCDEFGHIJKLMNOP while it must return QRSTUVWXYZABCDEFGHIJKLMNOP.
Some inputs and their expected outputs:
VQREQFGT // 2 positions to left == TOPCODER
ABCDEFGHIJKLMNOPQRSTUVWXYZ // 10 positions to left == QRSTUVWXYZABCDEFGHIJKLMNOP
LIPPSASVPH // 4 positions to left == HELLOWORLD
I think you have misunderstood what your (homework?) requirements are asking you to do. Lets look at your examples:
VQREQFGT // 2 positions to left == TOPCODER
Makes sense. Each character in the output is two characters before the corresponding input. But read on ...
ABCDEFGHIJKLMNOPQRSTUVWXYZ // 10 positions to left == QRSTUVWXYZABCDEFGHIJKLMNOP
Makes no sense (literally). The letter Q is not 10 characters before A in the alphabet. There is no letter in the alphabet that is before A in the alphabet.
OK so how do you get from A to Q in 10 steps?
Answer ... you wrap around!
A, Z, Y, X, W, V, U, T, S, R, Q ... 10 steps: count them.
So what the requirement is actually asking for is N characters to the left with wrap around. Even if they don't state this clearly, it is the only way that the examples "work".
But you just implemented N characters to the left without wrap around. You need to implement the wrap around. (I won't show you how, but there lots of ways to do it.)
There's another thing. The title of the question says "Decrement only letters" ... which implies to me that your requirement is saying that characters that are not letters should not be decremented. However, in your code you are decrementing every character in the input, whether or not it is a letter. (The fix is simple ... and you should work it out for yourself.)
what can I do to prevent it?
You make it wrap around.
If you want a value to go from 10 to 19 and then start at 10 again, in each iteration you subtract 10, increase by one, take the remainder of that divided by 20, and add 10 again.
Only here, 10 is 'A', 19 is Z, and instead of increasing by one, we add or subtract n.
private String toLeft() {
String word = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Example
byte lpad = 10; // Example
StringBuilder sb = new StringBuilder();
int n = -lpad; // I'm using n here to I can use '+ n' below
for (int i = 0; i < word.length(); i++) {
int shifted = word.charAt(i) - 'A' + n;
shifted %= ('Z' - 'A' + 1); // This is for positive n
while(shifted < 0) // And this for negative ones
{
shifted += ('Z' - 'A' + 1);
}
sb.append((char)(shifted + 'A'));
}
return sb.toString();
}
Please read #StephenC's excellent answer about wrap-around. In short, you don't shift left, you rotate left, such that B → A → Z → Y. When you rotate, you wrap around to the other end.
So, for letters you want A-Z to rotate. The easiest rotation method is using modulus (%).
Your logic will be as follows:
Convert letters A-Z into numbers 0-25: n = ch - 'A'
Apply shift and wrap around. Since you're shifting left, you're subtracting from the number, so to prevent negative numbers, you start by shifting a full cycle to the right: n = (n + 26 - shift) % 26
Convert numbers back to letters: ch = (char)(n + 'A')
Here is the code:
private static String rotateLeft(String text, int count) {
char[] buf = text.toCharArray();
for (int i = 0; i < buf.length; i++)
buf[i] = (char)((buf[i] - 'A' + 26 - count) % 26 + 'A');
return new String(buf);
}
Of course, you should validate input, and test your code:
private static String rotateLeft(String text, int count) {
char[] buf = text.toCharArray();
if (count <= 0 || count >= 26)
throw new IllegalArgumentException("Invalid count: " + count);
for (char ch : buf)
if (ch < 'A' || ch > 'Z')
throw new IllegalArgumentException("Invalid character: " + ch);
for (int i = 0; i < buf.length; i++)
buf[i] = (char)((buf[i] - 'A' + 26 - count) % 26 + 'A');
return new String(buf);
}
public static void main(String[] args) {
System.out.println(rotateLeft("VQREQFGT", 2));
System.out.println(rotateLeft("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 10));
System.out.println(rotateLeft("LIPPSASVPH", 4));
}
OUTPUT
TOPCODER
QRSTUVWXYZABCDEFGHIJKLMNOP
HELLOWORLD

The Character Class in Java

Here is a short program that counts the letters of any given word entered by the user.
I'm trying to figure out what the following lines actually do in this program:
counts[s.charAt(i) - 'a']++; // I don't understand what the - 'a' is doing
System.out.println((char)('a' + i) // I don't get what the 'a' + i actually does.
import java.util.Scanner;
public class Listing9_3 {
public static void main(String[] args) {
//Create a scanner
Scanner input = new Scanner (System.in);
System.out.println("Enter a word to find out the occurences of each letter: ");
String s = input.nextLine();
//Invoke the count Letters Method to count each letter
int[] counts = countLetters(s.toLowerCase());
//Display results
for(int i = 0; i< counts.length; i++){
if(counts[i] != 0)
System.out.println((char)('a' + i) + " appears " +
counts[i] + ((counts[i] == 1)? " time" : " times"));
***//I don't understand what the 'a' + i is doing
}
}
public static int[] countLetters(String s) {
int[] counts = new int [26]; // 26 letters in the alphabet
for(int i = 0; i < s.length(); i++){
if(Character.isLetter(s.charAt(i)))
counts[s.charAt(i) - 'a']++;
***// I don't understand what the - 'a' is doin
}
return counts;
}
}
Characters are a kind of integer in Java; the integer is a number associated with the character on the Unicode chart. Thus, 'a' is actually the integer 97; 'b' is 98, and so on in sequence up through 'z'. So s.charAt(i) returns a character; assuming that it is a lower-case letter in the English alphabet, subtracting 'a' from it gives the result 0 for 'a', 1 for 'b', 2 for 'c', and so on.
You can see the first 4096 characters of the Unicode chart at http://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF (and there will be references to other pages of the chart as well). You'll see 'a' there as U+0061 (which is hex, = 97 decimal).
Because you want your array to contains only the count of each letter from 'a' to 'z'.
So to index correctly each count of the letter within the array you would need a mapping letter -> index with 'a' -> 0, 'b' -> 1 to 'z' -> 25.
Each character is represented by a integer value on 16 bits (so from 0 to 65,535). You're only interested from the letters 'a' to 'z', which have respectively the values 97 and 122.
How would you get the mapping?
This can be done using the trick s.charAt(i) - 'a'.
This will ensure that the value returned by this operation is between 0 and 25 because you know that s.charAt(i) will return a character between 'a' and 'z' (you're converting the input of the user in lower case and using Character.isLetter)
Hence you got the desired mapping to count the occurences of each letter in the word.
On the other hand, (char)('a' + i) does the reverse operation. i varies from 0 to 25 and you respectively got the letters from 'a' to 'z'. You just need to cast the result of the addition to char otherwise you would see its unicode value be printed.
counts[s.charAt(i) - 'a']++; // I don't understand what the - 'a' is doing
assume charAT(i) is 'z'
now z-a will be equal to 25 (subtract the unicode / ASCII values).
so counts[25]=counts[25]+1; // just keeps track of count of each character

java ASCII conversion

Here is part of my code:
// randomly create lowercase ASCII values
int rLowercase1 = random.nextInt(122) + 97;
// convert ASCII to text
System.out.print((char)rLowercase1);
When I run my program, it displays symbols instead of lowercase letters. Is there any way that I can fix this so that it displays lowercase letters?
How about
rLowercase1 = 'a' + random.nextInt('z' - 'a' + 1);
Number of letters in alphabet can be calculated with 'z' - 'a' + 1 = 25 + 1 = 26.
Since random.nextInt(n) will return value from range [0; n) - n is excluded - it means that you can get 'a'+0 = 'a' as minimal value and 'a'+25 = 'z' as max value.
In other words your range of characters is from 'a' till 'z' (both included).
Change your code as:
int rLowercase1 = random.nextInt(26) + 97; // it will generate a-z
There are only 26 lower case letters:
int rLowercase1 = random.nextInt(26) + 97;
If you want only the 26 unaccented Latin letters, Change 122 to 26:
int rLowercase1 = random.nextInt(26) + 97;
I think the meaning of this is a little clearer if written like this:
int rLowercase1 = 'a' + random.nextInt(26);

Categories