This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a requirement where I need to return the alphabet when given an alphabet and a number.
Example if given, C and 4 I will return C+4 = G
Also if given C and -2 I will return C + (-2) = A
If I have AA then, AA + 4 = AD, So I will always want to take the last character from the string.
I was thinking of using string array to store alphabets, but it seems kind of bad solution. Is there any way by which I can get it done better ?
Alphabet characters are all already in order, all you need to do is add a number to one to get another.
I presume you want something like this:
addToChar('A', 4);
char addToChar(char inChar, int inNum)
{
return (char)(inChar + inNum);
}
You may want to check whether it is less than 'A' or greater than 'Z' as well.
In response to your edit:
void addToChar(char[] inChars, int inNum)
{
for (int i = inChars.length-1; inNum != 0 && i >= 0; i--)
{
int result = inChars[i]-'A'+inNum;
if (result >= 0)
{
inNum = result / 26;
result %= 26;
}
else
{
inNum = 0;
while (result < 0) // there may be some room for optimization here
{
result += 26;
inNum--;
}
}
inChars[i] = (char)('A'+result);
}
}
To deal with overflow: (somewhat less efficient) ('Z' + 1 outputs 'AA')
static String addToChar(String inChars, int inNum)
{
String output = "";
for (int i = inChars.length()-1; inNum != 0 || i >= 0; i--)
{
if (i < 0 && inNum < 0)
return "Invalid input";
int result = i >= 0 ? inChars.charAt(i)-'A'+inNum
: -1+inNum;
if (result > 0)
{
inNum = result / 26;
result %= 26;
}
else
{
inNum = 0;
while (result < 0)
{
result += 26;
inNum--;
}
}
output = (char)('A'+result) + output;
}
return output;
}
try this for example :
public class example {
public static void main(String[] args) {
int number = 2;
char example = 'c';
System.out.println((char)(example+number));
}
}
this is an example for the updated question :
still need to verify the input number and input String (lets say what happens if the number is 124 ?)
public class example {
public static void main(String[] args) {
int number = 1;
String example = "nicd";
//get the last letter from the string
char lastChar = example.charAt(example.length()-1);
//add the number to the last char and save it
lastChar = (char) (lastChar+number);
//remove the last letter from the string
example = example.substring(0, example.length()-1);
//add the new letter to the end of the string
example = example.concat(String.valueOf(lastChar));
//will print nice
System.out.println(example);
}
}
Have you ever google about character set? Like ASCII, a character is already represented by a number.
You don't need to store alphabet letters in an array; this is one reason why ASCII has all letters in consecutive order.
Perform the math operation, which implicitly converts the char to an int, then cast the result to a char. You'll have to check that you don't go before 'A' or after 'Z'.
Here's an ASCII table reference.
First, convert your character to an int with a cast, then add your int, and convert it back to a char. For instance:
char c = 'c';
int cInt = (int)c;
int gInt = cInt + 4;
char g = (char)gInt; // 'G'
Related
I'm trying to remove trailing zeroes from an integer and here is my code so far.
import java.math.BigInteger;
public class newuhu {
public static int numTrailingZeros(int s) {
BigInteger J = BigInteger.valueOf(s);
String sb = J.toString();
String Y = "";
while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '0') {
sb.replaceAll("0"," ");
}
return Integer.parseInt(Y);
}
Note: I turned my int into a Biginteger because I've been warned that some inputs may look like 20!, which is 2.432902e+18
However, my IntelliJ debugging tool tells me that variable sb isn't in the loop. So, I'm trying to understand what must be done to make sure sb is in the loop.
Please understand that I'm a beginner in Java so, I'm trying to learn something new.
replaceAll replaces all occurrences of string with character that you want (ie space) so you don't need loop at all, also you're concerned about overflow so you should actually use BigInteger as a parameter, not int (int wont fit anything close to 20!) but there's another issue with your code, you said you want to replace trailing zeros but right now you will replace every 0 with blank character, you should try to use something like https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
public class newuhu {
public static int numTrailingZeros(BigInteger s) {
String sb = s.toString();
return Integer.parseInt(sb.replaceAll("0", "")); // consider returning something else if you're working with BigInteger
}
Keep in mind that when doing BigInteger.valueOf(int) does not have an effect as a number to big for int will never be stored in an int. Also 20! is fine for int.
public static String trimTrailingZeros(String source) {
for (int i = source.length() - 1; i > 0; ++i) {
char c = source.charAt(i);
if (c != '0') {
return source.substring(0, i + 1);
}
}
return ""; // or return "0";
}
Or if you prever BigInteger.
public static BigInteger trimTrailingZeros(BigInteger num) {
while (num.remainder(BigInteger.TEN).signum() == 0) {
num = num.divide(BigInteger.TEN);
}
return num;
}
This should be fast as you only create one string (via substring).
(First: variables and fields should start with a small letter - when no constants.)
It should be
sb = sb.replaceAll(...)
as sb is not changed by replaceAll, only the replaced value is returned. The class String gives immutable values, that always remain the same, so you can assign a variable to a variable and changing values of either variable will never influence the other - no further sharing.
Then it should be:
sb = sb.replaceFirst("0$", "");
replaceAll would replace every 0, like "23043500" to "23435".
replaceFirst replaces the _regular expression: char '0' at the end $.
Overflow on the input number is not possible, as you are already passing an int.
public static int numTrailingZeros(int n) {
while (n != 0 && n % 10 == 0) {
n /= 10;
}
return n;
}
public static int numTrailingZeros(String n) {
n = n.replaceAll("0+", "");
if (n.isEmpty() || n.equals("-")) { // "-0" for pessimists?
n = "0";
}
return Integer.parseInt(n);
}
% is the modulo operator, the remainder of an integer division 147 % 10 == 7.
The name is misleading, or you are calculating something different.
public static int numTrailingZeros(int n) {
int trailingZeros = 0;
while (n != 0 && n % 10 == 0) {
n /= 10;
++trailingZeros ;
}
return trailingZeros ;
}
The problem here is that sb.replaceAll("0","") won't do anything. You're throwing away the return value that contains your replaced string. See here.
What you probably want is something like this:
while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '0') {
sb = sb.replaceAll("0"," ");
I'm not sure you need a while loop, though. ReplaceAll will... replace all of the zeros with spaces.
So here is the thing.
I have to write code to show a binary number X's next smallest "code-X number" which is bigger than binary number X.
code-X number is a binary number which have no continuously 1. For example: 1100 is not a code X number because it has 11, and 1001001001 is a code-X number
Here is my code
String a = "11001110101010";
String b = "";
int d = 0;
for(int i = a.length()-1; i>0;i--){
if(a.charAt(i) == '1' && a.charAt(i-1)=='1'){
while(a.charAt(i)=='1'){
b = b + '0';
if(i!=0){i--;}
d++;
}
}
b = b + a.charAt(i);
}
StringBuffer c = new StringBuffer(b);
System.out.println(c.reverse());
I plan on copy the binary string to string b, replace every '1' which next i is '1' into '0' and insert an '1'
like:
1100 ---> 10000
but i have no idea how to do it :)
May you help me some how? Thanks
Try this. This handles arbitrary length bit strings. The algorithm is as follows.
Needed to conditionally modify last two bits to force a change if the number is not a codeEx number. This ensures it will be higher. Thanks to John Mitchell for this observation.
Starting from the left, find the first group of 1's. e.g 0110
If not at the beginning replace it with 100 to get 1000
Otherwise, insert 1 at the beginning.
In all cases, replace everything to the right of the grouping with 0's.
String x = "10000101000000000001000001000000001111000000000000110000000000011011";
System.out.println(x.length());
String result = codeX(x);
System.out.println(x);
System.out.println(result);
public static String codeX(String bitStr) {
StringBuilder sb = new StringBuilder(bitStr);
int i = 0;
int len = sb.length();
// Make adjust to ensure new number is larger than
// original. If the word ends in 00 or 10, then adding one will
// increase the value in all cases. If it ends in 01
// then replacing with 10 will do the same. Once done
// the algorithm takes over to find the next CodeX number.
if (s.equals("01")) {
sb.replace(len - 2, len, "10");
} else {
sb.replace(len- 1, len, "1");
}
while ((i = sb.indexOf("11")) >= 0) {
sb.replace(i, len, "0".repeat(len - i));
if (i != 0) {
sb.replace(i - 1, i + 2, "100");
} else {
sb.insert(i, "1");
}
}
String str = sb.toString();
i = str.indexOf("1");
return i >= 0 ? str.substring(i) : str;
}
Prints
10000101000000000001000001000000001111000000000000110000000000011011
10000101000000000001000001000000010000000000000000000000000000000000
Using raw binary you can use the following.
public static void main(String[] args) {
long l = 0b1000010100000000010000010000000011110000000000110000000000011011L;
System.out.println(
Long.toBinaryString(nextX(l)));
}
public static long nextX(long l) {
long l2 = l >>> 1;
long next = Long.highestOneBit(l & l2);
long cutoff = next << 1;
long mask = ~(cutoff - 1);
return (l & mask) | cutoff;
}
prints
1000010100000000010000010000000010000000000000000000000000000000
EDIT: Based on #WJS correct way to find the smallest value just larger.
This is a slight expansion WJS' 99% correct answer.
There is just one thing missing, the number is not incremented if there are no consecutive 1's in the original X string.
This modification to the main method handles that.
Edit; Added an else {}. Starting from the end of the string, all digits should be inverted until a 0 is found. Then we change it to a 1 and break before passing the resulting string to WJS' codeX function.
(codeX version does not include sb.replace(len-2,len,"11");)
public static void main(String[] args) {
String x = "10100";
StringBuilder sb = new StringBuilder(x);
if (!x.contains("11")) {
for (int i = sb.length()-1; i >= 0; i--) {
if (sb.charAt(i) == '0') {
sb.setCharAt(i, '1');
break;
} else {
sb.setCharAt(i, '0');
}
}
}
String result = codeX(sb.toString());
System.out.println(x);
System.out.println(result);
}
I need to add two binary numbers and return the sum. No base conversions are allowed. I know the long method, using arrays. But is there anything shorter ? And by shorter I mean "having smaller code length". Thanks in advance.
In case I was not explicit enough, here is an example:
Input:
1101
11
Output: 10000
The sum of two (binary) integers a and b can be computed as a+b, because all arithmetic is done in binary.
If your input is in human readable strings rather than binary, you can compute their sum in binary using the standard BigInteger class:
import java.math.BigInteger;
String sum(String a, String b) {
return new BigInteger(a, 2).add(new BigInteger(b, 2)).toString(2);
}
Represent the binary numbers as two strings. Reverse the two strings. Then, you can iterate along both strings simultaneously, adding values to three arrays, two which represent the binary digit being added from the strings and the third to represent the carry digit. Create a fourth array representing the answer (you might have to find the limit for how long the answer can possibly be).
fill the answer array by using standard binary adding:
0 + 0 = 0 in the same position,
1 + 0 = 0 + 1 = 1 in the same position,
1 + 1 = 0 in the same position, and carry a 1 to the next position,
1 + 1 + 1 = 1 in the same position, and carry a 1 to the next position.
Reverse the array and you'll have the answer as a binary number.
Here are a couple options, not using any utility methods provided by Java. These don't account for sign (leading +/-) so they only handle whole numbers.
This first method converts the binary strings to integers, adds the integers, then converts the result back to binary. It uses a method-local inner class Convert to avoid duplicating the binaryToInt() code for each of the parameters.
static String binaryAdd1(String binary1, String binary2) {
class Convert {
int binaryToInt(String binary) {
int result = 0;
for (int i = 0; i < binary.length(); i++) {
char c = binary.charAt(i);
result *= 2;
if (c == '1') {
result++;
} else if (c != '0') {
throw new IllegalArgumentException(binary);
}
}
return result;
}
}
final Convert convert = new Convert();
int int1 = convert.binaryToInt(binary1);
int int2 = convert.binaryToInt(binary2);
String result = "";
int temp = int1 + int2;
do {
result = ((temp & 1) == 1 ? '1' : '0') + result;
temp >>= 1;
} while (temp > 0);
return result;
}
This second method uses binary addition logic, as specified by JHaps in his answer, to directly add together the two parameters. No intermediate conversion to integers here.
static String binaryAdd2(String binary1, String binary2) {
final String validDigits = "01";
String binarySum = "";
// pad the binary strings with one more significant digit for carrying
String bin1 = '0' + binary1;
String bin2 = '0' + binary2;
// add them together starting from least significant digit
int index1 = bin1.length() - 1;
int index2 = bin2.length() - 1;
boolean carry = false;
while (index1 >= 0 || index2 >= 0) {
char char1 = bin1.charAt(index1 >= 0 ? index1 : 0);
char char2 = bin2.charAt(index2 >= 0 ? index2 : 0);
if (validDigits.indexOf(char1) < 0)
throw new NumberFormatException(binary1);
if (validDigits.indexOf(char2) < 0)
throw new NumberFormatException(binary2);
if (char1 == char2) {
binarySum = (carry ? '1' : '0') + binarySum;
carry = char1 == '1';
} else {
binarySum = (carry ? '0' : '1') + binarySum;
}
index1--;
index2--;
}
if (binarySum.length() > 1 && binarySum.charAt(0) == '0') {
binarySum = binarySum.substring(1);
}
String result = binarySum.toString();
return result;
}
I have a string which represent a long. Like "12345678901" (11 chars long).
I convert it into a long using Long.parse(), that's fine.
Now, I want to send this long as a short string, like "eR%s" over the wire.
The goal is to have this final string as short as possible. Any idea what's the best way to do that? I can use more characters as the URL encoding (Like I can use /, %, :, etc.)
Java can handle a radix as high as 36 using the digits 0 - 9 and lower case letters a - z.
> Long.toString(12345678901L, 36)
"5o6aqt1"
> Long.parseLong("5o6aqt1", 36)
12345678901
You could create your own encoding using 65 of the 66 unreserved URI Characters (so your URI would not need escaping). The '-' sign needs to be used for negative numbers:
> Long65.toString(12345678901L)
"aFDIbA"
> Long65.parseLong65("aFDIbA")
12345678901
Here is the code for Long65()
import java.math.BigInteger;
public class Long65 {
private static int base = 65;
private static String URIchars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.~";
public static String toString(Long aNumber) {
StringBuilder result = new StringBuilder();
if (aNumber < 0) {
result.append('-');
aNumber = -aNumber;
}
int r = (int)(aNumber % base);
if (aNumber - r == 0)
result.append(URIchars.charAt(r));
else
result.append(Long65.toString((aNumber - r) / base) + URIchars.charAt(r));
return result.toString();
}
public static long parseLong65(String aNumber) {
char[] digits;
int sign = 1;
if (aNumber.charAt(0) == '-') {
sign = -1;
digits = aNumber.substring(1).toCharArray();
} else {
digits = aNumber.toCharArray();
}
BigInteger bigBase = BigInteger.valueOf(base);
BigInteger power = bigBase.pow(digits.length);
BigInteger total = BigInteger.valueOf(0);
for (char digit : digits){
power = power.divide(bigBase);
total = total.add(power.multiply(BigInteger.valueOf(URIchars.indexOf(digit))));
}
return sign * total.longValue();
}
}
Use a different base for your number if you want a shorter representation.
The bigger the numeric base you use, the smaller the representation. You can try base 16 for example:
Long.toString(num, 16)
This should return a string of at most 16 characters.
If that's not small enough, you can build a representation in a bigger base. However, if the resulting string needs to be URL escaped, this may not be useful. In base 256 for example, 8 chars would be enough for any number, but many of the 256 chars need to be escaped, making the resulting text longer. So you have to choose your alphabet carefully, if you choose to implement such an encoding/decoding scheme yourself.
Take a look at http://en.wikipedia.org/wiki/Base64 for example. You can use this Java implementation. You may also be interested in Base85 and its implementations.
To reply to the comments Base64 vs other options, I will say, it all depends on the constraints you have on the character set. I'm not talking about transmitting over an URL, but over a char stream which need to be a text stream. I can not simply send a byte array since non-printable chars might cause certain issues.
So I built something like that (see below) which transforms a long in base92 (almost). It uses all the printable chars excluding minus and pipe which I use for delimiters.
It's almost a cut&past of Base65 where I simply build the list of valid digits dynamically. Can be reuse for any base or any list of valid digits.
<!-- language: java -->
public class LongConverter {
private static String URIchars;
static {
StringBuilder result = new StringBuilder();
for (int i = 32; i < 255; i++) {
if ((i != 45) && (i != 124))
result.append((char)i);
}
URIchars = result.toString();
}
public static String toString(Long aNumber) {
int base = URIchars.length();
StringBuilder result = new StringBuilder();
if (aNumber < 0) {
result.append('-');
aNumber = -aNumber;
}
int r = (int) (aNumber % base);
if (aNumber - r == 0) result.append(URIchars.charAt(r));
else result.append(Long65.toString((aNumber - r) / base) + URIchars.charAt(r));
return result.toString();
}
public static long parseLong(String aNumber) {
int base = URIchars.length();
char[] digits;
int sign = 1;
if (aNumber.charAt(0) == '-') {
sign = -1;
digits = aNumber.substring(1).toCharArray();
} else {
digits = aNumber.toCharArray();
}
long total = 0;
long power = 1;
for (int i = 0; i < digits.length; i++)
power *= base;
for (char digit : digits) {
power /= base;
total += URIchars.indexOf(digit) * power;
}
return sign * total;
}
}
This question already has answers here:
Run-length decompression
(6 answers)
Closed 9 years ago.
I'm trying to take user input like a3b3 and decompress it to aaabbb. This is the code I came up with, and it prints a33b.
String getDecompressedText() {
int i;
int n = 1;
String d = "";
for (i = 0; i < compressedText.length(); i++){
if (Character.isDigit(compressedText.charAt(i)) == true) {
while (n < compressedText.charAt(i)-'0') {
d += compressedText.charAt(i);
n++;
}
}
else
d += compressedText.charAt(i);
}
return d;
here's your algorithm now:
for each character:
if it's not a digit, print it
if it is a digit, print the digit itself "digit - 1" times
not ideal. A few issues:
you printing the digit, not the letter preceding it. Use charAt(i-1)
you increment n, but never reset it back to 1. You should do that in the for loop.
you should indeed print the letter n - 1 times, since it got printed out once all by itself, so that's good
use a StringBuilder
the algorithm will break for things like a14 - 2-digit counts.
public static void main(String[] args) {
String compressedText = "a3b3";
int i;
int n = 1;
String d = "";
for (i = 0; i < compressedText.length(); i++) {
if (Character.isDigit(compressedText.charAt(i))) {
while (n < compressedText.charAt(i) - '0') {
d += compressedText.charAt(i - 1);
n++;
}
n = 0;
} else {
d += compressedText.charAt(i);
}
}
System.out.println(d);
}
Output:
aaabbbb
2 issues:
d += compressedText.charAt(i - 1); // Take the previous character, no the '3'
n = 0; // Reset the counter
Some notes:
Use a StringBuilder for concatenation in a loop
This will only work for single-digit numbers (0 - 9)