Single characters don't left-justify using format in Java? - java

A problem I'm having in my programming class is asking me to make a pattern like this:
I used the following code:
public static void ch5ex18c() {
System.out.println("Pattern C");
String num = "6 5 4 3 2 1";
for (int count = 10; count >= 0; count-=2){
System.out.printf("%-10s", num.substring(count, 11) + "\n");
}
}
and I got everything to print out well except the first number line:
I know I can fix this using an if statement, but I'd just prefer not to and I want to know why it would do this in the first place.

The problem is that your new lines are inserted before extra spaces ("1\n" + spaces), you need to remove the minus sign (that justifies left) and make some minor math alterations.
1\n spaces (shown on next line to make it seem like your justifying right
2 1\n spaces
and so on

Related

Hashmap in for loop not reading all the input

This is for AOC day 2. The input is something along the lines of
"6-7 z: dqzzzjbzz
13-16 j: jjjvjmjjkjjjjjjj
5-6 m: mmbmmlvmbmmgmmf
2-4 k: pkkl
16-17 k: kkkkkkkkkkkkkkkqf
10-16 s: mqpscpsszscsssrs
..."
It's formatted like 'min-max letter: password' and seperated by line. I'm supposed to find how many passwords meet the minimum and maximum requirements. I put all that prompt into a string variable and used Pattern.quote("\n") to seperate the lines into a string array. This worked fine. Then, I replaced all the letters except for the numbers and '-' by making a pattern Pattern.compile("[^0-9]|-"); and running that for every index in the array and using .trim() to cut off the whitespace at the end and start of each string. This is all working fine, I'm getting the desired output like 6 7 and 13 16.
However, now I want to try and split this string into two. This is my code:
HashMap<Integer,Integer> numbers = new HashMap<Integer,Integer>();
for(int i = 0; i < inputArray.length; i++){
String [] xArray = x[i].split(Pattern.quote(" "));
int z = Integer.valueOf(xArray[0]);
int y = Integer.valueOf(xArray[1]);
System.out.println(z);
System.out.println(y);
numbers.put(z, y);
}
System.out.println(numbers);
So, first making a hasmap which will store <min, max> values. Then, the for loop (which runs 1000 times) splits every index of the 6 7 and 13 16 string into two, determined by the " ". The System.out.println(z); and System.out.println(y); are working as intended.
6
7
13
16
...
This output goes on to give me 2000 integers seperated by a line each time. That's exactly what I want. However, the System.out.println(numbers); is outputting:
{1=3, 2=10, 3=4, 4=7, 5=6, 6=9, 7=12, 8=11, 9=10, 10=18, 11=16, 12=13, 13=18, 14=16, 15=18, 16=18, 17=18, 18=19, 19=20}
I have no idea where to even start with debugging this. I made a test file with an array that is formatted like "even, odd" integers all the way up to 100. Using this exact same code (I did change the variable names), I'm getting a better output. It's not exactly desired since it starts at 350=351 and then goes to like 11=15 and continues in a non-chronological order but at least it contains all the 100 keys and values.
Also, completely unrelated question but is my formatting of the for loop fine? The extra space at the beginning and the end of the code?
Edit: I want my expected output to be something like {6=7, 13=16, 5=6, 2=4, 16=17...}. Basically, the hashmap would have the minimum and maximum as the key and value and it'd be in chronological order.
The problem with your code is that you're trying to put in a nail with a saw. A hashmap is not the right tool to achieve what you want, since
Keys are unique. If you try to input the same key multiple times, the first input will be overwritten
The order of items in a HashMap is undefined.
A hashmap expresses a key-value-relationship, which does not exist in this context
A better datastructure to save your Passwords would probably just be a ArrayList<IntegerPair> where you would have to define IntegerPair yourself, since java doesn't have the notion of a type combining two other types.
I think you are complicating the task unnecessarily. I would proceed as follows:
split the input using the line separator
for each line remove : and split using the spaces to get an array with length 3
build from the array in step two
3.1. the min/max char count from array[0]
3.2 charachter classes for the letter and its negation
3.3 remove from the password all letters that do not correspond to the given one and check if the length of the password is in range.
Something like:
public static void main(String[] args){
String input = "6-7 z: dqzzzjbzz\n" +
"13-16 j: jjjvjmjjkjjjjjjj\n" +
"5-6 m: mmbmmlvmbmmgmmf\n" +
"2-4 k: pkkl\n" +
"16-17 k: kkkkkkkkkkkkkkkqf\n" +
"10-16 s: mqpscpsszscsssrs\n";
int count = 0;
for(String line : input.split("\n")){
String[] temp = line.replace(":", "").split(" "); //[6-7, z, dqzzzjbzz]
String minMax = "{" + (temp[0].replace('-', ',')) + "}"; //{6,7}
String letter = "[" + temp[1] + "]"; //[z]
String letterNegate = "[^" + temp[1] + "]"; //[^z]
if(temp[2].replaceAll(letterNegate, "").matches(letter + minMax)){
count++;
}
}
System.out.println(count + "passwords are valid");
}

How to add a space at the end of every sentence?

I have couple of sentence that I process in my Android app. At the end of every sentence, I need to add an extra white space. I tried below.
bodyText=body.replaceAll("\\.",". ");
This did work, until I find dots in between sentences. For an example, If there is a sentence with a decimal number, then the above code added a space to that number too. Check the below example, where I applied the above code and it did not work as expected.
Last year the overall pass percentage was 90. 95%. It was 96. 21% in 2016.
You can see how the decimal places are separated by a space.
How can I add a space only at the sentence end? Normally every sentence end will contain a full stop.
You can get result of your own code, like below
public static String modifySentence(String input) {
StringBuilder sb = new StringBuilder(input);
// Counter which will increase with every insertion of char in StringBuilder
int insertCounter = 1;
int index = input.indexOf(".");
// If index is not of last digit of input, or not a digit or not a space.
// In all above cases we need to skip
while (index >= 0) {
if ((index + 1 < input.length())
&& (!Character.isDigit(input.charAt(index + 1)))
&& (!Character.isSpaceChar(input.charAt(index + 1)))) {
sb.insert(index + insertCounter, " ");
insertCounter++;
}
index = input.indexOf(".", index + 1);
}
return sb.toString();
}
Input is like
System.out.println(modifySentence("Last year the overall pass percentage was 90.95%.It was 96.21% in 2016."));
System.out.println(modifySentence("Last year the overall pass percentage was 90.95%.It was 96.21% in 2016. And this is extra . test string"));
And output is
Last year the overall pass percentage was 90.95%. It was 96.21% in 2016.
Last year the overall pass percentage was 90.95%. It was 96.21% in 2016. And this is extra . test string
As wiktor-stribiżew commented, this same result can be achieved using your_string.replaceAll("\\.([^\\d\\s])", ". $1");. Or you can use your_string.replaceAll("\\.(?<!\\d\\.\\d)(\\S)", ". $1"), it will handle the case like if a number starts right after dot.
If you have any confusion regarding these regexes, you can ask directly (by mentioning him in comment) to wiktor-stribiżew. These regex credit goes to him.
I dont know this is correct way or not but you can check for latter after dot(.) if it is capital (Uppercase latter), then you can consider the end of this statment and add one space. expect if your statment is started from lowercase later you can not use this.
but it is difficult to check the first letter is capital or not.
but you can also do it with
String first = myString.substring(0,1);
myString should coming after dot(.), and it should not start with any number.
If you want to add additional space to a sentence that already has a space after period, you can do the following:
String sentence = "Last year the overall pass percentage was 90.95%. It was 96.21% in 2016.";
sentence = sentence.replaceAll("\\. ",". ");
But if you need to add space to sentences that are not separated by space after period, do the following:
import java.util.regex.*;
public class MyClass {
public static void main(String args[]) {
String sentence = "Last year the overall pass percentage was 90.95%.It was 96.21% in 2016.example.";
String[] sentenceArr=sentence.split("\\.");
String str = "";
for(int i = 0; i < sentenceArr.length; i++) {
if(Pattern.matches(".*\\d+",sentenceArr[i]) && Pattern.matches("\\d+.*",sentenceArr[i+1])){
str=str+sentenceArr[i]+".";
}
else{
str=str+sentenceArr[i]+". ";
}
}
System.out.println(str);
}
}
Input: Last year the overall pass percentage was 90.95%.It was 96.21% in 2016.example
Output: Last year the overall pass percentage was 90.95%. It was 96.21% in 2016. example.

Get Each Character From Output - Java

Right now I have a program that puts an inputted expression into Postfix Evaluation. Below is a copy of my console.
Enter an expression: ((5*2-1)/6+14/3)*(2*3-5)+7/2
5 2 * 1 - 6 / 14 3 / + 2 3 * 5 - * 7 2 / +
I now need to walk through the output, however this output is just a bunch of System.out.print 's put together. I tried using a stringBuilder however it cant tell the difference between 14 and a 1 and 4.
Is there anyway I can go through each character of this output? I need to put these numbers into a stack.
You can use String.split() and if you need only numbers regular expression.
Here is an Example:
public class Test {
public static void main(String[] args) {
String str = "1 * 2 3 / 4 5 6";
String[] arr = str.split(" ", str.length());
for (int i=0;i < arr.length;i++)
System.out.println(arr[i] + "is diggit? " + arr[i].matches("-?\\d+(\\.\\d+)?"));
}
}
str holds the long String. arr will hold the split sub strings.
you just need to make sure that each sub string differ one space from the other.
Well, you deleted your code while I was reading it, but here's a conceptually developed answer.
As you input every character, you want to push that to the stack.
The unique scenario you've mentioned 14 is unique in that it's two characters.
So what you would want to do is track if the last character was ALSO a number.
Here's a rough pseudo. Your stack should be all Strings to support this.
//unique case for digit
if(s.charAt(0).isDigit()) {
//check to see if the String at the top of a stack is a number by peeking at its first character
if(stack.peek().charAt(0).isDigit()) {
int i = Integer.parseInt(stack.pop()) * 10;
//we want to increment the entire String by 10, so a 1 -> 10
i = i + Character.getNumericValue(s.charAt(0)); //add the last digit, so 10 + 4 = 14
stack.push(Integer.toString(i)); //put the thing back on the stack
}
else {
//handle normally
stack.push(s.substring(0,1));
}
}
Is there a reason you need to parse the actual string?
If so, then what you do is, create a StringBuffer or StringBuilder, and wherever you put System.out.print in your code, append the buffer - including the spaces, which are what will help you differentiate between 1 4 and 14. Then you can convert that to a String. Then you can parse the String by splitting it by the spaces. Then iterate through the resulting String array.
If there is no reason for you to use the actual full string, you can instead use a List object and just add to it in the same places in the code. In this case, you don't need the spaces. Then you'll be able to simply iterate through the list.
You'll still be able to print you output - by printing the elements in the list.

Remove last n lines (sentences) in a String in Java

I am looking for an efficient way to remove last n lines from a String. Efficient as in- fast performing as well as something that does not create too may objects. Therefore would like to stay away from split(). Especially because, at times, my strings could be a few hundred or even thousand lines.
For instance, I am getting a string as such:
This is a sample code line 1.
This is a sample code line 2.
Warm Regards,
SomeUser.
The last 3 lines (an empty line, "Warm Regards,", and "SomeUser.") is what I am trying to get rid of. Note that the content (including the last 3 lines) isn't fixed.
I am thinking of counting the lines first using this solution here: https://stackoverflow.com/a/18816371/1353174 and then again, use another similar loop to reach to a position that is lines - n and do a substring till that position.
However, just posting this problem here to know if there are any other and perhaps more efficient ways to achieve this. External library-based solutions (like Apache Commons StringUtils) are also welcome.
You can use String.lastIndexOf to find last third occurrence of '\n' symbol and then do String.substring to get the result.
public static void main(String[] args) {
String s = "This is a sample code line 1.\n" +
"This is a sample code line 2.\n" +
"\n" +
"Warm Regards,\n" +
"SomeUser.";
int truncateIndex = s.length();
for (int i = 0; i < 3; i++) {
System.out.println(truncateIndex);
truncateIndex = s.lastIndexOf('\n', truncateIndex - 1);
}
System.out.println(s.substring(0, truncateIndex));
System.out.println("--");
}
This code snippet intentionally doesn't care for corner cases, such as when there is less than three lines in input string, to make code simple and readable.
public static final String SAMPLE_TEXT = "This is a sample code line 1.\nThis is a sample code line 2.\r\n\nWarm Regards,\r\nSomeUser.";
public static void main (String[] args) throws java.lang.Exception {
String[] lines = SAMPLE_TEXT.split("\\r?\\n"); // catches Windows newlines (\r) as well)
for (int i = 0; i < lines.length - 3; i++) { // lines.length - 3 to discard the last 3 lines
System.out.println(lines[i]);
}
}
Here's a runnable example:
http://ideone.com/nwaMcD
#scala.annotation.tailrec
def rmLines(in: String, nlines: Int): String =
if (nlines == 0) {
in
} else {
val lastBreakIndex = in.lastIndexOf('\n')
if (lastBreakIndex == -1) {
in
} else {
rmLines(in.substring(0, lastBreakIndex), nlines - 1)
}
}
Use regular expressions to do it : http://docs.oracle.com/javase/tutorial/essential/regex/

In Java can I select a place to begin a line/column when printing?

For example, say I want to write to a text file, and I want to line up my results into columns like so:
Peanut Butter Crunchy
Jelly Purple
Bread Wheat
Milk Whole
\t obviously doesn't line up the second column when the first words are different lengths. Is lining them up possible?
Yes, it is possible. You want to pad the strings to the right with white spaces. For example, if you specify that each column starts every 20 characters and your string is 12 characters, you need to add 8 whitespace characters to the end.
You could hand code a loop or you could use string.format(). I took a look around online and found this easy method which you can use. http://www.rgagnon.com/javadetails/java-0448.html
public static String padRight(String s, int n) {
return String.format("%1$-" + n + "s", s);
}
s is the string that you want to pad, n is the ideal length.
For example,
padRight("test", 10") -> "test "
To add to your code, just format each line. For example, for your first line, you could do
String line = padRight(peanutButterString, 20) + peanutButterAttribute
Make sure your values are in an array and you can easily loop through it and create the properly formatted string.

Categories