I need to increment a String in java from "aaaaaaaa" to "aaaaaab" to "aaaaaac" up through the alphabet, then eventually to "aaaaaaba" to "aaaaaabb" etc. etc.
Is there a trick for this?
You're basically implementing a Base 26 number system with leading "zeroes" ("a").
You do it the same way you convert a int to a base-2 or base-10 String, but instead of using 2 or 10, you use 26 and instead of '0' as your base, you use 'a'.
In Java you can easily use this:
public static String base26(int num) {
if (num < 0) {
throw new IllegalArgumentException("Only positive numbers are supported");
}
StringBuilder s = new StringBuilder("aaaaaaa");
for (int pos = 6; pos >= 0 && num > 0 ; pos--) {
char digit = (char) ('a' + num % 26);
s.setCharAt(pos, digit);
num = num / 26;
}
return s.toString();
}
The basic idea then is to not store the String, but just some counter (int an int or a long, depending on your requirements) and to convert it to the String as needed. This way you can easily increase/decrease/modify your counter without having to parse and re-create the String.
The following code uses a recursive approach to get the next string (let's say, from "aaaa" to "aaab" and so on) without the need of producing all the previous combinations, so it's rather fast and it's not limited to a given maximum string length.
public class StringInc {
public static void main(String[] args) {
System.out.println(next("aaa")); // Prints aab
System.out.println(next("abcdzz")); // Prints abceaa
System.out.println(next("zzz")); // Prints aaaa
}
public static String next(String s) {
int length = s.length();
char c = s.charAt(length - 1);
if(c == 'z')
return length > 1 ? next(s.substring(0, length - 1)) + 'a' : "aa";
return s.substring(0, length - 1) + ++c;
}
}
As some folks pointed out, this is tail recursive, so you can reformulate it replacing the recursion with a loop.
Increment the last character, and if it reaches Z, reset it to A and move to the previous characters. Repeat until you find a character that's not Z. Because Strings are immutable, I suggest using an array of characters instead to avoid allocating lots and lots of new objects.
public static void incrementString(char[] str)
{
for(int pos = str.length - 1; pos >= 0; pos--)
{
if(Character.toUpperCase(str[pos]) != 'Z')
{
str[pos]++;
break;
}
else
str[pos] = 'a';
}
}
you can use big integer's toString(radix) method like:
import java.math.BigInteger;
public class Strings {
Strings(final int digits,final int radix) {
this(digits,radix,BigInteger.ZERO);
}
Strings(final int digits,final int radix,final BigInteger number) {
this.digits=digits;
this.radix=radix;
this.number=number;
}
void addOne() {
number=number.add(BigInteger.ONE);
}
public String toString() {
String s=number.toString(radix);
while(s.length()<digits)
s='0'+s;
return s;
}
public char convert(final char c) {
if('0'<=c&&c<='9')
return (char)('a'+(c-'0'));
else if('a'<=c&&c<='p')
return (char)(c+10);
else throw new RuntimeException("more logic required for radix: "+radix);
}
public char convertInverse(final char c) {
if('a'<=c&&c<='j')
return (char)('0'+(c-'a'));
else if('k'<=c&&c<='z')
return (char)(c-10);
else throw new RuntimeException("more logic required for radix: "+radix);
}
void testFix() {
for(int i=0;i<radix;i++)
if(convert(convertInverse((char)('a'+i)))!='a'+i)
throw new RuntimeException("testFix fails for "+i);
}
public String toMyString() {
String s=toString(),t="";
for(int i=0;i<s.length();i++)
t+=convert(s.charAt(i));
return t;
}
public static void main(String[] arguments) {
Strings strings=new Strings(8,26);
strings.testFix();
System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString());
for(int i=0;i<Math.pow(strings.radix,3);i++)
try {
strings.addOne();
if(Math.abs(i-i/strings.radix*strings.radix)<2)
System.out.println(strings.number.toString()+' '+strings+' '+strings.toMyString());
} catch(Exception e) {
System.out.println(""+i+' '+strings+" failed!");
}
}
final int digits,radix;
BigInteger number;
}
I'd have to agree with #saua's approach if you only wanted the final result, but here is a slight variation on it in the case you want every result.
Note that since there are 26^8 (or 208827064576) different possible strings, I doubt you want them all. That said, my code prints them instead of storing only one in a String Builder. (Not that it really matters, though.)
public static void base26(int maxLength) {
buildWord(maxLength, "");
}
public static void buildWord(int remaining, String word)
{
if (remaining == 0)
{
System.out.println(word);
}
else
{
for (char letter = 'A'; letter <= 'Z'; ++letter)
{
buildWord(remaining-1, word + letter);
}
}
}
public static void main(String[] args)
{
base26(8);
}
I would create a character array and increment the characters individually. Strings are immutable in Java, so each change would create a new spot on the heap resulting in memory growing and growing.
With a character array, you shouldn't have that problem...
Have an array of byte that contain ascii values, and have loop that increments the far right digit while doing carry overs.
Then create the string using
public String(byte[] bytes, String charsetName)
Make sure you pass in the charset as US-ASCII or UTF-8 to be unambiguous.
Just expanding on the examples, as to Implementation, consider putting this into a Class... Each time you call toString of the Class it would return the next value:
public class Permutator {
private int permutation;
private int permutations;
private StringBuilder stringbuilder;
public Permutator(final int LETTERS) {
if (LETTERS < 1) {
throw new IllegalArgumentException("Usage: Permutator( \"1 or Greater Required\" \)");
}
this.permutation = 0;
// MAGIC NUMBER : 26 = Number of Letters in the English Alphabet
this.permutations = (int) Math.pow(26, LETTERS);
this.stringbuilder = new StringBuilder();
for (int i = 0; i < LETTERS; ++i) {
this.stringbuilder.append('a');
}
}
public String getCount() {
return String.format("Permutation: %s of %s Permutations.", this.permutation, this.permutations);
}
public int getPermutation() {
return this.permutation;
}
public int getPermutations() {
return this.permutations;
}
private void permutate() {
// TODO: Implement Utilising one of the Examples Posted.
}
public String toString() {
this.permutate();
return this.stringbuilder.toString();
}
}
Building on the solution by #cyberz, the following code is an example of how you could write a recursive call which can be optimized by a compiler that supports Tail Recursion.
The code is written in Groovy, since it runs on the JVM, its syntax closely resembles Java and it's compiler supports tail recursion optimization
static String next(String input) {
return doNext(input, "")
}
#TailRecursive
#CompileStatic
static String doNext(String input, String result) {
if(!self) {
return result
}
final String last = input[-1]
final String nonLast = self.substring(0, input.size()-1)
if('z' == last) {
return doNext(nonLast, (nonLast ? 'a' : 'aa') + result)
}
return doNext('', nonLast + (((last as Character) + 1) as Character).toString() + result)
}
Since none of the answers were useful to me, I wrote my own code:
/**
* Increases the given String value by one. Examples (with min 'a' and max 'z'): <p>
*
* - "aaa" -> "aab" <br>
* - "aab" -> "aac" <br>
* - "aaz" -> "aba" <br>
* - "zzz" -> "aaaa" <br>
*
* #param s
* #param min lowest char (a zero)
* #param max highest char (e.g. a 9, in a decimal system)
* #return increased String by 1
*/
public static String incString(String s, char min, char max) {
char last = s.charAt(s.length() - 1);
if (++last > max)
return s.length() > 1 ? incString(s.substring(0, s.length()-1), min, max) + min : "" + min + min;
else
return s.substring(0, s.length()-1) + last;
}
public static String incrementString(String string)
{
if(string.length()==1)
{
if(string.equals("z"))
return "aa";
else if(string.equals("Z"))
return "Aa";
else
return (char)(string.charAt(0)+1)+"";
}
if(string.charAt(string.length()-1)!='z')
{
return string.substring(0, string.length()-1)+(char)(string.charAt(string.length()-1)+1);
}
return incrementString(string.substring(0, string.length()-1))+"a";
}
Works for all standard string containing alphabets
I have approach using for loop which is fairly simple to understand. based on [answer]: https://stackoverflow.com/a/2338415/9675605 cyberz answer.
This also uses org.apache.commons.lang3.ArrayUtils. to insert letter on first position. you can create your own util for it. If someone finds helpful.
import org.apache.commons.lang3.ArrayUtils;
public class StringInc {
public static void main(String[] args) {
System.out.println(next("aaa")); // Prints aab
System.out.println(next("abcdzz")); // Prints abceaa
System.out.println(next("zzz")); // Prints aaaa
}
public static String next(String str) {
boolean increment = true;
char[] arr = str.toCharArray();
for (int i = arr.length - 1; i >= 0 && increment; i--) {
char letter = arr[i];
if (letter != 'z') {
letter++;
increment = false;
} else {
letter = 'a';
}
arr[i] = letter;
}
if (increment) {
arr = ArrayUtils.insert(0, arr, 'a');
}
return new String(arr);
}
It's not much of a "trick", but this works for 4-char strings. Obviously it gets uglier for longer strings, but the idea is the same.
char array[] = new char[4];
for (char c0 = 'a'; c0 <= 'z'; c0++) {
array[0] = c0;
for (char c1 = 'a'; c1 <= 'z'; c1++) {
array[1] = c1;
for (char c2 = 'a'; c2 <= 'z'; c2++) {
array[2] = c2;
for (char c3 = 'a'; c3 <= 'z'; c3++) {
array[3] = c3;
String s = new String(array);
System.out.println(s);
}
}
}
}
Related
So the program has to count letters of a string. I am not allowed to use loops except of recursive ones.
The method has to look like this:
static int numberOf(String text, char characterToCount)
Input:
abcbabcba (String) and b (char)
Output:
4
That's what my Code looks like so far ( I get Stackoverflow ) :
static int numberOf(String text, char characterToCount) {
int i = 0;
int erg = 0;
if (text.length() != 0) {
if (i != text.length()) {
if (text.charAt(i) == characterToCount) {
i++;
erg++;
numberOf(text, characterToCount);
} else {
i++;
numberOf(text, characterToCount);
}
} else {
return erg;
}
}
return 0;
}
EDIT
I'm only allowed to use String.charAt and String.length
The problem is that you aren't reducing text when you call the method so the length is never reduced to 0. Here is what you should be doing. Note that you do not need to pass an index to the method. Just keep reducing the text by 1 each time and just check the first character for equality to the target character.
public static void main(String[] args) {
System.out.println(numberOf("ksjssjkksjssss", 's'));
}
static int numberOf(String text, char characterToCount) {
if (text.isEmpty()) {
return 0;
}
if (text.charAt(0) == characterToCount) {
// call method and add 1 since you found a character
return numberOf(text.substring(1), characterToCount) + 1;
}
// just call the method.
return numberOf(text.substring(1), characterToCount);
}
The above prints
8
Ok, here is my modified version to meet your requirements of using only String.length and String.charAt. The char is really 16 bits so I use the high order byte to store the current index. I increment that index for each recursive call to maintain the current position of the search. When I add 256 to the character I am really adding 1 to the high order byte.
static int numberOf(String text, char ch) {
// stop when index exceeds text length
if (ch >> 8 >= text.length()) {
return 0;
}
if (text.charAt((ch >> 8)) == (ch & 0xff)) {
return numberOf(text, (char)(ch + 256)) + 1;
}
return numberOf(text, (char)(ch + 256));
}
This will not work as written on some character sets that are wider than 8 bits.
WJS's answer looks good but if you want simpler solution, this might help as well.
The problem in your solution is that your update of i and erg in one call stack is not seen/used by the next recursive call stack, since they are local variables and every stack will have their own copy of i and erg. They are always initialized as 0 in every call of numberOf method.
If substring isn't allowed then one way would be to make use of an extra variable that holds the index of position in the text you are comparing.
But on doing so you'll probably have to modify the signature of your method (if you don't want to use a class level static variable). And since you've mentioned that your method has to have only two arguments (text, charToCount), one way to achieve this easily would be to make use of a helper method (containing extra index argument) and your method can call it.
static int numberOf(String text, char characterToCount) {
return helper(text, characterToCount, 0);
}
static int helper(String text, char charToCount, int index) {
if (text.isEmpty() || index == text.length()) return 0;
int countCharOnRight = helper(text, charToCount, index+1);
return (text.charAt(index) == charToCount) ? 1 + countCharOnRight : countCharOnRight;
}
What
static int numberOf(String text, char characterToCount) {
return numberOfRecursive(text, characterToCount, 0);
}
// Recursive helper function
static int numberOfRecursive(String text, char characterToCount, int index) {
if (index == text.length()) // Abort recursion
return 0;
if (text.charAt(index) == characterToCount) // check char at index, then check next recursively
return numberOfRecursive(text, characterToCount, index + 1) + 1;
else
return numberOfRecursive(text, characterToCount, index + 1);
}
Why
Most recursive problems require a helper function, that actually performs the recursive part. It will be called from the original function with initial values, here with our text, character and a starting position of 0.
Then, the recursive function needs an abort condition, which I provide by a bound check. We terminate if our recursion reached the end of the string.
Finally the recursive function does some calculation which it bases on a recursive call. Here we add 1 to our result, if the char at our index position is the one to count. If not, we continue counting without adding 1.
I hope I could help.
The idea of recursion is that you call the same function/method a lot of times after some conditions. A good approach is to call the same function but reduce the string to check each time.
Class
public class StringUtils {
public int numberOf(String text, char characterToCount) {
int count = 0;
if (text.length() != 0) {
if(text.charAt(0) == characterToCount) { //Only increment when is the same character
count++;
}
count = count + numberOf(text.substring(1, text.length()), characterToCount); //Do a substring but remove the first character
}
return count;
}
}
Test
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class StringUtilsTest {
#Test
public void should_count_all_the_ocurrences() {
//Given
StringUtils utils = new StringUtils();
String sentence = "</www></palabraRandom></www></palabraRandom></palabraRandom></www>";
//When
int output = utils.numberOf(sentence, '>');
//Then
assertEquals(6, output);
}
}
So I think I got my solution.
It's maybe not that well but it works. Thanks for your help :)
public class CountLetters {
public static void main(String[] args) {
print("Bitte geben Sie den Text ein: ");
String text = readString();
text = toLowerCase(text, 0);
print("Bitte geben Sie ein Zeichen ein: ");
String zeich = readString();
zeich = toLowerCase(zeich, 0);
if (zeich.length() > 1) {
throw new PR1Exception("Bitte nur einen Buchstaben eingeben. ");
}
char zeichen = zeich.charAt(0);
if (zeichen > 0 && zeichen < 65 && zeichen > 90 && zeichen < 97 && zeichen > 123) {
throw new PR1Exception("Bitte nur Buchstaben eingeben.");
}
int anzahl = numberOf(text, zeichen);
println("-> " + anzahl);
}
static String toLowerCase(String text, int i) {
String lowerText = "";
if (i == text.length()) {
return lowerText;
} else if (text.charAt(i) < 'a') {
return lowerText += (char) (text.charAt(i) - 'A' + 'a') + toLowerCase(text, i + 1);
} else {
return lowerText += text.charAt(i) + toLowerCase(text, i + 1);
}
}
static int numberOf(String text, char characterToCount) {
return hilfe(text, characterToCount, 0, 0);
}
static int hilfe(String t, char ch, int i, int a) {
if (t.length() == a) {
return i;
} else if (t.charAt(a) == ch) {
return hilfe(t, ch, i + 1, a + 1);
} else {
return hilfe(t, ch, i, a + 1);
}
}
You can use an index variable if it is reached to the end returns 0. Otherwise, return 1 if it is letter or 0.
public class Main {
public static void main(String[] args) {
System.out.println(numberOf("Hello World-1234", 'o'));
}
private static int numberOf(String text, char characterToCount) {
if (!text.isEmpty()) {
return numberOf(text.substring(1), characterToCount) + (text.charAt(0) == characterToCount ? 1 : 0);
}
return 0;
}
}
EDIT: Implementation without substring
public class Main {
public static void main(String[] args) {
System.out.println(numberOf("Hello World-1234", 'o'));
}
private static int numberOf(String text, char characterToCount) {
if (text.isEmpty()) {
return 0;
}
char[] chars = text.toCharArray();
char[] newChars = new char[chars.length - 1];
System.arraycopy(chars, 1, newChars, 0, newChars.length);
return numberOf(new String(newChars), characterToCount) + (chars[0] == characterToCount ? 1 : 0);
}
}
I found it, thank u mate. I actually too confuse yesterday, till i forget everything that i learnt. So here is my code, what do you think?
I just don't know why my minChar not working when i delete this code :
if(stringValue.charAt(i) != 32){
public class MyString {
public static void main(String[] args) {
String stringValue = "Hello World";
SearchMyString str = new SearchMyString(stringValue);
str.stringInfo();
}
}
class SearchMyString{
private char maxChar;
private char minChar;
String stringValue;
int ascii;
public SearchMyString(String stringValue){
this.stringValue = stringValue;
}
char getMinChar(String stringValue, int n){
minChar = 'z';
for(int i = 0;i<n-1;i++){
if(stringValue.charAt(i)<minChar){
if(stringValue.charAt(i) != 32){
minChar = stringValue.charAt(i);
ascii = (int)stringValue.charAt(i);
}
}
}
return minChar;
}
public void stringInfo(){
int size = stringValue.length();
System.out.println("Smallest char : "+getMinChar(stringValue,size) + "\tASCII : " + ascii);
}
}
Use this method:
public static char getMaxChar(String a){
char max = a.charAt(0);
for (int i=0; i<a.length(); i++){
if ((a.charAt(i) > max)){
max = a.charAt(i);
}
}
return max;
}
Test case:
ACBDEFG
Returns
G
So what did we change?
For starters, if we are trying to get the character in the String that has the highest char int value, we don't need n. We are looping through the String, so all we need is the length, which can already be supplied by the .length() method.
To call the method, just do:
SearchMyString search = new SearchMyString();
search.getMaxChar(nama);
EDIT: So to make the method more reliable, instead of automatically setting max to 'A', we can set it to the first char of a (e.g, a.charAt(0))
I've been trying to create an algorithm where each letter adds points. I don't want to use charAt, I'd like to use the substring method.
My problem is that String letter does not seem to get each letter and the result is always 0.
Is there a way to get each letter and convert it to points?
public class WDLPoints{
public static void main(String[] args){
String word = "LDWWL";
System.out.println(getMatchPoints(word));
}
public static int getMatchPoints(String word) {
int points = 0;
String letter = word.substring(5);
for (int i = 0; i < word.length(); i++) {
if (letter.equals("W")) {
points+=3;
}
else if (letter.equals("D")) {
points+=1;
}
else {
points = 0;
}
}
return points;
}
}
You may try the following changes in your public static int getMatchPoints(String word) method:
for (int i = 0; i < word.length(); i++) {
String letter = word.substring(i, i + 1);
if (letter.equals("W")) {
points+=3;
}
else if (letter.equals("D")) {
points+=1;
}
}
word.substring(i, i + 1) will get a single letter word and will help you compute your score the way you want.
If you want to make it really simple you can just use String.toCharArray() and then iterate over the array of char and check its value:
public static int getMatchPoints(String word) {
int points = 0;
char[] arr = word.toCharArray();
for (char letter : arr) {
if (letter == 'W') {
points += 3;
}
else if (letter == 'D') {
points += 1;
}
}
return points;
}
I also removed your else statement because that was just setting the value to 0 if there is any other letter in the loop. I think you intended it to be points += 0 which does nothing, so it can just be removed.
Example Run:
Input:
String word = "LDWWL";
Output:
7
Note: I am aware you might not be allowed to use this solution, but I thought it would be good info on the possibilities since it does not technically use charAt()
Also I'd like to point out you misunderstand what substring(5) does. This will return all characters after the position of 5 as a single String, it does not separate the String into different characters or anything.
You will find that your variable letter is always the empty String. Here's a better way of doing things:
class WDLPoints
{
public static void main(String[] args)
{
String word = "LDWWL";
System.out.println(getMatchPoints(word));
}
// We have only one method to encode character values, all in one place
public static int getValueForChar(int c)
{
switch((char)c)
{
case 'W': return 3;
case 'D': return 1;
default: return 0; //all non-'W's and non-'D's are worth nothing
}
}
public static int getMatchPoints(String word)
{
// for all the characters in the word
return word.chars()
// get their integer values
.map(WDLPoints::getValueForChar)
// and sum all the values
.sum();
}
}
Assuming your string represents a football teams performance of the last 5 games, you could keep it simple and readable with something like:
public static int getMatchPoints(String word) {
String converted = word.replace('W', '3').replace('D', '1').replace('L', '0');
return converted.chars().map(Character::getNumericValue).sum();
}
This converts your example input "LDWWL" to "01330" and sums each char by getting its numeric value.
I have this assignment that needs me to decompress a previously compressed string.
Examples of this would be
i4a --> iaaaa
q3w2ai2b --> qwwwaaibb
3a --> aaa
Here's what I've written so far:
public static String decompress(String compressedText)
{
char c;
char let;
int num;
String done = "";
String toBeDone = "";
String toBeDone2 = "";
if(compressedText.length() <= 1)
{
return compressedText;
}
if (Character.isLetter(compressedText.charAt(0)))
{
done = compressedText.substring(0,1);
toBeDone = compressedText.substring(1);
return done + decompress(toBeDone);
}
else
{
c = compressedText.charAt(0);
num = Character.getNumericValue(c);
let = compressedText.charAt(1);
if (num > 0)
{
num--;
toBeDone = num + Character.toString(let);
toBeDone2 = compressedText.substring(2);
return Character.toString(let) + decompress(toBeDone) + decompress(toBeDone2);
}
else
{
toBeDone2 = compressedText.substring(2);
return Character.toString(let) + decompress(toBeDone2);
}
}
}
My return values are absolutely horrendous.
"ab" yields "babb" somehow.
"a" or any 1 letter string string yields the right result
"2a" yields "aaaaaaaaaaa"
"2a3b" gives me "aaaabbbbbbbbbbbbbbbbbbbbbbbbbbaaabbbbaaaabbbbbbbbbbbbbbbbbbbbbbbbbb"
The only place I can see a mistake in would probably be the last else section, since I wasn't entirely sure on what to do once the number reaches 0 and I have to stop using recursion on the letter after it. Other than that, I can't really see a problem that gives such horrifying outputs.
I reckon something like this would work:
public static String decompress(String compressedText) {
if (compressedText.length() <= 1) {
return compressedText;
}
char c = compressedText.charAt(0);
if (Character.isDigit(c)) {
return String.join("", Collections.nCopies(Character.digit(c, 10), compressedText.substring(1, 2))) + decompress(compressedText.substring(2));
}
return compressedText.charAt(0) + decompress(compressedText.substring(1));
}
As you can see, the base case is when the compressed String has a length less than or equal to 1 (as you have it in your program).
Then, we check if the first character is a digit. If so, we substitute in the correct amount of characters, and continue with the recursive process until we reach the base case.
If the first character is not a digit, then we simply append it and continue.
Keep in mind that this will only work with numbers from 1 to 9; if you require higher values, let me know!
EDIT 1: If the Collections#nCopies method is too complex, here is an equivalent method:
if (Character.isDigit(c)) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Character.digit(c, 10); i++) {
sb.append(compressedText.charAt(1));
}
return sb.toString() + decompress(compressedText.substring(2));
}
EDIT 2: Here is a method that uses a recursive helper-method to repeat a String:
public static String decompress(String compressedText) {
if (compressedText.length() <= 1) {
return compressedText;
}
char c = compressedText.charAt(0);
if (Character.isDigit(c)) {
return repeatCharacter(compressedText.charAt(1), Character.digit(c, 10)) + decompress(compressedText.substring(2));
}
return compressedText.charAt(0) + decompress(compressedText.substring(1));
}
public static String repeatCharacter(char character, int counter) {
if (counter == 1) {
return Character.toString(character);
}
return character + repeatCharacter(character, counter - 1);
}
Is there a nicer way of converting a number to its alphabetic equivalent than this?
private String getCharForNumber(int i) {
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
if (i > 25) {
return null;
}
return Character.toString(alphabet[i]);
}
Maybe something than can deal with numbers greater than 26 more elegantly too?
Just make use of the ASCII representation.
private String getCharForNumber(int i) {
return i > 0 && i < 27 ? String.valueOf((char)(i + 64)) : null;
}
Note: This assumes that i is between 1 and 26 inclusive.
You'll have to change the condition to i > -1 && i < 26 and the increment to 65 if you want i to be zero-based.
Here is the full ASCII table, in case you need to refer to:
Edit:
As some folks suggested here, it's much more readable to directly use the character 'A' instead of its ASCII code.
private String getCharForNumber(int i) {
return i > 0 && i < 27 ? String.valueOf((char)(i + 'A' - 1)) : null;
}
Rather than giving an error or some sentinel value (e.g. '?') for inputs outside of 0-25, I sometimes find it useful to have a well-defined string for all integers. I like to use the following:
0 -> A
1 -> B
2 -> C
...
25 -> Z
26 -> AA
27 -> AB
28 -> AC
...
701 -> ZZ
702 -> AAA
...
This can be extended to negatives as well:
-1 -> -A
-2 -> -B
-3 -> -C
...
-26 -> -Z
-27 -> -AA
...
Java Code:
public static String toAlphabetic(int i) {
if( i<0 ) {
return "-"+toAlphabetic(-i-1);
}
int quot = i/26;
int rem = i%26;
char letter = (char)((int)'A' + rem);
if( quot == 0 ) {
return ""+letter;
} else {
return toAlphabetic(quot-1) + letter;
}
}
Python code, including the ability to use alphanumeric (base 36) or case-sensitive (base 62) alphabets:
def to_alphabetic(i,base=26):
if base < 0 or 62 < base:
raise ValueError("Invalid base")
if i < 0:
return '-'+to_alphabetic(-i-1)
quot = int(i)/base
rem = i%base
if rem < 26:
letter = chr( ord("A") + rem)
elif rem < 36:
letter = str( rem-26)
else:
letter = chr( ord("a") + rem - 36)
if quot == 0:
return letter
else:
return to_alphabetic(quot-1,base) + letter
I would return a character char instead of a string.
public static char getChar(int i) {
return i<0 || i>25 ? '?' : (char)('A' + i);
}
Note: when the character decoder doesn't recognise a character it returns ?
I would use 'A' or 'a' instead of looking up ASCII codes.
Personally, I prefer
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".substring(i, i+1);
which shares the backing char[]. Alternately, I think the next-most-readable approach is
return Character.toString((char) (i + 'A'));
which doesn't depend on remembering ASCII tables. It doesn't do validation, but if you want to, I'd prefer to write
char c = (char) (i + 'A');
return Character.isUpperCase(c) ? Character.toString(c) : null;
just to make it obvious that you're checking that it's an alphabetic character.
if you define a/A as 0
char res;
if (i>25 || i<0){
res = null;
}
res = (i) + 65
}
return res;
65 for captitals;
97 for non captitals
Getting the alphabetical value from an int can be simply done with:
(char)('#' + i)
public static String abcBase36(int i) {
char[] ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
int quot = i / 36;
int rem = i % 36;
char letter = ALPHABET[rem];
if (quot == 0) {
return "" + letter;
} else {
return abcBase36(quot - 1) + letter;
}
}
You can convert the input to base 26 (Hexavigesimal) and convert each "digit" back to base 10 individually and apply the ASCII mapping. Since A is mapped to 0, you will get results A, B, C,..., Y, Z, BA, BB, BC,...etc, which may or may not be desirable depending on your requirements for input values > 26, since it may be natural to think AA comes after Z.
public static String getCharForNumber(int i){
// return null for bad input
if(i < 0){
return null;
}
// convert to base 26
String s = Integer.toString(i, 26);
char[] characters = s.toCharArray();
String result = "";
for(char c : characters){
// convert the base 26 character back to a base 10 integer
int x = Integer.parseInt(Character.valueOf(c).toString(), 26);
// append the ASCII value to the result
result += String.valueOf((char)(x + 'A'));
}
return result;
}
public static string IntToLetters(int value)
{
string result = string.Empty;
while (--value >= 0)
{
result = (char)('A' + value % 26 ) + result;
value /= 26;
}
return result;
}
To meet the requirement of A being 1 instead of 0, I've added -- to the while loop condition, and removed the value-- from the end of the loop, if anyone wants this to be 0 for their own purposes, you can reverse the changes, or simply add value++; at the beginning of the entire method.
Another variant:
private String getCharForNumber(int i) {
if (i > 25 || i < 0) {
return null;
}
return new Character((char) (i + 65)).toString();
}
This isn't exactly an answer, but some useful/related code I made. When you run it and enter any character in the command line it returns getNumericValue(char) ... which doesn't seem to be the same as the ASCII table so be aware. Anyways, not a direct answer to your question but hopefully helpful:
import java.lang.*;
import java.util.*;
/* charVal.java
*/
//infinite loops. whenever you type in a character gives you value of
//getNumericValue(char)
//
//ctrl+c to exit
public class charVal {
public static void main(String[] args) {
Scanner inPut = new Scanner(System.in);
for(;;){
char c = inPut.next().charAt(0);
System.out.printf("\n %s = %d \n", c, Character.getNumericValue(c));
}
}
}
Another approach starting from 0 and returning a String
public static String getCharForNumber(int i) {
return i < 0 || i > 25 ? "?" : String.valueOf((char) ('A' + i));
}
You can try like this:
private String getCharForNumber(int i) {
CharSequence css = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (i > 25) {
return null;
}
return css.charAt(i) + "";
}
public static void main(String[] args)
{
int rem,n=702,quo;
String s=" ";
while(n>0)
{
rem=(n-1)%26;
quo=(n-1)/26;
s=(char)(rem+97)+s;
if(quo==1)
{
s=(char)(97)+s;
break;
}
else
n=(n-1)/26;
}
System.out.print(s);
}
}
////We can also write the code like the below one. There is no much difference but it may help to understand the concept for some people.
public static void main(String[] args)
{
int rem,n=52,quo;
String s=" ";
while(n>0)
{
rem=n%26;
quo=n/26;
if(rem==0)
rem=26;
s=(char)(rem+96)+s;
if((quo==1 || quo==0) && n>26)
{
n=n/26;
s=(char)(n+96)+s;
break;
}
else
n=n/26-1;
}
System.out.print(s);
}
for(int i=0;i<ar.length();i++) {
char ch = ar.charAt(i);
System.out.println((char)(ch+16));;
}
The accepted answer best describes the solution. Nevertheless, it does not handle the case when you want to keep numbering over the value 27 like aa, ab, ...az, aaa, aab....
For doing so I achieved with the following:
protected String getAlphaNumber(int intValue) {
if (intValue == 0) {
return "";
}
intValue = Math.abs(intValue);
String prefix = "";
int charPosition = intValue % 26;
int blocks = intValue / 26;
if (charPosition == 0) { //the last letter, "z" (26)
blocks--;
charPosition = 26;
}
for (int i = 0; i < blocks; i++) {
prefix += "a";
}
return prefix + ((char) (charPosition + 96)); // "a"-"z" chars are located in the 97-122 indexes of the ASCII table, so shift all 96 positions.
}
import java.util.*;
class Integer2Letter
{
void main()
{
Scanner ob=new Scanner(System.in);
int n;
System.out.println("Enter an Integer");
n=ob.nextInt();//INPUT IN INTEGER FORMAT
if(n>0 && n<27)//RANGE CHECK
{
char ch= (char)(n+64);//IF N=1 THAN 64+1=65 WHICH EQUAL TO THE ASCII VALUE OF 'A'
System.out.println("the corresponding letter is="+ch);
}
else
{
System.out.println("Please enter the correct range");
}
}
}