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
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.
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!
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.
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