Having a hard time designing an efficient algorithm that accomplishes the following. If I start with a 2d vector A,
A = [1 2 3;
2 3 4;
5 6]
I want to take the rows that contain common elements and combine them (removing duplicates) resulting in 2d vector B:
B = [1 2 3 4;
5 6]
I can accomplish this in Matlab, but am having a hard time in C++. Any help is appreciated.
Try this, it worked for me with your example matrix. It looks like a lot of code, but there are functions just for the example and for debugging purpose.
void disp( const std::vector< int >& a )
{
for ( const auto item : a )
{
std::cout << item;
}
std::cout << "\n";
}
void disp( const std::vector< std::vector< int > >& matrix )
{
for ( const auto& row : matrix )
{
disp( row );
}
}
// I think there shall be some easier way for this.
bool hasCommonElements( const std::vector< int >& aVector1, const std::vector< int >& aVector2 )
{
for ( const auto item1 : aVector1 )
{
for ( const auto item2 : aVector2 )
{
if ( item1 == item2 )
{
return true;
}
}
}
return false;
}
void makeAllElementsUnique( std::vector< int >& aRow )
{
std::sort( aRow.begin(), aRow.end() );
aRow.erase( std::unique( aRow.begin(), aRow.end() ), aRow.end() );
}
void mergeRowsWithCommonValues( std::vector< std::vector< int > >& aMatrix )
{
for ( auto it = aMatrix.begin(); it != aMatrix.end(); ++it )
{
auto it2 = it + 1;
while ( it2 != aMatrix.end() )
{
if ( hasCommonElements( *it, *it2 ) )
{
(*it).insert( (*it).end(), (*it2).begin(), (*it2).end() ); // Merge the rows with the common value(s).
makeAllElementsUnique( (*it) );
it2 = aMatrix.erase( it2 ); // Remove the merged row.
}
else
{
++it2;
}
}
}
}
void example()
{
std::vector< std::vector< int > > matrix;
matrix.push_back( { 1, 2, 3 } );
matrix.push_back( { 2, 3, 4 } );
matrix.push_back( { 5, 6 } );
disp( matrix );
mergeRowsWithCommonValues( matrix );
disp( matrix );
}
Here is my own attempt, kinda messy, I know.
int index2 = 0;
int rowIndex = 0;
int tracker = 0;
int insert = 0;
// Loop over all rows
while (index2 < A.size()){
// Check if vector is empty. If so, copy the first row in.
if (B.empty()){
B.push_back(A[index2]);
index2++;
cout<<"Hit an empty.\n";
}
// If vector not empty, do the complicated stuff.
else if (!B.empty()){
for (int i = 0; i < A[index2].size(); i++){ // element in A
for (int j = 0; j < B.size(); j++){ // row in B
for (int k = 0; k < B[j].size(); k++){ // element in row in B
if (A[index2][i] == B[j][k]){
rowIndex = j;
tracker = 1;
}
}
}
}
// If tracker activated, we know there's a common element.
if (tracker == 1){
cout<<"Hit a positive tracker.\n";
for (int i = 0; i < A[index2].size(); i++){ // element in A
for (int j = 0; j < B[rowIndex].size(); j++){ // element in B at rowIndex
if (A[index2][i] != B[rowIndex][j])
insert++;
cout<<"Hit an insert increment.\n";
}
if (insert == B[rowIndex].size()){
cout<<"Hit an insert.\n";
B[rowIndex].push_back(A[index2][i]);
}
insert = 0;
}
index2++;
}else{
B.push_back(A[index2]);
index2++;
cout<<"Hit a zero tracker.\n";
}
}
tracker = 0;
}
Related
I wanna list all arrangement, the following is my sample code:
const unsigned char item1[] = {'b'};
const unsigned char item2[] = { 'A', 'C' ,'D'};
const unsigned char item3[] = {'1','2'};
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0; i < sizeof(item1) / sizeof(unsigned char); i++){
for (int j = 0; j < sizeof(item2) / sizeof(unsigned char); j++){
for (int k = 0; k < sizeof(item3) / sizeof(unsigned char); k++){
printf("%c%c%c\n",item1[i],item2[j],item3[k]);
}
}
}
return 0;
}
This will print all arrangement, but I am worried about if the array item is from item1 to item99, the code is difficult to maintain. Is there a better solution to print all arrangement? Thanks!
You might store your "iterator" in vector, then you might do something like:
bool increase(const std::vector<std::string>& v, std::vector<std::size_t>& it)
{
for (std::size_t i = 0, size = it.size(); i != size; ++i) {
const std::size_t index = size - 1 - i;
++it[index];
if (it[index] == v[index].size()) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
void do_job(const std::vector<std::string>& v, std::vector<std::size_t>& it)
{
for (std::size_t i = 0, size = v.size(); i != size; ++i) {
std::cout << v[i][it[i]];
}
std::cout << std::endl;
}
void iterate(const std::vector<std::string>& v)
{
std::vector<std::size_t> it(v.size(), 0);
do {
do_job(v, it);
} while (increase(v, it));
}
Demo
A nice way of accomplishing this is to look at the problem as an integer base conversion problem. So, the total number of combinations is the product of all the array sizes. The output string n would be enough to determine the array indeces that should be printed in the string.
Since you have tagged it as a C++ question I would use 2-D vectors, as this makes life much simpler:
int _tmain(int argc, _TCHAR* argv[])
{
// Initialize the vector
vector<vector<char>> v( 3 );
v[0].push_back( 'b' );
v[1].push_back( 'A' );
v[1].push_back( 'C' );
v[1].push_back( 'D' );
v[2].push_back( '1' );
v[2].push_back( '2' );
// This is a convenience vector of sizes of each 1-D vector
vector<size_t> sizes( v.size() );
// Get the total number of combinations and individual vector
// sizes
size_t total = 1;
for( size_t i = 0; i < v.size(); ++i )
{
sizes[i] = v[i].size();
total *= sizes[i];
}
size_t done = 0;
// Loop till all the combinations are printed
while( done != total )
{
// Remainder, which is the index of the element
// in the 1-D vector that is to be printed
size_t r = 0;
// Quotient to be used for the next remainder
size_t q = done;
// Combination to be printed
string s = "";
// Loop over the 1-D vectors, picking the correct
// character from each
for( size_t i = 0; i < v.size(); ++i )
{
r = q % sizes[v.size() - 1 - i];
q = static_cast<size_t>( floor( q/sizes[v.size() - 1 - i] ) );
s = v[v.size() - 1 - i][r] + s;
}
cout<<s<<"\n";
done++;
}
return 0;
}
I just don't know what to do with it...
The functions runs well in debug, but not in release.
I am trying to learn about artificial neural networks and C++ vectors.
Here is the code (in Python 2.7) that I'm writing in C++:
http://neuralnetworksanddeeplearning.com/chap1.html#exercise_852508
(just scroll a little to reach it)
I'm using MinGW 7.2.0 from MSYS2 (C++11).
There are some "teste" prints inside the backpropagation method, that is where the problem is comming from (I guess). I also overloaded operators +, - and * to make things easier.
I know that there are some libs like Armadillo that could make things easier, but I really wanna use this problem to learn better.
And here is the files:
neuralnetwork.h
(I made everything public to make things easier to look at)
#define MIN_NUMBER_TOLERANCE 1e-8
namespace nn
{
class neuralnetwork
{
//private:
public:
//total number of weights. useful to reserve memory
int numWeights;
//total number of biases. useful to reserve memory
int numBiases;
//total number of layers: 1 for input, n hidden layers and 1 for output
int numLayers;
//a vector to store the number of neurons in each layer: 0 index is about the input layer, last index is about the output layer
std::vector<int> sizes;
//stores all biases: num of neurons of layer 1 + ... + num of neurons of layer (numLayers - 1) (input layer has no bias)
std::vector<std::vector<double>> biases;
//stores all weights: (num of neurons of layer 1) x (num of neurons of layer ) + ... + ( num of neurons of layer (numLayers - 1) ) x ( num of neurons of layer (numLayers - 2) ) (input layer has no bias)
std::vector<std::vector<std::vector<double>>> weights;
//stores the output of each neuron of each layer
std::vector<std::vector<double>> layersOutput;
std::vector<std::vector<std::vector<double>>> derivativeWeights;
std::vector<std::vector<double>> derivativeBiases;
std::default_random_engine generator;
std::normal_distribution<double> distribution;
double randomNormalNumber(void);
double costDerivatives(const double&, const double&);
std::vector<double> costDerivatives(const std::vector<double> &, const std::vector<double> &);
void backPropagation(const std::vector<double>& neuralNetworkInputs, const std::vector<double>& expectedOutputs, // inputs
std::vector<std::vector<std::vector<double>>>& derivativeWeights, std::vector<std::vector<double>>& derivativeBiases); // outputs
void update_mini_batch( const std::vector<std::pair<std::vector<double>,std::vector<double>>> & mini_batch, double eta);
//public:
neuralnetwork(const std::vector<int>& sizes);
std::vector<double> feedforward(const std::vector<double>&);
};
std::vector<double> sigmoid(const std::vector<double> &);
double sigmoid(double);
std::vector<double> sigmoid_prime(const std::vector<double> &);
//double sigmoid_prime(double);
}
neuralnetwork.cpp
#include "neuralnetwork.h"
#include <iostream>
#include <assert.h>
#include <algorithm>
namespace nn
{
int counter = 0;
neuralnetwork::neuralnetwork(const std::vector<int> &sizes)
{
this->distribution = std::normal_distribution<double>( 0.0 , 1.0 );
this->numLayers = sizes.size();
this->sizes = sizes;
this->numWeights = 0;
this->numBiases = 0;
for ( int i = 1 ; i < this->numLayers ; i++ )
{
numWeights += this->sizes[ i ] * this->sizes[ i - 1 ];
numBiases += this->sizes[ i ];
}
this->weights.reserve( numWeights );
this->biases.reserve( numBiases );
this->derivativeWeights.reserve( numWeights );
this->derivativeBiases.reserve( numBiases );
this->layersOutput.reserve( this->sizes[ 0 ] + numBiases );
std::vector<double> auxVectorWeights;
std::vector<std::vector<double> > auxMatrixWeights;
std::vector<double> auxVectorBiases;
#ifdef DEBUG_BUILD
std::cout << "debugging!\n";
#endif
//just to accommodate the input layer with null biases and inputs (makes things easier to iterate and reading :D).
this->layersOutput.push_back( std::vector<double>( this->sizes[ 0 ] ) );
std::vector<std::vector<double>> matrixNothing( 0 );
this->weights.push_back( matrixNothing );
this->biases.push_back( std::vector<double>( 0 ) );
//since the second layer (index 1) because there is no weights (nor biases) for the neurons of the first layer
for ( int layer = 1 ; layer < this->numLayers ; layer++ )
{
//preallocate memory for the output of each layer.
layersOutput.push_back( std::vector<double>( this->sizes[ layer ] ) );
//-----------weights begin--------------
//auxMatrixWeights will store the weights connections between one layer (number of columns) and its subsequent layer (number of rows)
//auxMatrixWeights = new std::vector(this->sizes[layer], std::vector<double>( this->sizes[layer - 1] )); // it is not working...
//size[layer] stores the number of neurons on the layer
for ( int i = 0 ; i < this->sizes[ layer ] ; i++ )
{
//auxVectorWeights will have the size of the amount of wights necessary to connect the neuron i (from this layer) to neuron j (from next layer)
auxVectorWeights = std::vector<double>( this->sizes[ layer - 1 ] );
for ( int j = 0 ; j < auxVectorWeights.size() ; j++ )
{
auxVectorWeights[ j ] = this->randomNormalNumber();
}
auxMatrixWeights.push_back( auxVectorWeights );
}
this->weights.push_back( auxMatrixWeights );
auxMatrixWeights.clear();
//-----------weights end----------------
//-----------biases begin---------------
auxVectorBiases = std::vector<double>( this->sizes[ layer ] );
for ( int i = 0 ; i < auxVectorBiases.size() ; i++ )
{
auxVectorBiases[ i ] = this->randomNormalNumber();
}
this->biases.push_back( auxVectorBiases );
//-----------biases end-----------------
}
#ifdef _DEBUG
for ( int i = 0 ; i < this->weights.size() ; i++ )
{
std::cout << "layer " << i << "\n";
for ( int j = 0 ; j < this->weights[ i ].size() ; j++ )
{
std::cout << "neuron" << j << std::endl;
for ( const auto k : this->weights[ i ][ j ] )
{
std::cout << '\t' << k << ' ';
}
std::cout << std::endl;
}
}
#endif
}
template <class T>
inline int lastIndex(std::vector<T> vector , int tail)
{
return (vector.size() - tail);
}
double neuralnetwork::randomNormalNumber(void)
{
return this->distribution( this->generator );
}
double sigmoid(double z)
{
return 1.0 / ( 1.0 + exp( -z ) );
}
std::vector<double> sigmoid(const std::vector<double> & z)
{
int max = z.size();
std::vector<double> output;
output.reserve(max);
for(int i=0;i<max;i++)
{
output.push_back(0);
output[i] = 1.0 / ( 1.0 + exp( -z[i] ) );
}
return output;
}
/*double sigmoid_prime(double z)
{
return sigmoid( z ) * ( 1 - sigmoid( z ) );
}*/
std::vector<double> sigmoid_prime(const std::vector<double>& z)
{
int max = z.size();
std::vector<double> output;
output.reserve(max);
for(int i=0;i<max;i++)
{
output.push_back(sigmoid( z[i] ) * ( 1 - sigmoid( z[i] ) ) );
}
return output;
}
//scalar times vector
std::vector<double> operator* (double a , const std::vector<double> & b)
{
int size = b.size();
std::vector<double> result(size);
for ( int i = 0 ; i < size ; i++ )
{
result[i] = a * b[ i ];
}
return result;
}
// inner product
std::vector<double> operator* (const std::vector<double> & a , const std::vector<double> & b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size(); // or b.size(). they should have the same size.
std::vector<double> result;
result.reserve(size); // or b.size(). they should have the same size.
for ( int i = 0 ; i < size ; i++ )
{
result.push_back( a[ i ] * b[ i ] );
}
return result;
}
//matrix times columns vector
std::vector<double> operator* (const std::vector<std::vector<double>> & a , const std::vector<double> & b)
{
#ifdef _DEBUG
assert(a[0].size() == b.size());
for(int i = 0 ; i < ( lastIndex( a , 1 )) ; i++)
{
assert(a[i].size() == a[i+1].size());
}
#endif
int lines = a.size();
int columns = a[0].size();
std::vector<double> result;
result.reserve(lines);
int j = 0;
for ( int i = 0 ; i < lines ; i++ )
{
result.push_back(0);
for(j = 0 ; j < columns ; j++)
{
result[i] += a[ i ][ j ] * b[ j ];
}
}
return result;
}
//scalar times matrix (calls scalar times vector)
std::vector<std::vector<double>> operator* (double a , const std::vector<std::vector<double>> & b)
{
#ifdef _DEBUG
for(int i = 0 ; i < b.size()-1 ; i++)
{
assert(b[i].size() == b[i+1].size());
}
#endif
int lines = b.size();
int columns = b[0].size();
std::vector<std::vector<double>> result;
int j = 0;
for ( int i = 0 ; i < lines ; i++ )
{
result.push_back(a * b[ j ]);
}
return result;
}
std::vector<double> operator+(const std::vector<double>& a, const std::vector<double>& b)
{
assert(a.size() == b.size());
int size = a.size();
std::vector<double> result;
result.reserve(size);
for(int i = 0 ; i < size ; i++)
{
result.push_back(0);
result[i] = a[i] + b[i];
}
return result;
}
//sum of matrices
std::vector<std::vector<double>> operator+(const std::vector<std::vector<double>>& a, const std::vector<std::vector<double>>& b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size();
#ifdef _DEBUG
for(int i = 0 ; i < size ; i++)
{
assert(a[i].size() == b[i].size());
}
#endif
std::vector<std::vector<double>> result;
result.resize(size);
for(int i = 0 ; i < size ; i++)
{
result.push_back(a[i] + b[i]);
}
return result;
}
//subtraction of vectors
std::vector<double> operator-(const std::vector<double>& a, const std::vector<double>& b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size();
std::vector<double> result;
result.resize(size);
for(int i = 0 ; i < size ; i++)
{
result[i] = a[i] - b[i];
}
return result;
}
//subtraction of matrices (calls subtraction of vectors)
std::vector<std::vector<double>> operator-(const std::vector<std::vector<double>>& a, const std::vector<std::vector<double>>& b)
{
#ifdef _DEBUG
assert(a.size() == b.size());
#endif
int size = a.size();
#ifdef _DEBUG
for(int i = 0 ; i < size ; i++)
{
assert(a[i].size() == b[i].size());
}
#endif
std::vector<std::vector<double>> result;
result.resize(size);
for(int i = 0 ; i < size ; i++)
{
result.push_back(a[i] - b[i]);
}
return result;
}
//elementwise division
std::vector<double> operator/(const std::vector<double>& a, const std::vector<double>& b)
{
assert(a.size() == b.size());
int size = a.size();
std::vector<double> result;
result.reserve(size);
for(int i = 0 ; i < size ; i++)
{
if(b[i] < MIN_NUMBER_TOLERANCE)
{
throw std::runtime_error("Can't divide by zero!");
}
result[i] = a[i] / b[i];
}
return result;
}
double neuralnetwork::costDerivatives(const double &networkOutput , const double &expectedOutput)
{
return expectedOutput - networkOutput;
}
std::vector<double> neuralnetwork::costDerivatives(const std::vector<double> &networkOutput , const std::vector<double> &expectedOutput)
{
assert(expectedOutput.size() == networkOutput.size());
int size = networkOutput.size();
std::vector<double> output;
output.reserve(size);
for(int i = 0 ; i < size ; i++)
{
output.push_back(networkOutput[i] - expectedOutput[i]);
}
return output;
}
void neuralnetwork::backPropagation(const std::vector<double> &neuralNetworkInputs , const std::vector<double> &expectedOutputs, // inputs
std::vector<std::vector<std::vector<double>>>& derivativeWeights , std::vector<std::vector<double>>& derivativeBiases) // outputs
{
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
derivativeWeights.reserve( sizes.size() - 1 );
derivativeBiases.reserve( sizes.size() - 1 );
//to store one activation layer
std::vector<double> activation = neuralNetworkInputs;
//to store each one of the activation layers
std::vector<std::vector<double>> activations;
activations.reserve(sizes.size()); // numBiases is the same as the number of neurons (except 1st layer)
activations.push_back(activation);
int maxLayerSize = 0;
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
for ( int i = 1 ; i < numBiases ; i++ )
{
maxLayerSize = std::max(sizes[i], maxLayerSize);
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
// to store one weighted sum
std::vector<double> z;
z.reserve(maxLayerSize);
// to store each one of the weighted sums
std::vector<std::vector<double>> zs;
zs.reserve(sizes.size());
// layer and neuron counter
int layer, neuron;
for ( layer = 1 ; layer < numLayers ; layer++ )
{
z = (weights[layer] * activation) + biases[layer];
zs.push_back(z);
activation = sigmoid(z);
activations.push_back(activation);
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
std::vector<double> delta = costDerivatives(activations[ lastIndex( activations , 1 )] , expectedOutputs) * sigmoid_prime(z);
delta.reserve(maxLayerSize);
derivativeBiases.push_back(delta);
int j;
std::vector<std::vector<double>> dummyMatrix;
dummyMatrix.reserve(maxLayerSize);
for (neuron = 0; neuron < sizes[ lastIndex( sizes , 1 )]; neuron++)
{
dummyMatrix.push_back(std::vector<double>(activations[ lastIndex( activations , 2 )].size()));
for (j = 0; j < activations[ lastIndex( activations , 2 )].size(); j++)
{
dummyMatrix[neuron][j] = delta[neuron] * activations[ lastIndex( activations , 2 )][j];
}
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
derivativeWeights.push_back(dummyMatrix);
dummyMatrix.clear();
std::vector<double> sp;
sp.reserve(maxLayerSize);
std::vector<double> dummyVector;
dummyVector.reserve(maxLayerSize);
double dummyDouble = 0;
for(layer = 2 ; layer < numLayers ; layer++)
{
z = zs[ lastIndex( zs , layer )];
sp = sigmoid_prime(z);
for(j = 0 ; j < sizes[ lastIndex( weights , layer )] ; j++)
{
for (neuron = 0; neuron < sizes[ lastIndex( sizes , layer - 1 )]; neuron++)
{
dummyDouble += weights[ lastIndex( weights , layer - 1 )][neuron][j] * delta[neuron];
}
dummyVector.push_back(dummyDouble * sp[j]);
dummyDouble = 0;
}
delta = dummyVector;
dummyVector.clear();
derivativeBiases.push_back(delta);
for (neuron = 0; neuron < sizes[ lastIndex( sizes , layer )]; neuron++)
{
dummyMatrix.push_back(std::vector<double>(sizes[ lastIndex( sizes , layer + 1 )]));
for (j = 0; j < sizes[ lastIndex( sizes , layer + 1 )]; j++)
{
dummyMatrix[neuron][j] = activations[ lastIndex( activations , layer + 1 )][j] * delta[neuron];
}
}
derivativeWeights.push_back(dummyMatrix);
dummyMatrix.clear();
}
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
//both derivativeWeights and derivativeBiases are reversed. so let's reverse it.
std::reverse(derivativeWeights.begin(),derivativeWeights.end());
std::reverse(derivativeBiases.begin(),derivativeBiases.end());
std::cout << "teste "<< counter++ << std::endl;
system("PAUSE");
}
}
main.cpp
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "neuralnetwork.h"
#include <string>
void printAll(const std::vector<double> & v, const std::string & name)
{
int size = v.size();
std::cout << "\t" << name << ":\t";
for(int i = 0 ; i < size ; i++)
{
std::cout << v[i] << "\t";
}
std::cout << std::endl;
}
template<class T>
void printAll(const std::vector<T> & v, const std::string & name)
{
int size = v.size();
std::cout << name << ":" << std::endl;
for(int i = 0 ; i < size ; i++)
{
printAll(v[i], "\t" + ("[" + std::to_string(i)) + "]");
}
}
int main(int argc, char** argv )
{
nn::neuralnetwork n({2,4,3});
n.weights = {{},{{1,2},{3,4},{5,6},{7,8}} , {{9,8,7,6},{5,4,3,2},{1,2,3,4}}};
n.biases = {{},{1, 4, 6, 8} , {9, 2, 4}};
printAll(n.weights,"weights");
printAll(n.biases,"biases");
std::vector<std::vector<std::vector<double>>> derivativeWeights;
std::vector<std::vector<double>> derivativeBiases;
n.backPropagation({1,2},{1,2,3},derivativeWeights,derivativeBiases);
printAll(n.derivativeWeights,"derivativeWeights");
printAll(n.derivativeBiases,"derivativeBiases");
system("PAUSE");
return 0;
}
It looks like your problem is that you are only reserving memory for the vectors in the constructor, not allocating it.
The reserve method does not resize the vector, it is a performance optimization in cases where you know you will resize the vector in the future, but an optimizing compiler is free to ignore it.
This isn't causing a problem for 'weights' and 'biases' in this particular code becuase you are initializing them with vectors of the proper size, which does set them to the correct size. The problems are with derivativeWeights and derivativeBiases, where you reserve memory for the vectors, but they are never actually resized. This makes this memory potentially invalid if you try to dereference it. You could use resize instead of reserve, or push back the elements one by one, which will also resize the vector.
Another comment is that you don't have to use this-> for every member of the class, the 'this->' is assumed for members of the class if you don't use it.
I didn't found the problem, but I realised that, for this problem (artificial neural network), I can initialize each property of the class with each right sizes without loss of generality. So this is what I'm going to do.
I feel a little ashamed that I am not finding it... :/
I am trying to sort a vector of strings based on a custom comparator function -:
#include<bits/stdc++.h>
using namespace std;
template<typename T>
std::string ToString( const T& obj )
{
std::stringstream ss;
ss << obj;
return ss.str();
}
bool comp( string num1, string num2 )
{
bool swapped = false;
if ( num2.size() > num1.size() )
{
swap( num1, num2 );
swapped = true;
}
size_t i = 0;
size_t j = 0;
while ( i < num1.size() && j < num2.size() )
{
if ( num1[i] > num2[j] )
{
return !swapped;
}
else if ( num1[i] < num2[j] )
{
return swapped;
}
i++;
j++;
}
j = 0;
while ( i < num1.size() && j < num1.size() )
{
if ( num1[i] > num1[j] )
{
return !swapped;
}
else if ( num1[i] < num1[j] )
{
return swapped;
}
i++;
j++;
}
return true;
}
string largestNumber( vector<int>& nums )
{
vector<string> numsString( nums.size() );
for ( size_t i = 0; i < numsString.size(); i++ )
{
numsString[i] = ToString( nums[i] );
}
string result;
sort( numsString.begin(), numsString.end(), comp );
for ( size_t i = 0; i < numsString.size(); i++ )
{
result += numsString[i];
}
return result;
}
int main()
{
// Works okay if the size of vector is less than 17
vector<int> nums( 17, 0 );
largestNumber( nums );
}
I am using TDM-GCC 4.9.2 with -std=c++14 flag on Windows 7 64-bit.
I am getting a runtime error every time the size of the input vector is greater than 16.
What am I doing wrong ?
All elements in your vector<string> numsString end up having the same value 0 converted into string:
vector<int> nums( 17, 0 );
// ^
And, in your comp function, you are not checking if the numbers are equal. Add that as well at the top of the function:
if (num1 == num2) return false;
Hello I am looking for a way to write this C++ Code in a general way, so that if a want 20 columns I will not have to write 20 for loops:
for(int i=1; i<6; i++) {
for(int j=i; j<6; j++) {
for(int k=j; k<6; k++) {
for(int m=k; m<6; m++) {
std::cout << i << j << k << m << std::endl;
}
}
}
}
It is important that my numbers follow a >= Order.
I am very grateful for any help.
This recursive function should work:
#include <iostream>
bool inc( int *indexes, int limit, int n )
{
if( ++indexes[n] < limit )
return true;
if( n == 0 ) return false;
if( inc( indexes, limit, n-1 ) ) {
indexes[n] = indexes[n-1];
return true;
}
return false;
}
int main()
{
const size_t N=3;
int indexes[N];
for( size_t i = 0; i < N; ++i ) indexes[i] = 1;
do {
for( size_t i = 0; i < N; ++i ) std::cout << indexes[i] << ' ';
std::cout << std::endl;
} while( inc( indexes, 6, N-1 ) );
return 0;
}
live example
The design here is simple. We take a std::vector each containing a dimension count and a std::vector containing a current index at each dimension.
advance advances the current bundle of dimension indexes by amt (default 1).
void advance( std::vector<size_t>& indexes, std::vector<size_t> const& counts, size_t amt=1 ) {
if (indexes.size() < counts.size())
indexes.resize(counts.size());
for (size_t i = 0; i < counts.size(); ++i ) {
indexes[i]+=amt;
if (indexes[i] < counts[i])
return;
assert(counts[i]!=0);
amt = indexes[i]/counts[i];
indexes[i] = indexes[i]%counts[i];
}
// past the end, don't advance:
indexes = counts;
}
which gives us an advance function for generic n dimensional coordinates.
Next, a filter that tests the restriction you want:
bool vector_ascending( std::vector<size_t> const& v ) {
for (size_t i = 1; (i < v.size()); ++i) {
if (v[i-1] < v[i]) {
return false;
}
}
return true;
}
then a for loop that uses the above:
void print_a_lot( std::vector<size_t> counts ) {
for( std::vector<size_t> v(counts.size()); v < counts; advance(v,counts)) {
// check validity
if (!vector_ascending(v))
continue;
for (size_t x : v)
std::cout << (x+1);
std::cout << std::endl;
}
}
live example.
No recursion needed.
The downside to the above is that it generates 6^20 elements, and then filters. We don't want to make that many elements.
void advance( std::vector<size_t>& indexes, std::vector<size_t> const& counts, size_t amt=1 ) {
if (indexes.size() < counts.size())
indexes.resize(counts.size());
for (size_t i = 0; i < counts.size(); ++i ) {
indexes[i]+=amt;
if (indexes[i] < counts[i])
{
size_t min = indexes[i];
// enforce <= ordering:
for (size_t j = i+i; j < counts.size(); ++j) {
if (indexes[j]<min)
indexes[j]=min;
else
break; // other elements already follow <= transitively
}
assert(vector_ascending(indexes));
return;
}
assert(counts[i]!=0);
amt = indexes[i]/counts[i];
indexes[i] = indexes[i]%counts[i];
}
// past the end, don't advance:
indexes = counts;
}
which should do it without the vector_ascending check in the previous version. (I left the assert in to do testing).
This function works for me, but do not call it with 20 if you want it to finish.
#include <list>
#include <iostream>
std::list<std::list<int>> fun (std::list<std::list<int>> inputlist, int counter)
{
if(counter == 0)
{
return inputlist;
}
else
{
std::list<std::list<int>> outputlist;
for(std::list<int> oldlist : inputlist)
{
for(int i = 1; i<6; i++)
{
std::list<int> newlist = oldlist;
newlist.push_back(i);
outputlist.push_back(newlist);
}
}
return fun(outputlist, counter - 1);
}
}
int main()
{
std::list<int> somelist;
std::list<std::list<int>> listlist;
listlist.push_back(somelist);
std::list<std::list<int>> manynumbers = fun (listlist,5);
for (std::list<int> somenumbers : manynumbers)
{
for(int k : somenumbers)
{
std::cout<<k;
}
std::cout<<std::endl;
}
return 0;
}
Same with Processing (java) here :
void loopFunction(int targetLevel, int actualLevel, int min, int max, String prefix){
/*
targetLevel is the wanted level (20 in your case)
actualLevel starts from 1
min starts from 1
max is the max number displayed (6 in your case)
prefix starts from blank
see usage bellow (in setup function)
*/
for(int m=min; m<max; m++) {
if(targetLevel==actualLevel)
{
println(prefix+ " " + m);
}
else
{
loopFunction(targetLevel, actualLevel+1,m,max,prefix+ " " + m);
}
}
}
void setup(){
loopFunction(10,1,1,6,"");
}
Well, I am not the fastest in writing answer... when I started there was no other answer. Anyhow, here is my version:
#include <iostream>
#include <vector>
using namespace std;
class Multiindex {
public:
typedef std::vector<int> Index;
Multiindex(int dims,int size) :
dims(dims),size(size),index(Index(dims,0)){}
void next(){
int j=dims-1;
while (nextAt(j) && j >= 0){j--;}
}
Index index;
bool hasNext(){return !(index[0]==size-1);}
private:
bool nextAt(int j){
index[j] = index[j]+1;
bool overflow = (index[j]==size);
if (!overflow && j < dims-1){std::fill(index.begin() + j + 1,index.end(),index[j]);}
return overflow;
}
int dims;
int size;
};
int main() {
Multiindex m(4,6);
while (m.hasNext()){
cout << m.index[0] << m.index[1] << m.index[2] << m.index[3] << endl;
m.next();
}
cout << m.index[0] << m.index[1] << m.index[2] << m.index[3] << endl;
return 0;
}
I am working on a N dimensional grid.
I would like to generate nested loops depending on any dimension (2D, 3D, 4D, etc...).
How can I do that in an elegant and fast way ? Below a simple illustration of my problem.
I am writing in C++ but I think this kind of question can be useful for other languages.
I need to know the indices (i,j,k...) in my do stuff part.
Edit : lower_bound and upper_bound represents the indexes in the grid so they are always positive.
#include <vector>
int main()
{
// Dimension here is 3D
std::vector<size_t> lower_bound({4,2,1});
std::vector<size_t> upper_bound({16,47,9});
for (size_t i = lower_bound[0]; i < upper_bound[0]; i ++)
for (size_t j = lower_bound[1]; j < upper_bound[1]; j ++)
for (size_t k = lower_bound[2]; k < upper_bound[2]; k ++)
// for (size_t l = lower_bound[3]; l < upper_bound[3]; l ++)
// ...
{
// Do stuff such as
grid({i,j,k}) = 2 * i + 3 *j - 4 * k;
// where grid size is the total number of vertices
}
}
Following may help:
bool increment(
std::vector<int>& v,
const std::vector<int>& lower,
const std::vector<int>& upper)
{
assert(v.size() == lower.size());
assert(v.size() == upper.size());
for (auto i = v.size(); i-- != 0; ) {
++v[i];
if (v[i] != upper[i]) {
return true;
}
v[i] = lower[i];
}
return false;
}
And use it that way:
int main() {
const std::vector<int> lower_bound({4,2,1});
const std::vector<int> upper_bound({6,7,4});
std::vector<int> current = lower_bound;
do {
std::copy(current.begin(), current.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while (increment(current, lower_bound, upper_bound));
}
Live demo
An iterative approach could look like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> lower_bound({-4, -5, -6});
std::vector<int> upper_bound({ 6, 7, 4});
auto increase_counters = [&](std::vector<int> &c) {
for(std::size_t i = 0; i < c.size(); ++i) {
// This bit could be made to look prettier if the indices are counted the
// other way around. Not that it really matters.
int &ctr = c .rbegin()[i];
int top = upper_bound.rbegin()[i];
int bottom = lower_bound.rbegin()[i];
// count up the innermost counter
if(ctr + 1 < top) {
++ctr;
return;
}
// if it flows over the upper bound, wrap around and continue with
// the next.
ctr = bottom;
}
// end condition. If we end up here, loop's over.
c = upper_bound;
};
for(std::vector<int> counters = lower_bound; counters != upper_bound; increase_counters(counters)) {
for(int i : counters) {
std::cout << i << ", ";
}
std::cout << "\n";
}
}
...although whether this or a recursive approach is more elegant rather depends on the use case.
#include <iostream>
#include <vector>
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f)
{
std::vector<int> temp;
process(lower, upper, f, 0, temp);
}
template <typename Func>
void process(const std::vector<int>& lower, const std::vector<int>& upper, Func f,
int index, std::vector<int>& current)
{
if (index == lower.size())
{
f(current);
return;
}
for (int i = lower[index]; i < upper[index]; ++i)
{
current.push_back(i);
process(lower, upper, f, index + 1, current);
current.pop_back();
}
}
int main()
{
// Dimension here is 3D
std::vector<int> lower_bound({-4, -5, 6});
std::vector<int> upper_bound({6, 7, 4});
// Replace the lambda below with whatever code you want to process
// the resulting permutations.
process(lower_bound, upper_bound, [](const std::vector<int>& values)
{
for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
});
}
Probably some typos an whatnot, but I'd flatten the whole range.
This is based on the idea that the range can be described as
x_0 + d_0*(x_1+d_1*(x_2+d_2....)
So we can roll our own that way
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
//ranges
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
}
Edit: to be more generic:
template <typename D>
void multi_for(const std::vector<int>& lower_bound, const std::vector<int> upper_bound, D d) {
std::vector<int> ranges;
for (size_t i = 0; i < lower_bound.size(); i++) {
ranges.push_back(upper_bound[i]-lower_bound[i]);
}
size_t numel = std::accumulate(ranges.begin(), ranges.end(), std::multiplies<int,int>{});
for (int idx = 0; idx < numel; idx++) {
//if you don't need the actual indicies, you're done
//extract indexes
int idx2 = idx;
std::vector<int> indexes;
for (int i = 0; i < ranges.size(); i++) {
indexes.push_back(idx2%ranges[i]-lower_bound[i]);
idx2 = idx2/ranges[i];
}
//do stuff
d(idx,indexes);
}
}
//main
size_t* grid;//initialize to whateer
std::vector<int> lower_bound{-4,-5,6};
std::vector<int> upper_bound{6,7,4};
auto do_stuff = [grid](size_t idx, const std::vector<int> indexes) {
grid[idx] = 2 * indexes[0] + 3 *indexes[1] - 4 * indexes[2];
};
multi_for(lower_bound,upper_bound,do_stuff);
A recursive function may help you achieve what you want.
void Recursive( int comp )
{
if(comp == dimension)
{
// Do stuff
}
else
{
for (int e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
Some additions may be necessary in the function signature if you need to know the current indices (i,j,k,...) in your "Do Stuff" section.
This is a clean way to have access to these indices
void Recursive( int comp, int dimension )
{
static std::vector<int> indices;
if( comp == 0 ) // initialize indices
{
indices.clear();
indices.resize(dimension, 0);
}
if(comp == dimension -1)
{
// Do stuff
}
else
{
int& e = indices[comp];
for (e = lower_bound[comp]; e < upper_bound[comp]; e++)
Recursive(comp+1);
}
}
This is however not usable along multiple threads, due to the shared static vector.