Condensing an adjacency matrix for shortest tour - java
I have a program that reads a data file and inputs the data as a 16 x 16 adjacency matrix. I need to find 10 nodes of the graph out of the 16 for which there is a minimal tour. Could someone show me how to implement a traveling salesperson algorithm that accomplishes this? I know how to do it for all 16 nodes, but I don't know how to condense it to only 10.
public class Tour
{
public static final int N = 16;
public static final int INF = Integer.MAX_VALUE;
public static void printGrid(int[][] adjMat)
{
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 16; j++)
{
if(adjMat[i][j] == INF)
System.out.printf("%5s", 0);
else
System.out.printf("%5d", adjMat[i][j]);
}
System.out.println();
}
}
public static void TSP(int[][] adjMat)
{
adjMat = new int[N][N];
}
public static void main(String[] args) throws FileNotFoundException
{
File file = new File("american_tour.dat");
Scanner scanner = new Scanner(file);
scanner.useDelimiter("[\\s,]+");
int N = scanner.nextInt();
int[][] adjMat = new int[N][N];
for(int i=0; i < N; i++)
for (int j=0; j < N; j++)
adjMat[i][j] = scanner.nextInt();
printGrid(adjMat);
scanner.close();
}
}
Related
Reading data from file into 2d array
I need to read a file with a magic square in the format of: # # # # # # # # # # where the first line represents the square size and create a 2d array with the file values. I set up my readMatrix method to read through the lines, created a 2d array of the correct size and input each value to its correct position. private int[][] readMatrix(String fileName) throws FileNotFoundException { int n; File file = new File(fileName); Scanner fileScan = new Scanner(file); String line = fileScan.nextLine(); Scanner lineScan = new Scanner(line); n = lineScan.nextInt(); square = new int[n][n]; while (fileScan.hasNextLine()) { line = fileScan.nextLine(); while (lineScan.hasNext()) { for (int i = 0; i < n; i++) { lineScan = new Scanner(line); for (int j = 0; j < n; j++) { square[i][j] = lineScan.nextInt(); } } } } fileScan.close(); lineScan.close(); return square; public int[][] getMatrix() { int[][] copy; int n = square.length; copy = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { copy[i][j] = square[i][j]; } } return copy; However the tester for this program displays a magic square of the correct dimensions but with all the values being 0 and fails the getMatrix method(I'm assuming because the returned square doesn't match the file square). I tried moving the scanner objects around(inside/outside) the for/while loops in the readMatrix and tried using parseInt/scan next instead of nextInt with no success. I am stumped.
Try this code is able to display 1 - 9 from the 3 x 3 matrix. The variable type can be changed to your need. I used 'char' for ease. private static char[][] finalmatrix; public static void main(String[] args) throws Exception { finalmatrix = readMatrix("File.txt"); // Output matrix. for (int i = 0; i < finalmatrix.length ;i++) { for (int j = 0; j < finalmatrix[i].length ;j++) { System.out.print(finalmatrix[i][j] + " "); } System.out.println(""); } } private static char[][] readMatrix(String fileName) throws IOException { File file = new File(fileName); Scanner scan = new Scanner(file); int countRow = 0; int countColumn = 0; List temp = new ArrayList(); while (scan.hasNextLine()) { String line = scan.nextLine(); for (int i = 0; i < line.length(); i++) { // Count the number of columns for the first line ONLY. if (countRow < 1 && line.charAt(i) != ' ') { countColumn++; } // Add to temporary list. if (line.charAt(i) != ' ') { temp.add(line.charAt(i)); } } // Count rows. countRow++; } char[][] matrix = new char[countRow][countColumn]; // Add the items in temporary list to matrix. int count = 0; for (int i = 0; i < matrix.length ;i++) { for (int j = 0; j < matrix[i].length ;j++) { matrix[i][j] = (char) temp.get(count); count++; } } scan.close(); return matrix; }
Inputting adjacency matrix from a file
I am attempting to input the following file into my program in the form of an adjacency matrix. 16 -1,1075,716,792,1425,1369,740,802,531,383,811,2211,661,870,999,772 1075,-1,1015,1770,2403,1662,870,1858,941,1426,1437,3026,1486,211,1463,314 716,1015,-1,928,1483,646,390,1085,185,749,530,2034,1377,821,471,772 792,1770,928,-1,633,1089,1111,246,908,409,495,1447,1317,1565,672,1470 1425,2403,1483,633,-1,9999,1630,752,1432,9999,931,814,1938,2198,1016,2103 1369,1662,646,1089,9999,-1,820,1335,832,9999,605,1839,2030,1468,421,1419 740,870,390,1111,1630,820,-1,1224,360,965,690,2197,1480,750,630,705 802,1858,1085,246,752,1335,1224,-1,1021,442,737,1566,1190,1653,918,1558 531,941,185,908,1432,832,360,1021,-1,685,496,2088,1192,736,616,656 383,1426,749,409,9999,9999,965,442,685,-1,738,1858,1938,1221,926,1126 811,1437,530,495,931,605,690,737,496,738,-1,1631,1472,1232,188,1152 2211,3026,2034,1447,814,1839,2197,1566,2088,1858,1631,-1,2752,2824,1563,2744 661,1486,1377,1317,1938,2030,1480,1190,1192,1938,1472,2752,-1,1281,1660,1183 870,211,821,1565,2198,1468,750,1653,736,1221,1232,2824,1281,-1,1269,109 999,1463,471,672,1016,421,630,918,616,926,188,1563,1660,1269,-1,1220 772,314,772,1470,2103,1419,705,1558,656,1126,1152,2744,1183,109,1220,-1 However, I think I have something wrong with my logic or I'm not using the Scanner correctly. This is my code: public class Tour { public static final int N = 16; public static final int INF = Integer.MAX_VALUE; public static void printGrid(int[][] adjMat) { for(int i = 0; i < 16; i++) { for(int j = 0; j < 16; j++) { if(adjMat[i][j] == INF) System.out.printf("%5s", 0); else System.out.printf("%5d", adjMat[i][j]); } System.out.println(); } } public static void main(String[] args) throws IOException { File file = new File("american_tour.dat"); Scanner scanner = new Scanner(file); int[][] adjMat = new int[N][N]; for(int i = 0, n = scanner.nextInt(); i < n; i++) for(int j = 0; j < n; j++) adjMat[i][j] = n; scanner.close(); printGrid(adjMat); } } Could someone show me how to properly input the data from the file into an adjacency matrix?
Improving Mouad's answer, using the scanner's built in support for custom delimiters: Scanner scanner = new Scanner(file); scanner.useDelimiter("[\\s,]+"); int N = scanner.nextInt(); int[][] adjMat = new int[N][N]; for(int i=0; i < N; i++) { for (int j=0; j < N; j++) { adjMat[i][j] = scanner.nextInt(); } } scanner.close();
As your data does not respect a specific pattern for delimiters, try this instead : public static void main(String[] args) throws FileNotFoundException { File file = new File("E:\\american_tour.dat"); Scanner scanner = new Scanner(file); //N in the example equals 16 int N = scanner.nextInt(); //skip the first line scanner.nextLine(); int[][] adjMat = new int[N][N]; for(int i = 0; i < N; i++){ String[] lines = scanner.nextLine().split(","); for (int j=0; j<lines.length; j++) { adjMat[i][j] = Integer.parseInt(lines[j]); } } scanner.close(); }
How to resolve time-exceeded error(codechef) for stable-marraige?
I am trying to implement the stable marriage using lists and arrays. When i try to submit it on codechef it gives runtime exceeded errors.If someone could help but i want to use the very same data-structure i am using. import java.util.*; public class Main { private int size; private static LinkedList<Integer>[] menlist; private static int[][] womatrix; private static int[][] invwomatrix; private static int[] womatch; private static int[] menmatch; public static void main(String[] args){ Scanner Input = new Scanner(System.in); int TestCases = Input.nextInt(); while(TestCases-- > 0) { int size = Input.nextInt(); womatrix=new int[size][size]; invwomatrix=new int[size][size]; menlist=new LinkedList[size]; womatch=new int[size]; menmatch=new int[size]; for(int i = 0; i < size; i++){ int temp=Input.nextInt(); for(int j = 0; j < size; j++) { womatrix[i][j] = Input.nextInt(); invwomatrix[i][womatrix[i][j]-1]=j+1; } } for(int i = 0; i < size; i++){ int temp=Input.nextInt(); LinkedList<Integer> menpref = new LinkedList<Integer>(); for(int j = 0; j < size; j++) { int a=Input.nextInt(); menpref.add(a); } menlist[i]=menpref; } LinkedList<Integer> ll = new LinkedList<Integer>(); for(int i=0;i<size;i++){ womatch[i]=0; menmatch[i]=0; ll.add(i+1); } while((ll.isEmpty()!=true) || menlist[ll.getFirst()-1].isEmpty()!=true ){ int newman=ll.removeFirst(); //System.out.print("freeman "+newman+" "+menlist[newman-1].isEmpty()+"\n"); int women=(menlist[newman-1].removeFirst()); //System.out.print("highrank "+women+"intial_pair "+womatch[women-1]+"\n"); if(womatch[women-1]==0){ womatch[women-1]=newman; menmatch[newman-1]=women; //int a=ll.removeFirst(); } else{ int oldman=womatch[women-1]; if(invwomatrix[women-1][newman-1]<invwomatrix[women-1][oldman-1]){ womatch[women-1]=newman; menmatch[newman-1]=women; ll.addFirst(oldman); } else{ ll.addFirst(newman); } } /*for(int i=0; i<this.size; i++) { System.out.print((i+1)+" "+ menmatch[i] +"\n"); }*/ if(ll.isEmpty()==true){break;} } for(int k=0;k<size;k++){ System.out.print((k+1)+" "+menmatch[k] +"\n"); } } } }
ways to speed up the Full Counting Sort
I encountered a question on hackerrank. https://www.hackerrank.com/challenges/countingsort4 My first attempt passed all the test cases except the last one, due to timeout. After failed to come up with a more efficient algorithm, I improved the code by using StringBuilder instead of concatenating Strings directly. This brought the running time from more than 5 sec to 3.5 sec. My question is that is there any other way that I can improve the running time? Thanks. The following is my code. public class Solution { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(); scanner.nextLine(); int[] oriNum = new int[N]; String[] oriStr = new String[N]; int[] count = new int[100]; int[] indices = new int[100]; int[] output = new int[N]; // save the originals and the count array for (int i = 0; i < N; i++) { oriNum[i] = scanner.nextInt(); oriStr[i] = scanner.nextLine().trim(); count[oriNum[i]]++; } // accumulate the count array indices[0] = 0; for (int i = 1; i < 100; i++) { indices[i] = indices[i-1] + count[i-1]; } // output order for (int i = 0; i < N; i++) { int num = oriNum[i]; output[indices[num]++] = i; } int bar = N/2; StringBuilder sb = new StringBuilder(); for (int i = 0; i < N; i++) { int index = output[i]; if (index < bar) sb.append("- "); else sb.append(oriStr[index]+ " "); } System.out.println(sb.toString()); } }
You should try a plain buffered reader instead of Scanner. Scanner is surprisingly slow and I have participated in programming competitions where Scanner was the sole reason for "time limit exceeded".
import java.io.*; import java.util.*; import java.text.*; import java.math.*; import java.util.regex.*; public class Solution { public static void main(String[] args)throws Exception { BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); int n=Integer.parseInt(in.readLine()); int[] c=new int[100]; String[][] dt=new String[100][10300]; for(int i=0;i<n;i++) { String[] str=in.readLine().split(" "); int val=Integer.parseInt(str[0]); if(i<n/2) dt[val][c[val]]="-"; else dt[val][c[val]]=str[1]; c[val]++; } StringBuilder sb=new StringBuilder(""); for(int i=0;i<100;i++) if(i<n) for(int k=0;k<c[i];k++) if(dt[i][k]!=null) sb.append(dt[i][k]+" "); else break; System.out.println(sb.toString()); } }
This was my approach to problem. (it is in c++). void counting_sort(vector<int> &arr, int size, vector<vector<string> > foo, vector<int> first_half) { int max = *max_element(arr.begin(), arr.end()); int min = *min_element(arr.begin(), arr.end()); int range = max - min + 1; int count[range] = {0}; // counting frequency of numbers in array for (int i = 0; i < size; i++) { count[arr[i] - min]++; } // calculating cumulative sum for (int i = 1; i < range; i++) { count[i] += count[i - 1]; } vector<vector<string> > output(size); // making the new sorted array for (int i = size - 1; i >= 0; i--) // traversing from backward for stability { output[count[arr[i]-min] - 1] = foo[i]; count[arr[i]-min]--; } // copying the sorted array in original array int j=0; for (int i = 0; i < size; i++) { if(stoi(output[i][0]) == first_half[j]) { cout << "- "; j++; } else { cout << output[i][1] << ' '; } } } // Complete the countSort function below. void countSort(vector<vector<string>> arr) { vector<int> num; vector<int> first_half; for(int i=0; (unsigned)i<arr.size(); i++) { num.push_back(stoi(arr[i][0])); if(i < ((unsigned)arr.size()/2)) { first_half.push_back(stoi(arr[i][0])); } } sort(first_half.begin(), first_half.end()); counting_sort(num, num.size(), arr, first_half); }
Java Selection Sort Confusion
I don't understand what is happening in this code. Re-post from before with code included. Can someone please explain what is happening here? I understand conceptually that the list is being re-ordered one item at a time, but I just cant grasp this code. import java.io*; public class Example { public static void main(String[] args) throws IOException { int age[] = new int[10]; int i, j; int smallest; int temp; String line; BufferedReader in; in = new BUfferedReader(new InputStreamReader(System.in)); for(i = 0; i<= 9; i++) { System.out.println("Enter an age: "); line = in.readline(); age[i] = Integer.valueOf(line).intValue(); } for(i = 0; i<= 9, i++) { smallest = i; for(j = 1; j<=9; j++) { if(age[j] < age[smallest]) { smallest = j; } } for (i = 0; i<=9; i++) { System.out.println(age[i]); } } } }
This looks like an implementation of the Bubble Sort. There is a wide wealth of information on the topic of this classic (and inefficient!) algorithm both on The Internet and in books on the subject of fundamental algorithms.
import java.io*; public class Example { public static void main(String[] args) throws IOException { int age[] = new int[10]; int i, j; int smallest; int temp; String line; BufferedReader in; in = new BUfferedReader(new InputStreamReader(System.in)); for(i = 0; i<= 9; i++) { System.out.println("Enter an age: "); line = in.readline(); age[i] = Integer.valueOf(line).intValue(); } for(i = 0; i<= 9, i++) { smallest = i; for(j = 1; j<=9; j++)// MISTAKE IS IN THIS LINE; YOU SHOULD START THE VALUE OF J FROM I+1(for(j = i+1; j<=9; j++))) { if(age[j] < age[smallest]) { smallest = j; } } //ALSO AFTER FINDING THE SMALLEST ELEMENT YOU HAVE TO SWAP THE SMALLEST ELEMENT WITH I ELEMENT /*int temp=age[i]; age[i]=age[smallest]; age[smallest]=temp*/ for (i = 0; i<=9; i++) { System.out.println(age[i]); } } } }