Make parenthesis the first priority on an arithmetic expression on TAC - java

So I have here my code implementing Three Address Code in arithmetic expression.
class ThreeAddressCode {
private static final char[][] precedence = {
{'/', '1'},
{'*', '1'},
{'+', '2'},
{'-', '2'}
};
private static int precedenceOf(String t)
{
char token = t.charAt(0);
for (int i=0; i < precedence.length; i++)
{
if (token == precedence[i][0])
{
return Integer.parseInt(precedence[i][1]+"");
}
}
return -1;
}
public static void main(String[] args) throws Exception
{
int i, j, opc=0;
char token;
boolean processed[];
String[][] operators = new String[10][2];
String expr="", temp;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("\nEnter an expression: ");
expr = in.readLine();
processed = new boolean[expr.length()];
for (i=0; i < processed.length; i++)
{
processed[i] = false;
}
for (i=0; i < expr.length(); i++)
{
token = expr.charAt(i);
for (j=0; j < precedence.length; j++)
{
if (token==precedence[j][0])
{
operators[opc][0] = token+"";
operators[opc][1] = i+"";
opc++;
break;
}
}
}
System.out.println("\nOperators:\nOperator\tLocation");
for (i=0; i < opc; i++)
{
System.out.println(operators[i][0] + "\t\t" + operators[i][1]);
}
//sort
for (i=opc-1; i >= 0; i--)
{
for (j=0; j < i; j++)
{
if (precedenceOf(operators[j][0]) > precedenceOf(operators[j+1][0]))
{
temp = operators[j][0];
operators[j][0] = operators[j+1][0];
operators[j+1][0] = temp;
temp = operators[j][1];
operators[j][1] = operators[j+1][1];
operators[j+1][1] = temp;
}
}
}
System.out.println("\nOperators sorted in their precedence:\nOperator\tLocation");
for (i=0; i < opc; i++)
{
System.out.println(operators[i][0] + "\t\t" + operators[i][1]);
}
System.out.println();
for (i=0; i < opc; i++)
{
j = Integer.parseInt(operators[i][1]+"");
String op1="", op2="";
if (processed[j-1]==true)
{
if (precedenceOf(operators[i-1][0]) == precedenceOf(operators[i][0]))
{
op1 = "t"+i;
}
else
{
for (int x=0; x < opc; x++)
{
if ((j-2) == Integer.parseInt(operators[x][1]))
{
op1 = "t"+(x+1)+"";
}
}
}
}
else
{
op1 = expr.charAt(j-1)+"";
}
if (processed[j+1]==true)
{
for (int x=0; x < opc; x++)
{
if ((j+2) == Integer.parseInt(operators[x][1]))
{
op2 = "t"+(x+1)+"";
}
}
}
else
{
op2 = expr.charAt(j+1)+"";
}
System.out.println("t"+(i+1)+" = "+op1+operators[i][0]+op2);
processed[j] = processed[j-1] = processed[j+1] = true;
}
}
}
Sample Output
Input : a * b / c
t1 = a * b
t2 = t1 / c
What the program does is evaluate the arithmetic expression and shows them step by step by operators.
Can you help me to include parenthesis in the priorities? and achieve an output like this
Sample Output
Input : a * ( b + c )
t1 = b + c
t2 = a * t2
Right now, the parenthesis is treated like an operand.

I did not use any of your code. Sorry.
This was a fun one to think about. I have never considered how you would do something like this. It does not follow all of the best practices to a "T", but the question inspired me to consider how you would do this in a rudimentary way.
You could make much of this code smaller by using more Java Frameworks, but it was enjoyable to strictly try to work this out logically.
This code is missing most validation (i.e. The user inputs an erroneous expression)
It does however check if there are an equal number of open and close parenthesis.
Lastly, I had to wrap things up so I did not extend into expressions with nested parenthesis.
Example a * ( b * ( c / d ) - e ) >> this code does not handle this scenario, and would have to be enhanced to accommodate for this.
Otherwise, it should give a pretty good idea as to one way you could go about building a program to work through parenthesis.
I hope it helps
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MathPriority {
public static void main(String[] args) {
String expression = "a * (b * c) + (d / e)"; //You can work out how you want input to com in
List<String> priorityList = getPriorityList(expression);//Find parenthesis and sets priority.
expression = expression.replace(" ", "").replace("(", "").replace(")", "");//Take out any spaces and parenthesis
for (int i = 0; i < priorityList.size(); i++) {//Replaces the piece in parenthesis with var and outputs var
expression = expression.replace(priorityList.get(i), "t" + (i + 1));
System.out.println("t" + (i + 1) + " = " + priorityList.get(i));
}
System.out.println("t" + (priorityList.size() + 1) + " = " + expression);//pushes final variable set
}
//You can use this to build a List of indexes of a character within a String
public static List<Integer> getAllOccurencesOfChar(List<String> expression, String indexO) {
List<Integer> parIndexList = new ArrayList<>();
for (int i = 0; i < expression.size(); i++) {
if (expression.get(i).contains(indexO)) {
if (!parIndexList.contains(i) && i > 0) {
parIndexList.add(i);
}
}
}
return parIndexList;
}
//Outputs a list of substrings. They can later be used to parse through the inital string
public static List<String> getPriorityList(String expression) {
List<String> priorityList = new ArrayList<>();
expression = expression.replace(" ", "");
String[] eParts = expression.split("");
List<String> expressionParts = new ArrayList<>();//Get expression into single chars
for (String e : eParts) {//If you change this to an Array.List, it will not work. This type of list is fixed in size
expressionParts.add(e);
}
List<Integer> parIndexList = getAllOccurencesOfChar(expressionParts, "(");//find all open paranthesis
List<Integer> rParIndexList = getAllOccurencesOfChar(expressionParts, ")");//find all close paranthesis
if (parIndexList.size() != rParIndexList.size()) {
System.out.println("Your Equation does not have an equal number of open and close parenthesis");
System.exit(0);
}
//Work out the parenthesis
int loopIterator = parIndexList.size();//This will change as we iterate
for (int pars = loopIterator - 1; pars >= 0; pars--) {
int start = parIndexList.get(pars); //Define a start
int end = 0; //and End
//int end = rParIndexList.get(pars);
for (int contemplate = 0; contemplate < loopIterator; contemplate++) {//contemplate where given parenthesis starts and where its closing tag is
if (parIndexList.get(pars) < rParIndexList.get(contemplate)) {
end = rParIndexList.get(contemplate);//find first occurence and set true end
break;//then stop
}
}
String expre = "";
for (int concat = start + 1; concat < end; concat++) {
expre += expressionParts.get(concat);//put the priorityList's subExpression together
}
priorityList.add(expre);//add that subExpression to the list
expressionParts.subList(start, end + 1).clear();//remove these expressionParts
/*Re-establish where the parenthesis are, since we removed parts of the expression in the list*/
parIndexList = getAllOccurencesOfChar(expressionParts, "(");//find all open paranthesis
rParIndexList = getAllOccurencesOfChar(expressionParts, ")");//find all close paranthesis
loopIterator = parIndexList.size();//resize the forLoop
}
return priorityList;
}
public static List<Integer> getStartEndPosition(String fullExpression, String subExpression) {
List<Integer> sAndE = new ArrayList<>();
String[] eParts = subExpression.split("");
List<String> wordParts = new ArrayList<>();
wordParts.addAll(Arrays.asList(eParts));
/*Find multiples of same operand*/
List<Integer> add = getAllOccurencesOfChar(wordParts, "+");
List<Integer> subtract = getAllOccurencesOfChar(wordParts, "-");
List<Integer> divide = getAllOccurencesOfChar(wordParts, "/");
List<Integer> multiply = getAllOccurencesOfChar(wordParts, "*");
/*Find single Operands*/
int plus = subExpression.indexOf("+");
int minus = subExpression.indexOf("-");
int div = subExpression.indexOf("/");
int mult = subExpression.indexOf("*");
int multiOperands = plus + minus + div + mult;//See if multiples exist
int startingPosition = 0;
if (add.size() > 1 || subtract.size() > 1 || divide.size() > 1 || multiply.size() > 1
|| multiOperands > 0) {
//expression has multiple opreands of different types
String findStart = wordParts.get(0) + wordParts.get(1);
String findEnd = wordParts.get(wordParts.size() - 2) + wordParts.get(wordParts.size() - 1);
startingPosition = fullExpression.indexOf(findStart);
sAndE.add(startingPosition);
int endPosition = fullExpression.indexOf(findEnd);
sAndE.add(endPosition);
} else {
startingPosition = fullExpression.indexOf(subExpression);
sAndE.add(startingPosition);
sAndE.add(startingPosition + subExpression.length());
}
return sAndE;
}
}
String expression = "a * (b * c) + (d / e)"
Outputs:
t1 = d/e
t2 = b*c
t3 = a*t2+t1

Related

Add Two Polynomials Java Program

I am working on this simple program that adds two polynomials. However, I am getting wrong results and could not spot the mistake.
import java.util.LinkedList;
public class Polynomial {
private LinkedList<Term> terms = new LinkedList<Term>();
private class Term {
private int coef;
private int exp;
public Term(int coef, int exp) {
this.coef = coef;
this.exp = exp;
}
public int getCoef() {
return coef;
}
public int getExp() {
return exp;
}
public String toString() {
return (this.coef + "x^" + this.exp);
}
}
public String addPoly(String first, String second) {
LinkedList<Term> otherTerms = new LinkedList<Term>();
String result = "";
String [] termsArray1 = first.split(";");
String [] termsArray2 = second.split(";");
for (int i = 0; i < termsArray1.length; i++) {
String [] temp = termsArray1[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
terms.add(currentTerm);
}
for (int i = 0; i < termsArray2.length; i++) {
String [] temp = termsArray2[i].split("x\\^");
int currentCoef = Integer.parseInt(temp[0]);
int currentExp = Integer.parseInt(temp[1]);
Term currentTerm = new Term(currentCoef, currentExp);
otherTerms.add(currentTerm);
}
int i = 0;
int j = 0;
while (true){
if(i == terms.size() || j == otherTerms.size()) {
break;
}
if(terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
if(terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
result = result.substring(0, result.length()-1);
return result;
}
}
::Test::
String s3 = "5x^2;-4x^1;3x^0";
String s4 = "6x^4;-1x^3;3x^2";
Polynomial p = new Polynomial();
System.out.println(p.addPoly(s4, s3));
Expected result: 6x^4;-1x^3;7x^2;-4x^1;3x^0
Actual result: 3x^4;7x^2;-1x^1;10x^0
The problem is that when your loop exits, one of the following can still be true:
i < terms.size()
j < j == otherTerms.size()
And this is the case with your example input. This means that part of one of the terms has not been processed and integrated into the output.
A second problem is that your multiple if statements are not exclusive; after the first if block is executed and j++ has executed, it might well be that j is an invalid index in otherTerms when the second if is evaluated. This should be avoided by turning the second and third if into else if.
Here is a fix for that loop:
while (i < terms.size() || j < otherTerms.size()) {
if(i == terms.size() || j < otherTerms.size() && terms.get(i).getExp() < otherTerms.get(j).getExp()) {
result += (otherTerms.get(j).toString() + ";");
j++;
}
else if(j == otherTerms.size() || i < terms.size() && terms.get(i).getExp() > otherTerms.get(j).getExp()) {
result += (terms.get(i).toString() + ";");
i++;
}
else if(terms.get(i).getExp() == otherTerms.get(j).getExp()) {
Term temp = new Term((terms.get(i).getCoef() + otherTerms.get(j).getCoef()), terms.get(i).getExp());
result += (temp.toString() + ";");
i++;
j++;
}
}
Better approach
Your approach is not really OOP. Ideally, the first expression should serve to create one instance of Polynomial and the other expression should serve to create another instance of Polynomial. Then there should be a method that can add another Polynomial instance to the own instance. Finally there should be a toString method that returns the instance as a string in the required format. Your driver code would then look like this:
Polynomial a = new Polynomial("5x^2;-4x^1;3x^0");
Polynomial b = new Polynomial("6x^4;-1x^3;3x^2");
Polynomial sum = a.addPoly(b);
System.out.println(sum.toString());
This is much more object oriented, and will automatically avoid the code repetition that you currently have.

Given an integer N. What is the smallest integer greater than N in java

I was trying to write a code that takes an integer between 1 and 1_000_000 and gives back the smallest integer greater than that with the same digits, and if it doesn't exist, it prints 0.
For example
input: 156
output 165
input 330
output 0
input 27711
output 71127
My problem is, my code below doesn't return the correct output for other inputs.
For example, in input 4231, the output should be 4312.
I'm having trouble finding the best algorithm that returns the correct output for every input.
tnx in advance
import java.util.Scanner;
public class Test4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String x = sc.nextLine();
char[] chars = new char[x.length()];
char[] oldChars = new char[x.length()];
char temp;
for (int i = 0; i < x.length(); i++) {
chars[i] = x.charAt(i);
oldChars[i] = chars[i];
}
if (x.length() > 3){
for (int j = 0; j < x.length(); j++) {
if (chars[0] < chars[j]) {
temp = chars[0];
chars[0] = chars[j];
chars[j] = temp;
break;
}
}
for (int j = 1; j <= x.length() ; j++) {
for (int i = 1; i < x.length() - 1; i++) {
if (chars[i] > chars[i+1]){
temp = chars[i];
chars[i] = chars[i+1];
chars[i+1] = temp;
}
}
}
for (int i = 0; i < x.length(); i++) {
System.out.print(chars[i]);
}
}
else if (x.length() == 1)
System.out.println(0);
else {
temp = chars[x.length()-2];
chars[x.length()-2] = chars[x.length()-1];
chars[x.length()-1] = temp;
if (chars[x.length()-2] > oldChars[x.length()-2])
for (int i = 0; i < x.length(); i++) {
System.out.print(chars[i]);
}
else
System.out.println(0);
}
sc.close();
}
}
Try this, please
int muldigits(int n){
int result = 0;
String [] strings = String.valueOf(Math.abs(n)).split("(?!^)");
List<Integer> intsList = new ArrayList<>();
for (String string : strings) {
intsList.add(Integer.parseInt(string));
}
if(n<0){
Collections.sort(intsList);
String temp = Arrays.toString(intsList.toArray()).replace(", ", "");
System.out.println(temp);
result = - Integer.parseInt(temp.substring(1, temp.length()-1));
}else{
Collections.sort(intsList, Collections.reverseOrder());
String temp = Arrays.toString(intsList.toArray()).replace(", ", "");
result = Integer.parseInt(temp.substring(1, temp.length()-1));
}
return result;
}
Here is one approach.
Starting with the least N significant digits. N starts with 2. Save a copy.
then create all permutations of those N digits.
join them into a String and put in a TreeMap<String>
if there exists a next higher value of the original N digits, return the new value
with the new ending concatenated to the original.
else, increase N by one and repeat the process.
public class NextLargestInteger {
public static void main(String[] args) {
Generate 10 random numbers.
Random r = new Random();
for (int i = 0; i < 10; i++) {
int val = r.nextInt(Integer.MAX_VALUE);
System.out.printf("%-12s %-12s%n",val,nextHighest(Integer.toString(val)));
}
Prints something like
1446553155 1446553[515]
1801279982 18012[82799]
1894877459 18948774[95]
805018669 8050186[96]
521703779 5217037[97]
1926164416 19261644[61]
1236907656 12369076[65]
1326860288 1326860[828]
1049149602 10491496[20]
1516995584 1516995[845]
The brackets on the right show what endings were permuted to get the minimum
The primary method.
public static String nextHighest(String e) {
char[] digits = e.toCharArray();
// start two digits from the end
int i = digits.length - 2;
// tree set to store the permuted strings
NavigableSet<String> set = new TreeSet<>();
for (; i >= 0; i--) {
// the last N digits
char[] shortList =
Arrays.copyOfRange(digits, i, digits.length);
// save a copy of the original N digit ending
String originalTail = new String(shortList);
permute(shortList, digits.length - i, set);
// get the next higher ending from the set
String minTail = set.higher(originalTail);
// if it exists, return the value.
if (minTail != null) {
String head =
new String(Arrays.copyOfRange(digits, 0, i));
return String.format("%s[%s]", head, minTail);
}
// clear the set and try a larger ending.
set.clear();
}
// no success, return the original value.
return e;
}
Utility method to permute the character array
public static void permute(char[] elements, int length,
Set<String> vals) {
if (length == 1) {
vals.add(new String(elements));
} else {
for (int i = 0; i < length; i++) {
permute(elements, length - 1, vals);
if (length % 2 == 1) {
swap(elements, 1, length - 1);
} else {
swap(elements, i, length - 1);
}
}
}
}
Utility method to swap array elements.
public static void swap(char[] list, int i, int j) {
char temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
If you can use apache commons collections4 and performance does not matter you can use something like that:
package test;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.stream.Collectors;
public class NextNumberCalculator {
public int calculateNearest(int input) {
List<Character> inputChars = String.valueOf(input).chars()
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
return CollectionUtils.permutations(inputChars)
.stream()
.mapToInt(chars -> Integer.parseInt(StringUtils.join(chars, "")))
.filter(permutation -> permutation > input)
.min()
.orElse(0);
}
}
Here some unit test:
package test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class NextNumberCalculatorTest {
private NextNumberCalculator calculator;
#BeforeEach
void setUp() {
calculator = new NextNumberCalculator();
}
#Test
void calculateNearest() {
Assertions.assertEquals(165, calculator.calculateNearest(156));
Assertions.assertEquals(0, calculator.calculateNearest(330));
Assertions.assertEquals(71127, calculator.calculateNearest(27711));
Assertions.assertEquals(414, calculator.calculateNearest(144));
}
}

Arrange the numbers by subtracting

I have a java problem that I don't know how to solve the program is :
two number must got from user n,k.
I need to find a permuation of numbers from 1 to N such that the difference between two items >=k for example :
we get the numbers (n = 5 and k = 2 )
and the answer must be 1,4,2,5,3 :
and for (n=2 and k = 2) there is not answer because the difference between 1 and two is 1(1,2 or 2,1).
I hope you understand what I want.
and I write some codes that are wrong:
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
int n = user_input.nextInt();
int k = user_input.nextInt();
int a ;
if (n%2==0) a = (n-2)/2; else a = (n-1)/2 ;
if (k!=a) {System.out.println("Impossible"); return;}
int h = k+1;
int value = 0;
int t = 1;
boolean b = true;
String res = "1 ";
while (value<n-1) {
value++;
if (b){
t = t + h;
res = res + t + " ";
b = false;
}else {
t = t-k;
res = res + t + " ";
b = true;
}
}
System.out.println(res);
}
Here is the code
public class HelloWorld{
public static void calculationMethod(int n, int k) {
if(n<2 || n/2 < k) {
System.out.println("Impossible");
return;
}
else {
int i = (int)Math.ceil(n/2.0);
int j = n;
int start = i;
boolean flag = true;
while(i>=1 || j>start) {
if(flag) {
System.out.print(i + " " );
i--;
flag = false;
}
else {
System.out.print(j + " " );
j--;
flag = true;
}
}
}
}
public static void main(String []args){
calculationMethod(7,3);
}
}
The idea is to divide your range(n) in half. If k>n/2 then it is not possible to construct any such sequence.
If that is not the case, then have 2 pointers one at the middle of your range and one at the end of the range. and print them alternatively decrementing both pointers until u reach the beginning.
Feel free to improve the code.
public void calculationMethod(int n, int k) {
ArrayList<Integer> intList = new ArrayList<>();
for (int i = 1; i <= n; i++) {
int a = i;
int b = i + 2;
if (!intList.contains(a) && a<=n) {
intList.add(a);
}
if (!intList.contains(b) && b<=n) {
intList.add(b);
}
}
String mValues= TextUtils.join(",",intList);
Log.i("values", mValues);
}

java sort string array according to kurdish characters

Is there any short way to sort a string array by Kurdish characters? I've looked at some source on internet but I couldn't find any solution. There is a way to sort. Writing a code alike a novel but it is a very long work.
kurdish characters: a,b,c,ç,d,e,ê,f,g,h,i,î,j,k,l,m,n,o,p,q,r,s,ş,t,û,u,v,w,x,y,z
The Collator class should come in-handy here. To quote from the doc,
The Collator class performs locale-sensitive String comparison. You use this class to build searching and sorting routines for natural language text.
So try something like this:
Collator unicodeCollator = Collator.getInstance(Locale.UNICODE_LOCALE_EXTENSION);
Collections.sort(yourListOfCharacters, unicodeCollator);
Note that we are able to call java.util.Collections.sort directly as above, because Collator implements the Comparator interface.
If for whatever reasons Locale.UNICODE_LOCALE_EXTENSION doesn't work, here's the full list of supported locales. And you can create your own locale using the Locale constructor.
I've solved my problem: content of my file was like this:
*Nîzamettîn Ariç - Kardeş Türküler - Rojek Tê
Bê xem bê şer welat azad rojek tê
Rojek ronahî rojek bişahî rojek tê
Roj Roja me ye....
*Koma Çiya - Tolhildan ^ Daketine Meydanê
Daketine meydanê gerilayên dînemêr
Ji bona tolhildanê wek baz û piling û şêr...
My solution: thîs letters is proper for toLowerCase function:
ABCÇDEÊFGĞHİÎJKLMNOÖPQRSŞTÛUÜVWXYZ
just I was problem. because lowerCase(I) for turkish is ı; but for kurdish it is i.
code:
in onCreate():
...
alfabetBike();
...
public static void alfabetBike() {
for (int i = 0; i < tips.length(); i++) {
String[] derbasi_arr = sernavs[i];
String[] derbasi_got = gotins[i];
for (int j = 0; j < hejmar[i] - 1; j++) {
int indeks = j;
String yaMezin = derbasi_arr[j];
for (int k = j + 1; k < hejmar[i]; k++) {
if (compareTwoString(yaMezin.substring(1), derbasi_arr[k].substring(1)) > 1) {
yaMezin = derbasi_arr[k];
indeks = k;
}
}
if (indeks != j) {
derbasi_arr[indeks] = derbasi_arr[j];
String derbasi = derbasi_got[indeks];
derbasi_got[indeks] = derbasi_got[j];
derbasi_arr[j] = yaMezin;
derbasi_got[j] = derbasi;
}
}
gotins[i] = derbasi_got;
sernavs[i] = derbasi_arr;
}
}
private static void printFile(){
alfabetBike();
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File (root.getAbsolutePath() + "/alfabetfolder");
dir.mkdirs();
File file = new File(dir, "alfabet_title.txt");
File file2 = new File(dir, "alfabet.txt");
try {
FileOutputStream f = new FileOutputStream(file,false);
PrintWriter pw = new PrintWriter(f);
FileOutputStream f2 = new FileOutputStream(file2,false);
PrintWriter pw2 = new PrintWriter(f2);
for (int i = 0; i < tips.length(); i++) {
for (int j = 0; j < hejmar[i]; j++) {
Log.d("ssdddddd", "add" + hejmar[i] + "-" + j + " " + sernavs[i][j].trim());
pw.println(sernavs[i][j]);
pw.flush();
pw2.println(sernavs[i][j] + "\n" + gotins[i][j].trim());
pw2.flush();
}
}
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i("erroooor", "******* File not found. Did you" +
" add a WRITE_EXTERNAL_STORAGE permission to the manifest?");
} catch (IOException e) {
e.printStackTrace();
}
}
public static int compareTwoString(String yek, String du) {
String d1 = yek, d2 = du;
d1 = strLower(d1, d1.charAt(0));
d2 = strLower(d2, d2.charAt(0));
int length, yaDirej;
if (yek.length() > du.length()) {
yaDirej = 1;
length = yek.length();
} else if (yek.length() < du.length()) {
yaDirej = 2;
length = du.length();
} else {
yaDirej = 0;
length = yek.length();
}
for (int i = 0; i < length; i++) {
int id1 = -1, id2 = -1;
if (i == d1.length() || i == du.length()) {
return yaDirej;
}
for (int j = 0; j < tips.length(); j++) {
if (d1.charAt(i) == tips.charAt(j)) id1 = j;
if (d2.charAt(i) == tips.charAt(j)) id2 = j;
}
if (id1 > id2)
return 2;
else if (id2 > id1)
return 1;
else
continue;
}
return 0;
}
public static String strLower(String str, char ziman){
final StringBuilder mutable = new StringBuilder(str);
final StringBuilder yedek = new StringBuilder(str.toLowerCase());
for (int i = 0; i < str.length(); i++) {
if (ziman == '?' && mutable.charAt(i) == 'I')
mutable.setCharAt(i, 'i');
else if (ziman == '*' && mutable.charAt(i) == 'I')
mutable.setCharAt(i, 'ı');
else mutable.setCharAt(i,yedek.charAt(i));
}
return mutable.toString();
}
edit:
in AndroidManifest.xml
<manifest...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
....
</manifest...>
You can build your own comparison so that, no matter what characters you are dealing with, it is going to sort the way you want. As you can see from the following code, I have set the comparison value by counting from a-z so that a=0, b=1...etc Then, I used the bubble sort strategy, which is basically switching the smallest elements continuously to the left and shifting others to the right.
public class Sort {
public static String compare(String compare1, String compare2) {
for (int i = 0; i < compare1.length(); i++) {
if (letterValue(compare1, i) < letterValue(compare2, i)) {
return compare1;
} else if (letterValue(compare1, i) > letterValue(compare2, i)) {
return compare2;
} else if (letterValue(compare1, i) == -1 || letterValue(compare2, i) == -1) {
System.out.print("Some letters are not within the alphabet!");
}
}
return compare1;
}
public static boolean smaller(String compare1, String compare2) {
if (compare(compare1, compare2).equalsIgnoreCase(compare1)) {
return true;
} else {
return false;
}
}
public static int letterValue(String input, int letterPosition) {
String order = "abcçdeêfghiîjklmnopqrsştûuvwxyz";
int value = -1;
for (int i = 0; i < order.length(); i++) {
if (input.toLowerCase().charAt(letterPosition) == order.charAt(i)) {
value = i;
}
}
return value;
}
public static void main(String[] args) {
String[] input = {"BARÊZ", "ÇÊneR", "ASTÛ", "badîn", "BADÎN"};
String swap;
int i, d;
for (i = 0; i < (input.length - 1); i++) {
for (d = 0; d < input.length - i - 1; d++) {
if (!smaller(input[d], input[d + 1])) {
swap = input[d];
input[d] = input[d + 1];
input[d + 1] = swap;
}
}
}
System.out.println("Sorted list: ");
for (i = 0; i < input.length; i++) {
System.out.print(input[i] + " ");
}
}
}
Output
Sorted list:
ASTÛ badîn BADÎN BARÊZ ÇÊneR

Performance enhancing for a string searching program in eclipse

I have written a program to search for a given phrase in a paragraph and enclose the phrase with a curly braces in that paragraph. I have used BoyerMoore's Algorithm for searching purpose.In the same time i also need to enhance the performance of the program. Though i got the required output the performance is disastrous.
Here is the code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
public class BoyerMoore {
static class Pair {
public int start, end;
Pair(int start, int end) {
this.start = start;
this.end = end;
}
public int weight() {
return end - start;
}
public boolean contains(int point) {
return start <= point && point <= end;
}
public int returnStart() {
return start;
}
}
static class Group {
public List<Pair> pairs = new ArrayList<Pair>();
public Pair maxWeight;
Group(Pair start) {
add(start);
}
Group(List<Pair> pairs) {
for (Pair pair : pairs) {
add(pair);
}
}
public boolean contains(Pair pair) {
for (Pair my : pairs) {
if (my.contains(pair.start) || my.contains(pair.end))
return true;
}
return false;
}
public void add(Pair pair) {
pairs.add(pair);
if (maxWeight == null || maxWeight.weight() < pair.weight())
maxWeight = pair;
}
}
public static List<Integer> match(String pattern, String text) {
List<Integer> matches = new ArrayList<Integer>();
int m = text.length();
int n = pattern.length();
Map<Character, Integer> rightMostIndexes = preprocessForBadCharacterShift(pattern);
int alignedAt = 0;
while (alignedAt + (n - 1) < m) {
for (int indexInPattern = n - 1; indexInPattern >= 0; indexInPattern--) {
int indexInText = alignedAt + indexInPattern;
char x = text.charAt(indexInText);
char y = pattern.charAt(indexInPattern);
if (indexInText >= m)
break;
if (x != y) {
Integer r = rightMostIndexes.get(x);
if (r == null) {
alignedAt = indexInText + 1;
} else {
int shift = indexInText - (alignedAt + r);
alignedAt += shift > 0 ? shift : 1;
}
break;
} else if (indexInPattern == 0) {
matches.add(alignedAt);
alignedAt++;
}
}
}
return matches;
}
private static Map<Character, Integer> preprocessForBadCharacterShift(
String pattern) {
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (int i = pattern.length() - 1; i >= 0; i--) {
char c = pattern.charAt(i);
if (!map.containsKey(c))
map.put(c, i);
}
return map;
}
public static void main(String[] args) throws IOException {
BufferedReader input = new BufferedReader(new InputStreamReader(
System.in));
ArrayList<String> ListOfAllPhrase = new ArrayList<String>();
List<Pair> pairs = new ArrayList<Pair>();
List<Group> groups = new ArrayList<Group>();
ListOfAllPhrase.add("protein");
ListOfAllPhrase.add("protein kinase");
ListOfAllPhrase.add("protein kinase A anchor protein");
ListOfAllPhrase.add("protein kinase A anchor proteins");
ListOfAllPhrase.add("protein kinase A anchor protein activity");
ListOfAllPhrase.add("IL-6");
ListOfAllPhrase.add("SOX5");
ListOfAllPhrase.add("NOX5");
System.out.println("Input a sentence: ");
String line = input.readLine();
char[] lineInChar = line.toCharArray();
long startTime = System.currentTimeMillis();
for (int i = 0; i < ListOfAllPhrase.size(); i++) {
// offset.add((ListOfAllPhrase.get(i)).length());
List<Integer> matches = match(ListOfAllPhrase.get(i).toLowerCase(),
line.toLowerCase());
for (Integer integer : matches) {
pairs.add(new Pair(integer, (ListOfAllPhrase.get(i)).length()
+ integer));
}
}
System.out.println("Total time taken: "
+ (System.currentTimeMillis() - startTime));
for (Pair pair : pairs) {
List<Group> intersects = new ArrayList<Group>();
for (Group group : groups) {
if (group.contains(pair)) {
intersects.add(group);
}
}
if (intersects.isEmpty()) {
groups.add(new Group(pair));
} else {
List<Pair> intervals = new ArrayList<Pair>();
intervals.add(pair);
for (Group intersect : intersects) {
intervals.addAll(intersect.pairs);
}
groups.removeAll(intersects);
groups.add(new Group(intervals));
}
}
StringBuilder newBuilder = new StringBuilder();
int flag = 1;
System.out.println(lineInChar.length);
for (int a = 0; a <= lineInChar.length; a++) {
for (Group group : groups) {
if (a == group.maxWeight.start) {
newBuilder.append("{");
flag = 1;
break;
}
if (a == group.maxWeight.end && a == lineInChar.length) {
newBuilder.append("}");
flag = 0;
break;
}
if (a == lineInChar.length && a == group.maxWeight.end + 1) {
newBuilder.append("}");
flag = 0;
break;
}
if (a == group.maxWeight.end) {
newBuilder.append("}");
flag = 1;
break;
}
}
if (flag == 0)
continue;
newBuilder.append(lineInChar[a]);
flag = 1;
}
System.out.println("Final output: " + newBuilder);
}
}
What can I implement or do to increase the performance of my program?
Should i switch to another string search algorithm?
If anyone could help me with this?
I think you implemented the Boyer-Moore algorithm like it is described. Although I would suggest this:
Avoid 'Expensive' operations in a for loop. For instance the toLowerCase() operations in your main method. Rewrite the loop (33% speed gain in my test):
for (int i = 0; i < ListOfAllPhrase.size(); i++) {
// offset.add((ListOfAllPhrase.get(i)).length());
List<Integer> matches = match(ListOfAllPhrase.get(i).toLowerCase(),
line.toLowerCase());
for (Integer integer : matches) {
pairs.add(new Pair(integer, (ListOfAllPhrase.get(i)).length()
+ integer));
}
}
To :
ArrayList<String> lowerCaseListOfPhrases = new ArrayList<String>(ListOfAllPhrase.size());
for (String phrase : ListOfAllPhrase) {
lowerCaseListOfPhrases.add(phrase.toLowerCase());
}
String lowerCaseLine = line.toLowerCase();
for (String phrase : lowerCaseListOfPhrases) {
List<Integer> matches = match(phrase, lowerCaseLine);
for (Integer integer : matches) {
pairs.add(new Pair(integer, phrase.length() + integer));
}
}
Take a look at this fast implementation (See http://algs4.cs.princeton.edu/53substring/BoyerMoore.java.html):
public static List<Integer> match2(String pattern, String text) {
List<Integer> result = new ArrayList<Integer>();
int[] right = new int[256]; // Assuming a 256 character encoding
for (int c = 0; c < 256; c++)
right[c] = -1;
for (int j = 0; j < pattern.length(); j++)
right[pattern.charAt(j)] = j;
int M = pattern.length();
int N = text.length();
int skip;
for (int i = 0; i <= N - M; i += skip) {
skip = 0;
for (int j = M-1; j >= 0; j--) {
if (pattern.charAt(j) != text.charAt(i+j)) {
skip = Math.max(1, j - right[text.charAt(i+j)]);
break;
}
}
if (skip == 0) { // found
result.add(i);
skip += pattern.length();
}
}
return result;
}
I get a performance increase of +- 50% when executing this test:
public static void main(String[] args) throws IOException {
String phrase = "protein kinase A anchor protein activity";
String txt = "This is a test protein kinase A anchor protein activityThis is a test protein kinase A anchor protein activityThis is ";
List<Integer> result1 = null;
List<Integer> result2 = null;
long currentTime = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
result1 = match(phrase, txt);
}
System.out.println("ExecutionTime match: " + (System.currentTimeMillis() - currentTime));
currentTime = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
result2 = match2(phrase, txt);
}
System.out.println("ExecutionTime match2: " + (System.currentTimeMillis() - currentTime));
Assert.assertTrue(result1.equals(result2));
}
Output:
ExecutionTime match: 5590
ExecutionTime match2: 2663
If you do not mind about Boyer-Moore algorithm, please use Java built-in functionality:
public static List match3(String pattern, String text) {
List result = new ArrayList();
int index = text.indexOf(pattern);
while (index >= 0) {
result.add(index);
index = text.indexOf(pattern, index + 1);
}
return result;
}

Categories

Resources