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]);
}
}
}
}

Categories

Resources