How to get all possible combinations of substrings? - java

I have a String of following structure:
A1(N1,N2,N3)P4(O3,O5)Y1.
How to get all combinations? The rule is that options inside parenthesis should not go together. For this example the output should be:
A1N1P4O3Y1,
A1N2P4O3Y1,
A1N3P4O3Y1,
A1N1P4O5Y1,
A1N2P4O5Y1,
A1N3P4O5Y1.
There can be parenthesis, but it can be without it. Another example:
N3P5(L1,L2)Q1, output should be:
N3P5L1Q1,
N3P5L2Q1.
Anyone with elegant solution?

The main idea is to transform a string input into a StringTemplate that holds parts, that can be a single string or a group of strings.
For each part, a iterator is created. While some iterator can go next, update a string array that holds current part values and reset all iterators of parts that come before the part that changed. Feel free to clear repeated code and add nested groups support and syntax verifications if needed.
private static StringTemplate parse(String string) {
List<StringPart> parts = new ArrayList<StringPart>();
boolean insideGroup = false;
StringBuilder currentToken = new StringBuilder();
List<LiteralPart> groupParts = new ArrayList<LiteralPart>();
for (int i = 0; i < string.length(); i++) {
char ch = string.charAt(i);
if (ch == '(') {
if (currentToken.length() != 0) {
parts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
insideGroup = true;
} else if (ch == ')') {
if (insideGroup) {
if (currentToken.length() != 0) {
groupParts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
parts.add(new CompositePart(groupParts));
groupParts.clear();
insideGroup = false;
} else {
currentToken.append(ch);
}
} else if (ch == ',') {
if (insideGroup) {
if (currentToken.length() != 0) {
groupParts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
} else {
currentToken.append(ch);
}
} else {
currentToken.append(ch);
}
}
if (currentToken.length() != 0) {
parts.add(new LiteralPart(currentToken.toString()));
currentToken.delete(0, currentToken.length());
}
return new StringTemplate(parts);
}
private static final class StringTemplate {
private final List<StringPart> parts;
public StringTemplate(List<StringPart> parts) {
this.parts = parts;
}
public List<String> getCombinations() {
List<Iterator<String>> iterators = new ArrayList<Iterator<String>>(parts.size());
for (StringPart part : parts) {
iterators.add(part.getStrings().iterator());
}
String[] toJoin = new String[iterators.size()];
List<String> combinations = new ArrayList<String>();
int iteratorThatAdvanced;
int maxIteratorThatAdvanced = Integer.MIN_VALUE;
boolean first = true;
for (;;) {
iteratorThatAdvanced = -1;
for (int i = 0; i < iterators.size(); i++) {
Iterator<String> iterator = iterators.get(i);
if (first || iterator.hasNext()) {
String value = iterator.next();
toJoin[i] = value;
iteratorThatAdvanced = i;
if (!first && i >= maxIteratorThatAdvanced) {
maxIteratorThatAdvanced = i;
break;
}
}
}
if (iteratorThatAdvanced < 0) {
break;
}
if (!first) {
for (int i = 0; i < iteratorThatAdvanced; i++) {
Iterator<String> iterator = parts.get(i).getStrings().iterator();
iterators.set(i, iterator);
toJoin[i] = iterator.next();
}
}
combinations.add(join(toJoin));
first = false;
}
return combinations;
}
}
private static String join(String[] strings) {
StringBuilder builder = new StringBuilder();
for (String string : strings) {
builder.append(string);
}
return builder.toString();
}
private static abstract class StringPart {
abstract List<String> getStrings();
}
private static final class LiteralPart extends StringPart {
private final String literal;
public LiteralPart(String literal) {
this.literal = literal;
}
#Override
List<String> getStrings() {
return Collections.singletonList(literal);
}
}
private static final class CompositePart extends StringPart {
private final List<LiteralPart> parts;
public CompositePart(List<LiteralPart> parts) {
this.parts = new ArrayList<LiteralPart>(parts);
}
#Override
List<String> getStrings() {
List<String> strings = new ArrayList<String>(parts.size());
for (LiteralPart part : parts) {
strings.add(part.literal);
}
return strings;
}
}
Example:
public static void main(String[] args) {
StringTemplate template = parse("A1(N1,N2,N3)P4(O3,O5)Y1");
for (String combination : template.getCombinations()) {
System.out.println(combination);
}
template = parse("N3P5(L1,L2)Q1");
for (String combination : template.getCombinations()) {
System.out.println(combination);
}
}

Related

Parsing a tree from a nested list in Java

I have to create a tree from a nested list of integers in Java, like this:
((3,8,(7,(3,0,7),(8,8,2))),
(4,(7,9,8),8),
(((3,6,4),2,6),((9,2,9),4,7,(6,4,5) ),4,(6,4,5))
)
would be parsed to this tree: https://gyazo.com/189e2a4936913f9025b501be86aabc35/
I just can't seem to visualize how the nested list becomes the tree...
NOTE, a blank space means the tree value is empty
It seems a node is either a leaf with a number, or a list of nodes:
public abstract class Node {
}
public class NumberNode extends Node {
private final int number;
public NumberNode(int number) {
this.number = number;
}
#Override
public String toString() {
return Integer.toString(number);
}
}
public class ListNode extends Node {
private final List<Node> list = new ArrayList<>();
public ListNode(Collection<Node> nodes) {
list.addAll(nodes);
}
#Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append('(');
boolean first = true;
for (Node node: list) {
if (first) {
first = false;
} else {
buf.append(',');
}
buf.append(node);
}
buf.append(')');
return buf.toString();
}
}
You may want to use a scanner to tokenize your input:
public class Scanner {
private final Reader in;
private int c;
private Token token;
private int number;
public static enum Token {LPAR,RPAR,NUMBER,COMMA,EOF};
public Scanner(Reader in) throws IOException {
this.in = in;
c = in.read();
}
public Token getToken() {
return token;
}
public int getNumber() {
return number;
}
public Token nextToken() throws IOException {
while (c == ' ') {
c = in.read();
}
if (c < 0) {
return token = Token.EOF;
}
if (c >= '0' && c <= '9') {
number = c - '0';
c = in.read();
while (c >= '0' && c <= '9') {
number = 10*number + (c-'0');
c = in.read();
}
return token = Token.NUMBER;
}
switch (c) {
case '(':
c = in.read();
return token = Token.LPAR;
case ')':
c = in.read();
return token = Token.RPAR;
case ',':
c = in.read();
return token = Token.COMMA;
default:
throw new RuntimeException("Unknown character " + c);
}
}
}
You can then write a parser:
public static Node parse(Reader in) throws IOException {
Scanner scanner = new Scanner(in);
scanner.nextToken();
return parse(scanner);
}
private static Node parse(Scanner scanner) throws IOException {
switch (scanner.getToken()) {
case NUMBER:
int value = scanner.getNumber();
scanner.nextToken();
return new NumberNode(value);
case LPAR:
scanner.nextToken();
List<Node> nodes = parseList(scanner);
if (scanner.getToken() != Token.RPAR) {
throw new RuntimeException(") expected");
}
scanner.nextToken();
return new ListNode(nodes);
default:
throw new RuntimeException("Number or ( expected");
}
}
private static List<Node> parseList(Scanner scanner) throws IOException {
List<Node> nodes = new ArrayList<>();
if (scanner.getToken() != Token.RPAR) {
nodes.add(parse(scanner));
while (scanner.getToken() == Token.COMMA) {
scanner.nextToken();
nodes.add(parse(scanner));
}
}
return nodes;
}
To parse your example:
String s = "((3,8,(7,(3,0,7),(8,8,2))), (4,(7,9,8),8), (((3,6,4),2,6),((9,2,9),4,7,(6,4,5) ),4,(6,4,5)) )";
System.out.println(s);
Node node = parse(new StringReader(s));
System.out.println(node);
Output:
((3,8,(7,(3,0,7),(8,8,2))), (4,(7,9,8),8), (((3,6,4),2,6),((9,2,9),4,7,(6,4,5) ),4,(6,4,5)) )
((3,8,(7,(3,0,7),(8,8,2))),(4,(7,9,8),8),(((3,6,4),2,6),((9,2,9),4,7,(6,4,5)),4,(6,4,5)))

Comparing words

I have problem with my code. I wrote program for count words in text, but I have small problem with patterns which must be search in text. Maybe somebody can help me.
import java.util.*;
class KomparatorLicz implements Comparator<Word> {
#Override
public int compare(Word arg0, Word arg1) {
return arg1.amount - arg0.amount;
}
}
class KomparatorString implements Comparator<Word> {
#Override
public int compare(Word obj1, Word obj2) {
if (obj1.content == obj2.content) {
return 0;
}
if (obj1.content == null) {
return -1;
}
if (obj2.content == null) {
return 1;
}
return obj1.content.compareTo(obj2.content);
}
}
class Word
{
public String content;
public int amount;
public Word(String content, int amount) {
this.content = content;
this.amount = amount;
}
#Override
public String toString() {
return "Word [content=" + content + ", amount=" + amount + "]";
}
}
public class Source4 {
public static float procent(int wordCount, int oneWord)
{
return (((float)oneWord*100)/(float)wordCount);
}
public static void main(String[] args) {
String line, wordsLine[];
String klucze = null;
int valTemp;
int wordCount=0;
int keyWords=0;
HashMap<String, Word> slownik = new HashMap<String, Word>();
ArrayList<Word> lista= new ArrayList<Word>();
ArrayList<Object> keyWordsList = new ArrayList<Object>();
Scanner in = new Scanner(System.in);
String alph = in.nextLine();
keyWords = in.nextInt();
for(int i=0; i<keyWords; i++)
{
klucze = in.next();
keyWordsList.add(klucze);
}
while(in.hasNextLine())
{
line = in.nextLine();
if(line.equals("koniec")) break;
wordsLine = line.split("[^" + alph + "]");
for(String s : wordsLine) {
if(s != null && s.length() > 0)
{
wordCount++;
if(slownik.containsKey(s))
{
valTemp = slownik.get(s).amount;
slownik.remove(s);
valTemp++;
slownik.put(s, new Word(s,valTemp));
}
else
{
slownik.put(s, new Word(s,1));
}
}
}
}
for (String key : slownik.keySet())
{
lista.add(slownik.get(key));
}
Collections.sort(lista, new KomparatorString());
StringBuffer result = new StringBuffer();
int keyWordCounter=0;
int amountBuff=0;
float percentBuff=0;
for (int i = 0; i<lista.size();i++)
{
if(keyWordsList.contains(lista.get(i)))
{
result.append(amountBuff+" "+percentBuff+"%");
amountBuff = 0;
percentBuff = 0;
result.append("\n");
result.append(lista.get(i).amount+" "+(procent(wordCount,lista.get(i).amount)+"%"));
result.append(" "+lista.get(i).content);
result.append("\n");
keyWordCounter+=lista.get(i).amount;
}
else
{
amountBuff+=lista.get(i).amount;
percentBuff+=procent(wordCount,lista.get(i).amount);
}
}
result.append(amountBuff+" "+percentBuff+"%");
System.out.println("Wersja AK");
System.out.println(keyWords+" różnych słów kluczowych");
System.out.println(wordCount+" wystąpień wszystkich słów");
System.out.println(keyWordCounter+" "+procent(wordCount,keyWordCounter)+"% "+" wystąpień słów kluczowych");
System.out.println((wordCount-keyWordCounter)+" "+procent(wordCount,(wordCount-keyWordCounter))+"% wystąpień innych słów");
System.out.println(result);
}
}
It's wrong code if(keyWordsList.contains(lista.get(i))).
You need if(keyWordsList.contains(lista.get(i).content)).

Error at Linked list (java)

I created my own linked list, but when I tried to run it there is an error:
Exception in thread "main" java.lang.NullPointerException
at List.add(List.java:8) //if(t.val ==null)
at main.main(main.java:38) //linput.add(inputLine.split(" ")[i]);
Here is my List class:
class List{
String val;
List next=null;
private List t;
public void add(String word){
if(t.val ==null)
t.val=word;
else while(!t.next.val.equals(null))
{
t=t.next;
if(t.next.val.equals(null))
{
t.next.val=word;
break;
}
}
}
public int get(String word)
{
int i=0;
if(t.val.equals(word))
i=0;
else while(!t.next.val.equals(word))
{
t=t.next;
i++;
if(t.next.val.equals(word))
{
i++;
}
}
return i;
}
public String indexOf(int i)
{
int counter=0;
while(counter<i)
{
t=t.next;
counter++;
}
return t.val;
}
}
And here is my main function :
static public void main(String[] args)
{
List linput = new List();
String inputLine = "Hey look at me.";
for(int i = 0 ; i < inputLine.split(" ").length ; i++)
{
linput.add(inputLine.split(" ")[i]);
}
System.out.println(linput.indexOf(0)+" "+linput.indexOf(1)+" "+linput.indexOf(2));
}
I initialized t but next time there is an error like this:
private List t =new List();
Exception in thread "main" java.lang.StackOverflowError
at List.<init>(List.java:5)
at List.<init>(List.java:5)
at List.<init>(List.java:5)
Sorry. I can't give my full code, because the rest of my code is working well (reading from txt etc....).
The error seems to be related to the variable 't' (i.e., private List t).
Did you initialize this variable ? The if (t.val == null) seems to be cribbing this as t is null (uninitialized) at this point
You should have allocated object (using new) for this variable.
Can you share the full code for the constructor of List ?
Assuming you want to implement a simple forward list, rather than use the Java LinkedList class, you need to:
Change your implementation of the list to reference nodes in the list
handle traversal of the linked nodes in your word list
Here is an example:
WordList class
package com.example.words;
class WordList {
private WordNode head = null;
private int listSize = 0;
public void add(String word) {
// TODO add check for duplicate word
if (head == null) {
head = new WordNode();
head.setValue(word);
listSize++;
} else {
WordNode current = head;
while (current.getNext() != null) {
current = current.getNext();
}
WordNode newNode = new WordNode();
newNode.setValue(word);
current.setNext(newNode);
listSize++;
}
}
public int getWordIndex(String word) {
WordNode current = head;
int index = 0;
boolean found = false;
while (!found && current != null) {
found = current.getValue().equalsIgnoreCase(word);
if (!found) {
index++;
current = current.getNext();
}
}
if (found) {
return index;
} else {
return -1;
}
}
public String indexOf(int i) {
int index = 0;
WordNode current = head;
if (i <= listSize) {
while (index < i) {
current = current.getNext();
index++;
}
return current.getValue();
} else {
return null;
}
}
public int size() {
return listSize;
}
}
WordNode Class
package com.example.words;
public class WordNode {
private String value;
private WordNode next = null;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public WordNode getNext() {
return next;
}
public void setNext(WordNode link) {
next = link;
}
}
Test Driver
package com.example.words;
public class Test {
public static void main(String[] args) {
//TODO handle punctuation
WordList myList = new WordList();
String inputLine = "Hey look at me.";
String[] pieces = inputLine.split(" ");
for (int i=0; i < pieces.length; i++) {
myList.add(pieces[i]);
}
for (int i=0; i < pieces.length; i++) {
String value = myList.indexOf(i);
if (value.equalsIgnoreCase(pieces[i])) {
System.out.println("Following node is wrong:");
}
System.out.println ("node " + i + ". = " + value);
}
}
}
You tried to create t as a member variable of its own class like this:
class List {
[...]
private List t = new List();
[...]
}
This won't work because the constructor of List would be called indefinitely.
Try lazy instantiation of t instead. Replace all access of t with a getter:
private List getT() {
if (this.t == null) {
this.t = new List();
}
return t;
}

Exception in thread "main" java.lang.NullPointerException virtual stack class

I am trying to use this class to evaluate postfix expressions and when testing it am thrown this exception at line 32 where the virtual stack should push.
public class PostfixEval
{
private IntStack s;
public PostfixEval()
{
IntStack s = new IntStack();
}
public boolean isInteger(String s)
{
int i = 0;
boolean isDigit = true;
while(i < s.length() && isDigit)
{
isDigit = s.charAt(i) >= '0' && s.charAt(i) <= '9';
i++;
}
return isDigit;
}
public int eval(String e)
{
String[] tokens = e.split("\\s+");
for(int i=0; i<tokens.length; i++)
{
if(isInteger(tokens[i]))
{
s.push(Integer.parseInt(tokens[i]));
}
else
{
int a,b,c;
b = s.pop();
a = s.pop();
c = 0;
char d = tokens[i].charAt(0);
if(d == '+')
{
c = a + b;
}
else if(d == '-')
{
c = a - b;
}
else if(d == '*')
{
c = a*b;
}
else if(d == '/')
{
c = a/b;
}
else if(d == '%')
{
c = a%b;
}
else
{
System.out.println("Error");
System.exit(0);
}
s.push(c);
}
}
return s.peek();
}
}
I have used jgrasp to see what Integer.parseInt(tokens[i])) evaluates to and confirm it is a number from the split string. When trying to push a number that I type into the paramater of the push method it works, so why do I get null exception when using the PostfixEval to push?
Here is my stack class.
public class IntStack implements StackIntADT
{
// fields
private int[] stk;
private int sp;
// constructors
public IntStack()
{
sp = -1;
stk = new int[10];
}
public IntStack( int s )
{
sp = -1;
stk = new int[s];
}
// stack class methods
public void push(int element)
{
if(!isFull())
{
sp++;
stk[sp]=element;
}
else
{
System.out.println("Element" + element);
System.exit(0);
}
}
public int pop()
{
int rv = 0;
if(!isEmpty())
{
rv = stk[sp--];
}
else
{
System.out.println(rv);
System.exit(0);
}
return rv;
}
public int peek()
{
return stk[sp];
}
public boolean isEmpty()
{
return sp==-1;
}
public boolean isFull()
{
return sp==stk.length-1;
}
public int size()
{
return stk.length;
}
public String toString()
{
String s = "";
for(int x=0;x<10;x++)
{
s = s + " " + stk[x];
}
return s;
}
}
The constructor should not define a local s variable (which hides the member variable with the same name). The member variable is never assigned a value.
Change the constructor to this:
public PostfixEval() {
s = new IntStack();
}

ArrayList comparison

I have an ArrayList made out of classes objects .The class has several String fields . In some classes
some fields that are the same must be removed from the ArrayList .
The field from the class that I need to check is sorted_participants which is set to be the same in some objects.
This is my Class:
public class Neo4jCompensation {
private String number_of_participants;
private String amount;
private String sorted_participants;
private String unsorted_participants;
private String href_pdf_compensation;
private String signed_by_all;
public Neo4jCompensation() {
this.number_of_participants = "";
this.amount = "";
this.sorted_participants = "";
this.unsorted_participants = "";
this.href_pdf_compensation = "";
this.signed_by_all = "";
}
public String getNumber_of_participants() {
return number_of_participants;
}
public void setNumber_of_participants(String number_of_participants) {
this.number_of_participants = number_of_participants;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getSorted_participants() {
return sorted_participants;
}
public void setSorted_participants(String sorted_participants) {
this.sorted_participants = sorted_participants;
}
public String getUnsorted_participants() {
return unsorted_participants;
}
public void setUnsorted_participants(String unsorted_participants) {
this.unsorted_participants = unsorted_participants;
}
public String getHref_pdf_compensation() {
return href_pdf_compensation;
}
public void setHref_pdf_compensation(String href_pdf_compensation) {
this.href_pdf_compensation = href_pdf_compensation;
}
public String getSigned_by_all() {
return signed_by_all;
}
public void setSigned_by_all(String signed_by_all) {
this.signed_by_all = signed_by_all;
}
}
So I have a first list filled with Classes:
ArrayList<Neo4jCompensation> results_list=new ArrayList<Neo4jCompensation>();
I thought that very good way to find the duplicates is to make a copy of a list , compare the two for the same class fields values and remove the duplicates .
This is how I find the duplicates
ArrayList<Neo4jCompensation> results_list1=new ArrayList<Neo4jCompensation>();
for(Neo4jCompensation pp:results_list)
{
Neo4jCompensation ss=new Neo4jCompensation();
ss.setAmount(pp.getAmount());
ss.setHref_pdf_compensation(pp.getHref_pdf_compensation());
ss.setNumber_of_participants(pp.getNumber_of_participants());
ss.setSigned_by_all(pp.getSigned_by_all());
ss.setSorted_participants(pp.getSorted_participants());
ss.setUnsorted_participants(pp.getUnsorted_participants());
results_list1.add(ss);
}
for (int i = 0; i < results_list.size(); i++) {
Neo4jCompensation kk=new Neo4jCompensation();
kk=results_list.get(i);
for (int j = 0; j < results_list1.size(); j++) {
Neo4jCompensation n2=new Neo4jCompensation();
n2=results_list1.get(j);
if(i!=j)
{
String prvi=kk.getSorted_participants().trim();
String drugi=n2.getSorted_participants().trim();
if(prvi.equals(drugi))
{
// results_list1.remove(j);
out.println("<p> Are equal su :"+i+" i "+j+"</p>");
}
}
}
}
Since I know that I can not loop and remove the elements from the ArrayList at the same
time i tried to use iterators like this ...
int one=0;
int two=0;
Iterator<Neo4jCompensation> it = results_list.iterator();
while (it.hasNext()) {
Neo4jCompensation kk=it.next();
Iterator<Neo4jCompensation> it1 = results_list1.iterator();
while (it1.hasNext()) {
Neo4jCompensation kk1=it1.next();
String oo=kk.getSorted_participants().trim();
String pp=kk1.getSorted_participants().trim();
if(one<two && oo.equals(pp))
{
it1.remove();
}
two++;
}
one++;
}
But it fails and gives me back nothing in ArrayList results_list1 - before removal with iterator it has in it the right elements . How to remove the objects from the array list that have the same field values as some other objects in the ArrayList .
Why not use .removeAll()
results_list1.removeAll(resultList);
This will require you to implement equals and hashcode within Neo4jCompensation
public class Neo4jCompensation {
//Omitted Code
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((number_of_participants == null) ? 0
: number_of_participants.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Neo4jCompensation other = (Neo4jCompensation) obj;
if (number_of_participants == null) {
if (other.number_of_participants != null)
return false;
} else if (!number_of_participants.equals(other.number_of_participants))
return false;
return true;
}
}
Another approach could be:
Overrride equals method in your Neo4jCompensation and check for the sorted_participants and return accordingly. Then use Set as a collection of your objects. Set does not allow duplicates and it uses equals to determine the equality.
for (int i = 0; i < results_list.size(); i++) {
Neo4jCompensation kk=new Neo4jCompensation();
kk=results_list.get(i);
for (int j = 0; j < results_list1.size(); j++) {
Neo4jCompensation n2=new Neo4jCompensation();
n2=results_list1.get(j);
if(results_list1.contains(kk) { results_list1.remove(j); }
}
But you may want to use a Set instead of a List or a data structure that maintains order, like a SortedMap, with a sentinel value.

Categories

Resources