One-liner for nested for loops in C++ - c++

In Python I can do this:
>>> import itertools
>>> for i, j, in itertools.product(range(3), repeat=2): print i, j
...
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
Is it possible to have an easy-to-read, non-boost version of this in C++?

Ranges are not avalible, but range based loops come quite close.
#include <iostream>
int main(){
for (int i:{1,2,3}) { for (int j:{1,2,3}) {std::cout << i << " " << j <<std::endl;}};
}
or if you like to use the same range
#include <iostream>
int main(){
const auto range {1,2,3};
for (int i:range) {for (int j:range) {std::cout << i << " " << j <<std::endl;}};
}
and just for the fun of it with std::for_each (this one is perhaps hard to read, but it has no hand written loops)
#include <iostream>
#include <algorithm>
int main(){
const auto range {1,2,3};
std::for_each(range.begin(), range.end(), [range](int i) {std::for_each(range.begin(), range.end(), [i](int j) {std::cout << i << " " << j <<std::endl; } ); } );
}

Looping example (updated):
#include <array>
#include <iostream>
#include <utility>
template<int VRange, int VRepCount, int VValueRIndex = VRepCount> class
t_Looper
{
public: template<typename TAction> static void
process(::std::array<int, VRepCount> & values, TAction && action)
{
for(;;)
{
t_Looper<VRange, VRepCount, VValueRIndex - 1>::process(values, ::std::forward<TAction>(action));
auto & value{values[VRepCount - VValueRIndex]};
if((VRange - 1) != value)
{
++value;
}
else
{
value = 0;
break;
}
}
}
};
template<int VRange, int VRepCount> class
t_Looper<VRange, VRepCount, 0>
{
private: template<int... VIndexes, typename TAction> static void
invoke(::std::integer_sequence<int, VIndexes...>, ::std::array<int, VRepCount> const & values, TAction && action)
{
action(values[VIndexes]...);
}
public: template<typename TAction> static void
process(::std::array<int, VRepCount> & values, TAction && action)
{
invoke(::std::make_integer_sequence<int, VRepCount>(), values, ::std::forward<TAction>(action));
}
};
template<int VRange, int VRepCount, typename TAction> void
multiloop(TAction && action)
{
::std::array<int, VRepCount> values{};
t_Looper<VRange, VRepCount>::process(values, ::std::forward<TAction>(action));
}
int main()
{
multiloop<3, 2>([](int i, int j){::std::cout << i << " " << j << ::std::endl;});
multiloop<3, 4>([](int i, int j, int k, int l){::std::cout << i << " " << j << " " << k << " " << l << ::std::endl;});
return(0);
}
Run this code online

Is it possible to have an easy-to-read, non-boost version of this in C++?
No.
You cannot do that in pure C++. You would need a library or so.
There is an Extension for ranges that is experimental in C++14, but even with this, I am not sure if could make it.

if you do not mind creating your own .. dot-dot operator with the help of these two template functions:
template< int First, int Last , int Step = 1>
int ( &dotdot() )[ ( Step + Last - First ) / Step ]
{
static int result[ ( Step + Last - First ) / Step ];
for( int index = First; index <= Last; index += Step ){
result[ ( index - First ) / Step ] = index;
}
return result;
}
template< int Last, int First, int Step = 1 >
int ( &dotdot() )[ ( Step + Last - First ) / Step ]
{
static int result[ ( Step + Last - First ) / Step ];
for( int index = Last; index >= First; index -= Step ){
result[ ( Last - index ) / Step ] = index;
}
return result;
}
then you can:
for( int i : dotdot<0,2>() ) for( int j : dotdot<0,2>() ) std::cout << i << ' ' << j << '\n';
and the output:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
usage:
dotdot<'a','z'>() returns a to z
dotdot<'z','a',2>() returns z to a and step is 2
dotdot<-10,0>() returns -10 to 0
dotdot<-10,10,3>() returns -10 to 10 and step is 3

Related

Find similar numbers - array inconsistency

I'm trying to solve a simple beginner exercise, I compare two arrays and find the numbers that appear in both. The result is put into another array called result. For whatever reason the result should contain "2 44 55" but it shows "2 1 10 10". What did I do wrong?
#include <iostream>
void common_elements(int array_1[], int array_2[]){
int result[] {0};
int counter{0};
for (int i{0}; i < 10; i++){
for (int j{0}; j < 10; j++){
if (array_2[i] == array_1[j]){
result[counter] = array_1[j];
counter++;
}
}
}
if (counter == 0) {
std::cout << "There are 0 common elements";
} else {
std::cout << "There are " << counter << " common elements they are : ";
for (int k{0}; k < counter; k++){
std::cout << result[k] << " ";
}
}
}
int main(){
int data1[] {1,2,4,5,9,3,6,7,44,55};
int data2[] {11,2,44,45,49,43,46,47,55,88};
common_elements(data1,data2);
return 0;
}
I'm confused because when I std::cout the numbers during examination (two nested loops), the result is correct.
It is just containing one single element, because the compiler deduces the length to 1. This would mean the 2 is valid, all other values are "out of bound". Thanks for your help. I repaired it to
int result[10]{0};
Now it's working, thanks a lot.
Btw: It is a C++ course but it starts from the very beginning. That why this looks like C.
For starters the function should be declared at least like
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 );
Using the magic number 10 within the function as
for (int i{0}; i < 10; i++){
does not make sense. The function can be called for arrays that have different numbers of elements.
This declaration of an array
int result[] {0};
declares an array with only one element that also does not make sense.
Also the function should not output any message. It is the caller of the function that decides whether to output a message. The function should return a sequence of common elements of two arrays.
The function can be defined the following way
#include <vector>
#include <iterator>
#include <functional>
//...
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 )
{
std::vector<int> v;
if ( n1 != 0 && n2 != 0 )
{
if ( n2 < n1 )
{
std::swap( n1, n2 );
std::swap( array_1, array_2 );
}
for ( size_t i = 0; i < n1; i++ )
{
size_t count = 1;
for ( size_t j = 0; j < i; j++ )
{
if ( array_1[j] == array_1[i] ) ++count;
}
for ( size_t j = 0; count != 0 && j < n2; j++ )
{
if ( array_2[j] == array_1[i] )
{
--count;
}
}
if ( count == 0 ) v.push_back( array_1[i] );
}
}
return v;
}
And in main the function is called like
int data1[] {1,2,4,5,9,3,6,7,44,55};
int data2[] {11,2,44,45,49,43,46,47,55,88};
auto v = common_elements( data1, std::size( data1 ), data2, std::size( data2 ) );
if ( std::size( v ) == 0 )
{
std::cout << "There are 0 common elements";
}
else
{
std::cout << "There are " << std::size( v ) << " common elements they are : ";
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
Instead of the vector you could use std::map<intg, size_t>. In this case the container will contain how many times a common number is encountered in the both arrays.
Here is a demonstration program.
#include <iostream>
#include <vector>
#include <iterator>
#include <functional>
std::vector<int> common_elements( const int array_1[], size_t n1,
const int array_2[], size_t n2 )
{
std::vector<int> v;
if (n1 != 0 && n2 != 0)
{
if (n2 < n1)
{
std::swap( n1, n2 );
std::swap( array_1, array_2 );
}
for (size_t i = 0; i < n1; i++)
{
size_t count = 1;
for (size_t j = 0; j < i; j++)
{
if (array_1[j] == array_1[i]) ++count;
}
for (size_t j = 0; count != 0 && j < n2; j++)
{
if (array_2[j] == array_1[i])
{
--count;
}
}
if (count == 0) v.push_back( array_1[i] );
}
}
return v;
}
int main()
{
int data1[]{ 1,2,4,5,9,3,6,7,44,55 };
int data2[]{ 11,2,44,45,49,43,46,47,55,88 };
auto v = common_elements( data1, std::size( data1 ), data2, std::size( data2 ) );
if (std::size( v ) == 0)
{
std::cout << "There are 0 common elements";
}
else
{
std::cout << "There are " << std::size( v ) << " common elements they are : ";
for (const auto &item : v)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
}
The program output is
There are 3 common elements they are : 2 44 55

How to print and modify char in C++

I want to create a project that will print the '|' character as 4 layers going 1 3 5 7 something like
|
|||
|||||
|||||||
I wrote a for loop for this and the code is here:
for (int i = 1; i <= 4; i++) {
//for loop for displaying space
for (int s = i; s < 4; s++) {
cout << " ";
}
//for loop to display star equal to row number
for (int j = 1; j <= (2 * i - 1); j++) {
cout << "|";
}
// ending line after each row
cout << "\n";
}
So how can I make a code that will take user input like
cout << "Please enter a row number \n" << "Please enter a column number" << endl;
and let say the user entered 2 as row number 2 as column number I want the output to be something like
|
|
|||||
|||||||
Deletes 2 '|' character from the 2nd row
First I think putting every character in a array like char arr[] = { '|' , '||' , '|||', '||||'}
and deleting according to user input but I failed. Any help?
Here is a solution:
#include <iostream>
#include <vector>
std::size_t getLayerCount( )
{
std::cout << "How many layers to print: ";
std::size_t layerCount { };
std::cin >> layerCount;
return layerCount;
}
std::vector< std::vector<char> > generateShape( const std::size_t layerCount )
{
const std::size_t MAX_CHAR_COUNT_IN_A_ROW { layerCount * 2 };
constexpr char spaceChar { ' ' };
std::vector< std::vector<char> > shape( layerCount, std::vector<char>( MAX_CHAR_COUNT_IN_A_ROW, spaceChar ) );
for ( std::size_t row { }; row < layerCount; ++row )
{
for ( std::size_t offset { layerCount - row - 1 }; offset < layerCount + row; ++offset )
{
shape[ row ][ offset ] = '|';
}
shape[ row ][ MAX_CHAR_COUNT_IN_A_ROW - 1 ] = '\0';
}
return shape;
}
void printShape( const std::vector< std::vector<char> >& shape )
{
for ( const auto& row : shape )
{
std::cout.write( row.data( ), row.size( ) ).write( "\n", 1 );
}
}
void deleteSpecificChars( std::vector< std::vector<char> >& shape )
{
std::cout << "Please enter a row number: ";
std::size_t rowNumber { };
std::cin >> rowNumber;
std::cout << "Please enter a column number: ";
std::size_t colNumber { };
std::cin >> colNumber;
--rowNumber;
--colNumber;
const std::size_t layerCount { shape.size( ) };
const std::size_t posOfFirstCharInRow { layerCount - rowNumber - 1 };
const std::size_t posOfTargetCharInRow { posOfFirstCharInRow + colNumber };
const std::size_t posOfLastCharInRow { posOfFirstCharInRow + ( 2 * rowNumber ) };
for ( std::size_t idx { posOfTargetCharInRow }; idx <= posOfLastCharInRow; ++idx )
{
shape[ rowNumber ][ idx ] = ' ';
}
}
int main( )
{
const std::size_t layerCount { getLayerCount( ) };
std::vector< std::vector<char> > shape { generateShape( layerCount ) };
printShape( shape );
deleteSpecificChars( shape );
printShape( shape );
return 0;
}
Sample input/output:
How many layers to print: 4
|
|||
|||||
|||||||
Please enter a row number: 2
Please enter a column number: 2
|
|
|||||
|||||||
Another one:
How many layers to print: 5
|
|||
|||||
|||||||
|||||||||
Please enter a row number: 4
Please enter a column number: 4
|
|||
|||||
|||
|||||||||
Limiting your pile of bars to 4 levels, this should work:
You basically just want a fixed size string of bars, '|'.
Then remove n consecutive characters from that string.
The only thing you have to calculate is the starting index to start removing from, then replace n characters with blanks.
You can add some checks for row and col boundaries.
[Demo]
#include <iostream> // cout
#include <string>
int main()
{
std::string bars(16, '|');
auto get_start_deleting_pos = [](int row, int col) {
if (row == 1) { if (col > 1) { return -1; } return 0; }
else if (row == 2) { if (col > 3) { return -1; } return col; }
else if (row == 3) { if (col > 5) { return -1; } return 3 + col; }
else if (row == 4) { if (col > 7) { return -1; } return 8 + col; }
else return -1;
};
auto print_bars = [&bars]() {
std::cout << " " << bars[0] << "\n";
std::cout << " " << bars.substr(1, 3) << "\n";
std::cout << " " << bars.substr(4, 5) << "\n";
std::cout << bars.substr(9) << "\n";
};
auto start_deleting_from_row{4};
auto start_deleting_from_col{1};
auto num_chars_to_delete{4};
auto pos{ get_start_deleting_pos(start_deleting_from_row, start_deleting_from_col) };
if (pos != -1)
{
bars.replace(pos, num_chars_to_delete, num_chars_to_delete, ' ');
}
print_bars();
}
And if you want a more generic solution, where the user inputs the level, the row and col to start deleting from, and the number of characters to delete:
[Demo]
#include <iostream> // cout
#include <string>
auto get_size_for_levels(int l) { return l*l; }
auto get_index_for_row_and_col(int row, int col) { return (row - 1) * (row - 1) - 1 + col; }
auto get_num_cols_for_row (int row) { return row * 2 - 1; }
auto check_row_and_col(int levels, int row, int col) {
if (row < 1 or levels < row) { return false; }
if (col < 1 or get_num_cols_for_row(row) < col) { return false; }
return true;
}
int main()
{
auto levels{7}; // levels start at 1
auto start_deleting_from_row{4}; // rows start at 1
auto start_deleting_from_col{5}; // cols start at 1
auto num_chars_to_delete{6};
std::string bars(get_size_for_levels(levels), '|');
if (check_row_and_col(levels, start_deleting_from_row, start_deleting_from_col))
{
bars.replace(
get_index_for_row_and_col(start_deleting_from_row, start_deleting_from_col),
num_chars_to_delete,
num_chars_to_delete,
' ');
}
for (int l{1}; l <= levels; ++l)
{
std::cout
<< std::string(levels - l, ' ')
<< bars.substr(get_index_for_row_and_col(l, 1), get_num_cols_for_row(l))
<< "\n";
}
}

displaying a vector of deques in columns

I'm trying to display a vector of deques (std::vector<std::deque<int>> v) like this
v.at(0).at(0) v.at(1).at(0) v.at(2).at(0) v.at(3).at(0)
v.at(0).at(1) v.at(1).at(1) v.at(2).at(1) v.at(3).at(1)
v.at(0).at(2) v.at(1).at(2) v.at(2).at(2) v.at(3).at(2)
v.at(1).at(3) v.at(3).at(3)
v.at(3).at(4)
The first part of the vector is fixed at 7, the size of the actual columns are dynamic however depending on what the user chooses to do.
I was attempting something like
int row = 0;
int column;
for (column = 0; column < v.at(row).size(); column++){
cout << "v["<< row <<"]["<< column << "]" << v.at(row).at(column) << "\t";
while (row < v.size()){
cout << endl;
row++;
}
}
I'm getting errors like
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector
make: *** [Pile.h] Abort trap: 6
Having one of those blah brain days. Can someone help me print this out the way I want it?
Here is a demonstrative program that shows one of approaches to the task.
#include <iostream>
#include <iomanip>
#include <vector>
#include <deque>
#include <algorithm>
int main()
{
std::vector<std::deque<int>> v =
{
{ 0, 1, 2 },
{ 0, 1, 2, 3 },
{ 0, 1, 2 },
{ 0, 1, 2, 3, 4 }
};
size_t n = std::max_element( v.begin(), v.end(),
[]( const auto &x, const auto &y )
{
return x.size() < y.size();
} )->size();
for ( size_t i = 0; i < n; i++)
{
for ( size_t j = 0; j < v.size(); j++ )
{
std::cout << std::setw( 4 );
if ( i < v[j].size() )
{
std::cout << v[j][i];
}
else
{
std::cout << "";
}
}
std::cout << std::endl;
}
return 0;
}
Its output is
0 0 0 0
1 1 1 1
2 2 2 2
3 3
4
First of all, I suggest to get the max queue size
std::size_t maxQ { 0U };
for ( auto const & q : v )
maxQ = std::max(maxQ, q.size());
Now you can write a loop over (0U, maxQ( (the loop of lines) writing elements when available and space otherwise.
for ( auto i = 0U ; i < maxQ ; ++i )
{
for ( auto j = 0U ; j < v.size() ; ++j )
if ( i < v[j].size() )
; // print v[j][i]
else
; // print space
std::cout << std::endl; // endl of line
}
I leave to you cells printing details

How do I print the following pattern using 3 for loops instead of 4?

I'm trying to print the following pattern:
*
**
***
****
*****
****
***
**
*
Now, I know how to do it using 4 for loops:
for(i=1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
cout<<"*";
}
cout<<"\n";
}
to print the first half and to print the second half:
for(i=1;i<=n;i++)
{
for(j=n;j>i;j--)
{
cout<<"*";
}
cout<<"\n";
}
Looking closely, both the outer for loops are the same. i.e.,
for(i=1;i<=n;i++).
Is there anyway to nest both the 'j' for-loops inside the i-for loop?
Using only one loop:
#include <iostream>
#include <string>
int main() {
for (unsigned i = 0; i < 10; ++i)
std::cout << std::string( i < 5 ? (i+1) : 10 - (i+1), '*') << std::endl;
return 0;
}
Would you care for not even three loops, but just two loops?
int n=5, i, j, k;
for (i=0; i<n*2-1; i++)
{
j=i;
if (j >= n)
j=n*2-2-j;
for (k=0; k<=j; k++)
std::cout << '*';
std::cout << std::endl;
}
using 2 loops:
int g=1;
for(int i=0;i<=5;i++){
for (int y=0;y<=i;y+=g){
cout<<"*";
}
cout<<endl;
if (i==4 && g==1){
cout<<"*****";
i=3;
g=-1;
}}
Instead of printing 5 lines, and then another 5, you could print 10, and calculate the number of stars in each line.
for(i = 1; i <= 2*n - 1; i++)
{
for(j = 1; j <= n - abs(i - n); j++)
{
cout<<"*";
}
cout<<"\n";
}
The expression n-abs(i-n) evaluates to i for values of i between 1 and n, and to 2n-i for values of i greater than n.
Just for fun, how about one loop:
for (int i=1, j=0, dir=1; i!=0;) {
cout << '*';
++j;
if (j==i) {
cout << '\n';
j = 0;
i += dir;
if (i==6) {
dir = -1;
i -= 2;
}
}
}
You can do it in one loop (maybe cheating a little bit):
size_t max = 5;
size_t rows = max * 2 - 1;
std::string line(std::string(max, '*') + '\n');
for ( size_t j = 0, k = max; j < rows; ++j ) {
std::cout << line.c_str() + ( j < max ? --k : ++k );
}
I know you didn't ask for it, but for completeness here's one with zero loops (recursion instead):
#include <iostream>
void print_stars(int count)
{
if (count > 0)
{
std::cout << '*';
print_stars(count - 1);
}
}
void print_line(int lines, int stars)
{
if (lines == 1)
print_stars(stars);
else
{
if (stars > 0)
{
print_stars(stars);
std::cout << std::endl;
}
print_line(lines - 1, stars + 1);
std::cout << std::endl;
if (stars > 0)
print_stars(stars);
}
}
int main()
{
int star_count = 5;
print_line(star_count + 1, 0);
return 0;
}
The pattern can be outputted using only one for loop.
Here is a demonstrative program.
#include <iostream>
#include <iomanip>
int main()
{
while ( true )
{
const char c = '*';
std::cout << "Enter non-negative number (0 - exit): ";
unsigned int n;
if ( !( std::cin >> n ) || n == 0 ) break;
std::cout << '\n';
for ( unsigned int i = 1; i < 2 * n; i++ )
{
unsigned int w = i <= n ? i : 2 * n - i;
std::cout << std::setfill( c ) << std::setw( w + 1 ) << '\n';
}
std::cout << std::endl;
}
return 0;
}
If to enter sequentially
5 4 3 2 1 0
then the program output will look the following way
Enter non-negative number (0 - exit): 5
*
**
***
****
*****
****
***
**
*
Enter non-negative number (0 - exit): 4
*
**
***
****
***
**
*
Enter non-negative number (0 - exit): 3
*
**
***
**
*
Enter non-negative number (0 - exit): 2
*
**
*
Enter non-negative number (0 - exit): 1
*
Enter non-negative number (0 - exit): 0
Using the same variables of this well-structured program as function parameters you can write a separate function that outputs the pattern.
Here you are.
#include <iostream>
#include <iomanip>
std::ostream & pattern( unsigned int n, char c = '*', std::ostream &os = std::cout )
{
for ( unsigned int i = 1; i < 2 * n; i++ )
{
unsigned int w = i <= n ? i : 2 * n - i;
os << std::setfill( c ) << std::setw( w + 1 ) << '\n';
}
return os;
}
int main()
{
while ( true )
{
std::cout << "Enter non-negative number (0 - exit): ";
unsigned int n;
if ( !( std::cin >> n ) || n == 0 ) break;
std::cout << '\n';
pattern( n );
std::cout << std::endl;
}
return 0;
}
Take into account that for example it is a bad idea to use the standard class std::string to output the pattern because the program will be inefficient due to allocation and reallocation of the dynamic memory for an object of the class.
If not to use the standard stream manipulators then you can use standard algorithm std::fill_n to hide the inner loop. In this case the program also will have only one explicit loop.
For example
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
while ( true )
{
const char c = '*';
std::cout << "Enter non-negative number (0 - exit): ";
unsigned int n;
if ( !( std::cin >> n ) || n == 0 ) break;
std::cout << '\n';
for ( unsigned int i = 1; i < 2 * n; i++ )
{
unsigned int w = i <= n ? i : 2 * n - i;
*std::fill_n( std::ostream_iterator<char>( std::cout ), w, c ) = '\n';
}
std::cout << std::endl;
}
return 0;
}
#include <iostream>
using namespace std;
int main() {
int i;
int j;
int count = 1;
for(i= 0;i<10;i++) {
if(i < 5) {
for(j=0;j<=i;j++) {
cout<<"*";
}
} else {
for(j=i-count;j>0;j--) {
cout<<"*";
}
count +=2;
}
cout<< "\n";
}
return 0;
}

C++ multiple returns from single function

still pretty new to C++.
Had to write a function in class to count the number of each digit in a multi-dimensional array.
Now I didn't think you could return multiple int values from a single called function and then use all of these returns in a text based answer, so I attempted to return a different value depending on the value requested as parameter for each digit.
The code below is unnecessarily long and I'm still receiving the following errors.
main-1-3.cpp: In function 'int main()':
main-1-3.cpp:12:21: error: too few arguments to function 'int
count_numbers(int(*)[4], int)'
count_numbers(array);
^
main-1-3.cpp:7:12: note: declared here
extern int count_numbers(int array[4][4], int);
With a bit of debugging I could likely fix up these compile errors, but I feel like my method is extremely convoluted and was wondering if it were possible to call the function as:
count_number(array[4][4])
(Removing the need for the Q parameter) and then have count_numbersreturn all ten of the number values and the just output them as text like << ",3:" << three << instead of << ",8:" << count_numbers(array, 8) <<
Anyway, the function.cpp and main.cpp are below.
If anyone could point me in the right direction it would greatly appreciated. Just need to know the correct method so I can condense this code.
function.cpp
#include <iomanip>
#include <locale>
#include <sstream>
#include <string>
#include <iostream>
int count_numbers(int array[4][4], int Q)
{
int X=0;
int Y=0;
int zero=0;
int one=0;
int two=0;
int three=0;
int four=0;
int five=0;
int six=0;
int seven=0;
int eight=0;
int nine=0;
while(X<4)
{
if(array[X][Y]==0)
{
zero=zero+1;
}
if(array[X][Y]==1)
{
one=one+1;
}
if(array[X][Y]==2)
{
two=two+1;
}
if(array[X][Y]==3)
{
three=three+1;
}
if(array[X][Y]==4)
{
four=four+1;
}
if(array[X][Y]==5)
{
five=five+1;
}
if(array[X][Y]==6)
{
six=six+1;
}
if(array[X][Y]==7)
{
seven=seven+1;
}
if(array[X][Y]==8)
{
eight=eight+1;
}
if(array[X][Y]==9)
{
nine=nine+1;
}
Y++;
if(Y==4)
{
Y=0;
X++;
}
}
if(Q==0)
{
return zero;
}
if(Q==1)
{
return one;
}
if(Q==2)
{
return two;
}
if(Q==3)
{
return three;
}
if(Q==4)
{
return four;
}
if(Q==5)
{
return five;
}
if(Q==6)
{
return six;
}
if(Q==7)
{
return seven;
}
if(Q==8)
{
return eight;
}
if(Q==9)
{
return nine;
}
}
main.cpp
#include <iomanip>
#include <locale>
#include <sstream>
#include <string>
#include <iostream>
extern int count_numbers(int array[4][4], int);
int array[4][4] = { {1,2,3,4} , {1,2,3,4} , {1,2,3,4} , {1,2,3,4}};
int main()
{
count_numbers(array);
std::cout << ",0:" << count_numbers(array, 0) << ",1:" << count_numbers(array, 1) << ",2:" << count_numbers(array, 2) << ",3:" << count_numbers(array, 3) << ",4:" << count_numbers(array, 4) << ",5:" << count_numbers(array, 5) << ",6:" << count_numbers(array, 6) <<",7:" << count_numbers(array, 7) << ",8:" << count_numbers(array, 8) << ",9:" << count_numbers(array, 9) << std::endl;
}
PS. Ignore incorrect indentation its just from pasting to this site
PPS. Thanks for any assistance.
EDIT
Thank you "Vlad From Moscow" for the assistance.
My initial (terrible) code would have worked if I'd simply removed the (unintentional) count_number(array); call from main.cpp
However the for loop system proposed by Vlad allowed me to shrink the code by 80%. It now looks like this:
int count_numbers(int array[4][4], int Q)
{
int ans=0;
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
{
ans += array[i][j] ==Q;
}
}
return ans;
}
Thank you for the assistance which was great, I began coding on Python so it was my lack of understanding of loops in C++ which was the real problem here.
Anyway, problem solved..
This call
count_numbers(array);
does not make sense and moreover is invalid because the function requires two arguments instead of one.
The function itself can be written the following way
const size_t N = 4;
size_t count_number( const int ( &a )[N][N], int value )
{
size_t n = 0;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
n += a[i][j] == value;
}
}
return n;
}
and called like
std::cout << "0: " << count_number( array, 0 )
<< ", 1: " << count_number( array, 1 )
<< ", 2: " << count_number( array, 2 )
<< ", 3: " << count_number( array, 3 )
<< ", 4: " << count_number( array, 4 )
<< ", 5: " << count_number( array, 5 )
<< ", 6: " << count_number( array, 6 )
<< ", 7: " << count_number( array, 7 )
<< ", 8: " << count_number( array, 8 )
<< ", 9: " << count_number( array, 9 )
<< std::endl;
Here is a demonstrative program
#include <iostream>
const size_t N = 4;
size_t count_number( const int ( &a )[N][N], int value )
{
size_t n = 0;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
n += a[i][j] == value;
}
}
return n;
}
int main()
{
int array[N][N] =
{
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 }
};
bool first = true;
for ( int value = 0; value < 10; ++value )
{
size_t n = count_number( array, value );
if ( n )
{
std::cout << ( first ? first = false, "" : ", " )
<< value << ": " << n;
}
}
std::cout << std::endl;
}
Its output is
1: 4, 2: 4, 3: 4, 4: 4
A more general approach can look the following way
#include <iostream>
#include <iterator>
#include <algorithm>
template <typename InputIterator, typename T>
size_t count_number( InputIterator first,
InputIterator last,
const T &value )
{
size_t n = 0;
for ( ; first != last; ++first )
{
n += std::count( std::begin( *first ), std::end( *first ), value );
}
return n;
}
int main()
{
const size_t N = 4;
int array[N][N] =
{
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 } ,
{ 1, 2, 3, 4 }
};
bool first = true;
for ( int value = 0; value < 10; ++value )
{
size_t n = count_number( std::begin( array ), std::end( array ), value );
if ( n )
{
std::cout << ( first ? first = false, "" : ", " )
<< value << ": " << n;
}
}
std::cout << std::endl;
}
The program output will be the same as it is shown above.
If the array contains only digits that you need to count then the function can look like
const size_t N = 4;
void count_digits( const int ( &a )[N][N], size_t ( &digits)[10] )
{
for ( size_t &x : digits ) x = 0;
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
++digits[a[i][j]];
}
}
}
To call the function you need to declare in main an array like for example
size_t digits[10];
you can return int[] or event better since you are using c++ return vector<int>.
In your function you can replace one, two, .. with something like
vector<int> result(10);
This will create a vector with 10 entries, all of them 0.
Then replace thing like three = three + 1 with result[3] = result[3] + 1 or even more condensed result[3]++
Then at the end you can write ... << ",0:" << result[0] << ... or even do a for loop like:
for (int i = 0; i < 10; ++i) count << "," << i << ":" << result[i];
You can do all this with int[] as well if that's required but you need to take care of allocating and deallocating the memory. vector will simplify your code a lot.