Java calculator version 4 - java

The calculator is now almost working. It now gives me the same answer for every equation it reads in?
the output ends up as:
49+62*61-36
15.666666666666668
4/64
15.666666666666668
(53+26)
15.666666666666668
0*72
15.666666666666668
21-85+75-85
15.666666666666668
90*76-50+67
15.666666666666668
46*89-15
15.666666666666668
34/83-38
15.666666666666668
20/76/14+92-15
15.666666666666668
5*10/3-1
15.666666666666668
Instead of having the answer for each equation there?
Have i missed something out in my methods?
Thanks
All code is shown below. Any help will be much appreciated.
Stack class:
import java.util.Iterator;
import java.util.NoSuchElementException;
public class myStack<Item> implements Iterable<Item> {
private int N; // size of the stack
private Node first; // top of stack
private class Node {
private Item item;
private Node next;
}
/**
* Create an empty stack.
*/
public myStack() {
first = null;
N = 0;
assert check();
}
public boolean isEmpty() {
return first == null;
}
public int size() {
return N;
}
public void push(Item item) {
Node oldfirst = first;
first = new Node();
first.item = item;
first.next = oldfirst;
N++;
assert check();
}
public Item pop() {
if (isEmpty())
throw new NoSuchElementException("Stack underflow");
Item item = first.item; // save item to return
first = first.next; // delete first node
N--;
assert check();
return item; // return the saved item
}
public Item peek() {
if (isEmpty())
throw new NoSuchElementException("Stack underflow");
return first.item;
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
// check internal invariants
private boolean check() {
if (N == 0) {
if (first != null)
return false;
} else if (N == 1) {
if (first == null)
return false;
if (first.next != null)
return false;
} else {
if (first.next == null)
return false;
}
// check internal consistency of instance variable N
int numberOfNodes = 0;
for (Node x = first; x != null; x = x.next) {
numberOfNodes++;
}
if (numberOfNodes != N)
return false;
return true;
}
public Object[] toArray(String[] elementData) {
return (Object[]) elementData.clone();
}
public Iterator<Item> iterator() {
return new ListIterator();
}
// did not implement remove as it was not needed
private class ListIterator implements Iterator<Item> {
private Node current = first;
public boolean hasNext() {
return current != null;
}
public void remove() {
throw new UnsupportedOperationException();
}
public Item next() {
if (!hasNext())
throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
}
}
Array list class
import java.util.Arrays;
public class myArrayList<Item>{
private Object[] myStore;
private int actSize = 0;
public myArrayList() {
myStore = new Object[100];
}
public Object get(int index) {
if (index < actSize) {
return myStore[index];
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
public void add(Object obj) {
if (myStore.length - actSize <= 0) {
increaseListSize();
}
myStore[actSize++] = obj;
}
public Object remove(int index) {
if (index < actSize) {
Object obj = myStore[index];
myStore[index] = null;
int tmp = index;
while (tmp < actSize) {
myStore[tmp] = myStore[tmp + 1];
myStore[tmp + 1] = null;
tmp++;
}
actSize--;
return obj;
} else {
throw new ArrayIndexOutOfBoundsException();
}
}
public int size() {
return actSize;
}
private void increaseListSize() {
myStore = Arrays.copyOf(myStore, myStore.length * 2);
}
#SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size())
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(myStore, size(), a.getClass());
System.arraycopy(myStore, 0, a, 0, size());
if (a.length > size())
a[size()] = null;
return a;
}
}
The TestClass for equation handling
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
public class TestClass {
private static final int LEFT_ASSOC = 0;
private static final int RIGHT_ASSOC = 1;
static String OPERATORS1 = "+-*/()";
// Operators
private static final Map<String, int[]> OPERATORS = new HashMap<String, int[]>();
static {
// Map<"token", []{precedence, associativity}>
OPERATORS.put("+", new int[] { 0, LEFT_ASSOC });
OPERATORS.put("-", new int[] { 0, LEFT_ASSOC });
OPERATORS.put("*", new int[] { 5, LEFT_ASSOC });
OPERATORS.put("/", new int[] { 5, LEFT_ASSOC });
OPERATORS.put("(", new int[] {1, LEFT_ASSOC});
OPERATORS.put(")", new int[] {1, LEFT_ASSOC});
}
private static boolean isOperator(String token) {
return OPERATORS.containsKey(token);
}
// Test associativity of operator token
private static boolean isAssociative(String token, int type) {
if (!isOperator(token)) {
throw new IllegalArgumentException("Invalid token: " + token);
}
if (OPERATORS.get(token)[1] == type) {
return true;
}
return false;
}
// Compare precedence of operators.
private static final int cmpPrecedence(String token1, String token2) {
if (!isOperator(token1) || !isOperator(token2)) {
throw new IllegalArgumentException("Invalid tokens: " + token1
+ " " + token2);
}
return OPERATORS.get(token1)[0] - OPERATORS.get(token2)[0];
}
public static String[] infixToRPN(String[] inputTokens) {
myArrayList<String> out = new myArrayList<String>();
myStack<String> stack = new myStack<String>();
// For each token
for (String token : inputTokens) {
StringTokenizer tokens = new StringTokenizer(token,OPERATORS1,true);
while (tokens.hasMoreTokens()) {
token = tokens.nextToken();
// If token is an operator
if (isOperator(token)) {
// While stack not empty AND stack top element
// is an operator
while (!stack.isEmpty() && isOperator(stack.peek())) {
if ((isAssociative(token, LEFT_ASSOC) && cmpPrecedence(
token, stack.peek()) <= 0)
|| (isAssociative(token, RIGHT_ASSOC) && cmpPrecedence(
token, stack.peek()) < 0)) {
out.add(stack.pop());
continue;
}
break;
}
// Push the new operator on the stack
stack.push(token);
}
// If token is a left bracket '('
else if (token.equals("(")) {
stack.push(token);
}
// If token is a right bracket ')'
else if (token.equals(")")) {
while (!stack.isEmpty() && !stack.peek().equals("(")) {
out.add(stack.pop());
}
stack.pop();
}
// If token is a number
else {
out.add(token);
}
}
while (!stack.isEmpty()) {
out.add(stack.pop());
}
}
String[] output = new String[out.size()];
return out.toArray(output);
}
public static double RPNtoDouble(String[] tokens) {
myStack<String> stack = new myStack<String>();
// For each token
for (String token : tokens) {
//System.out.println( "Working this token: " + token );
// If the token is a value push it onto the stack
if (!isOperator(token)) {
stack.push(token);
} else {
// Token is an operator: pop top two entries
Double d2 = Double.valueOf(stack.pop());
Double d1 = Double.valueOf(stack.pop());
// Get the result
Double result = token.compareTo("+") == 0 ? d1 + d2 : token
.compareTo("-") == 0 ? d1 - d2
: token.compareTo("*") == 0 ? d1 * d2 : d1 / d2;
// Push result onto stack
stack.push(String.valueOf(result));
}
}
return Double.valueOf(stack.pop());
}
static public void main(String[] args) throws IOException {
File file = new File("testEquations.txt");
String[] lines = new String[1];
try {
FileReader reader = new FileReader(file);
#SuppressWarnings("resource")
BufferedReader buffReader = new BufferedReader(reader);
int x = 0;
String s;
while ((s = buffReader.readLine()) != null) {
lines[x] = s;
x++;
}
} catch (IOException e) {
System.exit(0);
}
// test printing string array
for (String s : lines) {
System.out.println("" + s);
String[] output =infixToRPN(lines);
System.out.println(RPNtoDouble(output));
}
}
}

Your problem is here:
String[] lines = new String[1];
try {
FileReader reader = new FileReader(file);
#SuppressWarnings("resource")
BufferedReader buffReader = new BufferedReader(reader);
int x = 0;
String s;
while ((s = buffReader.readLine()) != null) {
lines[x] = s;
x++;
}
...
you define array of string with a size = 1 but you don't check inside the loop if x is getting out of the borders of this array.
Do somethink like this:
int Size = // define the size..;
String[] lines = new String[Size];
...
while (x < Size && (s = buffReader.readLine()) != null)) {
lines[x] = s;
x++;
}
when your x becames bigger then Size, x < Size will evaluate false, thus getting out of the loop.
About one of the error you are getting ArrayIndexOutOfBoundsException:
Thrown to indicate that an array has been accessed with an illegal
index. The index is either negative or greater than or equal to the
size of the array. (source)
The other error NoSuchElementException :
Thrown by the nextElement method of an Enumeration to indicate that
there are no more elements in the enumeration (source).
Another problem is here:
// test printing string array
for (String s : lines)
{
System.out.println("" + s);
String[] output =infixToRPN(lines);
System.out.println(RPNtoDouble(output));
}
You have to pass s, and not lines into method infixToRPN, thats why you are getting the same output, because you are giving the same input.
Remember that infixToRPN receives a String [] not a string like 's', but this I leave to you to find a workaround.

Related

How do i properly add characters to string in recursion

So i have this function EDIT:Whole program as requested
//This is a java program to construct Expression Tree using Infix Expression
import java.io.*;
public class Infix_Expression_Tree
{
public static void main(String args[]) throws IOException
{
String result="";
File vhod = new File(args[0]);
try{
BufferedReader reader = new BufferedReader(new FileReader(vhod));
Tree t1 = new Tree();
String a = reader.readLine();
t1.insert(a);
t1.traverse(1,result);
System.out.println("rez "+ result);
ch = reader.readLine();
}catch(IOException e){
e.printStackTrace();
}
}
}
class Node
{
public char data;
public Node leftChild;
public Node rightChild;
public Node(char x)
{
data = x;
}
public void displayNode()
{
System.out.print(data);
}
}
class Stack1
{
private Node[] a;
private int top, m;
public Stack1(int max)
{
m = max;
a = new Node[m];
top = -1;
}
public void push(Node key)
{
a[++top] = key;
}
public Node pop()
{
return (a[top--]);
}
public boolean isEmpty()
{
return (top == -1);
}
}
class Stack2
{
private char[] a;
private int top, m;
public Stack2(int max)
{
m = max;
a = new char[m];
top = -1;
}
public void push(char key)
{
a[++top] = key;
}
public char pop()
{
return (a[top--]);
}
public boolean isEmpty()
{
return (top == -1);
}
}
class Conversion
{
private Stack2 s;
private String input;
private String output = "";
public Conversion(String str)
{
input = str;
s = new Stack2(str.length());
}
public String inToPost()
{
for (int i = 0; i < input.length(); i++)
{
char ch = input.charAt(i);
switch (ch)
{
case '+':
gotOperator(ch, 2);
break;
case '*':
gotOperator(ch,1);
break;
case '/':
gotOperator(ch, 3);
break;
case '(':
s.push(ch);
break;
case ')':
gotParenthesis();
//s.pop();
break;
default:
//gotOperator(ch, 0);
//break;
output = output + ch;
}
}
while (!s.isEmpty())
output = output + s.pop();
//System.out.println("to je output iz inToPost " +output);
return output;
}
private void gotOperator(char opThis, int prec1)
{
while (!s.isEmpty())
{
char opTop = s.pop();
if (opTop == '(')
{
s.push(opTop);
break;
} else
{
int prec2;
if (opTop == '+')
prec2 = 2;
else if(opTop=='*')
prec2=1;
else
prec2 = 3;
if (prec2 <= prec1)
{
s.push(opTop);
break;
} else
output = output + opTop;
}
}
s.push(opThis);
}
private void gotParenthesis()
{
while (!s.isEmpty())
{
char ch = s.pop();
if (ch == '(')
break;
else
output = output + ch;
}
}
}
class Tree
{
private Node root;
public Tree()
{
root = null;
}
public void insert(String s)
{
Conversion c = new Conversion(s);
s = c.inToPost();
Stack1 stk = new Stack1(s.length());
s = s + "#";
int i = 0;
char symbol = s.charAt(i);
Node newNode;
while (symbol != '#')
{
if (symbol >= '0' && symbol <= '9' || symbol >= 'A'
&& symbol <= 'Z' || symbol >= 'a' && symbol <= 'z')
{
newNode = new Node(symbol);
stk.push(newNode);
} else if (symbol == '+' || symbol == '/'
|| symbol == '*')
{
Node ptr1=null;
Node ptr2=null;
//if(!stk.isEmpty()){
ptr1 = stk.pop();
if(!stk.isEmpty()){
ptr2 = stk.pop();
}
//}
newNode = new Node(symbol);
newNode.leftChild = ptr2;
newNode.rightChild = ptr1;
stk.push(newNode);
}
/*else if(symbol=='/'){
Node ptr = stk.pop();
newNode = new Node(symbol);
newNode.leftChild = ptr;
newNode.rightChild=null;
stk.push(newNode);
}*/
symbol = s.charAt(++i);
}
root = stk.pop();
}
public void traverse(int type,String result)
{
System.out.println("Preorder Traversal:- ");
preOrder(root,result);
}
private void preOrder(Node localRoot, String result)
{
if(root==null){
return;
}
if (localRoot != null)
{
if(localRoot.data == '/'){
preOrder(localRoot.leftChild,result);
result=result + localRoot.data;
//StringBuilder stringBuilder1 = new StringBuilder();
//stringBuilder1.append(result).append(localRoot.data);
System.out.println(result);
//localRoot.displayNode();
preOrder(localRoot.rightChild,result);
return;
}else{
//System.out.println("trenutni root je" );
//localRoot.displayNode();
result=result + localRoot.data;
// StringBuilder stringBuilder1 = new StringBuilder();
//stringBuilder1.append(result).append(localRoot.data);
System.out.println(result);
preOrder(localRoot.leftChild,result);
//result=result + localRoot.data;
//System.out.print(root.data);
preOrder(localRoot.rightChild,result);
//System.out.print(root.data);
//preOrder(localRoot.rightChild);
return;
}
}
}
}
my problem with it is that with localRoot.DisplayNode() i get the result i want. But when i add the same thing to the String result it adds data, until i get to leaf of the tree(leaf doesnt have left/right child) so it returns to previous recursive call, and goes to right child, here somewhere the leaf(from which we came back) isnt in String anymore. How do i fix this?
String is defined in main method

How do I fix this ArrayIndexOutOfBoundsException in my hashtable?

I was wondering if anyone could help me this ArrayIndexOutOfBoundsException that occurs when trying to run a tester class.
The exception occurs at the remove method within the hashtable file. I have tried switching out my code with my friend's code but that didn't work either.
Any help would be greatly appreciated
===========================================================================
Here is the HashTable :
public class HashTable {
Object[] hTable;
int mSize;
int size;
HashTable() {
mSize = 101;
hTable = new Object[mSize];
}
HashTable(int initCap) {
mSize = initCap;
}
Object put(Object key, Object value) {
if (size == mSize) {
throw new IllegalStateException("No room within the hashtable");
}
int hashC = key.hashCode();
int index = hashC % mSize;
size++;
while (index < hTable.length) {
if (hTable[index] == null) {
hTable[index] = new Entry(key, value);
size++;
return null;
} else if (((Entry) hTable[index]).key.equals(key)) {
Object prevVal = ((Entry) hTable[index]).val;
hTable[index] = new Entry(key, value);
return prevVal;
} else if (((Entry) hTable[index]).rCheck) {
hTable[index] = new Entry(key, value);
while (index < hTable.length) {
index++;
if (hTable[index] == null) {
size++;
return null;
} else if (((Entry) hTable[index]).key.equals(key)) {
Object prevVal = ((Entry) hTable[index]).val;
((Entry) hTable[index]).remove();
return prevVal;
}
}
}
index++;
}
if (hTable[index] == null) {
hTable[index] = new Entry(key, value);
return null;
} else {
Object oldEntry = ((Entry) hTable[index]).val;
hTable[index] = new Entry(key, value);
return oldEntry;
}
}
Object get(Object key) {
int hashC = key.hashCode();
int index = hashC % mSize;
return ((Entry) hTable[index]).val;
}
Object remove(Object key) {
int hashC = key.hashCode();
int index = hashC % mSize;
Object returnObj = null;
while (hTable[index] != null) { //here is where the OutOfBounds error occurs
if (((Entry) hTable[index]).key.equals(key)) {
returnObj = ((Entry) hTable[index]).val;
((Entry) hTable[index]).remove();
size--;
break;
}
index++;
}
return returnObj;
}
int size() {
return size;
}
#Override
public String toString() {
String returnString = "";
for (int i = 0; i < hTable.length; i++) {
if (hTable[i] == null || ((Entry) hTable[i]).rCheck) {
returnString += "dummy\n";
continue;
}
returnString += "Index: " + i +
" \n Key: " + ((Integer) (((Entry) hTable[i]).key)).intValue() % 101 +
"\nValue: " + (String) (((Entry) hTable[i]).val) +
"\n++++++++++++++++++++++++++++++++++++++++++++++\n";
}
return returnString;
}
private class Entry {
Object key;
public boolean rCheck;
public Object val;
Entry() {
key = null;
val = null;
rCheck = false;
}
Entry(Object k, Object v) {
key = k;
val = v;
rCheck = false;
}
Object value() {
return val;
}
Object key() {
return key;
}
void remove() {
rCheck = true;
}
public String toString() {
return "";
}
}
}
Here is the hash table tester:
import java.io.*;
import java.util.*;
public class hashTest {
public static void main(String args[]) throws FileNotFoundException {
HashTable hashTable = new HashTable();
Scanner fileRead = new Scanner(new File("data1.txt"));
while(fileRead.hasNext()) {
Object key = fileRead.next();
fileRead.next();
Object value = fileRead.nextLine();
hashTable.put(key, value);
System.out.println(hashTable.get(key));
}
Scanner fileRead2 = new Scanner(new File("data2.txt"));
while(fileRead2.hasNext()){
Object key = fileRead2.next();
hashTable.remove(key);
fileRead2.nextLine();
}
Scanner fileRead3 = new Scanner(new File("data3.txt"));
while(fileRead3.hasNext()){
Object key = fileRead3.next();
fileRead3.next();
Object value = fileRead3.nextLine();
hashTable.put(key, value);
}
Scanner fileRead4 = new Scanner(new File("data4.txt"));
while(fileRead4.hasNext()){
Object key = fileRead4.next();
fileRead4.next();
Object value = fileRead4.nextLine();
hashTable.put(key, value);
}
}
}
===========================================================================
In the shared google drive link below you will find a zip containing data inputs.
https://drive.google.com/file/d/1iYrzWl9mtv_io3q7K1_m2EtPFUXGbC3p/view?usp=sharing
Your Problem is at this code block:
while (index < hTable.length) {
index++;
if (hTable[index] == null)...
At the last iteration index will be the same as hTable.length. In your Example index will be 100 where the condition will be accepted. In the next step index will be incremented: index = 101. At hTable[101] the ArrayIndexOutOfBoundsException will occur.

DFS puzzle game solver (java)

I'm working with DFS solver on 8 puzzle game. This code print all children from the tree until the correct state, but I want to print only the correct solution.
My output:
120
345
678
125
340
678
102
345
678
125
348
670
125
304
678
142
305
678
012
345
678
Expected output:
120
345
678
102
345
678
012
345
678
Code:
public class puzzle {
public static LinkedHashSet<String> OPEN = new LinkedHashSet<String>();
public static HashSet<String> CLOSED = new HashSet<String>();
public static boolean STATE = false;
public static void main(String args[]) {
int statesVisited = 0;
String start = "120345678";
String goal = "012345678";
String X = "";
String temp = "";
OPEN.add(start);
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
print(X);
int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE
if (X.equals(goal)) {
System.out.println("SUCCESS");
STATE = true;
} else {
// generate children
CLOSED.add(X);
temp = up(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
temp = down(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
temp = left(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
temp = right(X, pos);
if (!(temp.equals("-1")))
OPEN.add(temp);
}
}
}
/*
* MOVEMENT UP
*/
public static String up(String s, int p) {
String str = s;
if (!(p < 3)) {
char a = str.charAt(p - 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 3)) + '0' + newS.substring(p - 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT DOWN
*/
public static String down(String s, int p) {
String str = s;
if (!(p > 5)) {
char a = str.charAt(p + 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 3)) + '0' + newS.substring(p + 4);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT LEFT
*/
public static String left(String s, int p) {
String str = s;
if (p != 0 && p != 3 && p != 7) {
char a = str.charAt(p - 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 1)) + '0' + newS.substring(p);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT RIGHT
*/
public static String right(String s, int p) {
String str = s;
if (p != 2 && p != 5 && p != 8) {
char a = str.charAt(p + 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 1)) + '0' + newS.substring(p + 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
public static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
DFS returns the first path it finds. To get the shortest path use BFS.
You can use a map
private static Map<String, List<String>> paths = new HashMap<>();
to map each node (state) to the path that led to it:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
public class puzzle {
private static LinkedHashSet<String> OPEN = new LinkedHashSet<>();
private static HashSet<String> CLOSED = new HashSet<>();
private static Map<String, List<String>> paths = new HashMap<>();
public static boolean STATE = false;
public static void main(String args[]) {
String start = "120345678";
String goal = "012345678";
String X = "";
String temp = "";
OPEN.add(start);
paths.put(start, Arrays.asList(start));
while (OPEN.isEmpty() == false && STATE == false) {
X = OPEN.iterator().next();
OPEN.remove(X);
print(X);
int pos = X.indexOf('0'); // get position of ZERO or EMPTY SPACE
if (X.equals(goal)) {
System.out.println("SUCCESS" +"\n" + paths.get(X));
STATE = true;
} else {
// generate children
CLOSED.add(X);
temp = up(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
temp = down(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
temp = left(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
temp = right(X, pos);
if (!temp.equals("-1")) {
OPEN.add(temp);
updatePaths(temp, paths.get(X));
}
}
}
}
static void updatePaths(String s, List<String> path){
if(paths.containsKey(s)) return;
List<String> newPath = new ArrayList<>(path);
newPath.add(s);
paths.put(s, newPath);
}
/*
* MOVEMENT UP
*/
public static String up(String s, int p) {
String str = s;
if (!(p < 3)) {
char a = str.charAt(p - 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p - 3) + '0' + newS.substring(p - 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT DOWN
*/
public static String down(String s, int p) {
String str = s;
if (!(p > 5)) {
char a = str.charAt(p + 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p + 3) + '0' + newS.substring(p + 4);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT LEFT
*/
public static String left(String s, int p) {
String str = s;
if (p != 0 && p != 3 && p != 7) {
char a = str.charAt(p - 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p - 1) + '0' + newS.substring(p);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
/*
* MOVEMENT RIGHT
*/
public static String right(String s, int p) {
String str = s;
if (p != 2 && p != 5 && p != 8) {
char a = str.charAt(p + 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, p + 1) + '0' + newS.substring(p + 2);
}
// Eliminates child of X if its on OPEN or CLOSED
if (!OPEN.contains(str) && CLOSED.contains(str) == false)
return str;
else
return "-1";
}
public static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
Online code can be reviewed and executed here and a refactored version here
We need somehow save relation between steps to find only steps from successful path.
Here is my solution:
public class Puzzle {
public static LinkedHashSet<Step> open = new LinkedHashSet<>();
public static HashSet<Step> closed = new HashSet<>();
public static boolean problemSolved = false;
private static class Step {
final String data;
Step previous = null;
Step(String data) {
this.data = data;
}
Step(Step previous, String data) {
this.previous = previous;
this.data = data;
}
public String getData() {
return data;
}
public Step getPrevious() {
return previous;
}
#Override
public String toString() {
return new StringBuilder()
.append(data.substring(0, 3))
.append("\r\n")
.append(data.substring(3, 6))
.append("\r\n")
.append(data.substring(6, 9))
.toString();
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Step)) {
return false;
}
if (obj == this) {
return true;
}
return this.getData().equals(((Step) obj).getData());
}
#Override
public int hashCode() {
return this.getData().hashCode();
}
}
public static void main(String args[]) {
int statesVisited = 0;
Step startStep = new Step("120345678");
Step goalStep = new Step("012345678");
Step currentStep;
open.add(startStep);
while (!open.isEmpty() && !problemSolved) {
currentStep = open.iterator().next();
open.remove(currentStep);
// print(currentStep);
if (currentStep.equals(goalStep)) {
System.out.println("SUCCESS PATH: \r\n");
printSuccessPath(
getSuccessPathFromFinishStep(currentStep) // here currentStep is finish step
);
problemSolved = true;
} else {
// generate children
closed.add(currentStep);
Step nextStep = up(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
nextStep = down(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
nextStep = left(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
nextStep = right(currentStep);
if (nextStep != null) {
open.add(nextStep);
}
}
}
}
/*
* MOVEMENT UP
*/
public static Step up(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (!(p < 3)) {
char a = str.charAt(p - 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 3)) + '0' + newS.substring(p - 2);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
/*
* MOVEMENT DOWN
*/
public static Step down(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (!(p > 5)) {
char a = str.charAt(p + 3);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 3)) + '0' + newS.substring(p + 4);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
/*
* MOVEMENT LEFT
*/
public static Step left(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (p != 0 && p != 3 && p != 7) {
char a = str.charAt(p - 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p - 1)) + '0' + newS.substring(p);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
/*
* MOVEMENT RIGHT
*/
public static Step right(Step step) {
int p = step.getData().indexOf('0');
String str = step.getData();
if (p != 2 && p != 5 && p != 8) {
char a = str.charAt(p + 1);
String newS = str.substring(0, p) + a + str.substring(p + 1);
str = newS.substring(0, (p + 1)) + '0' + newS.substring(p + 2);
}
Step nexStep = new Step(step, str); // Creates new step with step as previous one
// Eliminates child of X if its on open or closed
if (!open.contains(nexStep) && !closed.contains(nexStep))
return nexStep;
else
return null;
}
private static void print(Step s) {
System.out.println(s);
System.out.println();
}
private static void printSuccessPath(List<Step> successPath) {
for (Step step : successPath) {
print(step);
}
}
private static List<Step> getSuccessPathFromFinishStep(Step finishStep) {
LinkedList<Step> successPath = new LinkedList<>();
Step step = finishStep;
while (step != null) {
successPath.addFirst(step);
step = step.getPrevious();
}
return successPath;
}
}
I've refactored your code a bit. And introduced new class Step which allows us to save relation between current step and previous one.
Logic is a bit complicated, but feel free to ask additional question if something if not clear for you)
And, by the way, here is the result:
SUCCESS PATH:
120
345
678
102
345
678
012
345
678
So, a clean(er) solution that does what you've asked for looks like this:
package basic;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
public class Puzzle {
private static class Node {
private final Node previous;
private final String data;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
return result;
}
public Node getPrevious() {
return previous;
}
public String getData() {
return data;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
return true;
}
public Node(String data) {
this.data = data;
this.previous = null;
}
public Node(String data, Node previous) {
this.data = data;
this.previous = previous;
}
}
public static void main(String args[]) {
Queue<Node> open = new LinkedList<>();
Set<Node> closed = new HashSet<>();
Node start = new Node("120345678");
Node goal = new Node("012345678");
open.add(start);
boolean solving = true;
while (!open.isEmpty() && solving) {
Node current = open.poll();
int pos = current.getData().indexOf('0');
if (!closed.contains(current)) {
if (current.equals(goal)) {
printPath(current);
System.out.println("SUCCESS");
solving = false;
} else {
// generate children
up(current, pos, open, closed);
down(current, pos, open, closed);
left(current, pos, open, closed);
right(current, pos, open, closed);
closed.add(current);
}
}
}
}
/*
* MOVEMENT UP
*/
private static void up(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition >= 3) {
char substitutedChar = current.getData().charAt(zeroPosition - 3);
open.add(new Node(current.getData().substring(0, zeroPosition - 3) + '0'
+ current.getData().substring(zeroPosition - 2, zeroPosition) + substitutedChar
+ current.getData().substring(zeroPosition + 1), current));
}
}
/*
* MOVEMENT DOWN
*/
private static void down(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition <= 5) {
char substitutedChar = current.getData().charAt(zeroPosition + 3);
open.add(new Node(current.getData().substring(0, zeroPosition) + substitutedChar
+ current.getData().substring(zeroPosition + 1, zeroPosition + 3) + '0'
+ current.getData().substring(zeroPosition + 4), current));
}
}
/*
* MOVEMENT LEFT
*/
private static void left(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition % 3 != 0) {
char substitutedChar = current.getData().charAt(zeroPosition - 1);
open.add(new Node(current.getData().substring(0, zeroPosition - 1) + '0' + substitutedChar
+ current.getData().substring(zeroPosition + 1), current));
}
}
/*
* MOVEMENT RIGHT
*/
private static void right(Node current, int zeroPosition, Queue<Node> open, Set<Node> closed) {
if (zeroPosition % 3 != 2) {
char substitutedChar = current.getData().charAt(zeroPosition - 1);
open.add(new Node(current.getData().substring(0, zeroPosition) + substitutedChar + '0'
+ current.getData().substring(zeroPosition + 2), current));
}
}
private static void printPath(Node current) {
Stack<String> stack = new Stack<>();
for (; current != null; current = current.getPrevious()) {
stack.push(current.getData());
}
while (!stack.isEmpty()) {
print(stack.pop());
}
}
private static void print(String s) {
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3, 6));
System.out.println(s.substring(6, 9));
System.out.println();
}
}
Do note that I haven't changed the basic board representation (you chose to use String, while I recommend using a 2d array, where swaps are much less costly and the code becomes easier to understand)
A few notes:
To print the entire "path" you must maintain connections between the "steps" of your solution
Avoid using globals where possible
Prefer using Interfaces (Set, Queue) as the types of your collections (and choose them based on how you would use them)
Java 8 doesn't require you to specify the concrete types used in a generic collection during construction (So use Set<String> set = new HashSet<>(); instead of using Set<String> set = new HashSet<String>();
Where possible, avoid using superfluous (and less readable) conditions / code structure (prefer if (booleanVariable) over if (booleanVariable == true)
(There are probably a few more things to take away from this, but this is a useful list to start with)
EDIT:
a version where data is a 2d array is added below
package basic;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
public class Puzzle {
private static class Node {
private final Node previous;
private final char[][] data;
public Node getPrevious() {
return previous;
}
public char[][] getData() {
return data;
}
public int getZeroX() {
return zeroX;
}
public int getZeroY() {
return zeroY;
}
private final int zeroX;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.deepHashCode(data);
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (!Arrays.deepEquals(data, other.data))
return false;
return true;
}
private final int zeroY;
public Node(Node previous, char[][] data, int zeroX, int zeroY) {
super();
this.previous = previous;
this.data = data;
this.zeroX = zeroX;
this.zeroY = zeroY;
}
}
public static void main(String args[]) {
Queue<Node> open = new LinkedList<>(); //Stack<Node> open = new Stack<>();
Set<Node> closed = new HashSet<>();
Node start = new Node(null, new char[][] { { '1', '2', '0' }, { '3', '4', '5' }, { '6', '7', '8' } }, 2, 0);
Node goal = new Node(null, new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { '6', '7', '8' } }, 0, 0);
open.add(start); //open.push(start);
boolean solving = true;
while (!open.isEmpty() && solving) {
Node current = open.poll(); //open.pop();
if (!closed.contains(current)) {
if (current.equals(goal)) {
printPath(current);
System.out.println("SUCCESS");
solving = false;
} else {
// generate children
up(current, open, closed);
down(current, open, closed);
left(current, open, closed);
right(current, open, closed);
closed.add(current);
}
}
}
}
/*
* MOVEMENT UP
*/
private static void up(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroY() > 0) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY() - 1][current.getZeroX()];
chars[current.getZeroY() - 1][current.getZeroX()] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX(), current.getZeroY() - 1));
}
}
/*
* MOVEMENT DOWN
*/
private static void down(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroY() < 2) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY() + 1][current.getZeroX()];
chars[current.getZeroY() + 1][current.getZeroX()] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX(), current.getZeroY() + 1));
}
}
/*
* MOVEMENT LEFT
*/
private static void left(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroX() > 0) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY()][current.getZeroX() - 1];
chars[current.getZeroY()][current.getZeroX() - 1] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX() - 1, current.getZeroY()));
}
}
/*
* MOVEMENT RIGHT
*/
private static void right(Node current, Queue<Node>/*Stack<Node>*/ open, Set<Node> closed) {
if (current.getZeroX() < 2) {
char[][] chars = copy(current.getData());
chars[current.getZeroY()][current.getZeroX()] = chars[current.getZeroY()][current.getZeroX() + 1];
chars[current.getZeroY()][current.getZeroX() + 1] = '0';
open.add/*push*/(new Node(current, chars, current.getZeroX() + 1, current.getZeroY()));
}
}
private static char[][] copy(char[][] data) {
char[][] newData = new char[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
newData[i][j] = data[i][j];
}
}
return newData;
}
private static void printPath(Node current) {
Stack<char[][]> stack = new Stack<>();
for (; current != null; current = current.getPrevious()) {
stack.push(current.getData());
}
while (!stack.isEmpty()) {
print(stack.pop());
}
}
private static void print(char[][] chars) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(chars[i][j]);
}
System.out.println();
}
System.out.println();
}
}
EDIT2: added comments of changes that turn this into DFS
Good luck!

How can I hold the max of a stack?

Been banging my head against a wall for a week and cannot seem to get anywhere. I want to be able to get the max from the stack and keep it in the stack so in the end there is a only one value in the Stack and that is the max. I believe my algorithm to keep the max is correct, but I think my pop method is malfunctioning and I cannot figure out why. Any guidance is appreciated. Both files I am working with are included
import java.io.File;
import java.io.IOException;
import java.util.ListIterator;
import java.util.Random;
public class LinkedListStack {
DoublyLinkedList<Integer> list = new DoublyLinkedList<Integer>();
public int size() {
if (list.isEmpty()) {
System.out.println("Stack is empty");
}
return list.size();
}
public void push(Integer s) {
list.add(s);
}
public Integer pop() {
/* need help with this method */
}
public Integer top() {
return list.iterator().next();
}
public boolean isEmpty() {
return list.isEmpty();
}
public String displayStack() {
return (list.toString());
}
public static void main(String[] args) throws IOException {
LinkedListStack stack = new LinkedListStack();
int n, seed;
File outputFile;
File dir = new File(".");
if (args.length > 0) {
n = Integer.parseInt(args[0]);
seed = Integer.parseInt(args[1]);
}else {
n = 10;
seed = 1;
}
if (args.length == 3) {
outputFile = new File(args[2]);
} else {
outputFile = new File(dir.getCanonicalPath() + File.separator + "Files/testOut_Stack");
}
OutputWriter out = new OutputWriter(outputFile);
Random r = new Random(seed);
Integer nextval;
for (int i = 0; i < n; i++) {
nextval = r.nextInt(10000);
if (stack.isEmpty()) {
stack.push(nextval);
}
if (nextval > stack.top()) {
stack.pop();
stack.push(nextval);
}
/* retain the max value that you see among the integers generated in the stack.
* In the end there should be only one integer in stack, which is the max value
*/
}
// write the content of stack -- which is the max value -- to file
out.writeOutput(stack.displayStack());
}
}
import java.io.File;
import java.io.IOException;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Random;
import csci3230.hw3.OutputWriter;
public class DoublyLinkedList<Item> implements Iterable<Item> {
private int n; // number of elements on list
private Node pre; // sentinel before first item
private Node post; // sentinel after last item
public DoublyLinkedList() {
pre = new Node();
post = new Node();
pre.next = post;
post.prev = pre;
}
// linked list node helper data type
private class Node {
private Item item;
private Node next;
private Node prev;
}
public boolean isEmpty() {
return (n == 0);
// your code
}
public int size() {
return n;
// your code
}
// add the item to the list
public void add(Item item) {
Node last = post.prev;
Node x = new Node();
x.item = item;
x.next = post;
x.prev = last;
post.prev = x;
last.next = x;
n++;
// your code
}
public ListIterator<Item> iterator() { return new DoublyLinkedListIterator(); }
// assumes no calls to DoublyLinkedList.add() during iteration
private class DoublyLinkedListIterator implements ListIterator<Item> {
private Node current = pre.next; // the node that is returned by next()
private Node lastAccessed = null; // the last node to be returned by prev() or next()
// reset to null upon intervening remove() or add()
private int index = 0;
public boolean hasNext() {
return (index < n); // your code
}
public boolean hasPrevious() {
return (index > 0);
// your code
}
public int previousIndex() {
return (index - 1);
// your code
}
public int nextIndex() {
return (index + 1);
// your code
}
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
lastAccessed = current;
Item item = current.item;
current = current.next;
index++;
return item;
// your code
}
public Item previous() {
if (!hasPrevious()) throw new NoSuchElementException();
current = current.prev;
index--;
lastAccessed = current;
return current.item;
// your code
}
// replace the item of the element that was last accessed by next() or previous()
// condition: no calls to remove() or add() after last call to next() or previous()
public void set(Item item) {
if (lastAccessed == null) throw new IllegalStateException();
lastAccessed.item = item;
// your code
}
// remove the element that was last accessed by next() or previous()
// condition: no calls to remove() or add() after last call to next() or previous()
public void remove() {
if (lastAccessed == null) throw new IllegalStateException();
Node x = lastAccessed.prev;
Node y = lastAccessed.next;
x.next = y;
y .prev = x;
n--;
if (current == lastAccessed) {
current = y;
}
else {
index--;
}
lastAccessed = null;
// your code
}
// add element to list
public void add(Item item) {
Node x = current.prev;
Node y = new Node();
Node z = current;
y.item = item;
x.next = y;
y.next = z;
z.prev = y;
y.prev = x;
n++;
index++;
lastAccessed = null;
// your code
}
}
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this)
s.append(item + " ");
return s.toString();
}
}
You can keep the first integer you pop as a temporary "largestValue" and compare every subsequent integer you pop with it to see whether you should replace it. At the very of your function, pop all values and add the largestValue back onto it.

Postfix Notation Evaluation

I was working on my code and I'm stuck at this point.
My question is to evaluate postfix notation entered from the keyboard.
Here is my code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.NoSuchElementException;
interface Stack<E> {
// The elements of the Stack are any kind of objects
// Access methods:
public boolean isEmpty ();
// Returns true only if the stack is empty.
public E peek ();
// Returns the element on the top od the stack.
// Transformation methods:
public void clear ();
// Clears the stack.
public void push (E x);
// Adds x on the top of the stack.
public E pop ();
// Removes and returns the element on the top.
}
class ArrayStack<E> implements Stack<E> {
private E[] elems;
private int depth;
#SuppressWarnings("unchecked")
public ArrayStack (int maxDepth) {
// Creating new empty stack
elems = (E[]) new Object[maxDepth];
depth = 0;
}
public boolean isEmpty () {
// Returns true only if the stack is empty.
return (depth == 0);
}
public E peek () {
// Returns the element on the top od the stack.
if (depth == 0)
throw new NoSuchElementException();
return elems[depth-1];
}
public void clear () {
// Clears the stack.
for (int i = 0; i < depth; i++) elems[i] = null;
depth = 0;
}
public void push (E x) {
// Adds x on the top of the stack.
elems[depth++] = x;
}
public E pop () {
// Removes and returns the element on the top.
if (depth == 0)
throw new NoSuchElementException();
E topmost = elems[--depth];
elems[depth] = null;
return topmost;
}
}
public class PostFixEvaluation {
static int evaluatePostfix(char [] izraz, int n)
{
ArrayStack e;
char ch;
int op1,op2,result=0;
int i=0;
while(i<n)
{
if(Character.isDigit(izraz[i]))
{
ch=izraz[i];
e.push(ch);
}
else
{
ch=izraz[i];
op1 =(int)e.pop();
op2 =(int)e.pop();
if(ch=='+')
{
result=op1+op2;
}
if(ch=='-')
{
result=op1-op2;
}
if(ch=='/')
{
result=op1/op2;
}
if(ch=='*')
{
result=op1*op2;
}
e.push(result);
}
i++;
}
return result;
}
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String expression = br.readLine();
char exp[] = expression.toCharArray();
int rez = evaluatePostfix(exp, exp.length);
System.out.println(rez);
br.close();
}
}
My problem is at the evaluatePostfix function. I can't use the push and pop functions because it gives me this error:
PostFixEvaluation.java:100: error: variable e might not have been initialized
e.push(ch);
^
PostFixEvaluation.java:105: error: variable e might not have been initialized
op1 =(int)e.pop();
^
Note: PostFixEvaluation.java uses unchecked or unsafe operations.
Can anyone help me solve this problem?
static int evaluatePostfix(char [] izraz, int n)
{
ArrayStack e;
char ch;
int op1,op2,result=0;
int i=0;
while(i<n)
{
if(Character.isDigit(izraz[i]))
{
ch=izraz[i];
e.push(ch);
}
else
{
ch=izraz[i];
op1 =(int)e.pop();
op2 =(int)e.pop();
if(ch=='+')
{
result=op1+op2;
}
if(ch=='-')
{
result=op1-op2;
}
if(ch=='/')
{
result=op1/op2;
}
if(ch=='*')
{
result=op1*op2;
}
e.push(result);
}
i++;
}
return result;
}
Initialize e in function evaluatePostfix
ArrayStack<Character> e = new ArrayStack(10); // maxDepth = 10

Categories

Resources