我的项目是根据给定的文本文件比较彩票号码出现的频率。我从逐行读取文件开始,然后提取数字,最后比较数字的频率。我在寻找各种各样的批评!
/**
* Author: Brandon F.
* Purpose: Compares lottery numbers to see which are the most frequent and least frequent
* Date: 4/25/2017
* Status: Works while comparing one most frequent and one least frequent, but will not work
* if trying to compare two most frequents and two least frequents at the same time.
*/
package imDone;
import java.io.IOException;
public class TheDriver {
public static void main(String args[]) throws IOException {
// starts by allocating memory to a string of where the text
// file is (should be in same file as bin and src directories are)
String fileName = "DownloadAllNumbers.txt";
// creates two arrays to keep track of all possible numbers in the
// lottery
int[] gg = new int[47];
int[] megaNums = new int[27];
// reads and records all of the lottery numbers
try {
Reader file = new Reader(fileName);
String[] aryLines = file.OpenFile();
// starts at line 5 because previous lines are irrelevent
// information
for (int i = 5; i < aryLines.length; i++) {
// adds one to each slow in the array by reading between the
// substring and trimming any extra whitespace
gg[Integer.parseInt(aryLines[i].substring(36, 38).trim()) - 1]++;
gg[Integer.parseInt(aryLines[i].substring(46, 50).trim()) - 1]++;
gg[Integer.parseInt(aryLines[i].substring(58, 62).trim()) - 1]++;
gg[Integer.parseInt(aryLines[i].substring(69, 74).trim()) - 1]++;
gg[Integer.parseInt(aryLines[i].substring(80, 86).trim()) - 1]++;
// adds the last digit to mega number array
megaNums[Integer.parseInt(aryLines[i].substring(90).trim()) - 1]++;
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
System.out.println("Top 5 most frequent NUMBERS");
getHotNumbers(gg);
// System.out.println("Top 5 most frequent MEGA-NUMBERS");
// getHotNumbers(megaNums);
System.out.println("Least fequent MEGA-NUMBERS");
getColdNumbers(megaNums);
// System.out.println("Least fequent NUMBERS");
// getColdNumbers(gg);
} // end of main
// gets the most frequent numbers in an array
public static void getHotNumbers(int[] noRe) {
// hotNums used for actual number, hotTime used for frequency
int[] hotNums = new int[5];
int[] hotTime = new int[5];
// easy to beat number to compare for largest number
int compare = 0;
// loops through 5 times setting the greatest number to 0 each time
for (int j = 0; j < 5; j++) {
int largest = 0;
compare = 0;
for (int i = 0; i < noRe.length; i++) {
// if compare is less than current number replace compare
if (compare < noRe[i]) {
compare = noRe[i];
largest = i;
}
}
// sets largest number in array to 0 to begin looking for next
// largest, and adds largest numbers to array list
noRe[largest] = 0;
hotNums[j] = largest;
hotTime[j] = compare;
}
// prints out largest numbers
for (int i = 0; i < 5; i++) {
System.out.println((i + 1) + ") " + (hotNums[i] + 1) + " - " + hotTime[i] + " times");
// checks to see if the next number is tied with current number
if ((i < 4) && hotTime[i] == hotTime[i + 1]) {
System.out.println(
" " + (hotNums[i + 1] + 1) + " - " + hotTime[i] + " times. (tied with pervious occurance)");
i++;
}
}
System.out.println();
} // end of getHotNumbers
// refer to getHotNumbers (it's the exact same except comparing lowest
// numbers).
public static void getColdNumbers(int[] noRe) {
int[] hotNums = new int[5];
int[] hotTime = new int[5];
int compare = 200;
for (int j = 0; j < 5; j++) {
int smallest = 200;
compare = 200;
for (int i = 0; i < noRe.length; i++) {
if (compare > noRe[i]) {
compare = noRe[i];
smallest = i;
}
}
noRe[smallest] = 200;
hotNums[j] = smallest;
hotTime[j] = compare;
}
for (int i = 0; i < 5; i++) {
System.out.println((i + 1) + ") " + (hotNums[i] + 1) + " - " + hotTime[i] + " times");
if ((i < 4) && hotTime[i] == hotTime[i + 1]) {
System.out.println(
" " + (hotNums[i + 1] + 1) + " - " + hotTime[i] + " times. (tied with pervious occurance)");
i++;
}
}
System.out.println();
} // end of getHotNumbers
} // end of class
文本文件外观的图片:
输出:
您可能注意到的唯一一件事是我的Reader
类,但是这是一个非常简单的代码来读取文本文件。
发布于 2017-04-26 10:26:01
首先,我认为这实际上是错误的代码(因此违背了cr.se的规则),因为您的解决方案只能找到最频繁或最不频繁的代码,而不是两者兼而有之。当您第二次调用该方法时,它甚至找不到最频繁的方法。
原因很明显。在方法中修改输入数组。快速修复方法是复制输入数组,然后使用该副本:
public static void getHotNumbers(int[] noRe) {
int[] input = new int[noRe.length];
System.arraycopy(noRe, 0, input, 0, noRe.length);
如果我们然后使用input
而不是noRe
,那么原版不会改变。
对于5种最频繁/最不频繁的算法也有很大的改进。
而不是5次遍历整个列表,每次都找到最大的元素。您应该只浏览一次,跟踪您遇到的5个最大的元素,并保持这5个元素的排序。
我还想指出,一个名为getSomething()
的函数应该返回那个something
。由于我们只能返回一个对象,但希望同时返回数字和它的频率,所以我们使用一个专门的类:
public class Frequency {
private final int number;
private final int frequency;
public Frequency(int number, int frequency) {
this.number = number;
this.frequency = frequency;
}
public int getNumber() {
return number;
}
public int getFrequency() {
return frequency;
}
}
现在让我们来看看我们将要使用的算法:
loop(all elements) {
if(element should be in top 5) {
remove the unwanted element
add element to result list
sort result list
}
}
我们看到的前5个总是“通缉”。因此,我们应该从创建频率列表开始,添加这5个频率,然后对列表进行排序:
private static List<Frequency> getHotNumbers(int[] noRe) {
List<Frequency> result = new ArrayList<>();
for(int i = 0; i < 5 && i < noRe.length; i++){
result.add(new Frequency(i, noRe[i]));
}
result.sort(comparator);
这类需要一个比较器。由于冷数和热数都使用相同的算法,让我们把比较器作为我们的方法的一个参数,这样我们就可以很容易地重复使用它。
private static List<Frequency> getTopFrequencies(int[] noRe,
Comparator<Frequency> comparator) {
现在我们已经解决了这个问题,下面是完整的方法实现:
private static List<Frequency> getTopFrequencies(int[] noRe,
Comparator<Frequency> comparator) {
List<Frequency> result = new ArrayList<>();
for(int i = 0; i < 5 && i < noRe.length; i++){
result.add(new Frequency(i, noRe[i]));
}
result.sort(comparator);
for(int i = 5; i < noRe.length; i++){
final Frequency nextFreq = new Frequency(i, noRe[i]);
if (comparator.compare(nextFreq,result.get(4)) < 1) {
result.remove(4);
result.add(nextFreq);
result.sort(comparator);
}
}
return result;
}
现在我们已经实现了我们的主要算法,我们所需要做的就是传递正确的比较器来使事情正常工作。
private static List<Frequency> getHotNumbers(int[] noRe){
return getTopFrequencies(noRe, (n1, n2) -> Integer.compare(n2.getFrequency(), n1.getFrequency()));
}
private static List<Frequency> getColdNumbers(int[] noRe){
return getTopFrequencies(noRe, (n1, n2) -> Integer.compare(n1.getFrequency(), n2.getFrequency()));
}
请注意,两个比较器之间唯一的区别是n1和n2的顺序。
现在,我对实现这个方法的方式只有一个问题。这是神奇的数字5
和4
。相反,让我们将所请求的数字增加作为参数传递。当我们这样做的时候,让我们也把重命名的noRe改进到清楚地表明它是输入频率。
private static List<Frequency> getTopNFrequencies(int n, int[] frequencies,
Comparator<Frequency> comparator) {
List<Frequency> result = new ArrayList<>();
for(int i = 0; i < n && i < frequencies.length; i++){
result.add(new Frequency(i, frequencies[i]));
}
result.sort(comparator);
for(int i = n; i < frequencies.length; i++){
final Frequency nextFreq = new Frequency(i, frequencies[i]);
if (comparator.compare(nextFreq,result.get(n-1)) < 1) {
result.remove(n-1);
result.add(nextFreq);
result.sort(comparator);
}
}
return result;
}
为了完成我的回答,下面是关于您的代码样式的一些需要改进的注释:
gg
和noRe
让我想到在线比赛的结束,而不是numbers
和frequencies
。//指getHotNumbers (除了比较最低的 //数字外,这是完全相同的)。
you did notice it's the exact same thing you're doing ...
get
我任何东西。Integer.MAX_VALUE
?数字47、27也是如此,在较小的程度上,数字5和4也是如此,大部分应该用常量代替。例如:私有静态最终int AMMOUNT_OF_LOTTERY_NUMBERS = 47;或者我们有不同的名称,但让它说明数字代表什么。//end of methodName
评论..。通常情况下,最好是采用更短的方法。如果它们安装在一个屏幕上并使用正确的缩进,那么您就不需要知道哪个方法被那个括号关闭了。如果它们不适合于一个屏幕,那么您可能应该将其部分提取到新的方法中,例如打印结果。https://codereview.stackexchange.com/questions/161795
复制相似问题