Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Java dev's, please look at this code.

Java dev's, please look at this code.
Thread Tools
Professional Poster
Join Date: Oct 2001
Status: Offline
Reply With Quote
Apr 11, 2005, 10:24 PM
 
I just got back from a programming competition. I'm very frustrated because I wrote what seems to be correct code for one of the problems, but I'm getting very strange results. After the competition I showed the code to several people and no one could figure out what's wrong with it. I'd like to know if it's a bug in Java 1.4.2_05 or my fault. Here's the problem:
You are given a file with a list of names of songs in it. For each song you find, you must increment it's popularity, it is also case insensitive. So if you find "oh yeah" and "oH YEah", that song has a popularity of 2. Finally you must display the top five most popular songs.

Here is the input file (songs.in):
Code:
ACM ROX syzygy 123 thisisasong5 myfavoritesong ACM ROX SYZYGY 123 thisisasong5 ACM ROX sYzYgY 123 Acm Rox syzygy ACM ROx
And here is my code:
[php]import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Comparator;
import java.util.TreeSet;
import java.util.Iterator;
import java.util.NoSuchElementException;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.FileReader;
import java.io.File;


public class Songs {
private static final String file = "songs.in";

TreeSet songs;

public static void main(String[] args) {
new Songs();
}
public Songs() {
songs = new TreeSet(new CompareSongs());
try {
BufferedReader in = new BufferedReader(new FileReader(file));

String aSong;
int asdf = 0; // just for debugging; ignore this variable
while ((aSong = in.readLine()) != null) {
asdf++;
Iterator i = songs.iterator();

boolean foundSong = false;
while (i.hasNext()) {
Song song = (Song)i.next();
System.out.println("Loop "+asdf+": "+song.name);
if (song.name.equalsIgnoreCase(aSong)) {
System.out.println("already have "+song.name);
song.popularity++;
foundSong = true;
}
}
if (foundSong == false) {
Song song1 = new Song(aSong);
song1.popularity++;
songs.add(song1);
System.out.println("Added song "+aSong);
}
}

try {
for (int i=0; i<5; i++) {
Song song2 = (Song)songs.last();
System.out.println(song2.name + " "+song2.popularity);
songs.remove(song2);
}
} catch (NoSuchElementException e) {
System.out.println("finish");
}
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
private class CompareSongs implements Comparator {
public int compare(Object o1, Object o2) {
if (((Song)o1).popularity > ((Song)o2).popularity) {
return 1;
} else if (((Song)o1).popularity < ((Song)o2).popularity) {
return -1;
} else {
return 0;
}
}
}
private class Song {
public int popularity=0;
public String name;
public Song(String name) {
popularity = 0;
this.name = name;
}
public boolean equals(Object o) {
if (this.name.equalsIgnoreCase(((Song)o).name))
return true;
else
return false;
}
}
}[/php]
The result from running this code is describe as follows: At first it will add the song to the TreeSet correctly, and the next time around it'll correctly show that there is one Song in the TreeSet. However, as more songs are added, the amount of songs returned by the Iterator remains only 1. It then says for a while that there are only two songs (when there should be a lot more), and sometimes it will actually decrease in the amount of Songs returned! (It will iterate through 3 songs, and then drop down to 1 song in the next loop around).

Any help figuring out what's going on is greatly appreciated!
     
Forum Regular
Join Date: Nov 2002
Location: PVD/MSP
Status: Offline
Reply With Quote
Apr 11, 2005, 11:48 PM
 
I'm not sure what the bug is in your code, but I'm just curious as to why you chose a TreeSet as your main data structure. I'm not meaning to criticize as there could be something I'm missing, but it seems to me the only benefit you get with a TreeSet is that retrieving the top 5 is quick. The trade off you made, though, is that insertion is very slow (because you iterate through all the data on each insertion to check for existance). Did you consider a Hashtable and then a sort at the end? I think that would offer better over all performance. Better yet a TreeMap seems to offer exactly what you're looking for: an automatic (and cheap) sorting, cheap tests for existance, cheap gets and cheap puts.

Again, I'm not meaning to criticize, I'm just curious. Good luck with the bug.
dearinter.net consensus life coaching.
     
Professional Poster
Join Date: Oct 2001
Status: Offline
Reply With Quote
Apr 12, 2005, 05:34 AM
 
Yes I'm aware there are better solutions to this problem, but when one is at a programming competition, efficiency is the last thing one thinks about I just wanted a quick and dirty solution.
     
Professional Poster
Join Date: Oct 2001
Status: Offline
Reply With Quote
Apr 12, 2005, 06:09 AM
 
Found out what's happening: My Comparator is returning that they are equals if their popularity is the same, and I was modifying the objects of the TreeSet while they were in it, which apparently is a no-no.

I should have just put them into an ArrayList and sorted the object's of that at the end of the loop using Arrays.sort(). Oh well.
     
Fresh-Faced Recruit
Join Date: Feb 2004
Status: Offline
Reply With Quote
Apr 12, 2005, 06:41 AM
 
... and Sets cannot hold equal Objects (in this case Songs with the same popularity).

The data structure you're looking for is probably a Heap (a Max Heap -- the root element is the largest and as soon as you remove it the 2nd largest element becomes the root and so on. However QuickSort is a bit faster).
     
Forum Regular
Join Date: Nov 2002
Location: PVD/MSP
Status: Offline
Reply With Quote
Apr 12, 2005, 09:08 AM
 
Originally posted by itistoday:
Yes I'm aware there are better solutions to this problem, but when one is at a programming competition, efficiency is the last thing one thinks about I just wanted a quick and dirty solution.
I've been to programming competitions, too. I tended to shoehorn everything into working with a Hashtable
dearinter.net consensus life coaching.
     
Forum Regular
Join Date: Dec 2004
Status: Offline
Reply With Quote
Apr 17, 2005, 02:37 AM
 
If programming competitions don't factor code efficiency into the score, then all they are doing is encouraging poor programming practice. If you can't solve the problem quickly and elegantly, then you shouldn't win.
     
Professional Poster
Join Date: Oct 2001
Status: Offline
Reply With Quote
Apr 17, 2005, 12:08 PM
 
Originally Posted by ideasculptor
If programming competitions don't factor code efficiency into the score, then all they are doing is encouraging poor programming practice. If you can't solve the problem quickly and elegantly, then you shouldn't win.
I disagree. I always try to find the most efficient and elegant solution to problems that I encounter when programming my own apps, but most people don't go to programming competition to fine tune code that no one will ever look at (or even use for that matter)—they go there to win.
     
Fresh-Faced Recruit
Join Date: Feb 2004
Status: Offline
Reply With Quote
Apr 17, 2005, 02:47 PM
 
Hmm, your code is neither efficient, elegant nor does it work!

http://www.devx.com/tips/Tip/13902
     
Professional Poster
Join Date: Oct 2001
Status: Offline
Reply With Quote
Apr 17, 2005, 03:17 PM
 
Originally Posted by bone666
Hmm, your code is neither efficient, elegant nor does it work!

http://www.devx.com/tips/Tip/13902
Hey thanks for pointing out the obvious! At a programming competition, I don't care about the former two, and the reason I'm posting here is because of the latter, the reason to which btw, had you read the thread, I've already figured out.

I just had a penchant for TreeSet (because I've used it before), and thought I knew how it worked. Had I known during the competition how TreeSet's really work, I would have done this:
[php]import java.util.ArrayList;
import java.util.Comparator;
import java.util.Arrays;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileReader;


public class Songs {
private static final String file = "songs.in";

public static void main(String[] args) {
new Songs();
}
public Songs() {
ArrayList songs = new ArrayList();
try {
BufferedReader in = new BufferedReader(new FileReader(file));

String aSong;
while ((aSong = in.readLine()) != null) {
boolean foundSong = false;
for (int i=0; i<songs.size(); i++) {
Song song = (Song)songs.get(i);
if (song.name.equalsIgnoreCase(aSong)) {
song.popularity++;
foundSong = true;
}
}
if (foundSong == false) {
Song song1 = new Song(aSong);
song1.popularity++;
songs.add(song1);
}
}
Object[] songsArray = songs.toArray();
Arrays.sort(songsArray, new CompareSongs());
for (int i=songsArray.length-1; i>(songsArray.length-6); i--) {
Song song = (Song)songsArray[i];
System.out.println(song.name);
}
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
private class CompareSongs implements Comparator {
public int compare(Object o1, Object o2) {
if (((Song)o1).popularity > ((Song)o2).popularity) {
return 1;
} else if (((Song)o1).popularity < ((Song)o2).popularity) {
return -1;
} else {
return ((Song)o1).name.compareToIgnoreCase(((Song)o2).nam e);
}
}
}
private class Song {
public int popularity=0;
public String name;
public Song(String name) {
popularity = 0;
this.name = name;
}
}
}[/php]
Thanks for that link though.
(Last edited by itistoday; Apr 17, 2005 at 03:34 PM. )
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 07:25 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2