Count the frequency of integers in an arrayBit-twiddling for a custom image formatSmallest MultipleCreate ranges from an array of integersUVA #10258 - Contest ScoreboardInterpreter programming challengeA Simple Console Based Keno/Lottery Game in C++RDS receiver - synchronization and error correctionC# TCP server/client classLeast cost swapping in C++Count the frequency of items in an array
Sleeping solo in a double sleeping bag
Is this kind of description not recommended?
Alchemist potion on Undead
Infinite loop in CURSOR
My two team members in a remote location don't get along with each other; how can I improve working relations?
Land Registry Clause
Is there any road between the CA State Route 120 and Sherman Pass Road (Forest Route 22S0) that crosses Yosemite/Serria/Sequoia National Park/Forest?
Was Switzerland really impossible to invade during WW2?
What can I do to keep a threaded bolt from falling out of it’s slot
How does the Saturn V Dynamic Test Stand work?
Chess software to analyze games
How to get distinct values from an array of arrays in JavaScript using the filter() method?
How big would a Daddy Longlegs Spider need to be to kill an average Human?
How can I describe being temporarily stupid?
Are there any OR challenges that are similar to kaggle's competitions?
Unbiased estimator of exponential of measure of a set?
How to avoid using System.String with Rfc2898DeriveBytes in C#
How could China have extradited people for political reason under the extradition law it wanted to pass in Hong Kong?
How to compare two different formulations of a problem?
To "hit home" in German
Is there a known non-euclidean geometry where two concentric circles of different radii can intersect? (as in the novel "The Universe Between")
Is there such a thing as too inconvenient?
Why don't sharp and flat root note chords seem to be present in much guitar music?
Did the twin engined Lazair ultralight have a throttle for each engine?
Count the frequency of integers in an array
Bit-twiddling for a custom image formatSmallest MultipleCreate ranges from an array of integersUVA #10258 - Contest ScoreboardInterpreter programming challengeA Simple Console Based Keno/Lottery Game in C++RDS receiver - synchronization and error correctionC# TCP server/client classLeast cost swapping in C++Count the frequency of items in an array
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I recently reviewed a question here on Code Review. The problem statement is
Write a program that prompts the user to input ten values between 80 and 85 and stores them in an array. Your program must be able to count the frequency of each value appears in the array.
I coded my own solution for the problem statement. My questions are
- Can this be optimized more?
- Did I miss anything in C++14 or C++17 that might improve the code?
- Is the code readable?
- Are the variable and function names good or can they be improved?
My goals were to write the best C++ I could, remove any magic numbers and allow the solution to scale for different sets of numbers.
#include "pch.h"
#include <iostream>
#include <array>
const size_t INPUTSIZE = 10;
const size_t FREQUENCYSIZE = 6;
const int MINLEGALVALUE = 80;
const int MAXLEGALVALUE = 85;
std::array<int, INPUTSIZE> getUserInput()
std::array<int, INPUTSIZE> inputValues;
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and " << MAXLEGALVALUE << ":" ;
std::cin >> inputValue;
if (inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
inputValues[i] = inputValue;
i++;
else
std::cout << "The number must be between" << MINLEGALVALUE << " and " << MAXLEGALVALUE << "n";
while (i < INPUTSIZE);
return inputValues;
std::array<unsigned, FREQUENCYSIZE> getFrequencyCounts(std::array<int, INPUTSIZE> inputValues)
std::array<unsigned, FREQUENCYSIZE> freqs = 0 ;
for (auto inputs : inputValues)
freqs[inputs - MINLEGALVALUE]++;
return freqs;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
unsigned rowLabel = MINLEGALVALUE;
for (auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
rowLabel++;
int main()
std::array<int, INPUTSIZE> inputValues = getUserInput();
std::array<unsigned, FREQUENCYSIZE> freqs = getFrequencyCounts(inputValues);
std::cout << "n";
printFrequencies(freqs);
c++ performance c++14 c++17
$endgroup$
add a comment |
$begingroup$
I recently reviewed a question here on Code Review. The problem statement is
Write a program that prompts the user to input ten values between 80 and 85 and stores them in an array. Your program must be able to count the frequency of each value appears in the array.
I coded my own solution for the problem statement. My questions are
- Can this be optimized more?
- Did I miss anything in C++14 or C++17 that might improve the code?
- Is the code readable?
- Are the variable and function names good or can they be improved?
My goals were to write the best C++ I could, remove any magic numbers and allow the solution to scale for different sets of numbers.
#include "pch.h"
#include <iostream>
#include <array>
const size_t INPUTSIZE = 10;
const size_t FREQUENCYSIZE = 6;
const int MINLEGALVALUE = 80;
const int MAXLEGALVALUE = 85;
std::array<int, INPUTSIZE> getUserInput()
std::array<int, INPUTSIZE> inputValues;
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and " << MAXLEGALVALUE << ":" ;
std::cin >> inputValue;
if (inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
inputValues[i] = inputValue;
i++;
else
std::cout << "The number must be between" << MINLEGALVALUE << " and " << MAXLEGALVALUE << "n";
while (i < INPUTSIZE);
return inputValues;
std::array<unsigned, FREQUENCYSIZE> getFrequencyCounts(std::array<int, INPUTSIZE> inputValues)
std::array<unsigned, FREQUENCYSIZE> freqs = 0 ;
for (auto inputs : inputValues)
freqs[inputs - MINLEGALVALUE]++;
return freqs;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
unsigned rowLabel = MINLEGALVALUE;
for (auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
rowLabel++;
int main()
std::array<int, INPUTSIZE> inputValues = getUserInput();
std::array<unsigned, FREQUENCYSIZE> freqs = getFrequencyCounts(inputValues);
std::cout << "n";
printFrequencies(freqs);
c++ performance c++14 c++17
$endgroup$
1
$begingroup$
You've asked for optimizations, but the input size is too small for the usual histogramming optimizations to matter, and anyway the program spends all of its time doing IO. Do you want to know about them anyway?
$endgroup$
– harold
7 hours ago
add a comment |
$begingroup$
I recently reviewed a question here on Code Review. The problem statement is
Write a program that prompts the user to input ten values between 80 and 85 and stores them in an array. Your program must be able to count the frequency of each value appears in the array.
I coded my own solution for the problem statement. My questions are
- Can this be optimized more?
- Did I miss anything in C++14 or C++17 that might improve the code?
- Is the code readable?
- Are the variable and function names good or can they be improved?
My goals were to write the best C++ I could, remove any magic numbers and allow the solution to scale for different sets of numbers.
#include "pch.h"
#include <iostream>
#include <array>
const size_t INPUTSIZE = 10;
const size_t FREQUENCYSIZE = 6;
const int MINLEGALVALUE = 80;
const int MAXLEGALVALUE = 85;
std::array<int, INPUTSIZE> getUserInput()
std::array<int, INPUTSIZE> inputValues;
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and " << MAXLEGALVALUE << ":" ;
std::cin >> inputValue;
if (inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
inputValues[i] = inputValue;
i++;
else
std::cout << "The number must be between" << MINLEGALVALUE << " and " << MAXLEGALVALUE << "n";
while (i < INPUTSIZE);
return inputValues;
std::array<unsigned, FREQUENCYSIZE> getFrequencyCounts(std::array<int, INPUTSIZE> inputValues)
std::array<unsigned, FREQUENCYSIZE> freqs = 0 ;
for (auto inputs : inputValues)
freqs[inputs - MINLEGALVALUE]++;
return freqs;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
unsigned rowLabel = MINLEGALVALUE;
for (auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
rowLabel++;
int main()
std::array<int, INPUTSIZE> inputValues = getUserInput();
std::array<unsigned, FREQUENCYSIZE> freqs = getFrequencyCounts(inputValues);
std::cout << "n";
printFrequencies(freqs);
c++ performance c++14 c++17
$endgroup$
I recently reviewed a question here on Code Review. The problem statement is
Write a program that prompts the user to input ten values between 80 and 85 and stores them in an array. Your program must be able to count the frequency of each value appears in the array.
I coded my own solution for the problem statement. My questions are
- Can this be optimized more?
- Did I miss anything in C++14 or C++17 that might improve the code?
- Is the code readable?
- Are the variable and function names good or can they be improved?
My goals were to write the best C++ I could, remove any magic numbers and allow the solution to scale for different sets of numbers.
#include "pch.h"
#include <iostream>
#include <array>
const size_t INPUTSIZE = 10;
const size_t FREQUENCYSIZE = 6;
const int MINLEGALVALUE = 80;
const int MAXLEGALVALUE = 85;
std::array<int, INPUTSIZE> getUserInput()
std::array<int, INPUTSIZE> inputValues;
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and " << MAXLEGALVALUE << ":" ;
std::cin >> inputValue;
if (inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
inputValues[i] = inputValue;
i++;
else
std::cout << "The number must be between" << MINLEGALVALUE << " and " << MAXLEGALVALUE << "n";
while (i < INPUTSIZE);
return inputValues;
std::array<unsigned, FREQUENCYSIZE> getFrequencyCounts(std::array<int, INPUTSIZE> inputValues)
std::array<unsigned, FREQUENCYSIZE> freqs = 0 ;
for (auto inputs : inputValues)
freqs[inputs - MINLEGALVALUE]++;
return freqs;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
unsigned rowLabel = MINLEGALVALUE;
for (auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
rowLabel++;
int main()
std::array<int, INPUTSIZE> inputValues = getUserInput();
std::array<unsigned, FREQUENCYSIZE> freqs = getFrequencyCounts(inputValues);
std::cout << "n";
printFrequencies(freqs);
c++ performance c++14 c++17
c++ performance c++14 c++17
asked 9 hours ago
pacmaninbwpacmaninbw
7,2822 gold badges20 silver badges44 bronze badges
7,2822 gold badges20 silver badges44 bronze badges
1
$begingroup$
You've asked for optimizations, but the input size is too small for the usual histogramming optimizations to matter, and anyway the program spends all of its time doing IO. Do you want to know about them anyway?
$endgroup$
– harold
7 hours ago
add a comment |
1
$begingroup$
You've asked for optimizations, but the input size is too small for the usual histogramming optimizations to matter, and anyway the program spends all of its time doing IO. Do you want to know about them anyway?
$endgroup$
– harold
7 hours ago
1
1
$begingroup$
You've asked for optimizations, but the input size is too small for the usual histogramming optimizations to matter, and anyway the program spends all of its time doing IO. Do you want to know about them anyway?
$endgroup$
– harold
7 hours ago
$begingroup$
You've asked for optimizations, but the input size is too small for the usual histogramming optimizations to matter, and anyway the program spends all of its time doing IO. Do you want to know about them anyway?
$endgroup$
– harold
7 hours ago
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
Names
All-caps names are typically reserved for macros. They don't seem to me to make much sense for const
variables. In fact, they only make minimal sense for object-like macros--they were originally used for function-like macros as kind of a warning that you should be cautious about passing an argument with side-effects, because they might happen more than once.
Minimize Magic
I'd typically try to keep the magic numbers to a minimum. For example, instead of defining FREQUENCYSIZE
by itself, I'd probably do something like this:
const int lower_bound = 80;
count int upper_bound = 85;
const int frequency_size = upper_bound - lower_bound + 1;
Separation of Concerns
I'd at least consider separating validating data from reading the data. I'd prefer to have a function on the general order of:
bool valid(int val)
return val >= lower_bound && val < upper_bound;
Class Usage
We have a number of different things related to reading and working with numbers in a specified range. It might be worth considering wrapping those bits and pieces into a coherent class for dealing with a value in a range, and let the outside world create and use objects of that class.
template <class T, T lower_bound, T upper_bound>
class bounded
public:
static bool valid(T val) return val >= lower_bound && val < upper_bound;
friend std::istream &operator>>(std::istream &is, bounded &b)
T val;
is >> val;
if (valid(val))
b.val = val;
else
is.setstate(std::ios_base::failbit);
return is;
friend std::ostream &operator<<(std::ostream &os, bounded const &b)
return os << b.val;
size_t index() return size_t(val - lower_bound);
static constexpr size_t range() return upper_bound - lower_bound + 1;
private:
T val;
;
That let's us simplify the rest of the code a bit, something on this general order:
int main()
using integer = bounded<int, 80, 85>;
std::array<integer, 10> inputs;
std::array<size_t, integer::range()> freqs ;
for (integer &i : inputs)
std::cin >> i;
++freqs[i.index()];
for (auto freq : freqs)
std::cout << freq << "n";
Technically, this doesn't meet the requirements as-is (e.g., it doesn't print out a prompt to tell the user to enter data), but I think it gives at least some idea of a direction things could go.
$endgroup$
add a comment |
$begingroup$
If you go for modern C++ the static variables should be marked as constexpr
instead of plain old const
.
As was said in the other question, it should be beneficial to create an array of length MAXLEGALVALUE - MINLEGALVALUE
and directly index into that array. That way there is probably less memory consumed and we count automatically.
Personally I would use std::size_t
or a well specified integer type like std::uint32_t
rather than unsigned
, which depends on the implementation.
In range based for loops where the type is unambiguous I am not really a fan of auto.
for (auto inputs : inputValues)
How do you know that copying it is cheap here? You have to check the type of the container. Also you should consider const correctness so rather use const int
or const auto
if you prefere that.
for (const int inputs : inputValues)
Note that you have a truncation warning here as MINLEGALVALUE is of type int
:
unsigned rowLabel = MINLEGALVALUE;
$endgroup$
add a comment |
$begingroup$
One idea for simplification is to count frequencies directly instead of putting all the values in an array that you only use for counting frequencies. You can then remove the getFrequencyCounts
function and the whole thing gets a little more efficient. This works well when you have a set of values in a dense range like [80,85]. If you have a lot of values far between eachother, using a set
or unordered_set
is probably a better choice. I found the code easy enough to read. Here are some ideas with comments in the code:
#include <array>
#include <iostream>
constexpr size_t INPUTSIZE = 10;
constexpr int MINLEGALVALUE = 80;
constexpr int MAXLEGALVALUE = 85;
constexpr size_t FREQUENCYSIZE = MAXLEGALVALUE - MINLEGALVALUE + 1;
std::array<unsigned, FREQUENCYSIZE> getUserInputFreq()
std::array<unsigned, FREQUENCYSIZE> inputValues0; // initialize with 0
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << ":";
// make sure the istream you read from succeeded in extracting
if(std::cin >> inputValue)
if(inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
// count frequencies directly if you don't actually need the
// input values
++inputValues[static_cast<size_t>(inputValue - MINLEGALVALUE)];
++i; // prefer prefix operator++
else
std::cout << "The number must be between" << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << "n";
else
break; // erroneous input or EOF
while(i < INPUTSIZE);
return inputValues;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
int rowLabel = MINLEGALVALUE;
for(auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
++rowLabel; // prefer prefix operator++
int main()
std::array<unsigned, FREQUENCYSIZE> freqs = getUserInputFreq();
std::cout << "n";
printFrequencies(freqs);
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f226448%2fcount-the-frequency-of-integers-in-an-array%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Names
All-caps names are typically reserved for macros. They don't seem to me to make much sense for const
variables. In fact, they only make minimal sense for object-like macros--they were originally used for function-like macros as kind of a warning that you should be cautious about passing an argument with side-effects, because they might happen more than once.
Minimize Magic
I'd typically try to keep the magic numbers to a minimum. For example, instead of defining FREQUENCYSIZE
by itself, I'd probably do something like this:
const int lower_bound = 80;
count int upper_bound = 85;
const int frequency_size = upper_bound - lower_bound + 1;
Separation of Concerns
I'd at least consider separating validating data from reading the data. I'd prefer to have a function on the general order of:
bool valid(int val)
return val >= lower_bound && val < upper_bound;
Class Usage
We have a number of different things related to reading and working with numbers in a specified range. It might be worth considering wrapping those bits and pieces into a coherent class for dealing with a value in a range, and let the outside world create and use objects of that class.
template <class T, T lower_bound, T upper_bound>
class bounded
public:
static bool valid(T val) return val >= lower_bound && val < upper_bound;
friend std::istream &operator>>(std::istream &is, bounded &b)
T val;
is >> val;
if (valid(val))
b.val = val;
else
is.setstate(std::ios_base::failbit);
return is;
friend std::ostream &operator<<(std::ostream &os, bounded const &b)
return os << b.val;
size_t index() return size_t(val - lower_bound);
static constexpr size_t range() return upper_bound - lower_bound + 1;
private:
T val;
;
That let's us simplify the rest of the code a bit, something on this general order:
int main()
using integer = bounded<int, 80, 85>;
std::array<integer, 10> inputs;
std::array<size_t, integer::range()> freqs ;
for (integer &i : inputs)
std::cin >> i;
++freqs[i.index()];
for (auto freq : freqs)
std::cout << freq << "n";
Technically, this doesn't meet the requirements as-is (e.g., it doesn't print out a prompt to tell the user to enter data), but I think it gives at least some idea of a direction things could go.
$endgroup$
add a comment |
$begingroup$
Names
All-caps names are typically reserved for macros. They don't seem to me to make much sense for const
variables. In fact, they only make minimal sense for object-like macros--they were originally used for function-like macros as kind of a warning that you should be cautious about passing an argument with side-effects, because they might happen more than once.
Minimize Magic
I'd typically try to keep the magic numbers to a minimum. For example, instead of defining FREQUENCYSIZE
by itself, I'd probably do something like this:
const int lower_bound = 80;
count int upper_bound = 85;
const int frequency_size = upper_bound - lower_bound + 1;
Separation of Concerns
I'd at least consider separating validating data from reading the data. I'd prefer to have a function on the general order of:
bool valid(int val)
return val >= lower_bound && val < upper_bound;
Class Usage
We have a number of different things related to reading and working with numbers in a specified range. It might be worth considering wrapping those bits and pieces into a coherent class for dealing with a value in a range, and let the outside world create and use objects of that class.
template <class T, T lower_bound, T upper_bound>
class bounded
public:
static bool valid(T val) return val >= lower_bound && val < upper_bound;
friend std::istream &operator>>(std::istream &is, bounded &b)
T val;
is >> val;
if (valid(val))
b.val = val;
else
is.setstate(std::ios_base::failbit);
return is;
friend std::ostream &operator<<(std::ostream &os, bounded const &b)
return os << b.val;
size_t index() return size_t(val - lower_bound);
static constexpr size_t range() return upper_bound - lower_bound + 1;
private:
T val;
;
That let's us simplify the rest of the code a bit, something on this general order:
int main()
using integer = bounded<int, 80, 85>;
std::array<integer, 10> inputs;
std::array<size_t, integer::range()> freqs ;
for (integer &i : inputs)
std::cin >> i;
++freqs[i.index()];
for (auto freq : freqs)
std::cout << freq << "n";
Technically, this doesn't meet the requirements as-is (e.g., it doesn't print out a prompt to tell the user to enter data), but I think it gives at least some idea of a direction things could go.
$endgroup$
add a comment |
$begingroup$
Names
All-caps names are typically reserved for macros. They don't seem to me to make much sense for const
variables. In fact, they only make minimal sense for object-like macros--they were originally used for function-like macros as kind of a warning that you should be cautious about passing an argument with side-effects, because they might happen more than once.
Minimize Magic
I'd typically try to keep the magic numbers to a minimum. For example, instead of defining FREQUENCYSIZE
by itself, I'd probably do something like this:
const int lower_bound = 80;
count int upper_bound = 85;
const int frequency_size = upper_bound - lower_bound + 1;
Separation of Concerns
I'd at least consider separating validating data from reading the data. I'd prefer to have a function on the general order of:
bool valid(int val)
return val >= lower_bound && val < upper_bound;
Class Usage
We have a number of different things related to reading and working with numbers in a specified range. It might be worth considering wrapping those bits and pieces into a coherent class for dealing with a value in a range, and let the outside world create and use objects of that class.
template <class T, T lower_bound, T upper_bound>
class bounded
public:
static bool valid(T val) return val >= lower_bound && val < upper_bound;
friend std::istream &operator>>(std::istream &is, bounded &b)
T val;
is >> val;
if (valid(val))
b.val = val;
else
is.setstate(std::ios_base::failbit);
return is;
friend std::ostream &operator<<(std::ostream &os, bounded const &b)
return os << b.val;
size_t index() return size_t(val - lower_bound);
static constexpr size_t range() return upper_bound - lower_bound + 1;
private:
T val;
;
That let's us simplify the rest of the code a bit, something on this general order:
int main()
using integer = bounded<int, 80, 85>;
std::array<integer, 10> inputs;
std::array<size_t, integer::range()> freqs ;
for (integer &i : inputs)
std::cin >> i;
++freqs[i.index()];
for (auto freq : freqs)
std::cout << freq << "n";
Technically, this doesn't meet the requirements as-is (e.g., it doesn't print out a prompt to tell the user to enter data), but I think it gives at least some idea of a direction things could go.
$endgroup$
Names
All-caps names are typically reserved for macros. They don't seem to me to make much sense for const
variables. In fact, they only make minimal sense for object-like macros--they were originally used for function-like macros as kind of a warning that you should be cautious about passing an argument with side-effects, because they might happen more than once.
Minimize Magic
I'd typically try to keep the magic numbers to a minimum. For example, instead of defining FREQUENCYSIZE
by itself, I'd probably do something like this:
const int lower_bound = 80;
count int upper_bound = 85;
const int frequency_size = upper_bound - lower_bound + 1;
Separation of Concerns
I'd at least consider separating validating data from reading the data. I'd prefer to have a function on the general order of:
bool valid(int val)
return val >= lower_bound && val < upper_bound;
Class Usage
We have a number of different things related to reading and working with numbers in a specified range. It might be worth considering wrapping those bits and pieces into a coherent class for dealing with a value in a range, and let the outside world create and use objects of that class.
template <class T, T lower_bound, T upper_bound>
class bounded
public:
static bool valid(T val) return val >= lower_bound && val < upper_bound;
friend std::istream &operator>>(std::istream &is, bounded &b)
T val;
is >> val;
if (valid(val))
b.val = val;
else
is.setstate(std::ios_base::failbit);
return is;
friend std::ostream &operator<<(std::ostream &os, bounded const &b)
return os << b.val;
size_t index() return size_t(val - lower_bound);
static constexpr size_t range() return upper_bound - lower_bound + 1;
private:
T val;
;
That let's us simplify the rest of the code a bit, something on this general order:
int main()
using integer = bounded<int, 80, 85>;
std::array<integer, 10> inputs;
std::array<size_t, integer::range()> freqs ;
for (integer &i : inputs)
std::cin >> i;
++freqs[i.index()];
for (auto freq : freqs)
std::cout << freq << "n";
Technically, this doesn't meet the requirements as-is (e.g., it doesn't print out a prompt to tell the user to enter data), but I think it gives at least some idea of a direction things could go.
answered 7 hours ago
Jerry CoffinJerry Coffin
29.8k4 gold badges62 silver badges132 bronze badges
29.8k4 gold badges62 silver badges132 bronze badges
add a comment |
add a comment |
$begingroup$
If you go for modern C++ the static variables should be marked as constexpr
instead of plain old const
.
As was said in the other question, it should be beneficial to create an array of length MAXLEGALVALUE - MINLEGALVALUE
and directly index into that array. That way there is probably less memory consumed and we count automatically.
Personally I would use std::size_t
or a well specified integer type like std::uint32_t
rather than unsigned
, which depends on the implementation.
In range based for loops where the type is unambiguous I am not really a fan of auto.
for (auto inputs : inputValues)
How do you know that copying it is cheap here? You have to check the type of the container. Also you should consider const correctness so rather use const int
or const auto
if you prefere that.
for (const int inputs : inputValues)
Note that you have a truncation warning here as MINLEGALVALUE is of type int
:
unsigned rowLabel = MINLEGALVALUE;
$endgroup$
add a comment |
$begingroup$
If you go for modern C++ the static variables should be marked as constexpr
instead of plain old const
.
As was said in the other question, it should be beneficial to create an array of length MAXLEGALVALUE - MINLEGALVALUE
and directly index into that array. That way there is probably less memory consumed and we count automatically.
Personally I would use std::size_t
or a well specified integer type like std::uint32_t
rather than unsigned
, which depends on the implementation.
In range based for loops where the type is unambiguous I am not really a fan of auto.
for (auto inputs : inputValues)
How do you know that copying it is cheap here? You have to check the type of the container. Also you should consider const correctness so rather use const int
or const auto
if you prefere that.
for (const int inputs : inputValues)
Note that you have a truncation warning here as MINLEGALVALUE is of type int
:
unsigned rowLabel = MINLEGALVALUE;
$endgroup$
add a comment |
$begingroup$
If you go for modern C++ the static variables should be marked as constexpr
instead of plain old const
.
As was said in the other question, it should be beneficial to create an array of length MAXLEGALVALUE - MINLEGALVALUE
and directly index into that array. That way there is probably less memory consumed and we count automatically.
Personally I would use std::size_t
or a well specified integer type like std::uint32_t
rather than unsigned
, which depends on the implementation.
In range based for loops where the type is unambiguous I am not really a fan of auto.
for (auto inputs : inputValues)
How do you know that copying it is cheap here? You have to check the type of the container. Also you should consider const correctness so rather use const int
or const auto
if you prefere that.
for (const int inputs : inputValues)
Note that you have a truncation warning here as MINLEGALVALUE is of type int
:
unsigned rowLabel = MINLEGALVALUE;
$endgroup$
If you go for modern C++ the static variables should be marked as constexpr
instead of plain old const
.
As was said in the other question, it should be beneficial to create an array of length MAXLEGALVALUE - MINLEGALVALUE
and directly index into that array. That way there is probably less memory consumed and we count automatically.
Personally I would use std::size_t
or a well specified integer type like std::uint32_t
rather than unsigned
, which depends on the implementation.
In range based for loops where the type is unambiguous I am not really a fan of auto.
for (auto inputs : inputValues)
How do you know that copying it is cheap here? You have to check the type of the container. Also you should consider const correctness so rather use const int
or const auto
if you prefere that.
for (const int inputs : inputValues)
Note that you have a truncation warning here as MINLEGALVALUE is of type int
:
unsigned rowLabel = MINLEGALVALUE;
answered 7 hours ago
misccomiscco
3,6726 silver badges17 bronze badges
3,6726 silver badges17 bronze badges
add a comment |
add a comment |
$begingroup$
One idea for simplification is to count frequencies directly instead of putting all the values in an array that you only use for counting frequencies. You can then remove the getFrequencyCounts
function and the whole thing gets a little more efficient. This works well when you have a set of values in a dense range like [80,85]. If you have a lot of values far between eachother, using a set
or unordered_set
is probably a better choice. I found the code easy enough to read. Here are some ideas with comments in the code:
#include <array>
#include <iostream>
constexpr size_t INPUTSIZE = 10;
constexpr int MINLEGALVALUE = 80;
constexpr int MAXLEGALVALUE = 85;
constexpr size_t FREQUENCYSIZE = MAXLEGALVALUE - MINLEGALVALUE + 1;
std::array<unsigned, FREQUENCYSIZE> getUserInputFreq()
std::array<unsigned, FREQUENCYSIZE> inputValues0; // initialize with 0
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << ":";
// make sure the istream you read from succeeded in extracting
if(std::cin >> inputValue)
if(inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
// count frequencies directly if you don't actually need the
// input values
++inputValues[static_cast<size_t>(inputValue - MINLEGALVALUE)];
++i; // prefer prefix operator++
else
std::cout << "The number must be between" << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << "n";
else
break; // erroneous input or EOF
while(i < INPUTSIZE);
return inputValues;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
int rowLabel = MINLEGALVALUE;
for(auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
++rowLabel; // prefer prefix operator++
int main()
std::array<unsigned, FREQUENCYSIZE> freqs = getUserInputFreq();
std::cout << "n";
printFrequencies(freqs);
$endgroup$
add a comment |
$begingroup$
One idea for simplification is to count frequencies directly instead of putting all the values in an array that you only use for counting frequencies. You can then remove the getFrequencyCounts
function and the whole thing gets a little more efficient. This works well when you have a set of values in a dense range like [80,85]. If you have a lot of values far between eachother, using a set
or unordered_set
is probably a better choice. I found the code easy enough to read. Here are some ideas with comments in the code:
#include <array>
#include <iostream>
constexpr size_t INPUTSIZE = 10;
constexpr int MINLEGALVALUE = 80;
constexpr int MAXLEGALVALUE = 85;
constexpr size_t FREQUENCYSIZE = MAXLEGALVALUE - MINLEGALVALUE + 1;
std::array<unsigned, FREQUENCYSIZE> getUserInputFreq()
std::array<unsigned, FREQUENCYSIZE> inputValues0; // initialize with 0
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << ":";
// make sure the istream you read from succeeded in extracting
if(std::cin >> inputValue)
if(inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
// count frequencies directly if you don't actually need the
// input values
++inputValues[static_cast<size_t>(inputValue - MINLEGALVALUE)];
++i; // prefer prefix operator++
else
std::cout << "The number must be between" << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << "n";
else
break; // erroneous input or EOF
while(i < INPUTSIZE);
return inputValues;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
int rowLabel = MINLEGALVALUE;
for(auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
++rowLabel; // prefer prefix operator++
int main()
std::array<unsigned, FREQUENCYSIZE> freqs = getUserInputFreq();
std::cout << "n";
printFrequencies(freqs);
$endgroup$
add a comment |
$begingroup$
One idea for simplification is to count frequencies directly instead of putting all the values in an array that you only use for counting frequencies. You can then remove the getFrequencyCounts
function and the whole thing gets a little more efficient. This works well when you have a set of values in a dense range like [80,85]. If you have a lot of values far between eachother, using a set
or unordered_set
is probably a better choice. I found the code easy enough to read. Here are some ideas with comments in the code:
#include <array>
#include <iostream>
constexpr size_t INPUTSIZE = 10;
constexpr int MINLEGALVALUE = 80;
constexpr int MAXLEGALVALUE = 85;
constexpr size_t FREQUENCYSIZE = MAXLEGALVALUE - MINLEGALVALUE + 1;
std::array<unsigned, FREQUENCYSIZE> getUserInputFreq()
std::array<unsigned, FREQUENCYSIZE> inputValues0; // initialize with 0
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << ":";
// make sure the istream you read from succeeded in extracting
if(std::cin >> inputValue)
if(inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
// count frequencies directly if you don't actually need the
// input values
++inputValues[static_cast<size_t>(inputValue - MINLEGALVALUE)];
++i; // prefer prefix operator++
else
std::cout << "The number must be between" << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << "n";
else
break; // erroneous input or EOF
while(i < INPUTSIZE);
return inputValues;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
int rowLabel = MINLEGALVALUE;
for(auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
++rowLabel; // prefer prefix operator++
int main()
std::array<unsigned, FREQUENCYSIZE> freqs = getUserInputFreq();
std::cout << "n";
printFrequencies(freqs);
$endgroup$
One idea for simplification is to count frequencies directly instead of putting all the values in an array that you only use for counting frequencies. You can then remove the getFrequencyCounts
function and the whole thing gets a little more efficient. This works well when you have a set of values in a dense range like [80,85]. If you have a lot of values far between eachother, using a set
or unordered_set
is probably a better choice. I found the code easy enough to read. Here are some ideas with comments in the code:
#include <array>
#include <iostream>
constexpr size_t INPUTSIZE = 10;
constexpr int MINLEGALVALUE = 80;
constexpr int MAXLEGALVALUE = 85;
constexpr size_t FREQUENCYSIZE = MAXLEGALVALUE - MINLEGALVALUE + 1;
std::array<unsigned, FREQUENCYSIZE> getUserInputFreq()
std::array<unsigned, FREQUENCYSIZE> inputValues0; // initialize with 0
size_t i = 0;
do
int inputValue = 0;
std::cout << "Please enter a number between " << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << ":";
// make sure the istream you read from succeeded in extracting
if(std::cin >> inputValue)
if(inputValue >= MINLEGALVALUE && inputValue <= MAXLEGALVALUE)
// count frequencies directly if you don't actually need the
// input values
++inputValues[static_cast<size_t>(inputValue - MINLEGALVALUE)];
++i; // prefer prefix operator++
else
std::cout << "The number must be between" << MINLEGALVALUE << " and "
<< MAXLEGALVALUE << "n";
else
break; // erroneous input or EOF
while(i < INPUTSIZE);
return inputValues;
void printFrequencies(std::array<unsigned, FREQUENCYSIZE> freqs)
int rowLabel = MINLEGALVALUE;
for(auto frequency : freqs)
std::cout << rowLabel << " " << frequency << "n";
++rowLabel; // prefer prefix operator++
int main()
std::array<unsigned, FREQUENCYSIZE> freqs = getUserInputFreq();
std::cout << "n";
printFrequencies(freqs);
answered 7 hours ago
Ted LyngmoTed Lyngmo
1434 bronze badges
1434 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f226448%2fcount-the-frequency-of-integers-in-an-array%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
$begingroup$
You've asked for optimizations, but the input size is too small for the usual histogramming optimizations to matter, and anyway the program spends all of its time doing IO. Do you want to know about them anyway?
$endgroup$
– harold
7 hours ago