Splitting input into integers - java

I am trying to split the input that I get through a scanner and split the integers inside the square brackets and put all of them into separate tree sets and perform operations based on the operators in the line. I am having issues with trying to parse the input and add the into the different tree sets, I keep getting InputMismatchExceptioneven after casting it to an integer. Would like to know where I am going wrong.
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int times = in.nextInt();
//iterate through number of times
for (int i = 0; i < times; i++) {
int num = in.nextInt();
System.out.println(num)
}
}
}
The input I take in is
6
[1,2,3] + [1,4,5]
[5,4,7,11] - [5,7]
[1,2,3] * [1,4,5]
[5,17,51,2,51] + [1,3,12,5,44,66,82]
[7,13,23,11,10] - [11,13,14,7,8,9,10]
[7,13,23,11,10] * [11,13,14,7,8,9,10]
Where my question is from

nextInt can't properly parse characters like [, ], , or + (if it is separated from number like + 4 instead of +4 which would simply represent 4).
That is why when you are trying to parse String like [1,2,3] + [3,4] with nextInt you are getting InputMismatchException because of [.
Probably one of simplest ways to parse your file is in a way like
int times = in.nextInt();
in.nextLine();//nextInt will not consume line separator, we need to do it explicitly
for (int i = 0; i < times; i++) {
String line = in.nextLine();
parse(line);
}
where parse method could be in from
private static final Pattern p = Pattern
.compile("\\[(?<set1>\\d+(?:,\\d+)*)\\]" // match first [1,2,3] and place it in group named set1
+ "\\s(?<operator>[-+*])\\s" // match operator, one of - + or *
+ "\\[(?<set2>\\d+(?:,\\d+)*)\\]"); // match second [2,3,4] and place in group named set2
private static void parse(String text) {
Matcher m = p.matcher(text);
if (m.matches()) {
String[] set1 = m.group("set1").split(",");
String[] set2 = m.group("set2").split(",");
String operator = m.group("operator");
if (operator.equals("+")){
//handle sum of sets
}
//handle rest of operators
else if (operator.equals("-")){
//...
}
//...
} else {
System.out.println("wrong text format:");
System.out.println(text);
}
}

Related

Why is my split method is not functioning as intended when I am splitting numbers from operator

Output of the code
public class Model {
private Scanner sc = new Scanner(System.in);
private String expression;
private String exp[];
public Model()
{
expression = sc.nextLine();
split();
}
public void split()
{
//splitting the entered expression to array of operators alone and array of the numbers then create Arraylist to combine the operators and numbers together as if it is a string expression but as an array
String num[]= this.expression.split("[/+/*/-]");
String preop[]= this.expression.split("[0123456789]"); // this will give [empty, operator, operator...] therefore we will create another array to fill in the ops excluding empty
System.out.println("Test: Printing num Array");
for(int i = 0; i<num.length;i++)
{
System.out.print(num[i]+",");
}
System.out.println("\nTest: Printing preOp Array");
for(int i = 0; i<preop.length;i++)
{
System.out.print(preop[i]+ ",");
}
ArrayList<String> op = new ArrayList<>();//I used arraylist because easier
for(int i = 1; i<preop.length;i++)
{
op.add(preop[i]);
}
System.out.println("\nTest of the fixed preOp array: " + op);
//putting the operands and the operators together in the same array
ArrayList<String> exp = new ArrayList<>();
//fill the arraylist with numbers then add the operators to it by using number (index of the operator +1 +count)
for(int i = 0; i <num.length;i++)
{
exp.add(num[i]);
}
int count = 0;
for(int i = 0; i <op.size();i++)
{
exp.add(i+1+count, op.get(i));
count++;
}
System.out.println("Test: " + exp);
}
The problem is that the op array is giving empty slot [op, op, empty, op] whenever user inputs a double digit numbers in the expression.
I was expecting similar results when user enters one digit numbers where it gives the intended results as in the image input with one digit numbers
it is because this
this.expression.split("[0123456789]");
You split by a single digit, so 43 is split into 2 parts as well with an empty string in between.
Also, you don't need to name all the digits in the regex, you can just do a range "[0-9]". If you want to match for 1 or more digits add a +. This should work:
this.expression.split("[0-9]+");
You can solve it in one go using a regex to split at any of the operators and keeping them using lookahead and lookbehind:
public static void main(String[] args) {
String first = "3+2*3-4";
String second = "3+2-43*3";
System.out.println(Arrays.toString(splitExpression(first)));
System.out.println(Arrays.toString(splitExpression(second)));
}
static String[] splitExpression(String input){
String regex = "((?<=(\\+|\\-|\\*|\\/))|(?=(\\+|\\-|\\*|\\/)))";
return input.split(regex);
}
output:
[3, +, 2, *, 3, -, 4]
[3, +, 2, -, 43, *, 3]

Split string after every n words in java and store it in an array

I have a string for example,
String s = "This is a String which needs to be split after every n words";
Suppose I have to divide this string after every 5 words of which the output should be,
Arraylist stringArr = ["This is a String which", "needs to be split after", "every n words"]
How can do this and store it in an array in java
While there isn't a built-in way for Java to do this, it's fairly easy to do using Java's standard regular-expressions.
My example below tries to be clear, rather than trying to be the "best" way.
It's based on finding groups of five "words" followed by a space, based on the regular expression ([a-zA-Z]+ ){5}) which says
• [a-zA-Z]+ find any letters, repeated (+)
• followed by a space
• (...) gather into groups
• {5} exactly 5 times
You may want things besides letters, and you may want to allow multiple spaces or any whitespace, not just spaces, so later in the example I change the regex to (\\S+\\s+){5} where \S means any non-whitespace and \s means any whitespace.
This first goes through the process in the main method, displaying output along the way that, I hope, makes it clear what's going on; then shows how the process could be made into a method.
I create a method that will split a line into groups of n words, then call it to split your string every 5 words then again but every 3 words.
Here it is:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LineSplitterExample
{
public static void main(String[] args)
{
String s = "This is a String which needs to be split after every n words";
//Pattern p = Pattern.compile("([a-zA-Z]+ +){5}");
Pattern p = Pattern.compile("(\\S+ +){5}");
Matcher m = p.matcher(s);
int last = 0;
List<String> collected = new ArrayList<>();
while (m.find()) {
System.out.println("Group Count = " + m.groupCount());
for (int i=0; i<m.groupCount(); i++) {
final String found = m.group(i);
System.out.printf("Group %d: %s%n", i, found);
collected.add(found);
// keep track of where the last group ended
last = m.end();
System.out.println("'m.end()' is " + last);
}
}
// collect the final part of the string after the last group
String tail = s.substring(last);
System.out.println(tail);
collected.add(tail);
String[] result = collected.toArray(new String[0]);
System.out.println("result:");
for (int n=0; n<result.length; n++) {
System.out.printf("%2d: %s%n", n, result[n]);
}
// Put a little space after the output
System.out.println("\n");
// Now use the methods...
String[] byFive = splitByWords(s, 5);
displayArray(byFive);
String[] byThree = splitByWords(s, 3);
displayArray(byThree);
}
private static String[] splitByWords(final String s, final int n)
{
//final Pattern p = Pattern.compile("([a-zA-Z]+ +){"+n+"}");
final Pattern p = Pattern.compile("(\\S+\\s+){"+n+"}");
final Matcher m = p.matcher(s);
List<String> collected = new ArrayList<>();
int last = 0;
while (m.find()) {
for (int i=0; i<m.groupCount(); i++) {
collected.add(m.group(i));
last = m.end();
}
}
collected.add(s.substring(last));
return collected.toArray(new String[0]);
}
private static void displayArray(final String[] array)
{
System.out.println("Array:");
for (int i=0; i<array.length; i++) {
System.out.printf("%2d: %s%n", i, array[i]);
}
}
}
The output I got by running this is:
Group Count = 1
Group 0: This is a String which
'm.end()' is 23
Group Count = 1
Group 0: needs to be split after
'm.end()' is 47
every n words
result:
0: This is a String which
1: needs to be split after
2: every n words
Array:
0: This is a String which
1: needs to be split after
2: every n words
Array:
0: This is a
1: String which needs
2: to be split
3: after every n
4: words
You can do it with a combination of replaceAll and split
S{N} - matches N iterations of S
() - regular expression capture group
$1 - back reference to the captured group
Replace every occurrence of N words with that occurrence followed by a special delimiter (in this case ###). Then split on that delimiter.
public static String[] splitNWords(String s, int count) {
String delim = "((?:\\w+\\s+){"+count+"})";
return s.replaceAll(delim, "$1###").split("###");
}
Demo
String s = "This is a String which needs to be split after every n words";
for (int i = 1; i < 5; i++) {
String[] arr = splitNWords(s, i);
System.out.println("Splitting on " + i + " words.");
for (String st : arr) {
System.out.println(st);
}
System.out.println();
}
prints
Splitting on 1 words.
This
is
a
String
which
needs
to
be
split
after
every
n
words
Splitting on 2 words.
This is
a String
which needs
to be
split after
every n
words
Splitting on 3 words.
This is a
String which needs
to be split
after every n
words
Splitting on 4 words.
This is a String
which needs to be
split after every n
words
I dont think there is a split every n words. You need to specify a pattern, like blank space. You can for instance, Split every blank and later iterate over the array created and make another one with tue number of words you want.
Regards

How to sort a array that contains special characters alphabetically?

I am looking for code that produces the following output in standard output from the following string prepared according to a certain format.
Assumptions and rules:
Each letter is used 2 times in the given string and the letters between the same 2 letters are to be considered child letters.
The given string is always given in proper format. The string format
does not need to be checked.
Example:
Input : abccbdeeda
Expected output:
a
--b
----c
--d
----e
Explanation: since the 2 letters "b" occur between the letters "a", the letter b takes 2 hyphens (--b)
Attempt
public static void main(String[] args) {
String input = "abccbdeeda";
System.out.println("input: " + input);
String[] strSplit = input.split("");
String g = "";
String h = "-";
ArrayList<String> list = new ArrayList<String>();
int counter = 1;
boolean secondNumber;
list.add(strSplit[0]);
int dual = 0;
for (int i = 1; i < strSplit.length; i++) {
secondNumber = list.contains(strSplit[i]);
if ((secondNumber)) {
counter--;
dual = counter * 2;
for (int f = 0; f < dual; f++) {
strSplit[i] = h.concat(strSplit[i]);
}
g = "";
dual = 0;
} else {
list.add(strSplit[i]);
counter++;
}
}
Arrays.sort(strSplit);
for (int p = 0; p < strSplit.length; p++) {
System.out.println(strSplit[p]);
}
}
input: abccbdeeda
My output:
----c
----e
--b
--d
a
I wasn't able to sort the output alphabetically. How can I sort alphabetically with those hyphen characters in them?
This task is nicely done with the help of a stack. If the current character is equal to the top of the stack, then the character is closed and can be removed, otherwise we met it for the first time and it must be added to the stack and the resulting string by adding before it stack.size() * 2 dashes.
When we have completely traversed the string we can sort the resulting string.
public static void main(String[] args) {
Stack<Character> stack = new Stack<>();
String string = "abccbdeeda";
StringBuilder result = new StringBuilder();
for(int i = 0; i < string.length(); i++) {
char curChar = string.charAt(i);
if(!stack.isEmpty() && curChar == stack.peek()) {
stack.pop();
} else {
result.append("-".repeat(stack.size() * 2)).append(curChar).append(" ");
stack.add(curChar);
}
}
System.out.println(result);
System.out.println(Arrays.toString(Arrays.stream(result.toString().split(" ")).sorted().toArray()));
}
Output
a --b ----c --d ----e
[----c, ----e, --b, --d, a]
You can go through the strSplit array and extract the charactors in each element to a separate list/array. To check whether the array element contains a letter you can write a regular expression.
Ex: private final Pattern x = Pattern.compile("[a-z]");
Write a separate method to match the patern to each element in the strSplit array. This method will return the charactor in your input string.
private String findCharactor(final StringBuilder element) {
final Matcher matcher = x.matcher(element);
if (matcher.find()) {
final int matchIndex = matcher.start(); //this gives the index of the char in the string
return element.substring(matchIndex);
}
}
Add these returned charactors to a separate array and sort it using sorting function.
Suppose your result list is:
List<String> resultList = Arrays.asList("----c", "----e", "--b", "--d", "a");
You can sort it alphabetically by a single line:
Collections.sort(resultList, (o1, o2) -> new StringBuilder(o1).reverse().toString().compareTo(new StringBuilder(o2).reverse().toString()));
You can use recursion for a depth-first traversal (preorder):
public static String dfs(String string, String prefix) {
if (string.length() == 0) return "";
int i = string.indexOf(string.charAt(0), 1);
return prefix + string.charAt(0) + "\n" // current
+ dfs(string.substring(1, i), prefix + "--") // all nested
+ dfs(string.substring(i + 1), prefix); // all siblings
}
Example call:
public static void main(String[] args) {
System.out.println(dfs("abccbdeeda", ""));
}

java program that takes a word and randomizes the letters and creates an anagram

I need to create a program that will take a word without spaces, punctuation, and all lowercase, and rearranges the letters randomly. It needs to have substrings or charAt, I cannot use an array since we have not learned them yet. It also hsa to be different everytime, really n! times I think. This is what I have so far-
public static void main(String[] args) {
Scanner kboard = new Scanner(System.in);
System.out.println("Enter a word that is less than 11 lowercase letters and has no punctuation or spaces: ");
String word = kboard.next();
while(word.length()>1)
{
System.out.print(word.charAt(1));
System.out.print(word.charAt(0));
word = word.substring(2);
}
System.out.println(word);
}
This rearranges the words, but it does not do it random every time. I thought I could do something like this, but I think it is messy and doesn't make much sense.
public static void main(String[] args) {
Scanner kboard = new Scanner(System.in);
String word, pt1 = "", pt2 = "", pt3 = "";
System.out.println("Enter a word that is less than 11 lowercase letters and has no punctuation or spaces: ");
word = kboard.nextLine();
int num1 = 0, num2 = 0, thing = 0;
while(thing<4)
{
thing = thing + 1;
num1 = (int)(word.length() * Math.random() + 1);
num2 = (word.length() - (word.length() % num1));
}
pt1 = word.substring(num1, num2);
pt2 = word.substring(num1, num2);
pt3 = word.substring(num1, num2);
System.out.print(pt1);
System.out.print(pt2);
System.out.print(pt3);
So what can I do to randomize the letters?
A simple solution to all "how do I randomize" a fixed set of elements is: shuffling.
Simply turn your String into a List of Character, to then shuffle that list.
( creating that list boils down to new ArrayList<>(yourWord.toCharArray() ).
GhostCat beat me in a few seconds :)
char[] arr = "abcdefg".toCharArray();
List<Character> list = new LinkedList<>(); // copy the chars to a list
for (int i = 0; i < arr.length; i++) {
list.add(arr[i]);
}
Collections.shuffle(list); // use to shuffle
for (int i = 0; i < arr.length; i++) { // copy the shuffled chars back to the array
arr[i] = list.get(i);
}
System.out.println(new String(arr));
This could be implemented very easily using standard libraries,
but it seems you cannot use arrays and lists,
which makes this exercise a bit harder than it needs to be.
You can implement the following algorithm:
Initialize the output as an empty string
while the word is not empty
Pick a character randomly
Append the character to the output
Remove the selected character from the word, by replacing word with the part before the index + the part after the index
This can be implemented reasonably efficiently using a StringBuilder:
String shuffled(Random random, String word) {
StringBuilder result = new StringBuilder(word.length());
StringBuilder rest = new StringBuilder(word);
while (rest.length() > 0) {
int index = random.nextInt(rest.length());
result.append(rest.charAt(index));
rest.deleteCharAt(index);
}
return result.toString();
}
If you cannot use a StringBuilder,
then you can work with strings,
but this will be less efficient,
and normally not recommended in Java.
(Because it involves many string concatenations, which is inefficient.)
String shuffled(Random random, String word) {
String result = "";
String rest = word;
while (!rest.isEmpty()) {
int index = random.nextInt(rest.length());
result += rest.charAt(index);
rest = rest.substring(0, index) + rest.substring(index + 1);
}
return result;
}
You can call this with:
String shuffled = shuffled(new Random(), word);
What about this :
public static void main(String[] args) {
String test = "onetwothree";
Random random = new Random();
for (int i=0;i<test.length();i++){
int randomCharacterPosition = random.nextInt(test.length());
String start = test.substring(0,randomCharacterPosition);
String end = test.substring(randomCharacterPosition);
test = end.concat(start);
}
System.out.println(test);
}
Basically you getting a string, randomly choose a position in string.
Using this position you dividing input string into two strings and swaping them.
Nothing more than random, substring and concat (which can be replaced with + operator)

Refine code. Search Strings

So the code I have is for a homework assignment where the user inputs a sentence (string) and I need to search through the string and return the smallest word. However, there must be a number inputted at the first spot in the string. Ex: "4 WHAT IS THIS". Output should be "IS" and ignore the number. The only way I figured out how to ignore the number is to make the loop skip over the first spot where the number would be. It works by itself but whenever I put it into the rest of my program it stops working. Is there anyway to make this program cleaner?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// Lexicographically smallest word
String TheSentence = sc.nextLine();
String[] myWords = TheSentence.split(" ");
int shortestLengths, shortestLocation;
shortestLengths = (myWords[1]).length();
shortestLocation = 1;
for (int i = 1; i < myWords.length; i++) {
if ((myWords[i]).length() < shortestLengths) {
shortestLengths = (myWords[i]).length();
shortestLocation = i;
}
}
System.out.println(myWords[shortestLocation]);
}
Inside your for loop (that should start at i = 0), add code like this:
try {
double value = Double.parseDouble(myWords[i]);
} catch (NumberFormatException e) {
// add the rest of your code here
}
The idea is that you try to transform your word to a number and if you fail, it means it's not a number, so you can use the length logic on the word.
The first thing you should do is to create the function you want to use instead of mixing the relevant code for the exercice with things like reading a line from the input stream.
You can test whether a character is a letter using Character.isLetter(char).
A good exercice is to build a solution using only that function and looking at each character separately (String.charAt(int) method) in a loop.
The solution is to remember where the currently shortest word starts and how long it is.
In practice, I would just use regexes like this:
public static String shortestWord(String sentence) {
String shortest = null;
Pattern word = Pattern.compile("\\w+");
Matcher m = word.matcher(sentence);
while (m.find()) {
String candidate = m.group();
if (shortest == null || shortest.length() > candidate.length())
shortest = candidate;
}
return shortest;
}
You could try using substring, e.g.
String result=inputString.substring(1)
'1' being the second letter in the string, substring returning every value save for the first.
The below basically just shortens up your code..other than that it doesn't change much. That being said..it would be much better to create all this in a method called shortestWord() or something. There is really no reason the code below shouldn't work though.
Revised Code:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] myWords = (sc.nextLine()).split(" ");
int shortestLocation = 1
for (int i = 2; i < myWords.length; i++) { // No reason to start at 1 as you have
// already made shortestLocation = 1
if (myWords[i].length() < myWords[shortestLocation].length()) {
shortestLocation = i;
}
}
System.out.println(myWords[shortestLocation]);
}
Suggested Code:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] myWords = (sc.nextLine()).split(" ");
System.out.println("The shortest word is: " + shortestWord(myWords));
}
public static String shortestWord(String[] myWords) {
int shortestLocation = 1
for (int i = 2; i < myWords.length; i++) { // No reason to start at 1 as you have
// already made shortestLocation = 1
if (myWords[i].length() < myWords[shortestLocation].length()) {
shortestLocation = i;
}
}
return myWords[shortestLocation];
}

Categories

Resources