如何从最大到最小组织一个数组中的前10个频繁值?

时间:2019-04-15 02:17:59

标签: c++ arrays

我正在做一个名为PowerBall数字彩票统计的家庭作业。 PowerBall号码已创建到一个文本文件中。在我解释我的问题之前,一个强力球有5个数字,范围从1-69,第6个数字是BAll,它是1-26之间的数字。我在程序中所做的第一件事是创建一个数组以传递文件中的所有值,然后我将一个数组中的5个幂分开,将另一个数组中的BALL分开。现在的问题是,我一直在试图找出如何在拥有幂的数组和拥有球的数组中找到前10个公共数字。

尝试解决这个问题,我使用了频率函数,并尝试比较数组中每个值的频率,但最终却获得了每个以随机顺序出现的次数。我曾想过使用排序算法,但是由于我试图显示数字及其频率,所以它不起作用,而排序算法只会帮助我显示频率,而不是按顺序显示数字和频率。

作为参考,我使用的值是:

39  12  21  23  67  6
33  43  60  59  15  4
25  16  32  49  19  4
54  50  21  64  68  4
44  62  20  37  16  12
66  52  50  24  25  5
10  53  50  63  14  21
67  30  34  16  53  21
69  36  45  47  18  14
45  5   59  55  50  14

代码:

#include <iostream>
#include <cctype>
#include <fstream>
#include <cstring>

using namespace std;

//Function prototype.
void powerValues(int [10][6], int [10], int [10][5]);
int frequency26(int [10], int);
int frequency69(int [][5], int);

int main()
{
    int num[10][6];
    int powerBall26[10];
    int powerBall69[10][5];

    //Function to store values from file in corresponding variable.
    powerValues(num, powerBall26, powerBall69);


    //Trying to find most frequent numbers to list top 10 common ones.
    for(int i = 1; i <= 69; i++)
    {
        for(int j = 0; j < 1; j++)
        {
            if(frequency69(powerBall69, i) > frequency69(powerBall69, 1))
            {
                cout << i << " " << frequency69(powerBall69, i) << endl;
            }
        }
    }

    return 0;
}

//This function grabs numbers from file to save numbers separately into two arrays.
//One array for powers(1-69) and other one for the powerBall(1-26).
void powerValues(int num[10][6], int powerBall26[10], int powerBall69[10][5])
{
    ifstream inFile;

    inFile.open("lotteryNumbers.txt");

    //Passing values from file into temp array.
    for(int i = 0; i < 10; i++)
    {
       for(int k = 0; k < 6; k++)
       {
          inFile >> num[i][k];
       }
    }

   //This loop stores the 6th power(AKA PowerBall) in array.
   for(int i = 0; i < 10; i++)
   {
       powerBall26[i] = num[i][5];
   }

   //This loop stores the first 5 powers in array.
   for(int i = 0; i < 10; i++)
   {
       for(int j = 0; j < 5; j++)
       {
           powerBall69[i][j] = num[i][j];
       }
   }

   inFile.close();
}

//Calculates frequency of a number(1-26) in powerBall26.
int frequency26(int powerBall26[10], int value)
{
    int freq = 0;
    for(int i = 0; i < 10; i++)
    {
        if(powerBall26[i] == value)
           freq++;
    }

     return freq;
}

//Calculates frequency of a number(1-69) in powerBall69.
int frequency69(int powerBall69[][5], int value)
{
    int freq = 0;
    for(int i = 0; i < 10; i++)
    {
        for(int j = 0; j < 5; j++)
        {
            if(powerBall69[i][j] == value)
                freq++;
        }
    }

    return freq;
}

我期望输出50:4,16:3,21:2,25:2,45:2,53:2,依此类推。相反,正如我之前提到的,我最终获得了基于频率的每个未组织数字的频率值。

1 个答案:

答案 0 :(得分:0)

如果您仍在努力获取彩票号码和强力球的前10个最频繁的号码,然后继续从Sam的评论中进行操作,则可以使用简单的struct(或pair等等。),以将彩票号码1-69与输入中的出现频率进行协调(对于强力球而言也是如此)。您甚至可以为此使用每行2-int的2D数组,但是使用结构可能会提供更具可读性的实现,因为它允许您使用成员名(例如numcount)而不是索引01

一个简单的struct就是处理每个号码的号码频率映射所需要的方式,它将允许您以后进行排序,以保留该号码与该号码和其关联的号码之间的关系,例如

struct freq {
    int num, count;     /* struct capturing number & count */
};

考虑使用C ++容器库std::array而不是为数组使用基本类型,该库将使array的容器成员函数可用,例如开始和结束迭代器,交换等。以及只需将algorithm.begin()迭代器以及一个比较表达式一起传递,就可以将数组与std::sort.end()库一起使用。

无论如何,您都将声明一个包含69个元素的数组用于彩票号码频率跟踪,并声明一个包含26个元素的数组用于您的强力球跟踪。使用容器库中的array,您可以执行以下操作:

#define NMAX 69   /* if you need a constant, #define one (or more) */
#define BMAX 26
...
    std::array<freq, NMAX> nfreq;   /* array of struct for number frequency */
    std::array<freq, BMAX> bfreq;   /* array of struct for ball frequency */

要初始化每个数组,只需将1-69中的序列号存储为.num成员,并将每个.count成员设置为零(对于球频率数组则为1-26),例如

    for (int i = 0; i < NMAX; i++)  /* initialize number freq array */
        nfreq[i].num = i + 1, nfreq[i].count = 0;

    for (int i = 0; i < BMAX; i++)  /* initialize ball freq array */
        bfreq[i].num = i + 1, bfreq[i].count = 0;

注意:如何将.num成员初始化为i + 1而不是初始化为i,以适应您的索引将为0-68的事实,而您需要存储的数字为1-69。)

现在从文件中读取所有数据。您无需将其存储在任何地方(除非您有其他需求),您只需要设置每个数字和强力球的频率即可。因此,您可以简单地循环读取,使用每行中的前5个数字来增加您的彩票号码频率数组nfreq中的计数,并使用每行中的最后一个数字对强力球频率数组{{ 1}}(球频率)。例如:

bfreq

剩下的全部工作是由 std::ifstream f (argv[1]); /* open filename given by 1st argument */ /* validations omitted */ while (getline (f, s)) { /* read each line/fill freq arrays */ std::stringstream ss (s); /* create stringstream from line */ size_t i = 0; /* initialize counter zero */ int tmp; /* tmp value to hold int read */ while (i < NVAL && ss >> tmp) /* read up to NVAL numbers */ nfreq[tmp - 1].count++, i++; /* increment nfreq count */ if (i < NVAL) { /* validate all number values read */ std::cerr << "error: less than " << NVAL << "values read.\n"; return 1; } if (!(ss >> tmp)) { /* validate ball value read */ std::cerr << "error: no powerball value read.\n"; return 1; } bfreq[tmp - 1].count++; /* increment ball freq count */ } 成员按降序对nfreqbfreq数组进行排序,然后输出每个数组的前10名(或直到{{1} }是.count)。利用std::sort所要做的就是编写一个表达式来比较每个数组的元素,然后将其与每个数组的开始和结束迭代器一起传递给.count,它将执行其余的部分。表达式可以是上面链接中提供的示例中所示的标准比较,也可以使用自己的简短自定义函数(或与0内联的lamba函数)。

在您的情况下,编写一个比较函数可能同样容易,否则,在每次排序调用中,您将本质上复制与lamba相同的代码。虽然不是必需的,但是您可以选择在每个数字的频率相同的情况下如何显示数字。下面的比较函数按std::sort排序(降序),然后如果std::sort等于.count排序(降序)。例如,完全由您决定

.count

然后,由于使用了容器库.num,因此将begin和end迭代器与compare函数一起传递给/* compare freq by count and if equal by num (descending) */ bool compare (const freq &a, const freq &b) { if (a.count != b.count) return a.count > b.count; else return a.num > b.num; } 就像这样简单:

array

(对std::sort做同样的事情)

然后只输出已排序数组的前10个元素即可。综上所述,您可以执行以下操作:

    std::sort (nfreq.begin(), nfreq.end(), compare);

使用/输出示例

使用文件bfreq中的数据,彩票号码的频率以及强力球值(频率为零时停止)将为:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <array>
#include <algorithm>

#define NVAL 5      /* if you need a constant, #define one (or more) */
#define NMAX 69
#define BMAX 26
#define NTOP 10

struct freq {
    int num, count;     /* struct capturing number & count */
};

/* compare freq by count and if equal by num (descending) */
bool compare (const freq &a, const freq &b)
{
    if (a.count != b.count)
        return a.count > b.count;
    else
        return a.num > b.num;
}

int main (int argc, char **argv) {

    if (argc < 2) { /* validate 1-argument available for filename */
        std::cerr << "error: insufficnent input\nusage: " << argv[0]
                << " filename\n";
        return 1;
    }

    std::string s;
    std::array<freq, NMAX> nfreq;   /* array of struct for number frequency */
    std::array<freq, BMAX> bfreq;   /* array of struct for ball frequency */

    for (int i = 0; i < NMAX; i++)  /* initialize number freq array */
        nfreq[i].num = i + 1, nfreq[i].count = 0;

    for (int i = 0; i < BMAX; i++)  /* initialize ball freq array */
        bfreq[i].num = i + 1, bfreq[i].count = 0;

    std::ifstream f (argv[1]);      /* open filename given by 1st argument */
    if (!f.good()) {    /* validate file open for reading */
        std::cerr << "error: file open failed '" << argv[1] << "'.\n";
        return 1;
    }

    while (getline (f, s)) {        /* read each line/fill freq arrays */
        std::stringstream ss (s);   /* create stringstream from line */
        size_t i = 0;               /* initialize counter zero */
        int tmp;                    /* tmp value to hold int read */
        while (i < NVAL && ss >> tmp)       /* read up to NVAL numbers */
            nfreq[tmp - 1].count++, i++;    /* increment nfreq count */
        if (i < NVAL) {     /* validate all number values read */
            std::cerr << "error: less than " << NVAL << "values read.\n";
            return 1;
        }
        if (!(ss >> tmp)) { /* validate ball value read */
            std::cerr << "error: no powerball value read.\n";
            return 1;
        }
        bfreq[tmp - 1].count++;     /* increment ball freq count */
    }

    /* sort number frequency array of struct by count descending */
    std::sort (nfreq.begin(), nfreq.end(), compare);
    for (int i = 0; i < NTOP && nfreq[i].count; i++)
        std::cout << std::setw(2) << nfreq[i].num << " : " 
                    << nfreq[i].count << '\n';
    std::cout << '\n';

    /* sort ball frequency array of struct by count descending */
    std::sort (bfreq.begin(), bfreq.end(), compare);
    for (int i = 0; i < NTOP && bfreq[i].count; i++)
        std::cout << std::setw(2) << bfreq[i].num << " : " 
                    << bfreq[i].count << '\n';
    std::cout << '\n';
}

仔细检查一下,如果还有其他问题,请告诉我。如果要在调用dat/pwrball.txt时内联使用lamda函数,而不是编写单独的$ ./bin/pwrballnumfreq dat/pwrball.txt 50 : 4 16 : 3 67 : 2 59 : 2 53 : 2 45 : 2 25 : 2 21 : 2 69 : 1 68 : 1 4 : 3 21 : 2 14 : 2 12 : 1 6 : 1 5 : 1 函数,则可以执行以下操作:

std::sort

哪个完全一样。 (在个人情况下,compare函数可能节省了几行代码)