I have a function that takes String and a char[] type variables as parameter.
public String compressLine(String line, char[] fileChars){
String outputLine = new String();
int count = 0;
char lastChar = fileChars[0];
for(char c : line.toCharArray()){
if(c!=lastChar){
outputLine += String.format("%o,", count);
lastChar = c;
count = 1;
}else{
count += 1;
}
}
outputLine += count;
return outputLine;
}
String line is a line of ascii art and the char[] fileChars consists of the characters that are used in the string mentioned beforehand.
Example of line:
"##########---"
Example of fileChars:
[-, #]
Algorithm works in the following manner: given a row of data, the algorithm replaces each row with numbers that say how many consecutive pixels are the same character, always starting with the number of occurrences of the character that is encountered first in the fileChars.
When I ran a test using the examples given above, It should return;
[0, 10, 3]
But the output I get is;
[0, 12, 3]
When I tried to solve the bug, I saw the integer count somehow hops from 7 to 10.
What is causing this?
Your problem is with this line:
outputLine += String.format("%o,", count);
The "%o" output format specifier specifies that the value of count should be output in Octal. When the decimal value of count is 10, the Octal equivalent is 12.
I expect that you want this instead:
outputLine += String.format("%d,", count);
PS: When it appears that the number "jumps" from 7 to 10, that's because '10' immediately follows '7' in octal.
%o means octal. I'm not sure how you ended up on using %o, but, you don't want octal. Octal is how you would count if you have 8 fingers. 0, 1, 2, 3, 4, 5, 6, 7.., oh last finger, so.. 10!
In octal, '12' is how you write the tenth number. Just like you'd use '10' to do that in decimal, and '1010' in binary.
You want %d for decimal.
Related
I am new to java and and working on a crud calculator that takes input and holds it in an ArrayList to perform the calculations.
I am trying to add two values in an ArrayList<Character> and then replace the "+" with the sum.
if(listEqu.contains('+')) {
while(listEqu.indexOf('+') > -1) {
int plus = listEqu.indexOf('+');
int prev = listEqu.get(plus-1);
int nxt = listEqu.get(plus+1);
Character sum = (char) (nxt + prev);
listEqu.set(plus, sum);
System.out.println(listEqu);
}
}
When the input is 1+1, this returns [1, b, 1].
What I want is to return [1, 2, 1] .
Any advice? Thanks!
The problem is actually that adding two characters doesn't do what you expect.
The value of '1' + '1' is 'b'. If you want the next digit after '1' you add the integer 1 to it; i.e. '1' + 1 is '2'.
For a deeper understanding, you need to understand how character data is represented in Java.
Each char value in Java is an unsigned 16 bit integer that corresponds to a code point (or character code) in the Unicode basic plane. The first 128 of these code points (0 to 127) correspond to a characters in the old ASCII character set. In ASCII the codes that represent digits are 48 (for '0') through to 39 (for '9'). And the lowercase letters are 97 (for 'a') through to 122 (for 'z').
So as you can see, '1' + '1' -> 49 + 49 -> 98 -> 'b'.
(In fact there is a lot more to it than this. Not all char values represent real characters, and some Unicode code-points require two char values. But this is way beyond the scope of your question.)
How could I specify addition of numbers instead of addition of the characters?
You convert the character (digit) to a number, perform the arithmetic, and convert the result back to a character.
Read the javadoc for the Character class; e.g. the methods Character.digit and Character.forDigit.
Note that this only works while the numbers remain in the range 0 through 9. For a number outside of that range, the character representation consists of two or more characters. For those you should be using String rather than char. (A String also copes with the 1 digit case too ...)
Few things that can be improved with your code :
Converting the characters 1 into equivalent integer value:
int prev = Integer.parseInt(String.valueOf(listEqu.get(plus-1)));
int nxt = Integer.parseInt(String.valueOf(listEqu.get(plus+1)));
// Note : int prev = listEqu.get(plus-1) would store an ascii value of `1` to prev value i.e 49
And then converting the sum of those two values into Character back to be added to the list using Character.forDigit as:
Character sum = Character.forDigit(nxt+prev,10);
// Note Character sum = (char) (nxt + prev); is inconvertible
// and char sum = (char) (nxt + prev); would store character with ascii value 98(49+49) in your case 'b' to sum
you should first convert your prevand nxt to int value and then add them together like follow:
if(listEqu.contains('+')) {
while(listEqu.indexOf('+') > -1) {
int plus = listEqu.indexOf('+');
int prev = Integer.parseInt(listEqu.get(plus-1));
int nxt = Integer.parseInt(listEqu.get(plus+1));
Character sum = (char) (nxt + prev);
listEqu.set(plus, sum);
System.out.println(listEqu);
}
}
nxt and prev are char values. Tey take their value in the ASCII table, where '1' is 61 and 'b' is 142 (thus, '1' + '1' = 'b')
You need to substract '0' to get the number they represent. ('1' - '0' = 61 - 60 = 1)
The sum is not necessarily writable with one character, so you shouldn't put it back into a char array.
If you want to convert an integer to a string, use Integer.toString(i).
(And, if you want to, get the first character of the string and put it in the array, if that's what you want)
You need to parse the characters to their corresponding decimal value before you perform the addition, and then back to a character after. The methods Character.digit(char, int) and Character.forDigit(int, int) can do that (and I would use char since that is the type of prev and nxt). Like,
char prev = listEqu.get(plus - 1);
char nxt = listEqu.get(plus + 1);
Character sum = Character.forDigit(Character.digit(nxt, 10)
+ Character.digit(prev, 10), 10);
Given I have the following integers:
1, 10, 100
I want to pad them with zeroes to have exactly 3 digits:
001
010
100
and I want to print them prefixed by 10 spaces:
001 //assume 10 spaces from the beginning of the line
010
100
I want to use Java formatter string to accomplish this but am only successful in accomplishing one of the above mention conditions but not both at once.
Below are 2 expressions that I created that accomplish each one of these conditions:
#Test
public void test1() {
String[] langs = { "TEXTX", "TEXTXXX", "TEXTXX" };
int[] nums = {1, 10, 100};
for (int i = 0; i < 3; i++) {
String s = langs[i];
int n = nums[i];
System.out.printf("%1$s%2$14s%3$03d\n", s, " ", n);
}
}
According to documentation the formatter string has the below form:
%[argument_index$][flags][width][.precision]conversion
but apparently the zero padding flag parameter cannot be followed by width parameter as it is being parsed as one number resulting in a "long width".
How can this be rewritten to accomplish the above mentioned conditions?
NOTE:
My only idea was to explicitly add a single space to the arguments and try to manipulate it as an argument. Something like this:
System.out.printf("%1$s%2$10s%3$03d\n", s, " ", n);
EDIT:
My apologies, I just realized that I didn't fully described my question. These numbers need to follow certain other strings of different length, like this:
textX 001
textXXX 010
textXX 100
So that the spacing is variable.
If the two only criterias are the padding of 10 Spaces and zero-padding of the numbers:
final String str = String.format("%10s%03d", " ", 2);
Edit after update from OP:
System.out.printf("%-10s%03d", "abc", 2);
How it Works:
We need two arguments for Our pattern, one for the String of length 10, and one for the integer.
%10s is a pattern for a String of length 10. In order to left align it, we add the -: %-10s. The second argument is the integer of length 3 that we want to left pad With zero: %03d.
If we dont want to rearrange or reuse an argument for multiple format specifiers, just pass the arguments in the order specified in the pattern.
This answer is based on your latest edit, which revealed this data:
textX 001
textXXX 010
textXX 100
Assuming that the second column always has a width of 3, then your problem distills down to figuring out how many spaces need to be added after the first text column. Here is how you could do this in Java 7:
String text = "textXXX";
int n = 10 - text.length();
String padding = String.format("%0" + n + "d", 0).replace("0", " ");
In Java 8 you could this to get the padding string:
String padding = String.join("", Collections.nCopies(n, " "));
I am trying a code problem to convert double to string and then insert that to an array. I tried various methods but these don't give expected output.
public int[] makePi() {
double PI = Math.PI;
String sPI = String.valueOf(PI);
int[] Arr = new int[3];
for(int i =0; i<3; i++)
{
Arr[i] = sPI.charAt(i);
}
return Arr;
}
Output should be an array with first three characters of PI as below :-
[ 3, 1, 4 ] while I am getting [51, 46, 49]
I will handle decimal character if needed.
Just a hint is needed.
Please don't provide full program that will be a spoiler. :-)
Look at the ASCII table. Do you see what are the corresponding chars for the integers you're getting? This should be a good hint for you.
Note that you're assigning the result to an int array, while you're running on characters.
you're storing chars into an int array. hence theie respective ascii values will be stored in array (you're effectively converting char to int)
3 (char) -> 51 (ASCII Value)
. (char) -> 46 (ASCII Value)
1 (char) -> 49 (ASCII Value)
your array length is 3, so only first 3 chars are converted to ascii which is 3.1, not 3.14
But now if you want to store it into an char array (which i feel you're trying to do), all you need is -
char[] charArray = sPI.toCharArray();
Plus, I dont think you want to store in int array as though you can convert ascii values int their respective int value, but what about '.' which is not a valid int.
What you get in your array are values of characters (so something like 70 for '3', I neither remember nor want to remember exact values). You must convert value of character into the number itself. Hint: characters are numbered in the following way:
'0' - n
'1' - n + 1
'2' - n + 2
and so on.
If you want to extract the numeric values of the digits, I would advise against doing explicit comparisons and arithmetic on the character values.
The Character class provides helper methods, which are less error-prone and more readable:
int outIndex = 0;
for (int i = 0; i < 3 /* && i < sPI.length() */; ++i) {
char c = sPI.charAt(i);
if (Character.isDigit(c)) {
Arr[outIndex++] = Character.getNumericValue(c);
}
}
/* assert outIndex == 3 */
return Arr;
I've commented out some code which I'd put in there for more robustness - it's not strictly necessary in this case, since we know that sPI has at least 3 digits in it. (Mind you, if we're going to hard-code that assumption, we may as well simply return new int[] { 3, 1, 4 };).
I need to convert five digit integer to alphanumeric string of length 5.Doing below but sometimes it doesn't provide alphanumeric but numeric value.
Long x = 12345L;
String code = Long.toHexString(x).toUpperCase();
I want to get Alphanumeric string of length 5 always.
Try this
static String alphaNumric(int value) {
String s = "abcde" + Integer.toString(value, 36);
return s.substring(s.length() - 5);
}
and
int[] tests = { 12345, 1, 36, 36 * 36, 32767, 99999 };
for (int i : tests)
System.out.println(i + " -> " + alphaNumric(i));
output
12345 -> de9ix
1 -> bcde1
36 -> cde10
1296 -> de100
32767 -> depa7
99999 -> e255r
That's hardly surprising.
For example, 0x12345 is 74565, so 74565 does not contain any of the digits A to F when converted to hexadecimal.
Given that 99999 is 0x1869F, you have plenty of room in your converted string to accommodate some "junk" data, consider introducing an additive constant (0xA0000 perhaps which at least guarantees at least one alpha character for positive inputs), or even a number that your XOR with your original.
I was wondering if it is possible to enter in binary numbers and have them translated back into text. For example I would enter "01101000 01100101 01101100 01101100 01101111" and it would covert it into the word "hello".
Just some logical corrections:
There are three steps here
Turning the binary set into an integer
Then the integer into a character
Then concatenate to the string you're building
Luckily parseInt takes a radix argument for the base. So, once you either chop the string up into (presumably) an array of strings of length 8, or access the necessary substring, all you need to do is (char)Integer.parseInt(s, 2) and concatenate.
String s2 = "";
char nextChar;
for(int i = 0; i <= s.length()-8; i += 9) //this is a little tricky. we want [0, 7], [9, 16], etc (increment index by 9 if bytes are space-delimited)
{
nextChar = (char)Integer.parseInt(s.substring(i, i+8), 2);
s2 += nextChar;
}
See the answer to this question: binary-to-text-in-java.