Traveling salesman code in java below (gives wrong result)
http://www.sanfoundry.com/java-program-solve-travelling-salesman-problem-unweighted-graph/
package com.hinguapps.graph;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TSP {
private int numberOfNodes;
private Stack < Integer > stack;
public TSP() {
stack = new Stack < Integer > ();
}
public void tsp(int adjacencyMatrix[][]) {
numberOfNodes = adjacencyMatrix[1].length - 1;
int[] visited = new int[numberOfNodes + 1];
visited[1] = 1;
stack.push(1);
int element, dst = 0, i;
int min = Integer.MAX_VALUE;
boolean minFlag = false;
System.out.print(1 + "\t");
while (!stack.isEmpty()) {
element = stack.peek();
i = 1;
min = Integer.MAX_VALUE;
while (i <= numberOfNodes) {
if (adjacencyMatrix[element][i] > 1 && visited[i] == 0) {
if (min > adjacencyMatrix[element][i]) {
min = adjacencyMatrix[element][i];
dst = i;
minFlag = true;
}
}
i++;
}
if (minFlag) {
visited[dst] = 1;
stack.push(dst);
System.out.print(dst + "\t");
minFlag = false;
continue;
}
stack.pop();
}
}
public static void main(String...arg) {
int number_of_nodes;
Scanner scanner = null;
try {
System.out.println("Enter the number of nodes in the graph");
scanner = new Scanner(System.in);
number_of_nodes = scanner.nextInt();
int adjacency_matrix[][] = new int[number_of_nodes + 1][number_of_nodes + 1];
System.out.println("Enter the adjacency matrix");
for (int i = 1; i <= number_of_nodes; i++) {
for (int j = 1; j <= number_of_nodes; j++) {
adjacency_matrix[i][j] = scanner.nextInt();
}
}
for (int i = 1; i <= number_of_nodes; i++) {
for (int j = 1; j <= number_of_nodes; j++) {
if (adjacency_matrix[i][j] == 1 &&
adjacency_matrix[j][i] == 0) {
adjacency_matrix[j][i] = 1;
}
}
}
System.out.println("The cities are visited as follows: ");
TSP tspNearestNeighbour = new TSP();
tspNearestNeighbour.tsp(adjacency_matrix);
} catch (InputMismatchException inputMismatch) {
System.out.println("Wrong Input format");
}
scanner.close();
}
}
Matrix should be :
0 10 5 40
2 0 5 1
6 13 0 12
1 8 9 0
Expected result: 1 3 2 4 1
Code result : 1 3 4 2 1
This implementation is wrong. This is a hard problem, because you need to either touch every path, or at the very least CONSIDER every path. This implementation basically boils down to "Each step, move to the closest node that I haven't visited". Since the stack is not keeping memory of where you have been, it does not backtrack to consider that a better path may have existed down one of the longer roads.
To fix this, the algorithm needs to keep the path in memory somehow, and not start printing the solution until the best solution has actually been found. (Can use recursion, a stack that holds the whole path, or some other method.)
Related
import java.util.*;
import java.io.*;
public class CarFueling {
static int compute_refills(int dist,int tank,int stops[],int n){
int current_refills=0;
int num_refills=0;
int last_refill=0;
while(current_refills<=n) {
last_refill = current_refills;
while ((current_refills <= n) && (stops[current_refills + 1] - stops[last_refill]) <= tank) {
current_refills = current_refills + 1;
}
if (current_refills == last_refill)
return -1;
if (current_refills <= n)
num_refills = num_refills + 1;
}
return num_refills;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int dist = scanner.nextInt();
int tank = scanner.nextInt();
int n = scanner.nextInt();
int stops[] = new int[n*n*n];// to solve array index out of bound exception increase the size of the array
for (int i = 0; i < n; i++) {
stops[i] = scanner.nextInt();
}
System.out.println(compute_refills(dist,tank,stops,n));
}
}
I think there is some issue in my while loop condition.
Input:
950
400
4
200 375 550 750
my output:
1
correct output:
2
If you look at the
(current_refills <= n) && (stops[current_refills + 1] ... )
part, two things:
current_refills <= n is true for both n-1 (the last element of a n-element array, as the first one has index 0), and n (which is already outside the array)
then stops[current_refills + 1] accesses an element "later", which is 1 or 2 elements above the max for these two cases
But actually this can work, just you could add 0 for the beginning of the trip and dist as the end:
int n = scanner.nextInt();
int stops[] = new int[n+2];
stops[0] = 0; // well, it is 0 already
stops[n+1] = dist;
for (int i = 1; i <= n; i++) {
stops[i] = scanner.nextInt();
}
Then compute_refills() may work correctly (though I haven't checked).
This question already has answers here:
Algorithm - Police and thief in Grid(N*N)
(2 answers)
Closed 4 years ago.
The question goes like this:
There is a N * N grid.
Each cell of the grid can have either a police denoted by P or a thief denoted by T.
A police can catch a thief only if they are in a same row.
A police can catch only one thief.
A police cannot catch a thief who is more than K units away from it.
Count maximum number of thieves that can be caught.
Example:
T P T
P T P
T T P
Output : 3
Approach:
The approach I have used is, a police needs to catch the thief farthest available from him in the given range i.e k. I have implemented this approach using 2 queues, one for policemen and other for thieves.
Out of 24 test-cases 18 got passed, rest got wrong answer.
If the approach is wrong I would like to know the correct answer.
And if some test case I am missing I would like to know that.
Below you can find my code snippet:
CODE:
import java.util.*;
public class policemenAndThief
{
public int maxThiefCaught(char[][] mat,int k)
{
int count = 0;
ArrayDeque<Integer> police = null;
ArrayDeque<Integer> thief = null;
int n = mat.length;
for(int i = 0 ; i < n ; i++)
{
police = new ArrayDeque<>(n);
thief = new ArrayDeque<>(n);
for(int j = 0 ; j < n ; j++)
{
if(mat[i][j] == 'T')
{
while(police.isEmpty() == false && j - police.peekFirst() > k)
{
police.pollFirst();
}
if(police.isEmpty())
{
thief.addLast(j);
}
else
{
police.pollFirst();
count++;
}
}
else
{
while(thief.isEmpty() == false && j - thief.peekFirst() > k)
{
thief.pollFirst();
}
if(thief.isEmpty())
{
police.addLast(j);
}
else
{
thief.pollFirst();
count++;
}
}
}
}
return count;
}
}
Using Linked list:
int count = 0;
for (int i = 0; i < N; i++) {
String row = N_A[i];
LinkedList<Integer> policeList = new LinkedList<>();
LinkedList<Integer> thiefList = new LinkedList<>();
for (int j = 0; j < N; j++) {
char c = row.charAt(j);
int jk = j + 1;
if (c == 'T') {
boolean add = true;
while (!policeList.isEmpty()) {
int p = policeList.pollFirst();
if ((jk - p) <= k) {
count++;
add = false;
break;
}
}
if (add) {
thiefList.add(jk);
}
} else {
boolean add = true;
while (!thiefList.isEmpty()) {
int t = thiefList.pollFirst();
if ((jk - t) <= k) {
count++;
add = false;
break;
}
}
if (add) {
policeList.add(jk);
}
}
}
}
System.out.println(count);
C++ Solution:
int solution (vector<vector<char> > A, int K) {
int res=0;
for(int i=0;i<A.size();i++)
{
vector<int> pol;
vector<int> thi;
for(int j=0;j<A[0].size();j++)
{
if (A[i][j] == 'P')
pol.push_back(j);
else if (A[i][j] == 'T')
thi.push_back(j);
}
// track lowest current indices of
// thief: thi[l], police: pol[r]
int l = 0, r = 0;
while (l < thi.size() && r < pol.size()) {
if (abs(thi[l] - pol[r]) <= K) {
res++;
l++;
r++;
}
// increment the minimum index
else if (thi[l] < pol[r])
l++;
else
r++;
}
pol.clear();
thi.clear();
}
return res;
}
It passes all 24 test cases.
I'm learning Java and I have this exercise where I need to find a pattern from a vector in a matrix and then copy the number of the rows where the pattern is found to another vector.
I'm trying to copy each row of the matrix to another vector and then compare it with the pattern, but it only saves the first row where the pattern is found
package exercise;
import java.io.*;
import java.util.Locale;
import java.util.Scanner;
public class Exercise {
static final int M = 7;
static final int N = 7;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Scanner fEnt = null;
Scanner fEnt1 = null;
PrintStream fSal = null;
double[] pattern = new double[M];
double[][] m = new double[N][N];
double[] aux = new double[N];
int[] res = new int[N];
int i, ax, j, vLon, k, z, w = 0;
boolean found, repeated;
System.out.print("Enter matrix filename: ");
String nomEnt = scanner.next();
System.out.print("Enter pattern filename: ");
String nomEnt1 = scanner.next();
System.out.print("Enter new filename: ");
String nomSal = scanner.next();
try {
fEnt = new Scanner(new File(nomEnt));
fEnt.useLocale(Locale.US);
fEnt1 = new Scanner(new File(nomEnt1));
fEnt1.useLocale(Locale.US);
fSal = new PrintStream(new File(nomSal));
i = 0;
ax = 0;
while (fEnt1.hasNext() && i < M) {
pattern[i] = fEnt1.nextDouble();
i++;
}
vLon = i;
j = 0;
i = 0;
while (fEnt.hasNext() && i < N) {
while (fEnt.hasNext() && j < N) {
m[i][j] = fEnt.nextDouble();
j++;
}
i++;
}
k = 0;
for (i = 0; i < N; i++) {
repeated = false;
for (j = 0; j < N; j++) {
aux[j] = m[i][j];
}
z = 0;
found = true;
while (z <= N - vLon) {
j = 0;
while (j < vLon && found) {
if (aux[z + j] != pattern[j]) {
found = false;
}
j++;
}
if (found) {
repeated = true;
}
z++;
}
if (repeated) {
res[k] = i;
k++;
}
w = k;
}
if (w == 0) {
System.out.println("The pattern wasn't found in the matrix");
} else {
for (i = 0; i < w; i++) {
fSal.print(String.valueOf(res[i]) + "\t");
}
fSal.println();
System.out.println("The vector has been saved.");
}
} catch (Exception e) {
System.out.println("Exception: " + e.toString());
} finally {
if (fEnt != null) {
fEnt.close();
}
if (fSal != null) {
fSal.close();
}
}
}
}
For example, if it reads the matrix
5 2 1 2 3 4
5 3 5 1 2 3
1 2 5 2 4 6
6 7 3 5 1 2
1 2 3 6 8 4
4 5 3 2 4 6
Then if the pattern is 1 2 3, it should save the following vector 1 2 5
This is a question of basic debugging. Therefore, TL;DR use your IDE's debugger.
Long version:
If you have an IDE, then use its debugging features. Eclipse and IntelliJ both have great debugging support and mountains of online tutorials on how to do it.
Things I found wrong while debugging your code (not everything):
Your matrix is only reading into the first line. 2nd, 3rd, etc. rows are all 0's. Also, you are setting N and M to 7 but they should be 6.
-- hint -- step through it and watch what happens right after you increment i, on your next entry into the loop on j. Line ~58
You are doing something wrong with your 'found' flag, causing your program to quit checking after it initially fails. Line ~70
-- hint -- double-check your logic here - I don't think 'found' means what you think it means in your code
I'm trying to solve an "Almost Sorted" challenge in hackerrank the problem is:
Given an array with elements, can you sort this array in ascending order using only one of the following operations?
Swap two elements.
Reverse one sub-segment.
Input Format
The first line contains a single integer, , which indicates the size of the array.
The next line contains integers separated by spaces.
Sample Input #1
2
4 2
Sample Output #1
yes
swap 1 2
Sample Input #2
3
3 1 2
Sample Output #2
no
Sample Input #3
6
1 5 4 3 2 6
Sample Output #3
yes
reverse 2 5
I tried to solve the challenge and my code is working but it seems it's to slow for big arrays.
Kindly asking you to help me to find a better solution for mentioned problem.
Below is my code:
import java.util.*;
public class Solution
{
private static int[] arr;
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int N = in.nextInt();
arr = new int[N];
for (int i = 0; i < N; i++)
{
arr[i] = in.nextInt();
}
if (IsSorted(arr))
{
System.out.println("yes");
return;
}
if(CheckSingleSwap(arr))
return;
if(CheckSingleReverse(arr))
return;
System.out.println("no");
}
private static boolean CheckSingleReverse(int[] arr)
{
int length = arr.length;
int limit = length - 2;
int current = 1;
List<Integer> indexes = new ArrayList<Integer>();
while (current < limit)
{
for (int i = 0; i < length; i++)
{
int temp = current + i;
for (int j = i; j <= temp && temp < length; j++)
{
indexes.add(j);
}
if (IsSorted(ReverseArrayPart(arr, indexes)))
{
System.out.println("yes");
System.out.println("reverse " + (indexes.get(0) + 1) + " " + (indexes.get(indexes.size() - 1) + 1));
return true;
}
indexes.clear();
}
current++;
}
return false;
}
private static int[] ReverseArrayPart(int[] arr, List<Integer> indexes)
{
int[] result = new int[arr.length];
int[] arrayPart = new int[indexes.size()];
int j = 0;
for (int i = 0; i < arr.length; i++)
{
if (indexes.contains(i))
{
arrayPart[j] = arr[i];
j++;
}
result[i] = arr[i];
}
for(int i = 0; i < arrayPart.length / 2; i++)
{
int temp = arrayPart[i];
arrayPart[i] = arrayPart[arrayPart.length - i - 1];
arrayPart[arrayPart.length - i - 1] = temp;
}
j = 0;
for (int i = 0; i < result.length; i++)
{
if (indexes.contains(i))
{
result[i] = arrayPart[j];
j++;
}
}
return result;
}
private static boolean CheckSingleSwap(int[] arr)
{
int count = 0;
int[] B = Arrays.copyOf(arr, arr.length);
Arrays.sort(B);
List<Integer> indexes = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] != B[i])
{
count++;
indexes.add(i+1);
}
}
if(count > 2)
return false;
System.out.println("yes");
System.out.println("swap " + indexes.get(0) + " " + indexes.get(1));
return true;
}
private static boolean IsSorted(int[] arr)
{
int length = arr.length;
for (int i = 0; i < length - 1; i++)
{
if (arr[i] > arr[i + 1])
{
return false;
}
}
return true;
}
}
For the following code, pass in A as the original array and B as the sorted array.
CheckSingleSwap:
Instead of adding the indices to another list, store the first swap you encounter, and keep going; if you find the corresponding other swap, then store it and record the finding; if you find a different swap, exit with false. At the end if you've recorded the finding, print the corresponding indices.
private static boolean CheckSingleSwap(int[] A, int[] B)
{
int L = A.length;
int firstSwap = -1, secondSwap = -1;
for(int i = 0; i < L; i++)
{
if(A[i] != B[i])
{
if (firstSwap == -1)
firstSwap = i;
else if (secondSwap == -1 && A[i] == B[firstSwap] && A[firstSwap] == B[i])
secondSwap = i;
else
return false;
}
}
if (firstSwap != -1 && secondSwap != -1)
{
System.out.println("yes");
System.out.println("swap " + (firstSwap + 1) + " " + (secondSwap + 1));
return true;
}
System.out.println("array is already sorted!");
return false; // or whatever you decide to do; maybe even an exception or enumerated type
}
CheckSingleReverse:
You are doing WAY too much here! You seem to be brute forcing every single possible case (at first glance).
What you can do instead is to find the region where all the numbers are different. If there are more than two of these, or two which are separated by more than one element, then return false immediately.
The reason for the "more than one" thing above is because of odd-number length regions - the middle element would be the same. If you find such two regions, treat them as one. Then you can proceed to find out if the region is reversed.
private static boolean CheckSingleReverse(int[] A, int[] B)
{
// find region
int L = A.length;
int diffStart = -1, diffEnd = -1; boolean mid = false, found = false;
for (int i = 0; i < L; i++)
{
if (A[i] != B[i])
{
if (found)
{
if (i - diffEnd == 2 && !mid)
{
mid = true;
found = false;
diffEnd = -1;
}
else
return false;
}
else if (diffStart == -1)
diffStart = i;
}
else
if (diffStart != -1 && diffEnd == -1)
{
found = true;
diffEnd = i - 1;
}
}
if (diffEnd == -1)
{
if (A[L - 1] != B[L - 1])
diffEnd = L - 1;
else if (!found)
{
System.out.println("array is already sorted!");
return false;
}
}
// find out if it's reversed
int count = (diffEnd - diffStart + 1) / 2;
for (int i = 0; i < count; i++)
{
int oneEnd = diffStart + i, otherEnd = diffEnd - i;
if (!(A[oneEnd] == B[otherEnd] && A[otherEnd] == B[oneEnd]))
return false;
}
System.out.println("yes");
System.out.println("reverse " + (diffStart + 1) + " " + (diffEnd + 1));
return true;
}
Just to give you an idea of the performance boost, on ideone.com, with an array length of 150, the original implementation of CheckSingleReverse took 1.83 seconds, whereas the new one took just 0.1 seconds. With a length of 250, the original actually exceeded the computational time limit (5 seconds), whereas the new one still took just 0.12 seconds.
From this it would seem that your implementation takes exponential time, whereas mine is linear time (ignoring the sorting).
Funnily enough, with an array size of 3 million I'm still getting around 0.26 seconds (ideone's execution time fluctuates a bit as well, probs due to demand)
I need to find the last digit in a array and see if it is equal to zero. Here is the code I'm using;
import java.util.Scanner;
public class NrOccurrence
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.print("Enter the integers between 1 and 100: ");
int[] numbers = new int[100], times = new int[100];
boolean zero = false;
while (zero == false)
{
for (int a = 0; a <= numbers.length; a++)
{
numbers[a] = scan.nextInt();
times[a]++;
if (numbers.equals(0))
{
zero = true;
}
}
}
for (int b = 0; b <= numbers.length; b++)
{
System.out.println(numbers[b] + " occurs " + times[b] + " times");
}
scan.close();
}
}
Create a method like this:
private boolean isLastItemZero(int[] numbers)
{
boolean isLastItemZero = false;
if ((numbers != null) && (numbers.length > 0))
{
isLastItemZero = numbers[numbers.length - 1] == 0;
}
return isLastItemZero;
}
And call it once you're done reading in all of the numbers from the user.
First of all for (int a = 0; a <= numbers.length; a++) will give youIndexOutOfBoundsException .Java uses 0 bases indexing which means that an array of size n has indices up to and including n-1. Change it tofor (int a = 0; a < numbers.length; a++) . Same thing here for (int b = 0; b <= numbers.length; b++)
Second i am not sure what you are trying to check here :
if (numbers.equals(0))
{
zero = true;
}
but you could simply do :
if(numbers[i] == 0);
Now if you wanna check if the last element in the array is 0you can simply do:
if(numbers[numbers.length - 1] == 0)
//do something
By definition, if the remainder of a number divided by 10 is 0, then the last digit must be 0. So you just need;
if(numbers[i] % 10 == 0) { zero = true; }
Hope this helps.