I am doing a Breadth First Search program that will read in an adjacency list type text file, then perform BFS on it accordingly. I am having trouble reading in the text file, then adding it as an array list of nodes.
How would I get it to correctly read each line and associate the connections for it?
I have tested my program by manually adding Nodes within my main, then making a graph and performing BFS on it.
Here is my Node class:
import java.util.*;
public class Node {
public String data; // data element
public boolean visited=false; // flag to track the already visited node
public List<Node> adjacentNodes = new LinkedList<Node>(); // adjacency list
// public List adjacentNodes = new LinkedList(); // adjacency list
public Node rootNode;
public Node(String data){
this.data = data;
}
public void addAdjacentNode(final Node node){
adjacentNodes.add(node);
node.adjacentNodes.add(this);
// adjacentNodes.add(rootNode);
// node.adjacentNodes.add(this)
}
}
And here is my Graph class: (Where I attempted to read in my text file is within my main)
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;
/*- enqueue the start node to a Queue
- make the start node as visited
- while queue is not empty
- dequeue the node lets say u
- print or whatever you want to
- for every adjacent node v of u
- if v is not already visited
- mark v as visited
- enqueue v to the Queue*/
public class Graph {
public List nodes = new ArrayList();
public void breadthFirstTraversal(Node rootNode){
Queue<Node> q = new LinkedList<Node>();
// Queue q = new LinkedList();
q.add(rootNode);
System.out.print(rootNode.data + " ");
// printNode(rootNode);
rootNode.visited=true;
while(!q.isEmpty()){
Node n = (Node)q.poll();
System.out.print(n.data + " ");
for(Node adj : n.adjacentNodes){
if(!adj.visited){
adj.visited=true;
q.add(adj);
}
}
clearNodes();
}
}
private void clearNodes() {
// TODO Auto-generated method stub
nodes = null; //clear nodes and set to null
}
/* private void printNode(Node node) {
// TODO Auto-generated method stub
System.out.print(node);
}*/
public static void main(String[] args) throws FileNotFoundException {
Graph g = new Graph();
Scanner scan = new Scanner(new File("Connections.txt")); // scanner to read file
String line = scan.nextLine(); // read first line
int nbLine = Integer.parseInt(line); // get number of lines
ArrayList<int[]> al = new ArrayList<int[]>();
for(int i = 0; i < nbLine; i++) { // read each line
line = scan.nextLine();
String[] token = line.split(" "); // split each number into different String
int[] points = new int[token.length - 1]; // prepare array of int[] - 1
// int[] point = new int[];
int[] point = new int[token.length];
for(int j = 0; j < token.length; j++){ // skip first one
points[j-1] = Integer.parseInt(token[j]); // store as int
al.add(points); // save in ArrayList
}
/* Scanner s = new Scanner(new File("C:/Users/cantuj3/Documents/Ass 2/Connections.txt"));
ArrayList<Node> list = new ArrayList<Node>();
while (s.hasNext()){
g.nodes.add(s.next());
//list.add(g);
}
s.close();*/
/* Node frankfurt = new Node("frankfurt");
Node mannheim = new Node("mannheim");
Node wurzburg = new Node("wurzburg");
Node stuttgard = new Node("stuttgard");
Node kassel = new Node("kassel");
Node karlsruhe = new Node("karlsruhe");
Node erfurt = new Node("erfurt");
Node numberg = new Node("numberg");
Node augsburg = new Node("augsburg");
Node munchen = new Node("munchen");
Graph g = new Graph();
g.nodes.add(frankfurt);
g.nodes.add(mannheim);
g.nodes.add(wurzburg);
g.nodes.add(stuttgard);
g.nodes.add(kassel);
g.nodes.add(karlsruhe);
g.nodes.add(erfurt);
g.nodes.add(numberg);
g.nodes.add(augsburg);
g.nodes.add(munchen);
frankfurt.addAdjacentNode(mannheim);
frankfurt.addAdjacentNode(wurzburg);
frankfurt.addAdjacentNode(kassel);
mannheim.addAdjacentNode(karlsruhe);
karlsruhe.addAdjacentNode(augsburg);
augsburg.addAdjacentNode(munchen);
munchen.addAdjacentNode(kassel);
munchen.addAdjacentNode(numberg);
wurzburg.addAdjacentNode(erfurt);
wurzburg.addAdjacentNode(numberg);
numberg.addAdjacentNode(stuttgard);
g.breadthFirstTraversal(frankfurt);*/
}
}
Here is my input file:
01 02
02 01 03
03 02 04 05
04 03
05 03 06
06 05
Here is that chunk of code I wrote in my main by itself:
Scanner scan = new Scanner(new File("Connections.txt")); // scanner to read file
String line = scan.nextLine(); // read first line
int nbLine = Integer.parseInt(line); // get number of lines
ArrayList<int[]> al = new ArrayList<int[]>();
for(int i = 0; i < nbLine; i++) { // read each line
line = scan.nextLine();
String[] token = line.split(" "); // split each number into different String
int[] points = new int[token.length - 1]; // prepare array of int[] - 1
// int[] point = new int[];
int[] point;
for(int j = 0; j < token.length; j++){ // skip first one
points[j-1] = Integer.parseInt(token[j]); // store as int
al.add(points); // save in ArrayList
}
Am I on the right track?
Your basic steps will need to be:
Read a line of the file
Turn that line into an object
Add that object to a collection
Repeat until you have no more lines to read
Since I don't want to do your work for you, I'll leave you with some samples:
Read a line of the file
String line = reader.readLine(); // in this case, 'reader' will be a BufferedReader referencing your file
Turn that line into an object
This depends on what your input file format looks like. As an example, if my input is something like this:
first_thing 10
second_thing 20
third_thing 30
...
then I could do:
String[] components = line.split(" ");
if (components.length == 2) {
MyCustomObject myCustomObject = new MyCustomObject(components[0], components[1]);
}
Add that object to a collection
String[] components = line.split(" ");
if (components.length == 2) {
MyCustomObject myCustomObject = new MyCustomObject(components[0], components[1]);
myCollection.add(myCustomObject); // you can choose the type of collection here
}
Repeat until you have no more lines to read
while ( (line = reader.readLine()) != null ) {
...
}
Hope this helps!
Related
Stack <String> stackx = new Stack<String>();
Scanner word = new Scanner(System.in);
Scanner countz = new Countz(System.in);
System.out.println("How many time you want to input");
int repeat=countz.nextInt();
for (int i=0;i<repeat;i++){
System.out.println("Data of - "+ (i+1) + ":");
String pintri = word.nextLine();
stackz.push(pintri);
}
System.out.println("Your data: "+stackx);
I want to print the stackx in reverse order, how to do that?
Thank you..
You can print the reversed stack recursively:
void printReversed(Stack<?> stack) {
if (stack.isEmpty()) return;
Object value = stack.pop();
printReversed(stack);
System.out.println(value);
stack.push(value); // restore the stack.
}
This is, of course, working by pushing values into another stack - the call stack.
You use the pop() function to start removing the elements one by one. Stack removes element in LIFO (Last in First out), so naturally the elements will be removed (and accessed by the code) in the reverse order.
If you do not care about performance, you could reverse your Stack, print it, then reverse it back.
Collections.reverse(stackx);
System.out.println("Your data: " + stackx);
Collections.reverse(stackx);
On the other hand, if performance is important, you could use a StringBuilder to print the contents of the Stack data like this
StringBuilder stringBuilder = new StringBuilder();
for (String entry : stackx) {
stringBuilder.insert(0, entry + ", ");
}
stringBuilder.insert(0, "[").replace(stringBuilder.length() - 2, stringBuilder.length() - 1, "]");
If you want to reverse a stack,
Create a new temporary stack
You can use a while loop to pop the top element from stackx and push them onto the temporary stack till stackx becomes empty
Print this temporary stack. It will contain the reversed elements.
Stack<String> reversedStack = new Stack<>();
while(stackx.size() > 0) {
reversedStack(stackx.pop());
}
System.out.println("reversed elements: " + reversedStack);
The input and output are as below:
Input: How many time you want to input
3
Data of - 1:
hello
Data of - 2:
world
Data of - 3:
welcome
Your data: [hello, world, welcome]
reversed elements: [welcome, world, hello]
Just like you do with a list. Just iterate starting with the last index to the first.
for (int i = stackx.size()-1; i>=0; i--) {
System.out.println(stackx.get(i));
}
Using 2 Stacks
Psedudo-code
FirstStack <- add elements (push)
//Before print
SecondStack <- add FirstStack
(while FirstStack is not empty pop element form FirstStack and push into SecondStack
//both Stack's have the same elements but is reverse order
//print from SecondStack
(while SecondStack is not empty pop element and write on screen)
Also for learning purpose you could consider doing your own stack. Algorithm is the same no matter from where is taken the stack implementation.
import java.util.Stack;
public class TestNode {
public static void main(String[] args)
{
TestNode t = new TestNode();
//initial stack
Stack<String> s = new Stack<String>();
s.push("a");
s.push("b");
s.push("c");
//initial stack - same results
//Node s = t.new Node();
//s.push("a");
//s.push("b");
//s.push("c");
//intermediary stack
Node n=t.new Node();
while(!s.empty())
{
n.push(s.pop());
}
n.print();
}
//custom made stack based on linked-nodes
class Node
{
Node n=null;
String data=null;
Node()
{
}
Node(String data, Node n)
{
this.data = data;
this.n = n;
}
public void push(String data)
{
n = new Node(data,n);
}
public boolean empty()
{
if(data==null)
return true;
return false;
}
public String pop()
{
String out = data;
if(out != null)
{
n.data = null;
if(n.n != null)
{
n = n.n;
}
return out;
}
return null;
}
public void print()
{
Node cn = n;
while(cn != null)
{
System.out.println(cn.data);
cn = cn.n;
}
}
}
}
Output
a
b
c
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.
I have been assigned a task that requires me to utilise a 2D Array. I have to read in a file and export it to a 2D array. I can only have a single method but I am unable to sort the array correctly. I am supposed to sort the data in 3 ways (alphabetically by name and with scores highest to lowest; highest to lowest scores for each student and highest to lowest by the average of 3 scores.) So far I have
import java.util.*;
import java.io.*;
public class ScoreSorter {
public static void main(String[] args) {
int student_num = 30;
String[][] DataInTableArr = new String[30][6];
try {
BufferedReader ReadIn = new BufferedReader(new FileReader("classZ.csv"));
for (int i = 0; i < 30; i++) {
String DataIn = ReadIn.readLine();
String[] DataInArr = DataIn.split(",");
DataInTableArr[i][0] = DataInArr[0];
DataInTableArr[i][1] = DataInArr[1];
DataInTableArr[i][2] = DataInArr[2];
DataInTableArr[i][3] = DataInArr[3];
int temptest1 = Integer.parseInt(DataInArr[1]);
int temptest2 = Integer.parseInt(DataInArr[2]);
int temptest3 = Integer.parseInt(DataInArr[3]);
}
} catch (Exception e) {
System.out.println("Whoops, you messed up, RESTART THE PROGRAM!!!!!");
}
}
}
I have no idea as to how to solve the rest of the task... I would appreciate if someone could tell me of the most efficient way and perhaps an example...
One plausible way is to create a Student class which implements Comparable interface, with the following members:
String name;
int scoreOne;
int scoreTwo;
int scoreThree;
compareTo(Student s) { //implement the comparison following 3 criteria you mentioned }
And, read the files row by row, for each row we create a Student object, and put all rows in a TreeSet. In this way, the TreeSet together with the compareTo method will help us sort the Students automatically.
Finally, iterate the sorted TreeSet to fill up the 2D array.
import java.util.*;
import java.io.*;
public class ScoreSorter {
public static void main(String[] args) {
int student_num = 30;
String[][] DataInTableArr = new String[30][6];
try {
BufferedReader ReadIn = new BufferedReader(new FileReader("classZ.csv"));
for (int i = 0; i < 30; i++) {
String DataIn = ReadIn.readLine();
String[] DataInArr = DataIn.split(",");
DataInTableArr[i][0] = DataInArr[0];
DataInTableArr[i][1] = DataInArr[1];
DataInTableArr[i][2] = DataInArr[2];
DataInTableArr[i][3] = DataInArr[3];
int temptest1 = Integer.parseInt(DataInArr[1]);
int temptest2 = Integer.parseInt(DataInArr[2]);
int temptest3 = Integer.parseInt(DataInArr[3]);
}
/*Code To be Inserted Here*/
} catch (Exception e) {
System.out.println("Whoops, you messed up, RESTART THE PROGRAM!!!!!");
}
}
}
If there are 6 columns such that First is name and the other 3 are scores then what does other 2 columns contain?? I ignore your array declaration :
String[][] DataInTableArr = new String[30][6];
and assume it to be 30x4 array
String[][] DataInTableArr = new String[30][4];
Logic for sorting Alphabetically
if(DataInTableArr[i][0].compareTo(DataInTableArr[i+1][0])){
/* Sorting Name of adjacent rows*/
String temp = DataInTableArr[i][0];
DataInTableArr[i][0] = DataInTableArr[i+1][0];
DataInTableArr[i+1][0] = temp;
/*Sorting the three marks similarly*/
temp = DataInTableArr[i][1];
DataInTableArr[i][1] = DataInTableArr[i+1][1];
DataInTableArr[i+1][1] = temp;
temp = DataInTableArr[i][2];
DataInTableArr[i][2] = DataInTableArr[i+1][2];
DataInTableArr[i+1][2] = temp;
temp = DataInTableArr[i][3];
DataInTableArr[i][3] = DataInTableArr[i+1][3];
DataInTableArr[i+1][3] = temp;
}
Put the above code in bubble sorting algorithm i.e. 2 loops.
Logic for sorting according to highest marks
In this case you have to find the highest marks in all three subjects of each DataInTableArr[i] and then compare the highest marks with that of next row.
Logic for sorting according to Average marks
Calculate the average of each i'th row as
(Integer.parseInt(DataInTableArr[i][1]) + Integer.parseInt(DataInTableArr[i][2]) + Integer.parseInt(DataInTableArr[i][3]))/3
and compare it with [i+1] th rows average.(same formula just replace [i] with [i+1])
Let me start by saying I have a file. For more info, you check it here.
I have already added the edges on the hashmap with multiple values. I have check it by adding this piece of code:
map.put(nodes.get(i), edges);
System.out.println(nodes.get(i) + " " + map.get(nodes.get(i)));
After adding each entry to map, I check it right away if it was successfully added. Yes, it worked.
Here's the output:
a0 [acodijkstra.Edge#b1c5fa]
a1 [acodijkstra.Edge#13caecd, acodijkstra.Edge#f84386, acodijkstra.Edge#1194a4e]
a2 [acodijkstra.Edge#15d56d5, acodijkstra.Edge#efd552, acodijkstra.Edge#19dfbff]
a3 [acodijkstra.Edge#10b4b2f, acodijkstra.Edge#750159, acodijkstra.Edge#1abab88]
But when creating another method to display the content of the map, I found out that the map is empty. Here's the code:
public void viewFile() {
for(int i=0; i<nodes.size();i++) {
System.out.println(nodes.get(i) + " " + this.map.get(nodes.get(i)));
}
}
The output of the above code is this:
a0 []
a1 []
a2 []
a3 []
What could be the possible reason for this? I am really confused why this happened.
For the code, here's the simplified version (if complied, this will result to errors since I edited some parts deemed unnecessary out):
class Reader {
HashMap<String, Vertex> vertexList;
Map<String, ArrayList<Edge>> map;
ArrayList<String> nodes;
ArrayList<Edge> edges;
public Reader(String fileName) {
vertexList = new HashMap<String, Vertex>();
map = new HashMap<String, ArrayList<Edge>>();
nodes = new ArrayList<String>();
edges = new ArrayList<Edge>();
readFile(fileName);
}
private void readFile(String fileName) {
try{
FileReader file = new FileReader(fileName);
Scanner sc = new Scanner(file);
int i = 0;
while (sc.hasNextLine()) {
input.add(sc.nextLine());
i++;
}
setNodes();
setVertices();
System.out.println();
file.close();
} catch(Exception e){
System.out.println(e);
}
}
public void setNodes() {
System.out.println();
for(int i=0; i<input.size(); i++) {
line = this.input.get(i);
nodes.add(line.substring(0,line.indexOf("-")).trim());
adjLine.add(line.substring(line.indexOf("-")+1).trim());
}
}
private void setVertices() {
String[] listEdges;
for(int i=0; i<nodes.size(); i++) {
//if vertex does not exist, create it
if(vertexList.containsKey(nodes.get(i))) {
vertexList.put(nodes.get(i), new Vertex(nodes.get(i)));
}
line = adjLine.get(i);
//separate adj edges to *
if(line.contains("*")) {
listEdges = line.split("\\*");
} else {
listEdges = new String[1];
listEdges[0] = line;
}
//add edges to specified vertex
for(int j=0; j < listEdges.length; j++ ) {
String[] word = listEdges[j].split(",");
edges.add(new Edge(vertexList.get(word[0]),Double.parseDouble(word[1])));
}
map.put(nodes.get(i), edges);
System.out.println(nodes.get(i) + " " + map.get(nodes.get(i)));
edges.clear();
}
}
Here:
map.put(nodes.get(i), edges);
System.out.println(nodes.get(i) + " " + map.get(nodes.get(i)));
edges.clear();
you're storing a reference to edges in the map, and then clearing edges. This is why, while the elements are still in the map, they are blank.
You need to stop reusing the same edges object, and create a new one for every vertex (why is edges even a member of your class, and not a local variable?)
import java.io.*;
import java.util.*;
class StepfordHouses {
private ArrayList<Integer> houses; // A list containing houses
private TreeSet<Integer> ordered; // An ordered treeset of houses
private TreeSet<Integer> processed; // Elements already processed
private String inpline[]; // An array of String holing houses heights in physical order
private int disorientedindex; // The index for the Street
private int size; // Number of houses in the Street
public StepfordHouses() // Constructor for init
{
houses = new ArrayList<Integer>();
ordered = new TreeSet<Integer>();
processed = new TreeSet<Integer>();
// Basic Input from Text-File (Codechef Requirment)
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
size = Integer.parseInt(br.readLine());
inpline = br.readLine().split(" ");
} catch (IOException e) {
System.out.println("BAAAAAAAAAM!!");
}
for (int c = 0; c < size; c++) // Populating Houses
{
Integer tmp = Integer.parseInt(inpline[c]);
houses.add(tmp);
ordered.add(tmp);
}
}
public int calcIndex()
{
int c = 0;
while (c < size) {
Iterator<Integer> it = ordered.iterator();
Integer h1 = houses.get(c); // Get an element from the raw ArrayList of Houses
Integer h = it.next(); // Get an element from the Iterator
while (h1.equals(h) != true) {
if (processed.contains(h1) == false) { // The element is not already processed
System.out.println(h1 + " " + h);
disorientedindex++;
}
h = it.next(); // Get an element from the Iterator
}
processed.add(h1);
c++;
it = null;
}
return disorientedindex;
}
}
public class Work {
public static void main(String args[]) {
StepfordHouses sh = new StepfordHouses();
System.out.println(sh.calcIndex());
}
}
The contains() method doesn't work the way I expect it to, i.e compare Integers!
The output is 15 , which should be 9 when
if(processed.contains(h1)==false) works correctly and returns true when an element is already present!
Where could the code be wrong?
The logic is flawed. processed.add(h1); is called N times but processed.contains(h1) is called N*N times. So depending on the input you can have disorientedindex <> N.