First and foremost this is an assignment for my college class. Please do not hack the answer out for me as it will not help me help myself. I'm merely looking for an experienced point of view as to why I have hit a brick wall on something that seems easy.
What I have done: I have an Election class that will add Candidate objects to an ArrayList of type Candidate. A Candidate object has the following attributes, a name, id, and total number of votes (that starts at zero, of course). These Candidate objects are created and stored into an Candidate[] within the main client. The Candidate object's are then added to the Arraylist of type Candidate - located in the Election class.
My Problem: The votes for a Candidate are read from a text file that consists of numbers 1 -24. Each vote corresponds to the id of a Candidate. In the countVotes method located in the Election class I'm reading the text file containing the votes. I am then trying to compare the votes read from the text file in real-time to a Candidate's id. If a vote and Id are equal then increment count to get total number of votes for a Candidate. However, this method will only work for one Candidate id at a time. For example if I fed the method call countVotes(readFile, cands[1]) it will work for only the specific Candidate. I know that I should probably store the votes in another ArrayList and then do comparison using two ArrayLists. I'm looking for insight on how to go about comparing the votes read from the text file to each Candidate's id and then setting the total number of votes counted for each Candidate.
Here is the Candidate class:
package problem_one;
public class Candidate <E> {
protected String name;
protected int id;
protected int votes;
public Candidate(String name, int id){
this.name = name;
this.id = id;
votes = 0;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public void setVotes(int votes) {
this.votes = votes;
}
public int getVotes(){
return votes;
}
public String toString(){
String display = "\nCandidate: " + getName() + "\nID: " + getId() + "\nVotes: " + getVotes() + "\n";
return display;
}
}
Here is the Election Class:
package problem_one;
import java.util.ArrayList;
import java.util.Scanner;
public class Election<E>{
@SuppressWarnings("rawtypes")
protected ArrayList<Candidate> ballot = new ArrayList<Candidate>();
public void addCandidate(Candidate<E> cand){
ballot.add(cand);
}
public void countVotes(Scanner readFile, Candidate cand){
Integer vote;
int count = 0;
while(readFile.hasNextInt()){
vote = readFile.nextInt();
if(vote.equals(cand.getId())){
count++;
cand.setVotes(count);
}
}
}
public String toString(){
String display = "";
for(Candidate cand : ballot){
display += cand;
}
return display;
}
}
Here is the main client:
package pa2_clients;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import problem_one.Candidate;
import problem_one.Election;
public class problem_one_client {
public static void main(String[] args) {
Election<Object> elect = new Election<Object>();
File file = new File("votes");
Scanner readFile;
Candidate[] cands = new Candidate[24];
cands[0] = new Candidate<Object>("Washingtion", 1);
cands[1] = new Candidate<Object>("Adams", 2);
cands[2] = new Candidate<Object>("Jefferson", 3);
cands[3] = new Candidate<Object>("Madison", 4);
cands[4] = new Candidate<Object>("Monroe", 5);
cands[5] = new Candidate<Object>("Quincy Adams", 6);
cands[6] = new Candidate<Object>("Jackson", 7);
cands[7] = new Candidate<Object>("Van Buren", 8);
cands[8] = new Candidate<Object>("Harrision", 9);
cands[9] = new Candidate<Object>("Tyler", 10);
cands[10] = new Candidate<Object>("Polk", 11);
cands[11] = new Candidate<Object>("Taylor", 12);
cands[12] = new Candidate<Object>("Fillmore", 13);
cands[13] = new Candidate<Object>("Pierce", 14);
cands[14] = new Candidate<Object>("Buchanan", 15);
cands[15] = new Candidate<Object>("Lincoln", 16);
cands[16] = new Candidate<Object>("Johnson", 17);
cands[17] = new Candidate<Object>("Grant", 18);
cands[18] = new Candidate<Object>("Hayes", 19);
cands[19] = new Candidate<Object>("Garfield", 20);
cands[20] = new Candidate<Object>("Arthur", 21);
cands[21] = new Candidate<Object>("Cleveland", 22);
cands[22] = new Candidate<Object>("McKinely", 23);
cands[23] = new Candidate<Object>("Roosevely", 24);
for(Candidate cand : cands){
elect.addCandidate(cand);
}
try {
readFile = new Scanner(file);
elect.countVotes(readFile, cands[0]);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(elect.toString());
}
}
The output from running the program:
Candidate: Washingtion
ID: 1
Votes: 1669
Candidate: Adams
ID: 2
Votes: 0
Candidate: Jefferson
ID: 3
Votes: 0
Candidate: Madison
ID: 4
Votes: 0
Candidate: Monroe
ID: 5
Votes: 0
Candidate: Quincy Adams
ID: 6
Votes: 0
Candidate: Jackson
ID: 7
Votes: 0
Candidate: Van Buren
ID: 8
Votes: 0
Candidate: Harrision
ID: 9
Votes: 0
Candidate: Tyler
ID: 10
Votes: 0
Candidate: Polk
ID: 11
Votes: 0
Candidate: Taylor
ID: 12
Votes: 0
Candidate: Fillmore
ID: 13
Votes: 0
Candidate: Pierce
ID: 14
Votes: 0
Candidate: Buchanan
ID: 15
Votes: 0
Candidate: Lincoln
ID: 16
Votes: 0
Candidate: Johnson
ID: 17
Votes: 0
Candidate: Grant
ID: 18
Votes: 0
Candidate: Hayes
ID: 19
Votes: 0
Candidate: Garfield
ID: 20
Votes: 0
Candidate: Arthur
ID: 21
Votes: 0
Candidate: Cleveland
ID: 22
Votes: 0
Candidate: McKinely
ID: 23
Votes: 0
Candidate: Roosevely
ID: 24
Votes: 0
EDIT:
Thank you Adriaan for your advice and time.
I was able to fix the problem by implementing another ArrayList to hold the votes read from the txt file. Furthermore, I now understand that using a Map as the data structure to hold the Candidate objects would be the better option.
The reason I decided to stay with my implementation is because I now have to implement a priority queue and I'm not sure how to use a Map with a priority queue. Otherwise, thank you again for the knowledge you have passed my way. Posting the updated code... Please feel free to comment on the updated solution.
Updated Candidate Class:
package problem_one;
public class Candidate {
private String name;
private int id;
private int votes;
public Candidate(String name, int id) {
this.name = name;
this.id = id;
votes = 0;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public void addVote() {
votes++;
}
public int getVotes() {
return votes;
}
public String toString() {
StringBuilder str = new StringBuilder();
str.append("\nCandidate: " + getName());
str.append("\nID: " + getId());
str.append("\nVotes: " + getVotes() + "\n");
return str.toString();
}
}
The Updated Election Class:
package problem_one;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Election {
private List<Candidate> ballot = new ArrayList<Candidate>();
private List<Integer> votes = new ArrayList<Integer>();
public void addCandidate(Candidate cand) {
ballot.add(cand);
}
public void readVotes(Scanner readFile) {
int vote;
while (readFile.hasNextInt()) {
vote = readFile.nextInt();
votes.add(vote);
}
}
public void countVotes(Candidate cand) {
for (int i = 1; i < votes.size(); i++) {
if (votes.get(i).equals(cand.getId())) {
cand.addVote();
}
}
}
public String toString() {
StringBuilder str = new StringBuilder();
for (Candidate cand : ballot) {
str.append(cand);
}
return str.toString();
}
}
The output:
Candidate: Washington
ID: 1
Votes: 1669
Candidate: Adams
ID: 2
Votes: 1495
Candidate: Jefferson
ID: 3
Votes: 103
Candidate: Madison
ID: 4
Votes: 32
Candidate: Monroe
ID: 5
Votes: 1474
Candidate: Quincy Adams
ID: 6
Votes: 1653
Candidate: Jackson
ID: 7
Votes: 44
Candidate: Van Buren
ID: 8
Votes: 2730
Candidate: Harrision
ID: 9
Votes: 112
Candidate: Tyler
ID: 10
Votes: 808
Candidate: Polk
ID: 11
Votes: 327
Candidate: Taylor
ID: 12
Votes: 33
Candidate: Fillmore
ID: 13
Votes: 1037
Candidate: Pierce
ID: 14
Votes: 41
Candidate: Buchanan
ID: 15
Votes: 313
Candidate: Lincoln
ID: 16
Votes: 1438
Candidate: Johnson
ID: 17
Votes: 428
Candidate: Grant
ID: 18
Votes: 1346
Candidate: Hayes
ID: 19
Votes: 1512
Candidate: Garfield
ID: 20
Votes: 1171
Candidate: Arthur
ID: 21
Votes: 539
Candidate: Cleveland
ID: 22
Votes: 132
Candidate: McKinely
ID: 23
Votes: 304
Candidate: Roosevelt
ID: 24
Votes: 33
EDIT FINAL SOLUTION:
Here is the final solution that I turned in... I didn't get to rework the code completely due to having other assignments to finish.
The comparator had to be implemented inside the for loop located in the Election class method startElectionProblemTwo. This was the only way I could get the comparator to produce the expected results. This happened because I didn't plan for changing the code down the road. Which is something I should have done from the beginning.
Also I wanted to read in the Candidates from a file but didn't get to implement this before the due date.
The comparator is used when the votes are equal. When the votes are equal we then check the number of consecutive terms served. Less terms served win, if the terms served are equal then we compare by name.
Candidate class:
package problem_one;
public class Candidate {
private String name;
private int id;
private int votes;
private int terms;
public Candidate(String name, int id, int terms){
this.name = name;
this.id = id;
this.terms = terms;
votes = 0;
}
public Candidate(){
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public void addVote() {
votes++;
}
public int getVotes() {
return votes;
}
public int getTerms() {
return terms;
}
public String toString() {
StringBuilder str = new StringBuilder();
str.append("Candidate: " + getName());
str.append("\nID: " + getId());
str.append("\nTerms: " + getTerms());
str.append("\nVotes: " + getVotes() + "\n");
return str.toString();
}
}
Election class:
package problem_one;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import problem_two.ElectionTieBreaker;
public class Election extends Candidate{
// Priority Queue using a max heap.
private List<Candidate> ballotPq;
// Stores the votes read from the *votes* file.
private List<Integer> votes = new ArrayList<Integer>();
public Election(String name, int id, int terms){
super(name, id, terms);
}
public Election(){
ballotPq = new ArrayList<Candidate>();
}
// Change to PQ offer method.
public void offer(Candidate cand) {
countVotes(cand);
ballotPq.add(cand);
int child = ballotPq.size() - 1;
int parent = ((child - 1) / 2);
while (parent >= 0 && ballotPq.get(parent).getVotes() < ballotPq.get(child).getVotes()) {
swap(parent, child);
child = parent;
parent = ((child - 1) / 2);
}
}
// Modified Priority Queue method poll.
private Candidate poll() {
// Return null if the ArrayList is empty.
if (isEmpty())
return null;
// Sets cand to the Candidate object at index 0.
Candidate cand = ballotPq.get(0);
// Check if there is only one Candidate object.
if (ballotPq.size() == 1) {
ballotPq.remove(0);
return cand;
}
// Move the last element to the head of the Priority Queue.
ballotPq.set(0, ballotPq.remove(ballotPq.size() - 1));
int parent = 0;
while (true) {
// Finds the parents left-child, i.e. Parents left child is at 2i + 1.
int leftChild = ((2 * parent) + 1);
// Break out of loop.
if (leftChild >= ballotPq.size()) {
break;
}
// Finds the parents right-child, i.e. Parents right child is at 2i + 2.
int rightChild = (leftChild + 1);
// Assert that the leftChild is the min child
int minChild = leftChild;
// If true sets the min child
if (rightChild < ballotPq.size() && ballotPq.get(leftChild).getVotes() < ballotPq.get(rightChild).getVotes()) {
minChild = rightChild;
}
// Swaps the parent and min child if true
if (ballotPq.get(parent).getVotes() < ballotPq.get(minChild).getVotes()) {
swap(parent, minChild);
parent = minChild;
} else {break;}
}
return cand;
}
// Checks if the ArrayList is empty.
private boolean isEmpty() {
return ballotPq.size() == 0;
}
// Swaps the parent and child at the specified indices.
private void swap(int i, int j) {
Candidate one = ballotPq.get(i);
Candidate two = ballotPq.get(j);
ballotPq.set(i, two);
ballotPq.set(j, one);
}
// Reads the votes from the *votes* txt file.
private void readVotes() {
File file = new File("votes");
Scanner readFile;
try {
readFile = new Scanner(file);
while (readFile.hasNextInt()) {
int vote = readFile.nextInt();
votes.add(vote);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
// Counts the total votes casted for each Candidate.
private void countVotes(Candidate cand) {
for (int i = 0; i < votes.size(); i++) {
if (votes.get(i).equals(cand.getId())) {
cand.addVote();
}
}
}
// Starts the election for problem one
public void startElectionProblemOne() {
readVotes();
offer(new Candidate("Washington", 1, 3));
offer(new Candidate("Adams", 2, 3));
offer(new Candidate("Jefferson", 3, 2));
offer(new Candidate("Madison", 4, 2));
offer(new Candidate("Monroe", 5, 2));
offer(new Candidate("Quincy Adams", 6, 1));
offer(new Candidate("Jackson", 7, 1));
offer(new Candidate("Van Buren", 8, 3));
offer(new Candidate("Harrision", 9, 1));
offer(new Candidate("Tyler", 10, 2));
offer(new Candidate("Polk", 11, 2));
offer(new Candidate("Taylor", 12, 3));
offer(new Candidate("Fillmore", 13, 2));
offer(new Candidate("Pierce", 14, 2));
offer(new Candidate("Buchanan", 15, 1));
offer(new Candidate("Lincoln", 16, 1));
offer(new Candidate("Johnson", 17, 2));
offer(new Candidate("Grant", 18, 3));
offer(new Candidate("Hayes", 19, 2));
offer(new Candidate("Garfield", 20, 1));
offer(new Candidate("Arthur", 21, 1));
offer(new Candidate("Cleveland", 22, 4));
offer(new Candidate("McKinely", 23, 1));
offer(new Candidate("Roosevelt", 24, 3));
System.out.println("Elected City Supervisor " + "\n" + poll());
for (int i = 0; i < 4; i++) {
System.out.println("Elected City Council " + "\n" + poll());
}
}
// Starts the election for problem two
public void startElectionProblemTwo(){
readVotes();
offer(new Candidate("Washington", 1, 3));
offer(new Candidate("Adams", 2, 3));
offer(new Candidate("Jefferson", 3, 2));
offer(new Candidate("Madison", 4, 2));
offer(new Candidate("Monroe", 5, 2));
offer(new Candidate("Quincy Adams", 6, 1));
offer(new Candidate("Jackson", 7, 1));
offer(new Candidate("Van Buren", 8, 3));
offer(new Candidate("Harrision", 9, 1));
offer(new Candidate("Tyler", 10, 2));
offer(new Candidate("Polk", 11, 2));
offer(new Candidate("Taylor", 12, 3));
offer(new Candidate("Fillmore", 13, 2));
offer(new Candidate("Pierce", 14, 2));
offer(new Candidate("Buchanan", 15, 1));
offer(new Candidate("Lincoln", 16, 1));
offer(new Candidate("Johnson", 17, 2));
offer(new Candidate("Grant", 18, 3));
offer(new Candidate("Hayes", 19, 2));
offer(new Candidate("Garfield", 20, 1));
offer(new Candidate("Arthur", 21, 1));
offer(new Candidate("Cleveland", 22, 4));
offer(new Candidate("McKinely", 23, 1));
offer(new Candidate("Roosevelt", 24, 3));
for (int i = 0; i < 24; i++) {
// Comparator for candidates
Collections.sort(ballotPq, new ElectionTieBreaker());
System.out.println(poll());
}
}
}
ElectionTieBreaker class:
package problem_two;
import java.util.Comparator;
import problem_one.Candidate;
public class ElectionTieBreaker implements Comparator<Candidate> {
@Override
public int compare(Candidate o1, Candidate o2) {
int flag = o2.getVotes() - o1.getVotes();
// if the votes are the same
if(flag != 0){
return flag;
}
if(o1.getTerms() - o2.getTerms() == 0){
flag = o1.getName().compareTo(o2.getName());
}else{
flag = o1.getTerms() - o2.getTerms();
}
return flag;
}
}
ProblemOneClient:
package pa2_clients;
import problem_one.Election;
public class ProblemOneClient {
public static void main(String[] args) {
Election election = new Election();
election.startElectionProblemOne();
}
}
ProblemTwoClient:
package pa2_clients;
import problem_one.Election;
public class ProblemTwoClient {
public static void main(String[] args) {
Election elect = new Election();
elect.startElectionProblemTwo();
}
}