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.
Related
Background:
The problem is from leetcode:
In an N by N square grid, each cell is either empty (0) or blocked
(1).
A clear path from top-left to bottom-right has length k if and
only if it is composed of cells C_1, C_2, ..., C_k such that:
Adjacent cells C_i and C_{i+1} are connected 8-directionally (ie., they are different and share an edge or corner)
C_1 is at location (0, 0) (ie. has value grid[0][0])
C_k is at location (N-1, N-1) (ie. has value grid[N-1][N-1])
If C_i is located at (r, c), then grid[r][c] is empty (ie. grid[r][c] == 0).
Return the length of the shortest such clear path from top-left to
bottom-right. If such a path does not exist, return -1.
Question:
I was quite certain that my algorithm was correct but for this test case:
[[0,1,0,0,0],[0,1,0,0,0],[0,0,0,0,1],[0,1,1,1,0],[0,1,0,0,0]]
I get 9, and the correct answer is 7. Is there something I am doing wrong in the code below?
Code:
class Solution {
public:
std::vector<std::vector<int>> dirs = {{0,1},{1,0},{-1,0},{0,-1},{1,1},{-1,-1},{1,-1},{-1,1}};
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
if(grid.empty())
return 0;
if(grid[0][0] == 1 || grid[grid.size()-1][grid.size()-1] == 1)
return -1;
int m = grid.size(), n = grid[0].size();
std::pair<int, int> start = {0,0};
std::pair<int, int> end = {m-1, n-1};
std::vector<std::vector<bool>> visited(m, std::vector<bool>(n, false));
std::priority_queue<std::pair<int,int>> q;
q.push(start);
visited[start.first][start.second] = true;
int count = 1;
while(!q.empty())
{
auto cur = q.top();
q.pop();
if(cur.first == end.first && cur.second == end.second)
return count;
for(auto dir : dirs)
{
int x = cur.first, y = cur.second;
if(isValid(grid, x + dir[0], y + dir[1]))
x += dir[0], y += dir[1];
if(!visited[x][y])
{
visited[x][y] = true;
q.push({x,y});
}
}
count++;
}
return -1;
}
bool isValid(std::vector<std::vector<int>>& grid, int i, int j)
{
if(i < 0 || i >= grid.size() || j < 0 || j >= grid[i].size() || grid[i][j] != 0)
return false;
return true;
}
};
This is not a problem for which you would use Dijkstra's algorithm. That algorithm is targetting weighted graphs, while the problem you are dealing with is unweighted. Moreover, the way you use a priority queue is wrong. A C++ priority queue will by default pop the element that is largest, but since you provide it coordinates, that means it will pop the element with the largest coordinates. This is obviously not what you need. In fact, you do not have anything to order nodes by, since this problem is about an unweighted graph.
Secondly, count is counting the total number of nodes you visit. That cannot be right, since you surely also visit nodes that are not on the shortest path that you eventually find.
This kind of problem is solved with a standard depth-first search. You can do it with two vectors (no need for stack, queue or deque, ...): the second vector gets populated with the unvisited neighbors of all the nodes in the first. Once that cycle is completed, you replace the first vector with the second, create a new second vector, and repeat... until you find the target node. The number of times you do this (outer) repetition corresponds to the length of the path.
Here is your shortestPathBinaryMatrix function with the necessary adaptations to make it work:
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
if(grid.empty())
return 0;
if(grid[0][0] == 1 || grid[grid.size()-1][grid.size()-1] == 1)
return -1;
int m = grid.size(), n = grid[0].size();
pair<int, int> start = {0,0};
pair<int, int> end = {m-1, n-1};
vector<vector<bool>> visited(m, vector<bool>(n, false));
// no priority queue needed: the graph is not weighted
vector<std::pair<int,int>> q;
q.push_back(start);
visited[start.first][start.second] = true;
int count = 1;
while(!q.empty())
{
// just iterate the vector and populate a new one
vector<std::pair<int,int>> q2;
for(auto const& cur: q) {
if(cur.first == end.first && cur.second == end.second)
return count;
for(auto dir : dirs)
{
int x = cur.first, y = cur.second;
if(isValid(grid, x + dir[0], y + dir[1]))
x += dir[0], y += dir[1];
if(!visited[x][y])
{
visited[x][y] = true;
q2.push_back({x,y});
}
}
}
count++;
q = q2; // prepare for next iteration
}
return -1;
}
I have the following recursive code which I want to change to iterative code. I am unsure of where to begin as the function is very complex with recursive calls at two locations. Any possible iterative implementations to the below function ?
int ncip(int dim, double R){
int n, r = (int)floor(R);
if (dim == 1)
return 1 + 2*r;
n = ncip(dim-1, R); // last coord 0
for (int i=1; i<=r; ++i){
n += 2*ncip(dim-1, sqrt(R*R - i*i) ); // last coord +- i
}
return n;
}
One common approach is to use a stack for the function calls. A simple implementation would be as follows and you can do some optimization on it
int ncip(int dim, double R){
typedef pair<int, double> data; // ties parameters into one unit
stack<data> s;
s.push(make_pair(dim,R)); // push the first set of parameters
int n = 0;
while(false == s.empty()) { // do the loop until stack is depleted
auto item = s.top(); // get the top item and pop it after
s.pop();
int r = static_cast<int>(floor(item.second));
if (item.first == 1) {
n += 1 + 2*r;
} else {
s.push(make_pair(item.first-1,item.second));
for (int i = 1; i <= r; ++i){
// since you have a multiplier 2 we push the same parameters twice
s.push(make_pair(item.first-1, sqrt(item.second*item.second - i*i) ));
s.push(make_pair(item.first-1, sqrt(item.second*item.second - i*i) ));
}
}
}
return n;
}
I have 2 List<long> (valueCov and valueWat) with long data typed values.
When a certain list element is not found I need to get the next
closer element with least different of the searching value.
For that:
I'm iterating through valueWat's elements(x) and if there is no exact
match for it in valueCov,then into that else part I need to find the
very closest element to "x".
I need a solution/method of finding closest next element from that
List.
Code Segment:
foreach (var y in sortedCov){
valueCov.Add(y.Value);
}
//Console.WriteLine("initial" + valueCov.Count);
foreach (var x in valueWat){
//foreach (var y in valueCov){
// var keys = new List<long>(y.Value);
int index = valueCov.BinarySearch(x);
int lower;
int upper;
if (index >= 0) {
lower = upper = index;
blockedWaterCoverMap.Add(x, valueCov[index]);
valueCov.RemoveAt(index);
}
else {
//foreach (var y in valueCov){
//subListCov = valueCov.FindAll((y < x + 7) && (y > x - 7));
// }
}
If I understood correctly You want a function like this:
int FindClosest(long data) {
int i = 0; // index of currently checked element from valueCov
int index = i; // returned index of the closest element
// here is current lowest distance to searched value:
long min = long.MaxValue;
// currently counted difference between input value
// and the next element of the list valueCov
long diff = 0;
foreach (var elem in valueCov) {
if ((diff = Math.Abs(elem - data)) <= min) {
min = diff;
index = i; // the searched index is updated
}
i++;
}
// random selection of the index from the closest
// found values
List<int> indices = new List<int>();
for (int n = 0; n < valueCov.Length; n++) {
if (valueCov[n] == valueCov[index])
indices.Add(n);
}
Random r = new Random();
index = indices[r.Next(indices.Count)];
return index;
}
Hope it helped.
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.
So I'm trying to make a basic program to learn the basics of C++, I'm generating 100 random numbers from 0 to 100 and storing them in a vector, I am then displaying the sum, mean, median, mode, high and low of the vector. I have everything else done except the mode which is where I get stuck. Here is the code I have so far.
int modeFunction()
{
numMode = 0;
count = 0;
for (int n = 0; n < 100; n++)
{
for (int y = 0; y < 100; y++)
{
if (numVector.at(y) == numVector.at(n))
{
numMode = numVector.at(y);
count++;
}
}
}
return numMode;
}
After that I get stuck because in my mind that should work but it doesn't. It just out puts the last number, usually 100. Any help would be much appreciated.
since all the values are between 0 and 100, you can find the mode efficiently with a histogram:
std::vector<int> histogram(101,0);
for( int i=0; i<100; ++i )
++histogram[ numVector[i] ];
return std::max_element( histogram.begin(), histogram.end() ) - histogram.begin();
Since mode is the number that occurs most frequent you shouldn't change numMode unless the new number's count is greater than numMode's count.
EDIT: To clarify, you need to keep a separate count for the current element and the current number that you think is the mode. Ideally, setting newMode to the first element is a good approach.
In addition, mode isn't necessary unique (i.e. "1 1 2 2"). You may want to keep that in mind if you care about that.
newMode = element[0]
modeCount = # of occurrence of newMode
for ( i-th element from [1 to end] ) {
tmpCount = # of occurrence of element[i]
if tmpCount > modeCount {
newMode = element[i]
modeCount = tmpCount
}
}
bmcnett's approach works great if number of elements are small enough. If you have large number of elements but the all element value are with in a small range using map/hashmap works well. Something like
typedef std::pair<int, int> mode_pair;
struct mode_predicate
{
bool operator()(mode_pair const& lhs, mode_pair const& rhs)
{
return lhs.second < rhs.second;
}
};
int modeFunction()
{
std::map<int, int> mode_map;
for (int n = 0; n < 100; n++)
mode_map[numVector[n]]++;
mode_predicate mp;
return std::max_element(mode_map.begin(), mode_map.end(), mp)->first;
}
Your algorithm is wrong - it outputs the last number in the array because that's all it can ever do. Every time the number at index y matches the number at index n you overwrite the results for the previous n. Since you're using the same loop conditions, y and n are always the same at at least one point in the nested loop for each possible n value - and you'll always end up with numMode being numVector.at(99).
You need to change your algorithm to save the count for each n index along the way (or at least which n index ended up with the greatest count), so that you can know at the end of the n loop which entry occured the most times.
Alternative solutions. Note: untested.
int mode1(const std::vector<int>& values)
{
int old_mode = 0;
int old_count = 0;
for(size_t n=0; n < values.size(); ++n)
{
int mode = values[n];
int count = std::count(values.begin()+n+1, values.end(), mode);
if(count > old_count)
{
old_mode = mode;
old_count = count;
}
}
return old_mode;
}
int mode2(const std::vector<int>& values)
{
return std::max_element(values.begin(), values.end(), [](int value)
{
return std::count(values.begin(), values.end(), value);
});
}
Mode means a number with highest frequency. The logic should be -
//Start of function
int mode = 0, globalCount = 0 ;
// Start of outer for loop
for i = 0 to length - 1
int localCount = 0
// Start of inner for loop
for j = 0 to length - 1
if vec[i] == vec[j]
++localCount
// End of Inner for loop
if ( localCount > globalCount )
globalCount = localCount
mode = vec[i]
// End of outer for loop
if globalCount > 1 // This should be checked whether vec has repetitions at all
return mode
else
return 0
// End of function
int number = array_list[0];
int mode = number;
int count = 1;
int countMode = 1;
for (int i=1; i<size_of_list; i++)
{
if (array_list[i] == number)
{ // count occurrences of the current number
count++;
if (count > countMode)
{
countMode = count; // mode is the biggest ocurrences
mode = number;
}
}
else
{ // now this is a different number
if (count > countMode)
{
countMode = count; // mode is the biggest ocurrences
mode = number;
}
count = 1; // reset count for the new number
number = array_list[i];
}
}