Equation parsing "100-x+200" and evaluating its value in java - java

The following code should be pretty self-evident. What I have made up so far to compute Y with variable x and some constants:
public static void main(String[] args) {
int x=50;
String str="100-x+200";
str=str.replaceAll("x", Integer.toString(x));
String [] arrComputeNumber = str.split("[-|+]");
String [] arrComputeOperator = str.split("[\\d]");
int y=Integer.parseInt(arrComputeNumber[0]);
for (int i = 0; i < arrComputeOperator.length; i++) {
if (arrComputeOperator[i].equals("-")) {
y-=Integer.parseInt(arrComputeNumber[i+1]);
} else if (arrComputeOperator[i].equals("+")) {
y+=Integer.parseInt(arrComputeNumber[i+1]);
}
}
System.out.println("y="+y);
}
Unfortunately it doesn't work since str.split("[\\d]") extracts wrongly.
It it extracts correctly I assume that above code would function correctly. Anyway this implementation is merely trivial and doesn't take parenthesis or +- combination (which becomes minus), etc. into consideration. I haven't found any better ways. Do you know any better ways to evaluate string as mathematical expression in Java?

You can use BeanShell. It is a Java interpreter.
Here is some code:
Interpreter interpreter = new Interpreter();
interpreter.eval("x = 50");
interpreter.eval("result = 100 - x + 200");
System.out.println(interpreter.get("result"));

Related

Generate patterns from a given string in java

Given a string str = ab12.
I'm trying to generate patterns as below
xbx2 ax1x abxx xx12
Here's one more example to make it a bit clear :
Original String 182d3c
Required pattern :
18xdxc 182x3x 18xx3c 182dxx 18xxxx See that 18 is constant and other two varying
x82dxc 1x2d3x xx2d3c 182dxx xx2dxx See now 2d is constant others are varying
so on and on...
Note that number of x in any pattern must be even.
I tried using regex but to no avail.
then i thought may be binary pattern generation algo will help (it seems somewhat like binary pattern with x), but still i'm not there. :(
If you need more info please comment, I'll be happy to share.
Any help would be greatly appreciated !
Thanks!
12 characters is a safe limit.
You can use bit-mask...Iterate through 0 to 2^l - 1, (where l = length of string) and check in the bit representation of i, if the number of set bits is even. If it is, mark the position of set bits as x's and keep the rest of the string.
This algorithm has complexity O(l * 2^l), which is fine as max(l) = 12. So, number of operations will be of the order 2.4e4, which is easily achievable in well under 1s.
EDIT: As requested, sample code in Java
EDIT2: Replaced previous code with new working code :)
import java.io.*;
import java.util.*;
import java.lang.*;
public class xes{
public static String convert(int n, int l){
StringBuilder s = new StringBuilder();
int g = 0;
while(n>0){
int c = n%2;
if(c==0)
s.append("0");
else{
s.append("1");
g++;
}
n/=2;
}
while(s.length()<l)
s.append("0");
if(g%2 == 0)
return ("" + s.reverse());
else
return "-1";
}
public static ArrayList<String> getAllPatterns(String s){
int l = s.length();
int p = (1<<l) - 1; //because you don't want all x's, so -1. 1<<l is same as power(2,l)
ArrayList<String> arr = new ArrayList<String>();
for(int i=1;i<p;i++){ //i started from i=1 since you don't want all characters visible in any string in arraylist...if you want, stat it with 0
String z = convert(i,l);
if(z.equals("-1"))
continue;
StringBuilder g = new StringBuilder(s);
for(int j=0; j < z.length(); j++){
if(z.charAt(j)=='1')
g.setCharAt(j,'x');
}
System.out.println(g);
arr.add("" + g);
}
return arr;
}
public static void main(String args[]){
ArrayList<String> patterns = getAllPatterns("1823");
}
}
This is the output:
18xx
1x2x
1xx3
x82x
x8x3
xx23
For another input, 1823ab, I'm getting all 30 possible (6C2 + 6C4) strings as output:
1823xx
182xax
182xxb
18x3ax
18x3xb
18xxab
18xxxx
1x23ax
1x23xb
1x2xab
1x2xxx
1xx3ab
1xx3xx
1xxxax
1xxxxb
x823ax
x823xb
x82xab
x82xxx
x8x3ab
x8x3xx
x8xxax
x8xxxb
xx23ab
xx23xx
xx2xax
xx2xxb
xxx3ax
xxx3xb
xxxxab

Extracting characters from a string and putting into specific arrays by type

I'm new to Java so I'm trying to write random programs to figure it out. I'm trying to write something that takes as user-input a quadratic equation like so: x^2 + 3x -1
Maybe this is too advanced (or maybe it isn't) but I'm wondering how to extract the characters one-by-one in a loop. If it was all digits I think I could use .isDigit() and save them to an array, but because they're different data types I'm not sure how to go about doing this. My 'code' so far looks like this
import java.lang.String;
import java.lang.StringBuffer;
import java.util.Scanner;
import java.lang.Character;
public class Lab
{
public static void main(String[] args)
{
Scanner user_input = new Scanner(System.in);
System.out.print("Please input the quadratic equation (ex: 2x^2 + 3x - 2): ");
String request = user_input.nextLine();
int myArr[];
String lettArr[];
for (int i = 0; i <= request.length(); i++)
{
String c = request.charAt(i);
if (request.isDigit(c))
{
myArr[1] += c;
}
if(request.isLowerCase(c))
{
lettArr[1] += c;
}
}
System.out.println(myArr[0]);
}
}
my .isDigit() and .isLowerCase() methods are not working. I think I'm using them in the right sense. This is pretty complex for my level and I'm wondering if this is a dead-end or an acceptable strategy.
Thanks.
I think what your are trying to do is to extract the coefficients from the user input. Your approach might work but there would be many case that you have to consider (+/- signs for example). Instead why don't you try Java's regular expressions
String input = "2x^2 - 4x + 1";
input = input.replaceAll("\\s", ""); //removes all whitespaces
Pattern p = Pattern.compile("(-?\\d+)x\\^2((\\+|-)\\d+)x((\\+|-)\\d+)");
Matcher m = p.matcher(input);
if (!m.matches()) {
System.out.println("Incorrect input");
return;
}
int a, b, c;
a = Integer.parseInt(m.group(1));
b = Integer.parseInt(m.group(2));
c = Integer.parseInt(m.group(4));
System.out.println(String.format("a=%d, b=%d, c=%d", a, b, c));
You can adapt this fragment and use it in your code. I , however, supposed that your coefficients are integer numbers. If you need them, instead, to be double you have to change the format of the given regex and also to change Integer.parseInt to Double.parseDouble. I could write this in more details if you are interested.
There are a few things wrong with your code:
public class Lab
{
public static void main(String[] args)
{
Scanner user_input = new Scanner(System.in);
System.out.print("Please input the quadratic equation (ex: 2x^2 + 3x - 2): ");
String request = user_input.nextLine();
int myArr[]; //not initialized
String lettArr[]; //should be a character type & not initialized
for (int i = 0; i <= request.length(); i++)
{
String c = request.charAt(i); // returns a char
if (request.isDigit(c))
{
myArr[1] += c; // not right, myArr is ints and c is a char
}
if(request.isLowerCase(c))
{
lettArr[1] += c; // not right
}
}
System.out.println(myArr[0]); //only prints one char (you might want this
}
}
1.
You are extracting a character from the input string and trying to add it to the second entry in an uninitialized array. You're line in code is:
myArr[1] += c;
myArr is an integer array and c is a character. You can't do that in java. What's more, you are trying to add a char to an int, which was not initialized in the first place!! The type of everything in an array must be the same. This gets more complicated when it comes to inheritance and such, but for now just know that you can't do that. If you wanted the Integer value of a character you can use:
Integer.parseInt(c)
I'm not sure what you are trying to do with your statement, but I'm 90% sure that it's not trying to do what you want it to. For reference:
myCharArr[i] = c;
assigns the i-th element (starting from 0) to the value of c. So if i=1 and myCharArr was initialized to 3 elements long, it would look like this:
[ ? | c | ?]
where ? is just a garbage value.
2.
In java you need to initialize your arrays, or use a more dynamic List object. The thing with primitive arrays is that their size cannot change, i.e. when an primitive array is initialized:
int arr[] = new int[5];
it stays the same size (in this case 5). If you use something like an ArrayList, you can add as many things as you want. The way you would initialize ArrayLists would be like:
ArrayList<Integer> intArr = new ArrayList<Integer>();
ArrayList<Character> charArr = new ArrayList<Character();
and with those initialized you can do:
intArr.add(someInt);
charArr.add(someChar);
You can use primitive arrays for this problem but it will save you a bit of trouble if you use Lists.
Read up on arrays.

A particular type of hash on a String concatenation

I need a specialised hash function h(X,Y) in Java with the following properties.
X and Y are strings.
h(X,Y) = h(Y,X).
X and Y are arbitrary length strings and there is no length limit on the result of h(X,Y) either.
h(X,Y) and h(Y,X) should not collide with h(A,B) = h(B,A) if X is not equal to A and Y is not equal to B.
h() does not need to be a secure hash function unless it is necessary to meet the aforementioned requirements.
Fairly high-performant but this is an open-ended criterion.
In my mind, I see requirements 2 and 4 slightly contradictory but perhaps I am worrying too much.
At the moment, what I am doing in Java is the following:
public static BigInteger hashStringConcatenation(String str1, String str2) {
BigInteger bA = BigInteger.ZERO;
BigInteger bB = BigInteger.ZERO;
for(int i=0; i<str1.length(); i++) {
bA = bA.add(BigInteger.valueOf(127L).pow(i+1).multiply(BigInteger.valueOf(str1.codePointAt(i))));
}
for(int i=0; i<str2.length(); i++) {
bB = bB.add(BigInteger.valueOf(127L).pow(i+1).multiply(BigInteger.valueOf(str2.codePointAt(i))));
}
return bA.multiply(bB);
}
I think this is hideous but that's why I am looking for nicer solutions. Thanks.
Forgot to mention that on a 2.53GHz dual core Macbook Pro with 8GB RAM and Java 1.6 on OS X 10.7, the hash function takes about 270 micro-seconds for two 8 (ASCII) character Strings. I suspect this would be higher with the increase in the String size, or if Unicode characters are used.
why not just add their hashCode's together?
Today I've decided to add my solution for this hash function problem. It was not tested very good and I did not measure its performance, so you can feed me back with your comments. My solution is situated below:
public abstract class HashUtil {
//determines that we want hash, that has size of 32 integers ( or 32*32 bits )
private static final int hash_size = 32;
//some constants that can be changed in sake of avoiding collisions
private static final BigInteger INITIAL_HASH = BigInteger.valueOf(7);
private static final BigInteger HASH_MULTIPLIER = BigInteger.valueOf(31);
private static final BigInteger HASH_DIVIDER = BigInteger.valueOf(2).pow(32*hash_size);
public static BigInteger computeHash(String arg){
BigInteger hash = new BigInteger(INITIAL_HASH.toByteArray());
for (int i=0;i<arg.length()/hash_size+1;i++){
int[] tmp = new int[hash_size];
for(int j=0;j<Math.min(arg.length()-32*i,32);j++){
tmp[i]=arg.codePointAt(i*hash_size+j);
}
hash = hash.multiply(HASH_MULTIPLIER).add(new BigInteger(convert(tmp)).abs()).mod(HASH_DIVIDER);
}
//to reduce result space to something meaningful
return hash;
}
public static BigInteger computeHash(String arg1,String arg2){
//here I don't forgot about reducing of result space
return computeHash(arg1).add(computeHash(arg2)).mod(HASH_DIVIDER);
}
private static byte[] convert(int[] arg){
ByteBuffer byteBuffer = ByteBuffer.allocate(arg.length*4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(arg);
return byteBuffer.array();
}
public static void main(String[] args){
String firstString="dslkjfaklsjdkfajsldfjaldsjflaksjdfklajsdlfjaslfj",secondString="unejrng43hti9uhg9rhe3gh9rugh3u94htfeiuwho894rhgfu";
System.out.println(computeHash(firstString,secondString).equals(computeHash(secondString,firstString)));
}
}
I suppose that my solution should not produce any collision for single string with length less then 32 (to be more precise, for single string with length less then hash_size variable value). Also it is not very easy to find collisions (as I think). To regulate hash conflicts probability for your particular task you can try another prime numbers instead of 7 and 31 in INITIAL_HASH and HASH_MULTIPLIER variables. What do you think about it? Is it good enought for you?
P.S. I think that it will be much better if you'll try much bigger prime numbers.
3) h(X,Y) and h(Y,X) should not collide with h(A,B) = h(B,A) if X is not equal to A and Y is not equal to B.
I think that this requirement rules any hash function that produces numbers that are smaller (on average) than the original Strings.
Any requirement of no collisions runs into the roadblock of the Pigeonhole Principle.
How strict are you being with requirement 4? If the answer is 'not completely strict' then you could just concatenate the two strings putting the smaller one first (this would result in a collision for h('A', 'B') and h('AB', ''))
If there are any characters which you are sure would never appear in the string values then you could use a single instance as a separator, which would fix the collision above.
From 4-th point we can get that h(x,"") should never collide with h(y,"") until x.equals(y) is true. So, you have no size limits on what produce h(x,y), cause it shoud produce unique result for each unique x. But there are infinite number of unique strings. This is not a correct hash function, I think.
Building on String#hashCode, this is not a perfect hash function, so it does not fulfill condition 4.
public static long hashStringConcatenation(String str1, String str2) {
int h1 = str1.hashCode();
int h2 = str2.hashCode();
if ( h1 < h2 )
{
return ((long)h1)<<32 & h2;
}
else
{
return ((long)h2)<<32 & h1;
}
}
Okay, #gkuzmin's comment made me think why I am doing the powers of 127. So, here's a slightly simpler version of the code. The changes are as follows:
I am no longer doing the powers of 127 but actually concatenating the codePointAt numbers as strings, converting the result into BigInteger for each input string and then adding the two BigIntegers.
To compact the answer, I am doing a mod 2^1024 on the final answer.
Speed is not any better (perhaps a little worse!) but then I think the way I am measuring the speed is not right because it probably also measures the time taken for the function call.
Here's the modified code. Does this fulfill all conditions, albeit 4 for such unfortunate cases where repetitions may occur over the 2^1024 result space?
public static BigInteger hashStringConcatenation(String str1, String str2) {
if(str1==null || str1.isEmpty() || str2 == null || str2.isEmpty()) {
return null;
}
BigInteger bA, bB;
String codeA = "", codeB = "";
for(int i=0; i<str1.length(); i++) {
codeA += str1.codePointAt(i);
}
for(int i=0; i<str2.length(); i++) {
codeB += str2.codePointAt(i);
}
bA = new BigInteger(codeA);
bB = new BigInteger(codeB);
return bA.add(bB).mod(BigInteger.valueOf(2).pow(1024));
}
I've decided to add another answer because #Anirban Basu have proposed another solution. So, I do not know how to provide link to his post and if somebody know how to do it - correct me.
Anirban's solution looks like this:
public static BigInteger hashStringConcatenation(String str1, String str2) {
if(str1==null || str1.isEmpty() || str2 == null || str2.isEmpty()) {
return null;
}
BigInteger bA, bB;
String codeA = "", codeB = "";
for(int i=0; i<str1.length(); i++) {
codeA += str1.codePointAt(i);
}
for(int i=0; i<str2.length(); i++) {
codeB += str2.codePointAt(i);
}
bA = new BigInteger(codeA);
bB = new BigInteger(codeB);
return bA.add(bB).mod(BigInteger.valueOf(2).pow(1024));
}
Your new solution now looks like a hash function, but it still has some problems. I suggest that you should think about this:
Maybe it will be better to throw NullPointerException or IllegalArgumentException when null was used as function argument? Are you sure, that you do not want to compute hash for empty strings?
To concatenate large amount of strings it is better to use StringBuffer instead of + operator. Use of this class will produce huge positive impact on your code performance.
Your hash function is not very secure - it is realy easy to compute strings, which will produce conflict.
You can try this code to check algorithm that can can demonstrate your hash function collision.
public static void main(String[] args){
String firstString=new StringBuffer().append((char)11).append((char)111).toString();
String secondString=new StringBuffer().append((char)111).append((char)11).toString();
BigInteger hash1 = hashStringConcatenation(firstString,"arbitrary_string");
BigInteger hash2 = hashStringConcatenation(secondString,"arbitrary_string");
System.out.println("Is hash equal: "+hash1.equals(hash2));
System.out.println("Conflicted values: {"+firstString+"},{"+secondString+"}");
}
So, It is realy easy to break your hash function. Moreover, it is good that it has 2^1024 result space, but a lot of real life conflicts for your implementation lies in very close and simple strings.
P.S. I think that you should read something about already developed hash algorithms, hash function that failed in a real life (like java String class hash function which computed hash using only 16 first characters in the past) and try to examine your solutions according to your requirements and real life. At least you can try to find hash conflict manually and if you succeed then your solution most likely already has some problems.
Here's my changed code according to #gkuzmin's suggestion:
public static BigInteger hashStringConcatenation(String str1, String str2) {
BigInteger bA = BigInteger.ZERO, bB = BigInteger.ZERO;
StringBuffer codeA = new StringBuffer(), codeB = new StringBuffer();
for(int i=0; i<str1.length(); i++) {
codeA.append(str1.codePointAt(i));
}
for(int i=0; i<str2.length(); i++) {
codeB.append(str2.codePointAt(i));
}
bA = new BigInteger(codeA.toString());
bB = new BigInteger(codeB.toString());
return bA.multiply(bB).mod(BigInteger.valueOf(2).pow(1024));
}
Note that in the result, I now multiply bA with bB instead of adding.
Also, added #gkuzmin's suggested test function:
public static void breakTest2() {
String firstString=new StringBuffer().append((char)11).append((char)111).toString();
String secondString=new StringBuffer().append((char)111).append((char)11).toString();
BigInteger hash1 = hashStringConcatenation(firstString,"arbitrary_string");
BigInteger hash2 = hashStringConcatenation(secondString,"arbitrary_string");
System.out.println("Is hash equal: "+hash1.equals(hash2));
System.out.println("Conflicted values: {"+firstString+"},{"+secondString+"}");
}
and another test with strings having only numeric values:
public static void breakTest1() {
Hashtable<String,String> seenTable = new Hashtable<String,String>();
for (int i=0; i<100; i++) {
for(int j=i+1; j<100; j++) {
String hash = hashStringConcatenation(""+i, ""+j).toString();
if(seenTable.contains(hash)) {
System.out.println("Duplication for " + seenTable.get(hash) + " with " + i + "-" + j);
}
else {
seenTable.put(hash, i+"-"+j);
}
}
}
}
The code runs. Of course, it is not an exhaustive check, but the breakTest1() function does not have any issues. #gkuzmin's function displays the following:
Is hash equal: true
Conflicted values: { o},{o }
Why do the two strings produce the same hash? Because they are effectively working with strings '11111arbitrary_string' in both cases. This is a problem.
How about the slightly modified function now?
public static BigInteger hashStringConcatenation(String str1, String str2) {
BigInteger bA = BigInteger.ZERO, bB = BigInteger.ZERO;
StringBuffer codeA = new StringBuffer(), codeB = new StringBuffer();
for(int i=0; i<str1.length(); i++) {
codeA.append(str1.codePointAt(i)).append("0");
}
for(int i=0; i<str2.length(); i++) {
codeB.append(str2.codePointAt(i)).append("0");
}
bA = new BigInteger(codeA.toString());
bB = new BigInteger(codeB.toString());
return bA.multiply(bB).mod(BigInteger.valueOf(2).pow(1024));
}
Here, we add a separator character "0" between each character codes, so the combination for characters 11 111 and 111 11 will no longer confuse the function because the concatenation will produce 110111 and 111011. However, it still will not break requirement 2 of the original question.
So does this now solve the problem albeit within the limits of the 2^1024 range?

CharacterSet to String and Int to Char casting

New to java. Trying to familiarize myself with syntax and overall language structure.
I am trying to mimic this php function in java which just converts all instances of a number to a particular character
for($x=10;$x<=20;$x++){
$string = str_replace($x, chr($x+55), $string);
}
so in php if a string was 1090412 it would be converted to something like A904C.
I am trying to do this in java by using string.replace but I cant for the life of me figure out how to cast the variables properly. I know that I can convert an integer to a character by casting it as (char), but not sure where to go from there. this gives me a compile error expecting a character set.
string=1090412;
for (x = 10; x <= 35; x++) {
string.replace( x, (char) (x + 55));
}
Well, although not the best way to do this, here is a method that works
import java.lang.*;
public class T {
public static void main(String[] args) {
String s = "1090412";
for (int i = 10; i <= 20; i++) {
s = s.replace(Integer.toString(i), "" + (char)(i + 55));
}
System.out.println(s);
}
}
The java.lang.String object has a replace method on it. It is overloaded to take either two char parameters or two CharSequence objects. The "" + (char)(i + 55) is just a quick way to create a CharSequence.

Translating a String containing a binary value to Hex

I am trying to translate a String that contains a binary value (e.g. 000010001010011) to it's Hex value.(453)
I've been trying several options, but mostly I get a converted value of each individual character. (0=30 1=31)
I have a function that translates my input to binary code through a non-mathematical way, but through a series of "if, else if" statements. (the values are not calculated, because they are not standard.) The binary code is contained in a variable String "binOutput"
I currently have something like this:
String bin = Integer.toHexString(Integer.parseInt(binOutput));
But this does not work at all.
Try using Integer.parseInt(binOutput, 2) instead of Integer.parseInt(binOutput)
Ted Hopp beat me to it, but here goes anyway:
jcomeau#intrepid:/tmp$ cat test.java; java test 000010001010011
public class test {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("The value of " + args[i] + " is " +
Integer.toHexString(Integer.parseInt(args[i], 2)));
}
}
}
The value of 000010001010011 is 453

Categories