I was looking through some old contest questions, and I found this one, it looked fun, http://dwite.ca/old/Problem5Jan2006.pdf , I tried using the floyd warshall algorithm to get the shortest path from any node to any other node, can you guys see what I did wrong? it does not give the desired output set out on the contest question page
import java.io.*;
import java.util.*;
public class DistanceBetween {
public static void main(String[] args) throws FileNotFoundException {
Scanner s = new Scanner(new File("DATA5.txt"));
int n = Integer.parseInt(s.nextLine());
int[][] dist = new int[60][60];
for(int y=0;y<60;++y)for(int x=0;x<60;++x)dist[y][x]=10000000;
Map<Character, Integer> map = new TreeMap<Character, Integer>();
for (int i = 0; i < n; ++i) {
String text[] = s.nextLine().split(" ");
int c = 0;
if (!map.containsKey(text[0].charAt(0))) {
map.put(text[0].charAt(0), c);
c++;
}
if (!map.containsKey(text[0].charAt(1))) {
map.put(text[0].charAt(1), c);
c++;
}
dist[map.get(text[0].charAt(0))][map.get(text[0].charAt(1))] = Integer.parseInt(text[1]);
}
for (int k = 0; k < map.size(); ++k) {
for (int i = 0; i < map.size(); ++i) {
for (int j = 0; j < map.size(); ++j) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
for (int i = 0; i < 5; ++i) {
String text = s.nextLine();
System.out.println(dist[map.get(text.charAt(0))][map.get(text.charAt(1))]);
}
}}
There are several problems in your code:
Overwritten mapping
Your int c is local variable of the for cycle which means the highest used mapping index doesn't survive to the next iteration, so the reading in next iteration overrides the previous one. So the distance matrix is not properly filled after data loading.
Solution: move the int c = 0; outside from the for loop.
Unidirectional roads
The roads are bidirectional in the instructions, but you register them only as unidirectional. As the consequence of that are higher on non-existent connections between towns.
Solution: add dist[map.get(text[0].charAt(1))][map.get(text[0].charAt(0))] = Integer.parseInt(text[1]); right after the similar one.
Besides these hard issues I have also couple hints for you. You do not have follow them but as if you want to improve your programming skills then you should think about them.
Messy code
Your code is hard to read, there are multiple restated information such as indicies, the solving process is in the single method etc. Such code is not only hard to read but also extremely hard to debug and fix. For your own good I recommend you to write it cleaner.
Algorithm efficiency
Floyd-Warshall's algorithm has a O(n^3) complexity. The size of problem (amount of towns) is A-M = 13. In this complexity it makes 13^3 = 2197 iterations. I know, it might not seem to be a lot, but consider the amount of tasks to solve in a given time limit.
I would recommend you to use Dijkstra's algorithm which has complexity O(|E| + |V|log|V|). In this task the worst case with some simplification is |E| = (|V|^2)/2, |V|=13. It means, that the final number of iterations is 5 (|V|^2 / 2 + |V|log|V|) = 5 (13^2 / 2 + 13 * log13) ~ 5 * 132 = 660. If I am not wrong and made any mistake, this is significantly less, especially when we consider the total amount of tasks.
Input reading
I might be wrong but I attended multiple programming contests and competitions and it never forced attendees to work with files. An input was always redirected from files to a standard input. I guess, that the main reason for this is a security, but the simplification is probably also highly beneficial.
Well that question I got, I am starting to do SPOJ now, and I gotta admit it is pretty difficult later on, but I came across the same kind of question http://www.spoj.com/problems/SHPATH/ , I also used Floyd Warshall
import java.util.*;
public class Floydwarshall {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String q = s.nextLine();
for(int t=0;t<Integer.parseInt(q);++t){
int n = Integer.parseInt(s.nextLine());
int[][] cost = new int[n][n];
for (int y = 0; y < n; ++y) {
for (int x = 0; x < n; ++x) {
cost[x][y] = 10000;
}
}
Map<String, Integer> map = new TreeMap<String, Integer>();
int c = 0;
for (int i = 0; i < n; ++i) {
String a = s.nextLine();
if (!map.containsKey(a)) {
map.put(a, c);
c++;
}
int f = Integer.parseInt(s.nextLine());
for (int j = 0; j < f; ++j) {
String text[] = s.nextLine().split(" ");
cost[map.get(a)][Integer.parseInt(text[0]) - 1] =
cost[Integer.parseInt(text[0]) - 1][map.get(a)] = Integer.parseInt(text[1]);
}
}
for (int k = 0; k < map.size(); ++k) {
for (int i = 0; i < map.size(); ++i) {
for (int j = 0; j < map.size(); ++j) {
cost[i][j] = Math.min(cost[i][j], cost[i][k] + cost[k][j]);
}
}
}
int num = Integer.parseInt(s.nextLine());
for (int i = 0; i < num; ++i) {
String text[] = s.nextLine().split(" ");
System.out.println(cost[map.get(text[0])][map.get(text[1])]);
}
}
}}
now it runs alright for the sample input, but when I hand it in, it gives me this
NZEC (non-zero exit code) - this message means that the program exited returning a value different from 0 to the shell. For languages such as C, this probably means you forgot to add "return 0" at the end of the program. For interpreted languages (including JAVA) NZEC will usually mean that your program either crashed or raised an uncaught exception.
Problem is I cannot kind where it crashes or raises an uncaught exception since it
works with the sample input
Related
I got this exercise where i need to build a program in java that creates a 1-dimensional table where 10 integers will be stored, which will be read from the keyboard. At the end the program will display all the integers that are larger than average. (As you can see i've done this). But i need to display the numbers that are larger than average in ascending order. So there should be another instruction in the end, please help 🙏 I should say that im a beginner in java though. shuma=sum, mesatarja=average tabela = array though
please see it and help me solve this :)
Scanner in = new Scanner (System.in);
int [] tabela = new int [10];
System.out.print("Ju lutem jepni 10 nr te plote: ");
for (int i = 0; i<tabela.length; i++) {
tabela[i] = in.nextInt();
}
System.out.println("Tabela = " + Arrays.toString(tabela));
int shuma = 0;
for (int i = 0; i < tabela.length; i++)
shuma = shuma + tabela[i];
double mesatarja = shuma*1.0/tabela.length;
System.out.println("Mesatarja e numrave eshte: " + mesatarja);
System.out.print("Numrat me te medhenj se mesatarja jane: ");
for (int i = 0; i < tabela.length; i++) {
if (tabela[i] > mesatarja) {
System.out.print(tabela[i] + ", ");
}
}
The simplest idea that comes to mind is to sort the array. You should use any sort algorithm after filling your array.
Example using "buble sort":
for (int i = 0; i < tabela.length-1; i++)
for (int j = 0; j < tabela.length-i-1; j++)
if (tabela[j] > tabela[j+1])
{
int temp = tabela[j];
tabela[j] = tabela[j+1];
tabela[j+1] = temp;
}
Here you can find an explanation of the algorithms and their examples.
So I help tutor an Algebra 2 class at my local high school, and the class is currently looking over matrices. Though not there, they will eventually get to multiplication of matrices. After taking Computer Science last year and learning Java, the teacher I help thought I should try to write a program to multiple matrices.
At the moment, I have up to defining the numbers for the first array that holds the information for the first matrix. However, I have a small issue. As represented by this picture:
the line asking for the index integers is being repeated after already recording the integers. I assume this is due to my layered for loops, but I can't be for certain. Usually new eyes see problems clearer. Any who could help me would be appreciated.
Code:
package matrixmultiplication;
import java.util.*;
public class MatrixMultiplication {
public static void main(String[] args) {
System.out.println("What is the size of the first matrix?");
int matrix1Rows = matrixRows();
int matrix1Columns = matrixColumns();
int[] matrix1 = new int[matrix1Rows * matrix1Columns];
doubleSpace();
System.out.println("What is the size of the second matrix?");
int matrix2Rows = matrixRows();
int matrix2Columns = matrixColumns();
int[] matrix2 = new int[matrix2Rows * matrix2Columns];
doubleSpace();
if (matrix1Columns != matrix2Rows) {
System.out.println("These cannot be multiplied!");
System.exit(0);
} else {
matrix1Numbers(matrix1Rows, matrix1Columns);
}
}
public static int matrixRows() {
System.out.print("Rows:");
Scanner rowSc = new Scanner(System.in);
int rows = rowSc.nextInt();
return rows;
}
public static int matrixColumns() {
System.out.print("Columns:");
Scanner colSc = new Scanner(System.in);
int cols = colSc.nextInt();
return cols;
}
public static int[] matrix1Numbers(int rows, int cols) {
int[] numb = new int[rows * cols];
for (int j = 0; j <= numb.length; j += rows) {
for (int i = 1; i <= cols; i++) {
for (int k = 1; k <= rows; k++) {
System.out.println("What is the value for index ("
+ k + "," + i + ")?");
Scanner inp = new Scanner(System.in);
if (j + k <= numb.length) {
numb[j + k - 1] = inp.nextInt();
}
}
}
}
for (int i = 0; i < numb.length; i++) {
System.out.println(numb[i]);
}
return numb;
}
public static void doubleSpace() {
System.out.println();
System.out.println();
}
}
I use NetBeans 8.2 and the latest working version of Java for NetBeans.
I'm not familiar with the matrixmultiplication package, so I may be rambling here.
for (int j = 0; j <= numb.length; j += rows){
I'm not entirely sure what the outer for loop your have is for, but this most outer for loop causes you to ask for the values of the indices cols times more than you want.
I feel that you originally wanted to use this outer for loop to iterate through each row, and wasn't planning on having the second for loop iterating through cols perhaps?
Also, Kevin Anderson mentions this above. You might avoid this problem altogether if you return a double int array as opposed to storing all values in the matrix in a single dimension. I personally feel it would make more sense.
Just nitpicking, but I wouldn't make a new scanner every time you want to use one in a different method. You could just make a field at the top of your class, instantiate it once in your main method, and then pass it in as a parameter to all methods using the scanner.
I'm wondering if there are ways to improve the efficiency of the following code. (Or maybe there is a better algorithm?)
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++){
int m = sc.nextInt(), n = sc.nextInt(), maxM = 0, maxN = 0;
for (int j = 0; j < m; j++){
int newMonster = sc.nextInt();
if (newMonster > maxM){
maxM = newMonster;
}
}
for (int j = 0; j < n; j++){
int newMonster = sc.nextInt();
if (newMonster > maxN){
maxN = newMonster;
}
}
System.out.println(maxM >= maxN? "Godzilla": "MechaGodzilla");
}
Basically, I am reading in a bunch of numbers and want to find the maximum. For more detailed explanation of the original problem, please go to https://open.kattis.com/problems/armystrengthhard/
The current code takes more than 1s to complete running, but I'm not sure which part (reading inputs or comparing numbers) takes more time.
I would use a CPU profiler to work out why it is spending so much CPU, however it is highly likely your program spends most of it's time performing IO operations i.e. sc.nextInt() or System.out.println
Each IO operations is 1K to 10K times more expensive than any other operation you are doing.
im new to Java and currently trying to learn how to best store numbers in arrays.
the specific problem im working on is trying to find a way to better implement the below methods by storing the computations in an array.
the code looks like this:
public static long myF(int N) {
long[] computedValues;
computedValues = new long[N+1];
computedValues[0] = 0;
computedValues[1] = 1;
for (int i = 2; i < computedValues.length ;i++){
computedValues[i] = computedValues[(i-1)]+computedValues[(i-2)];
System.out.println("array["+(i)+"] = "+computedValues[i]);
}
return computedValues[N-1];
}
public static void runMyF() {
for (int N = 0; N < 100; N++)
StdOut.println(N + " " + myF(N));
}
public static void main(String[] args) {
runMyF ();
}
Main in this code is supposed to call runMyF(), and then runMyF() is supposed to call myF().
My problem is that I cant get computedValues[0] = 0; computedValues[1] = 1; included in the output and the second problem is that ie get this error message when runMyF() calls myF():
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at algs11.MyFib.myF(MyFib.java:21)
at algs11.MyFib.runMyF(MyFib.java:30)
at algs11.MyFib.main(MyFib.java:37)
Any help please?
#Dukeling, your solution was a bit over my pay grade (sorry) - I think there are some bugs in my code and I need help to find them. Thank you.
You're incrementing the wrong variable.
for (int i = 2; i < computedValues.length; N++){
should be
for (int i = 2; i < computedValues.length; i++){
Note the N++ changed to i++.
Remember to initialize computedValues[0] and computedValues[1]. This should appear before the loop:
computedValues[0] = 0;
if (N > 0) // needed because when N = 0, the below will be out of bounds
computedValues[1] = 1;
It should probably be computedValues = new long[N+1];, otherwise the array is too small.
You need to return the correct value - change return computedValues[N]; to return 0;.
Additional efficiency:
I guess the point is to compare the efficiency of the two method. If not, you should declare computedValues outside of the function as an ArrayList and, in the function, add to it as required. This will cause you to only compute each value once for the entire run of the program.
static ArrayList<Long> computedValues = new ArrayList<Long>(Arrays.asList(0l,1l));
public static long myF(int N) {
for (int i = computedValues.size(); i <= N; i++){
computedValues.add(computedValues.get(i-1) + computedValues.get(i-2));
System.out.println("array[" + i + "] = " + computedValues.get(i));
}
return computedValues.get(N);
}
You forgot the initial numbers in the array:
long[] computedValues;
computedValues = new long[N];
computedValues[0] = 0;
computedValues[1] = 1;
You are initializing computedValues to a new long
computedValues = new long[N];
I think you wanted to do this :
computedValues[i] = F(N);
Also, in your loop you are not incementing i which makes it as infinite loop. Change it to
for (int i = 2; i < computedValues.length ;i++)
You can use a method that returns an arraylist:
ArrayList<Long>series=new ArrayList<Long>();
for(int i=0;i<100;i++)
{
if(i==0)series.add(new Long(0));
if(i==1)series.add(new Long(1));
if(i>1)series.add(new Long(series.get(i-1).longValue()+series.get(i-2).longValue()));
}
the list will have 0,1,1,2,3,5,8,....
Currently, I am having problems with the Backpropagation algorithm.
I am trying to implement it and use it to recognize the direction of faces (left, right, down, straight).
Basically, I have N images, read the pixels and change its values(0 to 255) to values from 0.0 to 1.0. All images are 32*30.
I have an input layer of 960 neurons, a hidden layer of 3 neurons and an output layer of 4 neurons. For example, the output <0.1,0.9,0.1,0.1> means that the person looks to the right.
I followed the pseudy-code. However, it doesn't work right - it does not compute the correct weights and consequently it can't handle the training and test examples.
Here are parts of the code:
// main function - it runs the algorithm
private void runBackpropagationAlgorithm() {
for (int i = 0; i < 900; ++i) {
for (ImageUnit iu : images) {
double [] error = calcOutputError(iu.getRatioMatrix(), iu.getClassification());
changeHiddenUnitsOutWeights(error);
error = calcHiddenError(error);
changeHiddenUnitsInWeights(error,iu.getRatioMatrix());
}
}
}
// it creates the neural network
private void createNeuroneNetwork() {
Random generator = new Random();
for (int i = 0; i < inHiddenUnitsWeights.length; ++i) {
for (int j = 0; j < hiddenUnits; ++j) {
inHiddenUnitsWeights[i][j] = generator.nextDouble();
}
}
for (int i = 0; i < hiddenUnits; ++i) {
for (int j = 0; j < 4; ++j) {
outHddenUnitsWeights[i][j] = generator.nextDouble();
}
}
}
// Calculates the error in the network. It runs through the whole network.
private double [] calcOutputError(double[][] input, double [] expectedOutput) {
int currentEdge = 0;
Arrays.fill(hiddenUnitNodeValue, 0.0);
for (int i = 0; i < input.length; ++i) {
for (int j = 0; j < input[0].length; ++j) {
for (int k = 0; k < hiddenUnits; ++k) {
hiddenUnitNodeValue[k] += input[i][j] * inHiddenUnitsWeights[currentEdge][k];
}
++currentEdge;
}
}
double[] out = new double[4];
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < hiddenUnits; ++i) {
out[j] += outHddenUnitsWeights[i][j] * hiddenUnitNodeValue[i];
}
}
double [] error = new double [4];
Arrays.fill(error, 4);
for (int i = 0; i < 4; ++i) {
error[i] = ((expectedOutput[i] - out[i])*(1.0-out[i])*out[i]);
//System.out.println((expectedOutput[i] - out[i]) + " " + expectedOutput[i] + " " + out[i]);
}
return error;
}
// Changes the weights of the outgoing edges of the hidden neurons
private void changeHiddenUnitsOutWeights(double [] error) {
for (int i = 0; i < hiddenUnits; ++i) {
for (int j = 0; j < 4; ++j) {
outHddenUnitsWeights[i][j] += learningRate*error[j]*hiddenUnitNodeValue[i];
}
}
}
// goes back to the hidden units to calculate their error.
private double [] calcHiddenError(double [] outputError) {
double [] error = new double[hiddenUnits];
for (int i = 0; i < hiddenUnits; ++i) {
double currentHiddenUnitErrorSum = 0.0;
for (int j = 0; j < 4; ++j) {
currentHiddenUnitErrorSum += outputError[j]*outHddenUnitsWeights[i][j];
}
error[i] = hiddenUnitNodeValue[i] * (1.0 - hiddenUnitNodeValue[i]) * currentHiddenUnitErrorSum;
}
return error;
}
// changes the weights of the incomming edges to the hidden neurons. input is the matrix of ratios
private void changeHiddenUnitsInWeights(double [] error, double[][] input) {
int currentEdge = 0;
for (int i = 0; i < input.length; ++i) {
for (int j = 0; j < input[0].length; ++j) {
for (int k = 0; k < hiddenUnits; ++k) {
inHiddenUnitsWeights[currentEdge][k] += learningRate*error[k]*input[i][j];
}
++currentEdge;
}
}
}
As the algorithm works, it computes bigger and bigger weights, which finally approach infinity (NaN values). I checked the code. Alas, I didn't manage to solve my problem.
I will be firmly grateful to anyone who would try to help me.
I didn't check all of your code. I just want to give you some general advices. I don't know if your goal is (1) to learn the direction of faces or (2) to implement your own neural network.
In case (1) you should consider one of those libraries. They just work and give you much more flexible configuration options. For example, standard backpropagation is one of the worst optimization algorithms for neural networks. The convergence depends on the learning rate. I can't see which value you chose in your implementation, but it could be too high. There are other optimization algorithms that don't require a learning rate or adapt it during training. In addition, 3 neurons in the hidden layer is most likely not enough. Most of the neural networks that have been used for images have hundreds and sometimes even thousands of hidden units. I would suggest you first try to solve your problem with a fully developed library. If it does work, try implementing your own ANN or be happy. :)
In case (2) you should first try to solve a simpler problem. Take a very simple artificial data set, then take a standard benchmark and then try it with your data. A good way to verify that your backpropagation implementation works is a comparison with a numerical differentation method.
Your code is missing the transfer functions. It sounds like you want the logistic function with a softmax output. You need to include the following in calcOutputError
// Logistic transfer function for hidden layer.
for (int k = 0; k < hiddenUnits; ++k) {
hiddenUnitNodeValue[k] = logistic(hiddenUnitNodeValue[k]);
}
and
// Softmax transfer function for output layer.
sum = 0;
for (int j = 0; j < 4; ++j) {
out[j] = logistic(out[j]);
sum += out[j];
}
for (int j = 0; j < 4; ++j) {
out[j] = out[j] / sum;
}
where the logistic function is
public double logistic(double x){
return (1/(1+(Math.exp(-x)));
}
Note that the softmax transfer function gives you outputs that sum to 1, so they can be interpreted as probabilities.
Also, your calculation of the error gradient for the output layer is incorrect. It should simply be
for (int i = 0; i < 4; ++i) {
error[i] = (expectedOutput[i] - out[i]);
}
I haven't tested your code but I am almost certain that you start out with to large weights.
Most of the introductions on the subjects leave it at "init the weights with random values" and leaving out that the algorithm actually diverges (goes to Inf) for some starting values.
Try using smaller starting values, for example between -1/5 and 1/5 and shrink it down.
And additionally do an method for matrix multiplication, you have (only) used that 4 times, much easier to see if there is some problem there.
I had a similar problem with a neural network processing grayscale images. You have 960 input values ranging between 0 and 255. Even with small initial weights, you can end up having inputs to your neurons with a very large magnitude and the backpropagation algorithm gets stuck.
Try dividing each pixel value by 255 before passing it into the neural network. That's what worked for me. Just starting with extremely small initial weights wasn't enough, I believe due to the floating-point precision issue brought up in the comments.
As suggested in another answer, a good way to test your algorithm is to see if your network can learn a simple function like XOR.
And for what it's worth, 3 neurons in the hidden layer was plenty for my purpose (identifying the gender of a facial image)
I wrote an entire new neural-network library and it works. It is sure that in my previous attempt I missed the idea of using transfer functions and their derivatives. Thank you, all!