I try to write an application which will have a function called 'special_reorder' and is the core of my application. Perhaps it's the most complicated function in my app. This function is a class member of a class similar to std::map, however it doesn't automatically sort contained elements. After function call such class object should be recreated the way that map elements are put into next diffrent order. The thing I want to accomplish is that every next function call should make next unique elements sequence diffrent then any previous to appear in this object until the function has been called n times where n is a number of all diffrent combinations. I'm weak in maths, but I know that number of permutations is x! = n where x is a number of elements in the map. I want this function to be not so slow. I think that keys should be mainly utilized for reordering because they are of type short in the class instance in my app.
Here is a class code:
#ifndef MY_MAP_H
#define MY_MAP_H
template<typename A, typename B>
class my_map
{
private:
int count, len ;
A *keys ;
B *values ;
void resizeContent()
{
A *new_k = new A[len * 2] ;
B *new_val = new B[len * 2] ;
for(int aa = 0; aa < len; aa++)
{
new_k[aa] = keys[aa] ;
new_val[aa] = values[aa] ;
delete[] keys ;
delete[] values ;
keys = new_k ;
values = new_val ;
len *= 2 ;
}
}
public:
my_map()
{
count = 0 ;
len = 10 ;
keys = new A[len] ;
values = new B[len] ;
}
~my_map()
{
delete[] keys ;
delete[] values ;
}
void special_reorder()
{
}
int size()
{
return count ;
}
void replace(int first, int second)
{
if(first >= count || second >= count || first < 0 || second < 0)
return ;
A k_tmp = keys[first] ;
B v_tmp = values[first] ;
keys[first] = keys[second] ;
values[first] = values[second] ;
keys[second] = k_tmp ;
values[second] = v_tmp ;
}
void insert(A key, B val)
{
if(count == len)
resizeContent() ;
keys[count] = key ;
values[count++] = val ;
}
B& operator[] (const int index)
{
return values[index] ;
}
} ;
#endif
Please help me implement that function or give me some good idea of how to do this.
Since you are using c++ consider
std::next_permutation
as a solution to your issue.
Related
I'm trying to implement a function using a map in a map like that :
typedef std::map<int, float> inner_map;
typedef std::map<int, inner_map> outer_map;
I'm filling the map this way. The idea is the first map contains a int key and an other map which contains another key and a float. If the pair I obtain is known, I increment the value otherwise I fill the map.
for (int y = 2; y < imgSize.y - 2; y++){
for (int x = 2; x < imgSize.x - 2; x++) {
thisPos = x + y*imgSize.x ;
{SOME CODE}
lj = labelMap[thisPos] ;
if (condition) {
// get the 2 label
li = pro_label_mod[thisPos] ;
// look if it lj is in the map
is_lj = pi_matrix.count(lj) ;
// this lj has already been observed
if (is_lj == 1) {
is_li = pi_matrix[lj].count(li);
// this pair is known -> I increment
if (is_li==1) {
pi_matrix[lj][li] += 1.0f ;
}
else {
pi_matrix.at(lj).insert(pi_matrix[lj].end(), std::make_pair(li, 1.0f)) ;
}
}
else {
inner_map inter ; inter.insert(std::make_pair(li, 1.0f)) ;
pi_matrix.emplace(lj, inter) ;
}
}
numb_lj[lj] += 1.0f ;
}
}
And then, I would like to iterate throught the map in my code. I did that with iterators such as :
std::vector<std::pair<int,float> > max_pi(size_lj) ;
float maxValue, thisValue ; int label_max ;
for (outer_map::iterator it_lj = pi_matrix.begin(), it_lj_end = pi_matrix.end(); it_lj != it_lj_end; ++it_lj) {
maxValue = 0.0f ;
label_max = 0 ;
inner_map &innerMap = it_lj->second;
for(inner_map::iterator it_li = innerMap.begin(), it_li_end = innerMap.end(); it_li != it_li_end; ++it_li) {
thisValue = it_li->second / numb_lj[it_lj->first] ;
if (thisValue >= maxValue) {
maxValue = thisValue ;
label_max = it_li->first ;
}
}
max_pi[it_lj->first] = std::make_pair(label_max, maxValue) ;
i+=1;
}
However, i'm getting a segmentation fault at the lines of the for loop (either the first one or the second one). BUT ! Not every time. I'm calling this function at each frame and I can have 5 calls without a BAD_ACCESS and suddenly, it crashes.. Sometimes after the first call and then the 10th.
I really can't see why and how to solve it..
Thank you in advance for any clues/comments which could be helpful !
It appears that your design of a nested map is causing all sorts of unnecessary complications. More natural appears a single map with a pair<int,int> as key:
using key_type = std::pair<int,int>;
using map_type = std::map<key_type,float>;
void add_to_map(map_type&map, key_type const&key)
{
map[key] += 1.f; // also works as desired if map.count(key)==0
}
// find key and value of first element with maximum value
map_type::value_type find_max(map_type const&map)
{
auto max = map.begin();
for(auto it=max; it!=map.end(); ++it)
if(it.second > max.second)
max = it;
return *max;
}
no need to juggle with map::count or map::iterator.
I'm practicing in programming and I generating all combinations in c++. I know how to generate all combination in
certain length
My result is something like that
A A A
A A B
A A C
A B A
A B B
A B C
A C A
A C B
A C C
B A A
.....
and my problem is, I don't know, how to generate all combinations with unknown length. For example I want word length = 5 and program will generate all combination in exactly length 5. How to do it?
A A A A A
A A A A B
A A A A C
A A A B A
.........
(Sorry for my english)
See the link Print all permutations with repetition of characters
The below recursive function in the page, can create last+1 length permutations.
/* The main function that recursively prints all repeated
permutations of the given string. It uses data[] to store all
permutations one by one */
void allLexicographicRecur (char *str, char* data, int last, int index)
{
int i, len = strlen(str);
// One by one fix all characters at the given index and recur for
// the/ subsequent indexes
for ( i=0; i<len; i++ )
{
// Fix the ith character at index and if this is not the last
// index then recursively call for higher indexes
data[index] = str[i] ;
// If this is the last index then print the string stored in
// data[]
if (index == last)
printf("%s\n", data);
else // Recur for higher indexes
allLexicographicRecur (str, data, last, index+1);
}
}
I think this can serve your purpose.
Call allLexicographicRecur with the required (length-1) value for the 'last' parameter.
This is actually nothing more than counting.
If you have the letters A, B, and C, you are counting in base 3.
A is 0, B is 1 and C is 2.
Quick and dirty:
#include <string>
#include <iostream>
int main()
{
for(int i = 0; i < 100; i++) {
const int base = 3;
const char zero_char = 'A';
const size_t length = 5;
std::string out;
for(int n = i; n > 0; ) {
int d = n%base;
out = static_cast<char>(zero_char + d) + out;
n /= base;
}
while(out.length() < length) out = zero_char + out;
std::cout << out << '\n';
}
}
see it live
The possible combinations are baselength, so if you want all combinations for A, B, C with 5 digits, change the limit of the first for loop to 35 ( = 243):
for(int i = 0; i < 243; i++)
You may use something like:
bool increase(const std::string& s, 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] >= s.size()) {
it[index] = 0;
} else {
return true;
}
}
return false;
}
void do_job(const std::string& s,
const std::vector<std::size_t>& it)
{
for (std::size_t i = 0; i != it.size(); ++i) {
std::cout << s[it[i]] << " ";
}
std::cout << std::endl;
}
void cartesian_product(const std::string& s, std::size_t n)
{
std::vector<std::size_t> it(n, 0u);
do {
do_job(s, it);
} while (increase(s, it));
}
Demo
I have an array....I need to check whether all its elements are equal to one and pass this as a while condition. That is...my code should be executed till all the members of the array becomes one.
My code goes like this:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int ele[10];int crd[10];int dist[10] ; int fid[10] ;
int a; int i ; int j;int k = 0,l=0 ; // a is number of villages
cin>> a ;
for(i = 0;i<a;i++){
cin>>ele[i] ;
}
for(i=0;i<a;i++){
cin>>crd[i] ;
}
for(k = 0;k<a;k++){
while(ele[k]= 1){
for(i=0;i<a;i++){
if(ele[i] == 0 && ele[i+1] == 1 ){
dist[l] = std::abs(crd[i+1] - crd[i]) ;
fid[l] = i ;
l++ ;
}else if(ele[i]==1 && ele[i+1] == 0 ){
dist[l] = std::abs(crd[i+1] - crd[i]) ;
fid[l] = i + 1;
l++ ;
// ele[i+1] = 1
}
}
for(i=0;i<l;i++){
cout<<fid[i] ;
}
for(i=0;i<l;i++){
cout<<dist[i]<<" " ;
}
for(i=0;i<l;i++){
if(dist[0]>dist[i]){
swap(dist[0],dist[i]) ;
ele[fid[i]] = 1 ;
//swap()
}else if(l=1){
ele[fid[0]] = 1 ;
}
}
for(i=0;i<a;i++){
cout<<ele[i]<<endl ;
}
cout<<dist[0] ;
}
}
}
The error lies in this statement.
while(ele[k]= 1)
It will always return true as ele[k] is assigned the value 1 which is not 0 leading to an infinite loop. Also there is no need to include so many for loops and while loops. Your condition should be something like:
k=0;
while(k < a)
{
ele[k] = 1;
k++;
}
And there is no need of any for loops at all. Your question does not match with the code you have written. If indeed, you mean to simply replace all values of ele[k] with 1, the above code I have provided should suffice and there would be no use of any other statements in your code. Primarily I believe you should study up while loops and understand how they work essentially. Also, no matter what code the error is in, you should never post unformatted code.
FYI: I am new to programming.
I have an arraysize of 10 and the sentinel value is 0.
My original array is [1 2 3] ( user input) but my reverse is [0 0 0 0 0 0 0 3 2 1].
I need help to make my reverse array [3 2 1].
Here is my code:
int temp;
for (int i = 0; i < arraysize/2; i++)
{
temp = array[arraysize-1-i];
array[arraysize - i - 1] = array[i];
array[i] = temp;
}
cout << "The reverse array: ";
for (int i = 0; i < arraysize; i++)
cout << array[i]<< ' ';
cout << endl;
Just use the standard library algorithms
auto end = std::find(std::begin(array),std::end(array),0);
std::reverse(std::begin(array),end);
//And if you only want to print the non-zero values:
size_t effectiveArraySize = end - std::begin(array);
If the fixed size array is not part of your requirement, you should put your user data in a vector that automaticaly grows as large as you need, instead of using an array that might turn out to be too small:
std::vector<int> v;
while(true) {
int t;
cin >> t;
if (t == 0) {
break;
}
v.push_back(t);
}
std::reverse(v.begin(),v.end());
That way, you don't have any sentinel values in your array / vector to begin with.
Note: Using the respective functions from the STL (std::reverse and std::find) is better, I was just guessing that you are bound to implement this on your own.
Step one: Write a proper reverse function. One that takes (a pointer to) the beginning as well as (a pointer to) the end of the range that should be reversed.
Step two: Write a function to find (the first position of) your sentinel in an array (given via beginning and end, again)
Step three: Connect the two: Reverse from the beginning to the position of your sentinel.
Example without templates:
void reverse(int * from, int * to) {
while ((to - from) > 1) {
--to;
int temp = *from;
*from = *to;
*to = temp;
++from;
}
}
int const * find(int const * from,
int const * const to,
int const value) {
while ((from != to) && (*from != value)) {
++from;
}
return from;
}
void reverse_until (int * const from,
int * const to,
int const sentinel) {
int const * const position_sentinel = find(from, to, sentinel);
reverse(from, from + (position_sentinel - from));
// return the sentinel position from this function
// if you want only the reversed part
}
Tested with:
int main() {
int test[10];
for (size_t i = 0; i < 10; ++i) {
test [i] = i + 1;
}
reverse_until (test, test + 10, 6);
copy(test, test + 10, ostream_iterator<int>{cout, " "});
return 0;
}
(live here)
You need to find the actual length of the array, before performing the reverse operation, and then use that length for all further operations.
Like this:
int actualArraySize = 0;
while(actualArraySize < arraysize && array[actualArraySize]!=0)
{
actualArraySize++;
}
int temp;
for (int i = 0; i < actualArraySize/2; i++)
{
temp = array[actualArraySize-1-i];
array[actualArraySize - i - 1] = array[i];
array[i] = temp;
}
cout << "The reverse array: ";
for (int i = 0; i < actualArraySize; i++)
cout << array[i]<< ' ';
cout << endl;
Note that, actualArraySize can be less than or equal to arraysize, but, not more than it, because of the condition in while(actualArraySize < arraysize && array[actualArraySize]!=0), which means that stop when either a 0 is found or the size of the array is reached.
I´m new to C++ and have researched about arrays, pointers and so on, but I can´t figure out how to make this work. Hope you can help!
I need an two dimensional array frases that contains 3 x 2 objects MGFrase. They will be retrieved by a method getFrase so I can use MGFrase´s method setTone to change it´s property altura, which is an array of ints.
In the code below, I expected to change alturas[0] of frases[1, 0] but it keeps changing frases[0, 0].
Is this the right way to create the array? Is there a problem in the methods?
If my question is not clear enough or isn´t on par with the forum´s rules please let me know so I can edit it, I´m new here.
Thank you all in advance!
MGComposition::MGComposition(){
MGFrases** frases;
frases = new MGFrase* [3];
for( int n = 0 ; n < 3 ; n ++ ){
frases [n] = new MGFrase[2];
}
for( int n = 0 ; n < 3 ; n ++ ){
frases[n, 0] = new MGFrase();
frases[n, 1] = new MGFrase();
}
}
MGFrase* MGComposition::getFrase( int channel , int numFrase ){
return frases[ channel, numFrase] ;
}
void MGComposition::log(){
cout << "- Composition --\n";
for( int n = 0 ; n < 3 ; n ++ ){
frases[ n , 0]->log();
frases[ n , 1]->log();
}
}
MGFrase::MGFrase(){
int alturas [10];
}
void MGFrase::setTone(int tone, int index) {
alturas[index] = tone;
}
void MGFrase::log() {
cout << "\n\nLog de MGFrase\n";
cout << "\nAlturas \n";
for (int nota = 0; nota < numNotes; nota++) {
cout << alturas [nota] << ", ";
}
}
MGGenerator::MGGenerator() {
MGComposition* composition;
composition = theComposition;
MGFrase* fraseDoBaixo;
fraseDoBaixo = composition->getFrase(1, 0);
fraseDoBaixo->setTone(8, 0);
composition->log();
}
PS: This is how it is now with the solution:
MGFrase*** frases;
frases = new MGFrase** [3];
for( int n = 0 ; n < 3 ; n ++ ){
frases [n] = new MGFrase*[2];
}
for( int n = 0 ; n < 3 ; n ++ ){
frases[n][0] = new MGFrase();
frases[n][1] = new MGFrase();
}
An array of pointers with two dimensions implemented as a jagged array needs three asterisks: one asterisk per dimension, plus an asterisk for it being an array of pointers. A pair of square brackets could work to replace one asterisk. Your declaration new MGFrase* [3] makes an array of three pointers, hence it is missing one asterisk.
This whole asterisk counting business quickly gets rather annoying. Fortunately, you can avoid all of it by using C++ containers, such as std::array<T,N> or std::vector<T> in place of arrays of pointers. Here is how you could make it work:
std::array<std::array<std::unique_ptr<MGFrase>,2>,3> frases;
MGComposition::MGComposition(){
for( int n = 0 ; n < 3 ; n ++ ){
frases[n][0] = make_unique<MGFrase>(new MGFrase());
frases[n][1] = make_unique<MGFrase>(new MGFrase());
}
}
This approach uses a fixed-size 2×3 array of std::unique_ptr<MGFrase> objects, which takes care of memory cleanup for you. Now your code would not create a memory leak due to a missing destructor.
You are not properly indexing your arrays. Each dimension needs to have its own square brackets []. So for a two dimensional array you would access it as:
foo[row][col]
What you have:
frases[n, 0] = new MGFrase();
Is using the comma operator which ignores the left hand side and uses the right hand side for the index.
With that you can fix you function as:
MGComposition::MGComposition(){
frases = new MGFrase* [3];
for( int n = 0 ; n < 3 ; n ++ ){
frases [n] = new MGFrase[2];
}
for( int n = 0 ; n < 3 ; n ++ ){
frases[n][0] = new MGFrase();
frases[n][1] = new MGFrase();
}
}
MGFrase* MGComposition::getFrase( int channel , int numFrase ){
return frases[ channel][numFrase] ;
}
void MGComposition::log(){
cout << "- Composition --\n";
for( int n = 0 ; n < 3 ; n ++ ){
frases[n][0]->log();
frases[n][1]->log();
}
}
MGFrase::MGFrase(){
int alturas [10];
}
void MGFrase::setTone(int tone, int index) {
alturas[index] = tone;
}
MGGenerator::MGGenerator( MGComposition* theComposition ) {
MGComposition* composition;
composition = theComposition;
MGFrase* fraseDoBaixo;
fraseDoBaixo = composition->getFrase(1, 0);
fraseDoBaixo->setTone(8, 0);
}