I can't know why this error happened in my code.(Actually, this is my first time to use std:: list.) When I use it++ it makes error 'list iterator outside of range', and when I use ++it it makes error 'list iterator not incrementable'. Please help me!
#include<stdio.h>
#include<stdlib.h>
#include<list>
#include<stack>
using namespace std;
typedef struct tag_vpos { int data; list <int>::iterator pos; } vpos;
list<int> row[100];
stack<vpos> save[100];
int col[100][100], n, r, rowsize[100];
//int row[100][100];
long long cnt;
void arr(int x, int y) {
list<int>::iterator it = row[y].begin();
while (it != row[y].end()) {
if (!col[x][*it]) {
vpos t = { *it, it }, temp;
int val = *it;
col[x][val] = 1;
row[y].erase(it++);
save[y].push(t);
if (x == r - 1) { // if x th column is the end of right
if (y == r - 1) cnt++; // if y th column is the bottom, count this
else arr(0, y + 1);// else fill next row, first column
}
else { arr(x + 1, y); } // else fill next right square
temp = save[y].top();
row[y].insert(temp.pos, temp.data);
save[y].pop();
col[x][temp.data] = 0;
}
else it++;
}
return;
}
void main() {
printf("Input n, r (paint r x r field with n colors, same color cannot be used in same column and row) \n: ");
scanf("%d %d", &n, &r);
for (int i = 0; i < r; i++) {
for (int j = 0; j < n; j++) row[i].push_back(j);
rowsize[i] = n;
}
printf("start\n");
arr(0, 0);
printf("There are %ld ways to paint.\n", cnt);
}
To remove elements from STL container while iterating you combine the container's erase function (they all have this) with the remove or remove_if algorithm. Otherwise your invalidating your iterators underneath yourself.
void delete_elements(std::list &list)
{
list.erase(
std::remove_if(
list.begin(),
list.end(),
[](char x){return std::isspace(x);}),
list.end() );
}
Related
I was trying to practice C++ iterators by defining the very common mergesort algorithm when I encountered inconsistent program behavior. My question is NOT how to implement mergesort (which I both know and also realize has many example answers), but rather when creating recursive vectors using iterators that I receive inconsistent final results.
I'm aware that I could solve the issue by copying the values into L and R arrays through a for loop, but I would like to understand why using iterators is not working. This is running on CLION with C++ 14. This post Best way to extract a subvector from a vector? did not answer my question, as I'm creating vector similar to methods prescribed.
void merge2(vector<int> &arr, int l, int m, int r)
{
vector<int> L{arr.begin()+l, arr.begin()+m+1};
vector<int> R{arr.begin()+m+1,arr.begin()+r+1};
int i = 0, j = 0, k = l;
int n1 = m - l + 1;
int n2 = r - m;
while (i < (n1) && j < (n2)){
if (L[i]<=R[i]){ //R[i] is replaced by R[j]
arr[k] = L[i++];
}
else {
arr[k] = R[j++];
}
k++;
}
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
while(j < n2){
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void merge2Sort(vector<int> &arr, int l, int r)
{
if (l < r)
{
// Same as (l+r)/2, but avoids overflow for
// large l and h
// int m = (l+r-l)/2;
// int m = l+(r-l)/2;
int m = (l+r)/2;
// Sort first and second halves
merge2Sort(arr, l, m);
merge2Sort(arr, m+1, r);
merge2(arr, l, m, r);
}
}
int main(int argc, char **argv){
vector<int> arr = {12, 11, 13, 5, 6, 7};
merge2Sort(arr, 0, arr.size()-1);
for(auto i = arr.begin(); i != arr.end(); i++){
cout << *i << " ";
}
return 0;
}
Sometimes I receive the correct answer 5 6 7 11 12 13 and other times the incorrect answer 5 6 7 11 13 12. The answer should not vary by attempt.
Correct Answer to reflect answer and comments. Answer corrects indexing error and relies upon iterators. Also noting from comments that vectors when initialized from iterators should use () and not {}.
template <class It>
void merge(It left, It middle, It right)
{
// Beeing generic, you need to retrieve the type.
using value_type = typename std::iterator_traits<It>::value_type;
// You can copy only the first half
std::vector<value_type> left_side_copy(left, middle);
It L = left_side_copy.begin();
It R = middle;
while (L != left_side_copy.end() && R != right)
{
if ( *L <= *R )
{
*left = *L;
++L;
}
else {
*left = *R;
++R;
}
++left;
}
// Copy only the leftovers, if there are any
std::copy(L, left_side_copy.end(), left);
}
template <class It>
void merge_sort(It left, It right)
{
if (auto dist = std::distance(left, right); dist > 1)
{
It middle = left + dist / 2;
merge_sort(left, middle);
merge_sort(middle, right);
merge(left, middle, right);
}
}
int main(void)
{
std::vector<int> arr {
5, 12, 11, 13, 5, 4, 7, 13, 6
};
merge_sort(arr.begin(), arr.end());
for(auto const &i : arr) {
std::cout << ' ' << i;
}
std::cout << '\n';
}
You're using index i instead of j in vector R. Replace R[i] with R[j] see below
void merge2(vector<int> &arr, int l, int m, int r)
{
//..
while (i < (n1) && j < (n2)){
if (L[i]<=R[j]){ //R[i] is replaced by R[j]
arr[k] = L[i++];
}
else {
arr[k] = R[j++];
}
k++;
}
//...
}
The line int m = l+(r-l)/2; is incorrect. You probably meant int m = (l+r-l)/2; although I think it would be better to keep int m = (l+r)/2;.
I am learning to implement a mergesort algorithm for use to count inversions. Here is my current implementation of mergesort. However it is not working as it does not return a sorted array. Will anyone be able to tell me what is being done wrongly in this code which I have written? It should sort the array v which is input into the function.
void mergeCountInversion(vector<int> v, int l, int r)
{
if (l >= r)
{
return;
}
int m = (l + r)/2;
//call merge sort to return two sorted arrays
mergeCountInversion(v, l, m);
mergeCountInversion(v, m+1, r);
int left = l;
int right = m+1;
std::vector<int> vtemp ;
//merge and sort the two sorted array, storing the sorted array in vtemp
for (int k = l; k <= r; ++k){
if (left >= m+1)
{
vtemp.push_back(v[right]);
right++;
}
else if (right > r)
{
vtemp.push_back(v[left]);
left++;
}
else
{
if (v[left] <= v[right])
{
vtemp.push_back(v[left]);
left++;
}
else{
vtemp.push_back(v[right]);
right++;
count += m + 1 - left;
}
}
}
//replace v with the sorted array vtemp
for (int i = 0; i < vtemp.size(); ++i)
{
v[l+i] = vtemp[i];
}
}
There are several issues in your code.
You are passing the vector by value, but you should pass it by refernce.
If you declare the function as void You can't return 0;, just return;.
When you create vtemp you should know exactly its size: r - l. So you can reserve memory for it and you don't need to push_back.
You have to pass count to the function too.
Your function can be:
void mergeCountInversion(vector<int> & v, int l, int r, int & count) {
if (l >= r) return;
int m = (l + r)/2;
//call merge sort to return two sorted arrays
mergeCountInversion(v, l, m, count);
mergeCountInversion(v, m+1, r, count);
int left = l;
int right = m+1;
std::vector<int> vtemp(r-l);
//merge and sort the two sorted array, storing the sorted array in vtemp
for (int k = l; k <= r; ++k) {
if (left >= m+1) {
vtemp[k] = v[right];
right++;
}
else if (right > r) {
vtemp[k] = v[left];
left++;
}
else {
if (v[left] <= v[right]) {
vtemp[k] = v[left];
left++;
}
else {
vtemp[k] = v[right];
right++;
count += m + 1 - left;
}
}
}
//replace v with the sorted array vtemp
for (int i = 0; i < vtemp.size(); ++i)
v[l+i] = vtemp[i];
}
You defined
void mergeCountInversion(vector<int> v, int l, int r)
then you first call mergeCountInversion recursively, and modify v after the calls returned.
The problem is that the changes to v made in the recursive calls will never be seen, because v is passed by value.
Try to pass v by reference:
void mergeCountInversion(vector<int>& v, int l, int r)
such that all calls work on the same copy of v.
I have written an implementation of Donald Knuth's Algorithm X for solving exact cover problems and applied it to Sudoku for the purpose of solving Project Euler Problem 96. My code is a translation from Python into C++ of Ali Assaf's implementation of the same algorithm.
My version is solves most of the grids contained in this text file, but it hangs for Grid 06.
Grid 06
100920000
524010000
000000070
050008102
000000000
402700090
060000000
000030945
000071006
I have used a bunch of exploratory cout statements, but I have not been able to figure out what is causing the program to hang.
Please let me know if you need more information to be able to understand my code.
#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution);
void select_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r);
void deselect_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r);
// square boxes only
static const int BOX_SIZE = 3; // standard sudoku grid
static const int SIZE = BOX_SIZE*BOX_SIZE;
int main() {
int top_left_sum = 0;
// initialize the sparse matrix representation of the sudoku problem
map<int, set<int>> C; // constraints/columns
for (int i = 0; i < 4*SIZE*SIZE; i++) {
C[i] = set<int>();
}
map<int, array<int, 4>> R; // subsets/rows
for (int i = 0; i < SIZE*SIZE*SIZE; i++) {
// i is the subset index and encodes location and number on grid
int index = i/SIZE;
int row = i/(SIZE*SIZE);
int column = (i/SIZE) % SIZE;
int box = BOX_SIZE*(row/BOX_SIZE) + column/BOX_SIZE;
int value = i % SIZE;
// there are 4 constaints satisfied by each number placement
array<int, 4> subset;
// insert the keys of constraints that subset satisfies
subset[0] = (index); // row-column
subset[1] = (SIZE*SIZE + SIZE*row + value); // row-number
subset[2] = (2*SIZE*SIZE + SIZE*column + value); // column-number
subset[3] = (3*SIZE*SIZE + SIZE*box + value); // box-number
R.insert(pair<int, array<int, 4>>(i, subset));
for (auto c : subset) {
C[c].insert(i);
}
}
ifstream ifs("../sudoku.txt");
string line;
while (getline(ifs, line)) {
if (line[0] == 'G') {
map<int, set<int>> X = C;
map<int, array<int, 4>> Y = R;
vector<int> solution;
for (int i = 0; i < SIZE; i++) {
getline(ifs, line);
for (int j = 0; j < SIZE; j++) {
if (line[j] != '0') {
int r = SIZE*SIZE*i + SIZE*j + line[j] - '1';
solution.push_back(r);
vector<set<int>> cs;
select_row(&X, &Y, &cs, r);
}
}
}
solve(&X, &Y, &solution);
sort(solution.begin(), solution.end());
top_left_sum += 100*(solution[0] % SIZE + 1)
+ 10*(solution[1] % SIZE + 1)
+ solution[2] % SIZE + 1;
// display solution
for (size_t i = 0; i < solution.size(); i++) {
if (i % 9 == 0) cout << endl;
cout << solution[i] % 9 + 1 << ' ';
} cout << endl << endl;
}
}
ifs.close();
cout << top_left_sum << endl;
return 0;
}
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution) {
if ((*X).empty()) return true;
// find the column with the minimum number of nonzero elements
map<int, set<int>>::iterator c_min = (*X).begin();
for (map<int, set<int>>::iterator c = ++(*X).begin();
c != (*X).end(); ++c) {
if ((*c).second.size() < (*c_min).second.size()) {
c_min = c;
}
}
// for each row pointed to by c_min, call solve recursively
for (auto r : (*c_min).second) {
(*solution).push_back(r);
vector<set<int>> cs;
select_row(X, Y, &cs, r);
if (solve(X, Y, solution)) return true;
deselect_row(X, Y, &cs, r);
(*solution).pop_back();
}
return false;
}
void select_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r) {
for (auto j : (*Y)[r]) {
for (auto i : (*X)[j]) {
for (auto k : (*Y)[i]) {
if (k != j) (*X)[k].erase(i);
}
}
(*cs).push_back((*X)[j]);
(*X).erase(j);
}
return;
}
void deselect_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r) {
for (array<int, 4>::reverse_iterator j = (*Y)[r].rbegin();
j != (*Y)[r].rend(); ++j) {
(*X)[*j] = (*cs).back();
(*cs).pop_back();
for (auto i : (*X)[*j]) {
for (auto k : (*Y)[i]) {
if (k != *j) (*X)[k].insert(i);
}
}
}
return;
}
As PaulMackenzie pointed out, the problem with my code was that I was erasing objects which still had pointers to them initialized, specifically the integers inside the set (*c_min).second that I iterate over in my solve function.
I fixed this by making a copy of (*c_min).second and iterating over the copy.
The fixed version of the solve function looks like this:
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution) {
if ((*X).empty()) return true;
// find the column with the minimum number of nonzero elements
map<int, set<int>>::iterator c_min = (*X).begin();
for (map<int, set<int>>::iterator c = ++(*X).begin();
c != (*X).end(); ++c) {
if ((*c).second.size() < (*c_min).second.size()) {
c_min = c;
}
}
set<int> c = (*c_min).second; // ADDED LINE
// for each row pointed to by c_min, call solve recursively
for (auto r : c) { // CHANGED LINE
(*solution).push_back(r);
vector<set<int>> cs;
select_row(X, Y, &cs, r);
if (solve(X, Y, solution)) return true;
deselect_row(X, Y, &cs, r);
(*solution).pop_back();
}
return false;
}
how to find of what vertices is made cycle in undirected graph if there is only one cycle in graph?
I have code for finding cycle in graph, but right now I need code that will find of what vertices cycle is made.
Here is code(in C++) for finding cycle:
bool dfs(int x)
{
state[x] = 1;
for(int j = 0; j < ls[x].size(); j++)
{
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
t = 0; // Graph contains cycle.
return t;
}
if(state[ls[x][j]] == 0)
{
parent[ls[x][j]] = x;
dfs(ls[x][j]);
}
}
}
void detect_cycle()
{
memset(state, 0, sizeof state);
memset(parent, 0, sizeof parent);
for(int i = 1; i <= n; i++)
if(state[i] == false)
dfs(i);
}
Thanks.
Here is the final code. Thanks guys.
bool dfs(int x)
{
state[x] = 1;
for(int j = 0; j < ls[x].size(); j++)
{
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
if(t)
{
printf("Cycle entry: %d\n", ls[x][j]);
printf("Cycle contains: %d, %d ", ls[x][j], x);
int cycleNode = parent[x];
while(cycleNode != ls[x][j])
{
printf("%d ", cycleNode);
cycleNode = parent[cycleNode];
}
}
t = 0;
return t;
}
if(state[ls[x][j]] == 0)
{
parent[ls[x][j]] = x;
dfs(ls[x][j]);
}
}
}
A naive method - just throw away any node with degree 1, until all nodes have degree 2. This is the cycle in the graph.
If i'm right, then parent[] is an array (parent[i] is the number of the node that you vivted straight before you visited the i-th one).
Then you know that if the graph contains the cycle (you visit a node you have already visited), you know at least one node in the cycle (suppose its the k-th one). In this case, the parent[k] node also belongs to the cycle, and parent[parent[k]], and so on.
So, we get the next code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
vector <int> state;
vector <vector <int> > ls; //graph
vector <int> parent;
bool t = 1;
int theNodeInTheCycle;
void dfs(int x)
{
state[x] = 1;
for(int j = 0; j < ls[x].size(); j++)
{
if(state[ls[x][j]] == 1 && parent[x] != ls[x][j])
{
parent[ls[x][j]] = x;
theNodeInTheCycle = ls[x][j]; //ls[x][j] belongs to the cycle since state[ls[x][j]]==1
t = 0;
}
if(state[ls[x][j]] == 0)
{
parent[ls[x][j]] = x;
dfs(ls[x][j]);
}
}
}
vector <int> GetCycle ()
{
vector <int> cycle;
int firstNodeInTheCycle = theNodeInTheCycle;
do
{
theNodeInTheCycle = parent[theNodeInTheCycle];
cycle.push_back (theNodeInTheCycle);
} while (theNodeInTheCycle != firstNodeInTheCycle);
reverse (cycle.begin (), cycle.end ()); //to get them in the right order
return cycle;
}
int main()
{
int n; cin>>n; //the number of nodes (from 0 to n-1)
int m; cin>>m; //the number of edges
state.resize (n);
ls.resize (n);
parent.resize (n);
for (int i = 0; i < m; ++i)
{
int a, b; cin>>a>>b;
ls[a].push_back(b);
ls[b].push_back(a);
}
for (int i = 0; i<n; ++i)
if (state[i]==0)
dfs(i);
if (t==0)
{
vector <int> cycle = GetCycle ();
for (int i = 0; i < cycle.size (); ++i)
cout<<cycle[i]<<" ";
cout<<"\n";
}
else cout<<"No cycle\n";
}
when you run dfs, if a vertex is marked when dfs() before, there must be a cycle.
A
/
B
| \
C E
\ /
D
if there is only one cycle in graph, the vertex marked before is the entry of cycle, as B below, whatever the start vertex of dfs is.
and in your code,
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
t = 0; // Graph contains cycle.
return t;
}
in the first if() {},parent and t is unnecessary,change to:
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
cout<<"cycle's entry:"<<j<<endl;
// Graph contains cycle.
return false;
}
besides,your code need a return true; outside the for of dfs().
I have list of pair [x;y] where x is unique and y can be duplicate(integers).
Here lies a problem:
Given a pair [x;y], find new pair [k;m], such that:
k > x
m >= y
k - x is minimized.
Now, I've solved this problem with this logic; I sort pairs by x, and then start naive O(n^2) algorithm on it. It seems to work fine, except it's too slow.
Can I do better?
The actual problem im trying to solve, is here: http://www.spoj.com/problems/VBOSS/
and my current code:
#include <stdio.h>
#include <utility>
#include <queue>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
struct employee
{
int id;
int salary;
int height;
int parent_index;
int sub_ordinates;
int cur;
bool important;
bool operator < (const employee& e) const
{
if(height == e.height)
return salary > e.salary;
return (height > e.height);
}
};
// problem states explictly that no two employees
// have same salary.
struct salary_predicate
{
inline bool operator() (const employee& struct1, const employee& struct2)
{
return (struct1.salary > struct2.salary);
}
};
const int MAX_EMPLOYEES = 30000;
const int MAX_QUERIES = 200;
employee employees[MAX_EMPLOYEES];
int queries[MAX_QUERIES];
int main()
{
int test_cases;
scanf("%d", &test_cases);
while(test_cases--)
{
int employeeCount, queryCount;
scanf("%d %d", &employeeCount, &queryCount);
int i = 0;
int j = 0;
while(i < employeeCount)
{
employees[i].parent_index = -1;
employees[i].sub_ordinates = 0;
employees[i].cur = i;
employees[i].important = false;
scanf("%d %d %d", &employees[i].id, &employees[i].salary, &employees[i].height);
i++;
}
map<int, int> mapper;
while(j < queryCount)
{
scanf("%d", &queries[j]);
mapper.insert(pair<int, int>(queries[j], -1));
j++;
}
// now step1; sort employees structure
// based on SALARY!!
sort(employees, employees + employeeCount, salary_predicate());
for(int k = 0; k < employeeCount; k++)
{
employees[k].cur = k;
if(mapper.find(employees[k].id) != mapper.end())
{
mapper[employees[k].id] = k;
employees[k].important = true;
}
}
int found = 0;
for(int l = employeeCount - 1; l >= 0; l--)
{
int gef = l - 1;
// check out information about previous worker,
// he might give us some valuable information!
// with his help, we know if we can skip some shit :)
if(l + 1 < employeeCount && employees[l + 1].parent_index != -1)
{
// if previous employee is smaller than our current employee
// then we can skip some people, becase we know that answer cant be
// smalle than that :)
if(employees[l + 1].height <= employees[l].height)
gef = employees[l + 1].parent_index - 1;
}
// find boss!
for(int b = gef; b >= 0; b--)
{
if(employees[b].height >= employees[l].height)
{
employees[l].parent_index = b;
employees[b].sub_ordinates += employees[l].sub_ordinates + 1;
break;
}
}
// this bit makes sure if we have processed all necessay things,
// then we can basically stop our work.
if(employees[l].important) found++;
if(found == mapper.size()) break;
}
// time to print it out.
for(int b = 0; b < queryCount; b++)
{
int id = queries[b];
int index = mapper[id];
int parent_index = employees[index].parent_index;
int parent = parent_index < 0 ? 0 : employees[parent_index].id;
printf("%d %d\r\n", parent, employees[index].sub_ordinates);
}
}
return 0;
}
salary=x, and height=y.
I would start by eliminating all records where m<y or k<=x. Then find the item with the smallest k value out of what's left. Both of these should be linear, so your overall complexity should also be linear.
struct p {
int k, m;
};
p find_item(p xy, std::vector<p> &values) {
auto end = std::partition(values.begin(), values.end(),
[xy](p const &v) { return xy.k < v.k || xy.m >= v.m; });
return *std::min_element(values.begin(), end,
[](p const &a, p const &b) { return a.k < b.k; });
}