Representing a Graph in Java - java

I am developing a maze system but not graphically maze system. The maze is actually referred as undirected graph I think because they don't direct to each other. The maze looks like this from a text file:
11 3
2 3
0 3
1 4
5 4
5 7
6 7
7 8
8 9
9 10
0 5
I don't know if I did was right to represent this in graph. If you check my code, it seems to be right, isn't it?
import java.io.*;
import java.util.Scanner;
class Arc {
public int nodeNo;
public Arc next;
public Arc(int nodeNo, Arc next) {
this.nodeNo = nodeNo;
this.next = next;
}
public String toString(){
return "" + nodeNo;
}
}
class Node {
int index;
Arc adjList;
Node(int index, Arc adjList) {
this.index = index;
this.adjList = adjList;
}
public String toString() {
return "" + index;
}
}
public class Maze {
Node[] stack;
private Scanner scan;
private static Scanner scan2;
public Maze(String mazeFile) throws FileNotFoundException {
scan = new Scanner(new File(mazeFile));
stack = new Node[12];
for (int n = 0; n < stack.length; n++) {
stack[n] = new Node(n, null);
}
while (scan.hasNext()) {
int v1 = indexForNode(scan.next());
int v2 = indexForNode(scan.next());
stack[v1].adjList = new Arc(v2, stack[v1].adjList);
stack[v2].adjList = new Arc(v1, stack[v2].adjList);
}
}
int indexForNode(String index) {
for (int n = 0; n < stack.length; n++) {
if (stack[n].index == Integer.parseInt(index)) {
return n;
}
}
return -1;
}
public void print(){
System.out.println();
for(int n = 0; n < stack.length; n++){
System.out.print(stack[n]);
for(Arc arc = stack[n].adjList; arc != null; arc = arc.next){
System.out.print(" --> " + stack[arc.nodeNo].index);
}
System.out.println("\n");
}
}
public static void main(String[] args) throws FileNotFoundException {
scan2 = new Scanner(System.in);
System.out.print("Enter maze file name: ");
String file = scan2.nextLine();
Maze maze = new Maze(file);
maze.print();
}
}

In general, I would say no: this is not a good approach. A basic graph, where the edges don't have weights, is implemented as a series of nodes with a Many ↔ Many relationship.
So basically your Node would look like this:
public class Node {
private List<Node> out;
}
See this question for more information.

Related

How do I check for duplicates from my 2d Array? Java

What I want is if [1][0] is already in the list then if inputting [0][1] is considered as duplicate thus not adding it to the loop. That's the only thing that I wanted to accomplish and yet it seems impossible; at least for me.
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class MatrixGraph{
List<List<Integer>> graph;
Scanner input = new Scanner(System.in);
ArrayList<Connection> Links = new ArrayList<Connection>();
boolean visited[];
int nodes;
int vertices;
int matrix[][];
class Node {
String name;
boolean visited;
ArrayList<Node> neighbors = new ArrayList<Node>();
Node(String name) {
this.name = name;
visited = false;
}
}
class Connection {
double fare;
Node source, destination;
Connection(Node source, Node destination) {
this.source = source;
this.destination = destination;
}
}
public static void main(String[] args){
Scanner s = new Scanner(System.in);
System.out.println("Enter the number of vertices");
int V = s.nextInt();
MatrixGraph amg = new MatrixGraph(V);
int n1 = V-1; int n2 = V*n1; int maxSize = n2/2;
while (true){
System.out.println("Enter the number of edges");
int E = s.nextInt();
if (E > maxSize){
System.out.println("Too Much Edges!");
continue;
}else{
System.out.print("\n");
for(int i=0;i<E;i++){
System.out.print("Source: ");
int mark = s.nextInt();
System.out.print("Destination: ");
int mac = s.nextInt();
if (mark == mac) {
System.out.println("\nERROR TRAPPED!!\nNo Loops Allowed Here!\nAdd New Edge!");
i--;
continue;
} else if(mark > (V-1)||mac > (V-1)) {
i--;
System.out.println("\nLOL No\n");
}
amg.addEdge(mark,mac);
amg.addEdge1(mark,mac);
}
}
}
}
MatrixGraph(int vertices){
graph = new ArrayList<>();
visited = new boolean[vertices];
this.vertices=vertices;
matrix=new int[vertices][vertices];
for (int i = 0; i < vertices; i++){
graph.add(i, new ArrayList<>());
}
}
public void addEdge(int source,int destination){
matrix[source][destination]= 1;
matrix[destination][source]= 1;
}
public void addEdge1(int a, int b) {
graph.get(a).add(b);
graph.get(b).add(a);
}
}

Possible to create two different sized arrays/matrices from a file?

Basically, I'm trying to create two different sized 2D arrays from a text file that looks like this:
2
add
3 4
2 1 7 -10
0 5 -3 12
1 7 -2 -5
0 1 2 3
4 5 6 7
8 9 0 1
subtract
2 2
2 12
10 0
4 6
9 1
The 2 is the number of problems (add and subtract), the 3 and 4 are the number of rows and columns, and the numbers below it are the two separate matrices being filled into the 2D arrays. If I just stop there, this program works correctly:
class Matrices {
private Scanner fileReader;
private int rows;
private int columns;
int problems;
String method;
public Matrices(String file) throws FileNotFoundException {
this.fileReader = new Scanner(new FileInputStream(file));
problems = fileReader.nextInt();
method = fileReader.next();
if(method.equals("add")) {
rows = fileReader.nextInt();
columns = fileReader.nextInt();
}
}
public int[][] readMatrix() throws FileNotFoundException {
int[][] result = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
result[i][j] = fileReader.nextInt();
}
}
return result;
}
public int[][] add(int[][] a, int[][] b) {
int[][] result = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
result[i][j] = a[i][j] + b[i][j];
}
}
return result;
}
public void printMatrix(int[][] matrix) {
for ( int[] anArray : matrix ) {
for ( int anInt : anArray ) {
System.out.print(anInt+ " ");
}
System.out.println();
}
}
}
With this driver:
public class MatricesDriver {
public static void main(String[] args) throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter name of file: ");
String filename = keyboard.next();
Matrices matrixReader = new Matrices(filename);
int[][] a = matrixReader.readMatrix();
int[][] b = matrixReader.readMatrix();
System.out.println("Matrix 1: ");
matrixReader.printMatrix(a);
System.out.println();
System.out.println("Matrix 2: ");
matrixReader.printMatrix(b);
System.out.println();
System.out.println("Addition: ");
int[][] addition = matrixReader.add(a,b);
matrixReader.printMatrix(addition);
}
}
It creates and prints the matrices just fine, with no problems. However, whenever I try to create and print the next two matrices (the 2x2 arrays below subtract in the text file), it returns the following error:
Enter name of file:
data/Matrices.txt
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at baker.Matrices.readMatrix(Matrices.java:27)
at baker.MatricesDriver.main(MatricesDriver.java:15
My question is, what adjustments should I make so that the program recognizes that two of the 2D arrays are to be 3x4, and the two following are to be 2x2?
I would recommend decomposing your implementation into the following parts:
class Matrix - holds the values of one matrix from problem definition
class Problem - holds the operation and the two matrices from problem definition
The Matrix class could look like:
class Matrix {
private int[][] values;
public Matrix(int[][] values) {
this.values = values;
}
public int[][] getValues() {
return values;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Matrix [values=\n");
for (int i = 0; i < values.length; i++) {
sb.append("\t" + Arrays.toString(values[i]) + "\n");
}
sb.append("]");
return sb.toString();
}
}
The Problem class could be:
class Problem {
private String operation;
private Matrix first;
private Matrix second;
public Problem(String operation, Matrix firstMatrix, Matrix secondMatrix) {
this.operation = operation;
first = firstMatrix;
second = secondMatrix;
}
public String getOperation() {
return operation;
}
public Matrix getFirst() {
return first;
}
public Matrix getSecond() {
return second;
}
#Override
public String toString() {
return "Problem [\noperation=" + operation + ", \nfirst=" + first + ", \nsecond=" + second + "\n]";
}
}
Based on this, your "driver" class does the following:
Get the filename from user input
Read from file the number of problems and construct a list with this initial size
For the number of problems (i.e. 2) get the operation, rows, and colums and construct a new Problem object containing these information and put the Problem into the list ...
Here is one simple solution - still room for improvement here :-)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class MatricesDriver {
public static void main(String[] args) throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter name of file: ");
String filename = keyboard.next();
List<Problem> problems = readProblems(filename);
System.out.println(problems);
keyboard.close();
}
private static List<Problem> readProblems(final String filename) throws FileNotFoundException {
Scanner fileReader = new Scanner(new FileInputStream(filename));
int numberOfProblems = fileReader.nextInt();
List<Problem> problems = new ArrayList<>(numberOfProblems);
for (int i = 1; i <= numberOfProblems; i++) {
problems.add(readProblem(fileReader));
}
fileReader.close();
return problems;
}
private static Problem readProblem(Scanner fileReader) throws FileNotFoundException {
fileReader.nextLine(); // go to next line
String operation = fileReader.nextLine(); // read problem operation
int rows = fileReader.nextInt(); // read number of rows
int columns = fileReader.nextInt(); // read number of columns
Matrix firstMatrix = readMatrix(rows, columns, fileReader);
Matrix secondMatrix = readMatrix(rows, columns, fileReader);
return new Problem(operation, firstMatrix, secondMatrix);
}
private static Matrix readMatrix(final int rows, final int columns, final Scanner fileReader) throws FileNotFoundException {
int[][] result = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
result[i][j] = fileReader.nextInt();
}
}
return new Matrix(result);
}
}
Tested with your input file.
HTH
You tried to structure your data?
you can use that:
properties-file
For create array or vector without a fixed size use arrayList, you can make a arrayList from a arrayList

Creating a more concise traversal of a stack for DFS algorithm - Java [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I am trying to get this code running as fast as possible when traversing through my stack of my DFS currently the input files are like so:
0 2
2 1
1 4
4 5
5 6
10 8
8 9
9 6
7 6
3 4
0 1
3 9
0 4
Where my Maze class will tie the numbers together and create a graph for me. After the graph is created my DFS class runs through traversing giving one or all solutions to the .txt file submitted. My DFS class looks like so:
import java.util.Scanner;
import java.util.Stack;
public class DFS {
//starting node, the route to the next node, has node been visited
private int startNode;
private int[] route2;
private boolean[] visited;
// 2 main arguments - Maze File & user input
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goal = 1;
route2 = new int[maze.node];
visited = new boolean[maze.node];
if(inputInt == 1){
startDFSone(maze, startNode, goal);
}
else if (inputInt == 2){
startDFSall(maze, startNode, goal);
}
else {
System.out.println("input invalid. No Solution Returned");
}
}
//Put path to goal in the stack
public Stack<Integer> route2(int toGoalNode) {
if (!visited[toGoalNode]) {
return null;
}
Stack<Integer> pathStack = new Stack<Integer>();
for (int route2GoalNode = toGoalNode; route2GoalNode != startNode; route2GoalNode = route2[route2GoalNode]) {
pathStack.push(route2GoalNode);
}
pathStack.push(startNode);
reverseStack(pathStack);
return pathStack;
}
//Reverse the stack
public void reverseStack(Stack<Integer> stackToBeReverse) {
if (stackToBeReverse.isEmpty()) {
return;
}
int bottom = popBottomStack(stackToBeReverse);
reverseStack(stackToBeReverse);
stackToBeReverse.push(bottom);
}
//Pop the bottom of the stack
private int popBottomStack(Stack<Integer> stackToBeReverse) {
int popTopStack = stackToBeReverse.pop();
if (stackToBeReverse.isEmpty()) {
return popTopStack;
} else {
int bottomStack = popBottomStack(stackToBeReverse);
stackToBeReverse.push(popTopStack);
return bottomStack;
}
}
//performs DFS and unsets visited to give the result of all paths
private void startDFSall(Maze maze, int node, int goal) {
visited[node] = true;
if(node == goal) {
printPath(goal);
} else {
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route2[con] = node;
startDFSall(maze, con, goal);
}
}
}
visited[node] = false;
}
//performs DFS and maintains visited marker giving only one path
private void startDFSone(Maze maze, int node, int goal) {
visited[node] = true;
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route2[con] = node;
startDFSone(maze, con, goal);
}
}
}
//Traverse the connections to the goal and print the path taken
public void printPath( int toGoal) {
int goalNode = 1;
if (visited[toGoal]) {
System.out.println("Completed Path: ");
for (int t : route2(toGoal)) {
if (t == toGoal) {
System.out.print(t);
} else {
System.out.print(t + " -> ");
}
}
System.out.println();
}
}
/**
*
* #param args
*/
public static void main(String[] args) {
Scanner scanFile = new Scanner(System.in);
int goalNode = 1;
System.out.print("Enter maze file: ");
String file = scanFile.nextLine();
Maze maze = new Maze(file);
Scanner scanInt = new Scanner(System.in);
System.out.print("Enter desired feedback (1 = one soultion, 2 = all): ");
int inputInt = scanInt.nextInt();
maze.print();
System.out.println();
DFS dfs = new DFS(maze, inputInt);
dfs.printPath(goalNode);
}
}
I am asking for some example or pointers to get my code (specifically the traversal of the stack) more concise so that when I implement my testing for completion time of the code I can minimize it as much as humanly possible.
I'll link my Maze class below if it might help. Thanks.
import java.io.*;
import java.util.*;
public class Maze {
final static Set<Integer> Nodes = new HashSet<Integer>();
List<Integer>[] adjList;
int node; //declaring value for my nodes.
int con; // declaring a connection
/**
* This constructors takes an integer parameter for reading node indexes in
* a list of adjacent nodes.
*
* #param node - integer parameter for passing the nodes value from the file
* and create a list of adjacent nodes.
*/
Maze(int node) {
this.node = node;
this.con = 0;
adjList = (List<Integer>[]) new List[node];
for (int index = 0; index < node; index++) {
adjList[index] = new LinkedList<Integer>();
}
}
/**
* The main constructor that takes a String for reading maze file.
*
* #param mazeFile
*/
public Maze(String mazeFile) {
this(getNodeSize(mazeFile));
Scanner scan;
try {
//Creates a scanner for reading the file and loops through linking the nodes to their connections.
scan = new Scanner(new File(mazeFile));
while (scan.hasNextInt()) {
int node1 = scan.nextInt();
int node2 = scan.nextInt();
addCon(node1, node2);
}
} catch (FileNotFoundException ex) {
System.out.println("File Not Found.");
}
}
/**
* This method returns a size of the set of nodes by taking a String
* parameter which the name of the maze file.
*
* #param mazeFile - String parameter for reading maze file for scanning the
* size of the nodes.
* #return - returns an integer value for the size of the set of nodes.
*/
public static int getNodeSize(String mazeFile) {
Scanner scanNodeSize;
try {
scanNodeSize = new Scanner(new File(mazeFile));
while (scanNodeSize.hasNextInt()) {
int node1 = scanNodeSize.nextInt();
int node2 = scanNodeSize.nextInt();
Nodes.add(node1);
Nodes.add(node2);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return Nodes.size();
}
/**
* This method adds an con by adding two different nodes in array of list
* called adjacency list.
*
* #param node1 - first node.
* #param node2 - next node.
*/
private void addCon(int node1, int node2) {
con++; //Increase con by one whenever this addcon method is called.
adjList[node1].add(node2);
adjList[node2].add(node1);
}
/**
* Print the nodes and its cons by looping through the adjacency list.
*/
public void print() {
for (int n = 0; n < node; n++) {
System.out.print(n + " connected to ");
for (int w : adjList[n]) {
System.out.print(w + " ");
}
System.out.println();
}
}
/**
* This method returns a list of nodes to allow objects to be the target for
* "for-each" statement.
*
* #param nodes - an Integer parameter for getting the number of nodes in a
* list.
* #return - returns a list of nodes.
*/
public Iterable<Integer> getadjList(int nodes) {
return adjList[nodes];
}
/**
* Unit testing To test if it reads the file.
*
* #param args
*/
public static void main(String[] args) {
System.out.print("Enter File: ");
Scanner scanFile = new Scanner(System.in);
String file = scanFile.nextLine();
Maze M = new Maze(file);
M.print();
}
}
Also any general input would be fantastic.

Issue passing argument to my main using DFS - Java

I am trying to get this code running as fast as possible when traversing through my stack of my DFS currently the input files are like so:
0 2
2 1
1 4
4 5
5 6
10 8
8 9
9 6
7 6
3 4
0 1
3 9
0 4
Where my Maze class will tie the numbers together and create a graph for me. After the graph is created my DFS class runs through traversing giving one or all solutions to the .txt file submitted.I have recently altered my Maze class as for it to run more efficiently but am being thrown errors and the data is parsing through to my DFS to be outputted. My Maze class is as follows:
import java.io.*;
import java.util.*;
public class Maze {
private final Map<Integer, Set<Integer>> adjList = new HashMap<>();
/**
* The main constructor that takes a String for reading maze file.
*
* #param file
*/
public Maze(File file) throws FileNotFoundException {
try (Scanner scan = new Scanner(file)) {
while (scan.hasNextInt()) {
int node1 = scan.nextInt();
int node2 = scan.nextInt();
this.connect(node1, node2);
this.connect(node2, node1);
}
}
}
/**
* Makes a unidirectional connection from node1 to node2.
*/
private void connect(int node1, int node2) {
if (!this.adjList.containsKey(node1)) {
this.adjList.put(node1, new HashSet<Integer>());
}
this.adjList.get(node1).add(node2);
}
/**
* Returns a human-readable description of the adjacency lists.
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Map.Entry<Integer, Set<Integer>> adj : this.adjList.entrySet()) {
int from = adj.getKey();
Set<Integer> to = adj.getValue();
s.append(from).append(" connected to ").append(to).append('\n');
}
return s.toString();
}
/**
* Returns the set of nodes connected to a particular node.
*
* #param node - the node whose neighbors should be fetched
*/
public Iterable<Integer> getadjList(int node) {
return Collections.unmodifiableSet(adjList.get(node));
}
/**
* Demonstration of file reading.
*/
public static void main(String[] args) throws FileNotFoundException {
System.err.print("Enter File: ");
Scanner scanFile = new Scanner(System.in);
String file = scanFile.nextLine();
Maze m = new Maze(new File(file));
System.out.println(m);
}
}
And my DFS looks like so.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Stack;
public class DFS {
//starting node, the route to the next node, has node been visited
private int startNode;
private int[] route;
private boolean[] visited;
// 2 main arguments - Maze File & user input
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.node];
visited = new boolean[maze.node];
//Takes user's input and runs desired function
if(inputInt == 1){
findOne(maze, startNode, goalNode);
}
else if (inputInt == 2){
findAll(maze, startNode, goalNode);
}
else {
System.out.println("input invalid. No Solution Returned");
}
}
//Put path to goal in the stack
public Stack<Integer> route(int toGoalNode) {
if (!visited[toGoalNode]) {
return null;
}
Stack<Integer> pathStack = new Stack<Integer>();
for (int routeGoalNode = toGoalNode; routeGoalNode != startNode; routeGoalNode = route[routeGoalNode]) {
pathStack.push(routeGoalNode);
}
pathStack.push(startNode);
reverseStack(pathStack);
return pathStack;
}
//Reverse the stack
public void reverseStack(Stack<Integer> stackToBeReverse) {
if (stackToBeReverse.isEmpty()) {
return;
}
int bottom = popBottomStack(stackToBeReverse);
reverseStack(stackToBeReverse);
stackToBeReverse.push(bottom);
}
//Pop the bottom of the stack
private int popBottomStack(Stack<Integer> stackToBeReverse) {
int popTopStack = stackToBeReverse.pop();
if (stackToBeReverse.isEmpty()) {
return popTopStack;
} else {
int bottomStack = popBottomStack(stackToBeReverse);
stackToBeReverse.push(popTopStack);
return bottomStack;
}
}
//performs DFS and unsets visited to give the result of all paths
private void findAll(Maze maze, int node, int goal) {
visited[node] = true;
if(node == goal) {
printPath(goal);
} else {
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route[con] = node;
findAll(maze, con, goal);
}
}
}
visited[node] = false;
}
//performs DFS and maintains visited marker giving only one path
private void findOne(Maze maze, int node, int goal) {
visited[node] = true;
for (int con : maze.getadjList(node)) {
if (!visited[con]) {
route[con] = node;
findOne(maze, con, goal);
}
}
}
//Traverse the connections to the goal and print the path taken
public void printPath( int toGoal) {
int goalNode = 1;
if (visited[toGoal]) {
System.out.println("Completed Path: ");
for (int t : route(toGoal)) {
if (t == toGoal) {
System.out.print(t);
} else {
System.out.print(t + " -> ");
}
}
System.out.println();
}
}
public static void main(String[] args) throws FileNotFoundException {
Scanner scanFile = new Scanner(System.in);
int goalNode = 1;
System.out.print("Enter maze file: ");
String file = scanFile.nextLine();
Maze maze = new Maze(new File(file));
Scanner scanInt = new Scanner(System.in);
System.out.print("Enter desired feedback (1 = one soultion, 2 = all): ");
int inputInt = scanInt.nextInt();
// maze.toString();
System.out.println(maze);
DFS dfs = new DFS(maze, inputInt);
dfs.printPath(goalNode);
}
}
I've been looking over it for a while and can't figure out exactly why the data is parsing and being used. Ive altered a few things here and there but have been thrown even more errors. They specifically say
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at DFS.findOne(DFS.java:90)
at DFS.<init>(DFS.java:22)
at DFS.main(DFS.java:127)
Referencing to the lines of code:
visited[node] = true;
findOne(maze, startNode, goalNode);
DFS dfs = new DFS(maze, inputInt);
Now essentially im lead to believe that there is no argument being passed, if someone could pin point the problem and lend a hand in helping me out it would be greatly appreciated. Thanks again
EDIT:: Old version of Maze class
import java.io.*;
import java.util.*;
public class Maze {
static Set<Integer> Nodes = new HashSet<Integer>();
List<Integer>[] conList;
int node; //declaring value for my nodes.
int con; // declaring a connection
//Constructor takes an int parameter to read through the list of corresponding nodes
Maze(int node) {
this.node = node;
this.con = 0;
conList = (List<Integer>[]) new List[node];
for (int index = 0; index < node; index++) {
conList[index] = new LinkedList<Integer>();
}
}
//Constructor that takes a String of the maze file
public Maze(String mazeFile) {
this(nodeSize(mazeFile));
Scanner scan;
try {
//Creates a scanner for reading the file and loops through linking the nodes to their connections.
scan = new Scanner(new File(mazeFile));
while (scan.hasNextInt()) {
int firstNode = scan.nextInt();
int secondNode = scan.nextInt();
addCon(firstNode, secondNode);
}
} catch (FileNotFoundException ex) {
System.out.println("File Not Found.");
}
}
/*Takes String parameter which is the name of the maze file.
* Method designed to return the the size of the set of nodes
*/
public static int nodeSize(String mazeFile) {
Scanner scanNodeSize;
try {
scanNodeSize = new Scanner(new File(mazeFile));
//while scan has more int's left repeat.
while (scanNodeSize.hasNextInt()) {
int firstNode = scanNodeSize.nextInt();
int secondNode = scanNodeSize.nextInt();
Nodes.add(firstNode);
Nodes.add(secondNode);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return Nodes.size();
}
//Method designed to connect the first and second nodes
private void addCon(int firstNode, int secondNode) {
con++;
conList[firstNode].add(secondNode);
conList[secondNode].add(firstNode);
}
//outputs the nodes and their connection's (#remove later?)
public void print() {
for (int n = 0; n < node; n++) {
System.out.print(n + " connected to ");
for (int w : conList[n]) {
System.out.print(w + " ");
}
System.out.println();
}
}
//method returns a list, enabling nodes to be easily accessible.
public Iterable<Integer> getconList(int nodes) {
return conList[nodes];
}
}
You are getting an index out of bounds exception at 0. This should lead you to believe that the array has not properly been initialized. You initialize the visited[] array with maze.node however nowhere in your code do we see where this node variable is located. You need to give a proper value to maze.node if you want this to even be runnable.
*EDIT - My above answer is no longer applicable now that we have your previous Maze class which explains why the code will not run.
There are so many things wrong with the code in its current state so I will try and give you some direction here:
Your new way of creating a Maze is to read from the file and connect the 2 points and store them in an Map. The issue with this is that you cannot just get the next element since you have to have the key to get the element. To fix this you should use a different data structure.
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.node]; //!!! maze.node isn't a thing anymore
visited = new boolean[maze.node]; //!!! maze.node isn't a thing anymore
You can see that you are trying to access maze.node which use to be a variable of Maze. It no longer is. You need to find a new way of getting a node from Maze. To do this you need to grab the node from your data structure in a different way:
public DFS(Maze maze, int inputInt) {
int startNode = 0;
int goalNode = 1;
route = new int[maze.adjList.getNode()];
visited = new boolean[maze.adjList.getNode()];
You have a lot of options for a different data structure for you adjacency list but something such as this:
http://theoryofprogramming.com/adjacency-list-in-java/
will give you a decent starting point.

File input for Dijkstra's algorithm

I am having trouble figuring out how to read an input file with java. The file has the following format:
u1 v1 w1
u2 v2 w2
...
um vm wm
-1
source
Each 3-tuple denotes an edge, which is specified by its source-vertex, its destination-vertex, and its weight (example: newyork boston 30). The description of the graph is terminated by a “flag”, the integer -1. A string follows this flag; this string is the name of the source vertex for the Dijkstra shortest-path algorithm. That is, you are to determine and print out the shortest path from this source vertex to every other vertex in the graph.
Here is my current work.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Vertex implements Comparable<Vertex> {
public final String name;
public Edge[] adjacencies;
public double minDistance = Double.POSITIVE_INFINITY;
public Vertex previous;
public Vertex(String argName) {
name = argName;
}
public String toString() {
return name;
}
public int compareTo(Vertex other) {
return Double.compare(minDistance, other.minDistance);
}
}
class Edge {
public final Vertex target;
public final double weight;
public Edge(Vertex argTarget, double argWeight) {
target = argTarget;
weight = argWeight;
}
}
public class Dijkstra {
public static void computePaths(Vertex source) {
source.minDistance = 0.;
PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
vertexQueue.add(source);
while (!vertexQueue.isEmpty()) {
Vertex u = vertexQueue.poll();
// Visit each edge exiting u
for (Edge e : u.adjacencies) {
Vertex v = e.target;
double weight = e.weight;
double distanceThroughU = u.minDistance + weight;
if (distanceThroughU < v.minDistance) {
vertexQueue.remove(v);
v.minDistance = distanceThroughU;
v.previous = u;
vertexQueue.add(v);
}
}
}
}
public static ArrayList<Vertex> getShortestPathTo(Vertex target) {
ArrayList<Vertex> path = new ArrayList<Vertex>();
for (Vertex vertex = target; vertex != null; vertex = vertex.previous)
path.add(vertex);
Collections.reverse(path);
return path;
}
public String[] readFile(String fileName) throws FileNotFoundException {
Scanner input = new Scanner(new File(fileName));
String line = "";
while (input.hasNext()) {
line = line.concat(input.nextLine());
}
String[] graph = line.split("");
return graph;
}
public static void main(String[] args) throws FileNotFoundException {
final String TEST = "/TestInput.txt";
Scanner input = new Scanner(new File(TEST));
String line = "";
while (input.hasNext()) {
line = line.concat(input.nextLine());
}
String[] graph = line.split(" ");
for (int i = 0; i < graph.length; i++) {
System.out.println(graph[i]);
}
Vertex[] verts = new Vertex[graph.length];
Edge[] edges = new Edge[graph.length];
Vertex v1 = new Vertex("");
Vertex v2 = new Vertex("");
Vertex source = new Vertex("");
int count = 0;
outerloop: for (int i = 0; i < (graph.length); i++) {
if (graph[i].equals("-1")) {
// do algorithm initialization here w/ source
}
if (i == 0) {
verts[i] = new Vertex(graph[i]);
count++;
} else {
innerloop: for (int j = count; j >= 0; j--) {
if (i / 3 == 0) {
if (graph[i].equals(verts[j].toString())) {
break innerloop;
} else if (j == 0) {
verts[count] = new Vertex(graph[i]);
v1 = verts[count];
count++;
}
}
if (i / 3 == 1) {
if (graph[i].equals(verts[j])) {
break innerloop;
} else if (j == 0) {
verts[count] = new Vertex(graph[i]);
v2 = verts[count];
count++;
}
}
if (i / 3 == 2) {
}
}
}
}
for (int i = 0; i < verts.length; i++) {
System.out.println(verts[i]);
}
}
}
So my only problem is how to get from the given .txt file format to a graph. Any suggestions are welcome.
Use a Scanner to parse the file data. For each tuple, if the source vertex hasn't been created, create it, otherwise find it in the pre-existing graph -- create a search function. Do the same for the target vertex. Next, create an edge with a weight equal to the third token in the tuple, and add the target vertex to the edge. Finally, add the edge to the adjacency list of the source vertex.
For the previously mentioned search function, you can implement something that can search through each vertex of the graph starting from any vertex. Recursion will be necessary.
public static Vertex search(Vertex src, String name);
A simpler solution is to keep a list of all the vertices you create as your constructing the graph and search through that.
public static Vertex search(List<Vertex> vertices, String name);
When your done constructing the graph and you have the name of the vertex where Dijkstra's algorithm will begin, you can use the search function to get a reference to the vertex.
Dijkstra.computePath(search(vertices, startVertexName));
And, that's it. Here's an example of how to parse your file data:
List<Vertex> vertices = new ArrayList<Vertex>();
String src =
"Pittsburgh Philadelphia 323 "+
"Pittsburgh Ohio 125 "+
"Ohio Philadelphia 400 "+
"-1 Ohio";
//new Scanner(new File(fileName));
Scanner scnr = new Scanner(src);
String src, target;
int weight;
while(scnr.hasNext())
{
src = scnr.next();
if(src.equals("-1"))
break;
else {
target = scnr.next();
weight = scnr.nextInt();
}
//call search(), implement logic in addToGraph()
addVertexToGraph(src, target, weight, vertices);
}
String startVertexName = scnr.next();
scnr.close();
Note that Scanner.next returns the next token separated by white space (the default delimiter), so your file data must be formatted that way.
Here's a shot:
/**
* Read the file using provided filename, construct vertices etc.
*
* #param fileName name of the file to read.
* #return true if everything is OK
* #throws FileNotFoundException if file is not found or not readable
*/
public boolean readFile(final String fileName) throws FileNotFoundException {
final Scanner input = new Scanner(new File(fileName));
boolean result = false;
while (input.hasNext()) {
final String line = line = input.nextLine();
if ("-1".equals(line)) {
// end of data
if (input.hasNext()) {
final String nameOfTheSource = input.next();
// TODO: do something with nameOfTheSource
result = true;
} else {
// bad input format: there should be something after -1
}
} else {
final String Scanner vert = new Scanner(line);
try {
final String sourceName = vert.next();
final String targetName = vert.next();
final int weight = vert.nextInt(); // assuming int for weight
// TODO: create Vertices and Edge here
} catch (final NoSuchElementException ex) {
// bad input format for "line"!
}
}
}
return result;
}
Not tested.
{import Stack.Dijkstra;
{import java.io.File;
{import java.io.FileNotFoundException;
{import java.util.Scanner;
{public class App {
{public static void main(String[] args) throws {FileNotFoundException {
{Vertex v1 = new Vertex("A");
{Vertex v2 = new Vertex("B");
{Vertex v3 = new Vertex("C");
{`v1.addNeighbour(new Edge(1, v1, v2));
{`v1.addNeighbour(new Edge(10, v1, v2));
{`v2.addNeighbour(new Edge(1, v2, v3));
{`Dijkstra dijkstra = new Dijkstra();
{`dijkstra.computePath(v1);
{`System.out.println(dijkstra.getShortestPathTo(v3));
{`final String test = "X:\\neon3\\eclipse\\TestInput.txt";
{`Scanner input = new Scanner(new File(test));
{`String line = "";
{`while (input.hasNext()) {
{`line = line.concat(input.nextLine());
}
{`String[] graph = line.split(" ");
{`for (int i = 0; i < graph.length; i++) {
{`System.out.println(graph[i]);
}
}
}`}

Categories

Resources