首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >比较彩票号码的频率

比较彩票号码的频率
EN

Code Review用户
提问于 2017-04-26 01:16:10
回答 1查看 1.2K关注 0票数 2

我的项目是根据给定的文本文件比较彩票号码出现的频率。我从逐行读取文件开始,然后提取数字,最后比较数字的频率。我在寻找各种各样的批评!

代码语言:javascript
复制
/**
 * 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类,但是这是一个非常简单的代码来读取文本文件。

EN

回答 1

Code Review用户

发布于 2017-04-26 10:26:01

首先,我认为这实际上是错误的代码(因此违背了cr.se的规则),因为您的解决方案只能找到最频繁或最不频繁的代码,而不是两者兼而有之。当您第二次调用该方法时,它甚至找不到最频繁的方法。

原因很明显。在方法中修改输入数组。快速修复方法是复制输入数组,然后使用该副本:

代码语言:javascript
复制
 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。由于我们只能返回一个对象,但希望同时返回数字和它的频率,所以我们使用一个专门的类:

代码语言:javascript
复制
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;
    }
}

现在让我们来看看我们将要使用的算法:

代码语言:javascript
复制
loop(all elements) {
    if(element should be in top 5) {
        remove the unwanted element
        add element to result list
        sort result list
    }
}

我们看到的前5个总是“通缉”。因此,我们应该从创建频率列表开始,添加这5个频率,然后对列表进行排序:

代码语言:javascript
复制
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);

这类需要一个比较器。由于冷数和热数都使用相同的算法,让我们把比较器作为我们的方法的一个参数,这样我们就可以很容易地重复使用它。

代码语言:javascript
复制
private static List<Frequency> getTopFrequencies(int[] noRe,
            Comparator<Frequency> comparator) {

现在我们已经解决了这个问题,下面是完整的方法实现:

代码语言:javascript
复制
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;
}

现在我们已经实现了我们的主要算法,我们所需要做的就是传递正确的比较器来使事情正常工作。

代码语言:javascript
复制
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的顺序。

现在,我对实现这个方法的方式只有一个问题。这是神奇的数字54。相反,让我们将所请求的数字增加作为参数传递。当我们这样做的时候,让我们也把重命名的noRe改进到清楚地表明它是输入频率。

代码语言:javascript
复制
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;
}

为了完成我的回答,下面是关于您的代码样式的一些需要改进的注释:

  • 使用实际显示变量是什么的名称。ggnoRe让我想到在线比赛的结束,而不是numbersfrequencies
  • 不要只是复制粘贴代码。如果您不知道如何使用比较器,那么重用该算法将是非常困难的。但打印结果只是文字复制粘贴,而不是方法调用:私有静态void printResult(int[] hotNums,int[] hotTime){ for (int i= 0;i< 5;i++) { System.out.println((i + 1) + ")“+ (hotNums我 + 1) +-”+ hotTime我 +“);if ((i < 4) && hotTime我 == hotTimeI+1) { System.out.println(“+ (hotNumsI+1 + 1) +”)-“+ hotTime我 +”次数。(与透水现象相关联);i++;} System.out.println();}

//指getHotNumbers (除了比较最低的 //数字外,这是完全相同的)。

代码语言:javascript
复制
you did notice it's the exact same thing you're doing ...
  • 你创建了一个专门的类来读取文件.但不要用它来真正读文件?为什么所有这些代码都不是专门用于解析专门类中的文件的呢?
  • //获取数组中最频繁的数字: 公共静态无效getHotNumbers(int[] noRe) {那么它们在哪里?这个方法没有get我任何东西。
  • 整数比较= 200;这个神奇的数字200是什么?为什么不是10?还是1000?还是Integer.MAX_VALUE?数字47、27也是如此,在较小的程度上,数字5和4也是如此,大部分应该用常量代替。例如:私有静态最终int AMMOUNT_OF_LOTTERY_NUMBERS = 47;或者我们有不同的名称,但让它说明数字代表什么。
  • //end of methodName评论..。通常情况下,最好是采用更短的方法。如果它们安装在一个屏幕上并使用正确的缩进,那么您就不需要知道哪个方法被那个括号关闭了。如果它们不适合于一个屏幕,那么您可能应该将其部分提取到新的方法中,例如打印结果。
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/161795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档