I haven't coded all winter, and it seems like everything I learned about efficiency from my data structures class leaked out my head. I was wondering if I can get some help in making my code less verbose, and more efficient, as some of the things I do seem redundant. My code is correct (I'm confident as I tested it), and completes the assignment, as the class isn't a class where we learn programming like in previous classes, but just learn different types of languages.
I am to assume perfect input format and correct inputs, which will be from a .input file I will be using to redirect in an Unix environment.
The simple program is to match the best candidate for a voter with several candidates. There are 10 imaginary topics which the imaginary voter answered; a "-1" means disagreement, a "0" means doesn't care, a "1" means agreement. The candidates also took the same survey on the same topics, and the same rules apply to them. If the voter OR the candidate voted a "0" for a particular topic, the total agreement value isn't affected. If the values between the voter and the candidate are same, this increments the agreement value. If the values are different, the agreement value is decremented. At the end, the candidates with the highest values are presented to the voter. An example:
Voter answers:
0 0 0 1 1 1 -1 -1 -1 1
Candidates answers:
Cand #1: 1 1 1 1 1 1 1 1 1 1 Cand #2: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 Cand #3: 1 1 1 1 0 0 0 0 0 0 Cand #1 has a total of 4 agreements, and 3 disagreements, so total of 1. Cand #2 has 3 agreements, and 4 disagreements, so a total of -1. Cand #3 has a total of 1 agreement, and 0 disagreements, so total of 1.
Here is my code:
/**
* Purpose:
* Status: Testing
* Last update: 01/30/15
* Submitted: 02/04/15
* @author
* @version: 2015.01.30
* BestMatch Class
*/
public class BestMatch {
private String[] voterAnswers;
private String[][] candAnswers;
/**
* Constructor for class
* @param voterAnswers a String[] containing opinion values of voter
* @param candAnswers a 2D array containing opinion of candidates
* initializes the class fields
*/
public BestMatch(String[] voterAnswers, String[][] candAnswers) {
this.voterAnswers = voterAnswers;
this.candAnswers = candAnswers;
}
/**
* Computes the total agreement value of each candidate
* @return returns an array of agreement values
* @throws Exception If the number of opinions differ
*/
private int[] computeAgreementValues() throws Exception {
int[] values = new int[candAnswers.length];
if (candAnswers[0].length == voterAnswers.length + 1) {
for (int i = 0; i < values.length; i++) {
int agreementValue = 0;
for (int j = 1; j < candAnswers[0].length; j++) {
DONOTHING: if (Integer.parseInt(voterAnswers[j - 1].trim()) == 0
|| Integer.parseInt(candAnswers[i][j].trim()) == 0) {
break DONOTHING;
} else if (voterAnswers[j - 1].trim().compareTo(
candAnswers[i][j].trim()) == 0) {
agreementValue++;
} else {
agreementValue--;
}
}
values[i] = agreementValue;
}
} else
throw new Exception(
"Unmatched amount of values from voter and candidates.");
return values;
}
/**
* Get candidates with highest values
* @return
* @throws Exception
*/
private String[] getCandidates() throws Exception {
int[] theArray = computeAgreementValues();
int maxValue = findMaxValue(theArray);
StringBuilder s = new StringBuilder("");
for (int i = 0; i < theArray.length; i++) {
if (theArray[i] == maxValue) {
s.append(candAnswers[i][0] + " ");
}
}
String[] strArray = s.toString().trim().split(" ");
return strArray; //is it possible to do return in one line?
}
/**
* Helper method to find largest value in array
* @param theArray
* @return
*/
private int findMaxValue(int[] theArray) {
int max = theArray[0];
for (int i = 1; i < theArray.length; i++) {
if (max == theArray.length) { // largest possible value is size of
// array
break;
} else if (theArray[i] > max) {
max = theArray[i];
}
}
return max;
}
/**
* Get the best candidates for the voter
* @param names an Array of name values
* @return return a String statement
* @throws Exception
*/
public String getBestCandidates() throws Exception {
String[] names = getCandidates();
StringBuilder s = new StringBuilder(
"The best candidate(s) for this particular voter is/are:");
for (int i = 0; i < names.length; i++) {
s.append(" " + names[i]);
if (i == names.length - 1) {
s.append(".");
} else {
s.append(",");
}
}
return s.toString().trim();
}
public static void main(String[] args) throws Exception {
String[][] strArray = new String[4][11];
String[][] candArray = {
{ "Cand#1", "1", "-1", "0", "1", "-1", "1", "0", "1", "1", "0" },
{ "Cand#2", "0", "1", "-1", "1", "0", "-1", "1", "1", "0", "1" },
{ "Cand#3", "1", "1", "-1", "1", "1", "1", "1", "-1", "-1", "1" },
{ "Cand#4", "-1", "-1", "-1", "-1", "-1", "-1", "-1", "-1",
"-1", "-1" },
{ "Cand#5", "1", "1", "-1", "1", "1", "1", "1", "-1", "-1", "1" } };
String[] vArray = { "1", "0", "-1", "1", "1", "0", "1", "-1", "-1", "0" };
// System.out.println(candArray.length);
BestMatch bm = new BestMatch(vArray, candArray);
// System.out.println(candArray[0][1]);
System.out.println(bm.getBestCandidates());
}
}
A summary of what I do:
I take in the voter answers as an array of values, and the candidates answers as a 2D array. (Note: the X axis of the voter array has 10, while the candidates has 11, because the first slot of the candidates are the names). I then just loop through each candidate and compare against the values in the voter array. I put the agreement values in a separate array containing agreements values per candidate.
I then loop through THAT array, and find the highest value. I then loop through the array again, and find all candidates with that value and put that into a string, which I output.
I need tips on cutting down operations, making my code more terse, and any other general tips, and reminders.