Getting rid of non-unique entries in an adjacency list - c++

I'm currently working on a project for my upper-level C++ class, and we are building a program that makes a maze, then solves it, the makes a PNG of said maze. Pretty cool stuff. Anyways, I'm current on the bit where I need to make the maze.
My program makes valid mazes just fine, but I have to make each number output unique. The output just spits out two indicies in a 2d matrix that have walls between them, sample output for a 3X4 maze is as follows:
rjeffor1:hydra20 ~/cs302/labs/lab5> ./mazemake 3 4 <- 9:49AM
1 2
1 5
2 1
2 3
3 2
5 1
5 9
6 7
7 6
8 9
9 8
9 5
However, my last problem is that I need to get rid of duplicate walls, for example 1 2 and 2 1. EDIT: and by this I mean just get rid of the 2 1, I still need the wall and therefore the 1 2.
Here is my function in which I attempt to fix the problem:
void aL::make_unique()
{
vector<int>::iterator it, it0;
//need to iterate thru all but last index
for (int i=0; i<(int)adjList.size()-1; i++) {
for (int j=0; j<(int)adjList.size(); j++) {
//find it
if (i!=j) {
it0 = std::find(adjList[i].begin(), adjList[i].end(), j);
it = std::find(adjList[j].begin(), adjList[j].end(), i);
if (it!=adjList[j].end() && it!=adjList[j].end())
//erase it if anything is there
adjList[j].erase(it);
}
}
}
}
Help is appreciated, my brain is so done at this point
EDIT: here is how I populate the adjancency lists, based on indicies directly left right above and below each index
aL::aL (const int &rows, const int &cols)
{
adjList.resize(rows*cols);
//run thru and figure out where indicies AREN'T
//to fill in their adjacency list
for (int i=0; i<(int)adjList.size(); i++) {
//if not on the left edge
if (i%cols!=0)
adjList[i].push_back(i-1);
//not on the right edge
if ((i+1)%cols!=0)
adjList[i].push_back(i+1);
//not on the top edge
if (i>=cols)
adjList[i].push_back(i-cols);
//not on the bottom edge
if (i<(rows*cols)-cols)
adjList[i].push_back(i+cols);
}
}

You could remove the need to post-process and make it unique at the end if you check as you are adding to your list. Don't add "a b" if "b a" is already there.

Related

Erasing duplicates from nested map (k-core algorithm)

i am trying to finish a homework and came with an error.
What i am trying to do is: There is an unordered map with keys containing values as unordered_set which may have keys inside that "may have the same names as keys of unordered outer map".
To be spesific, i am trying to implement a k-core algorithm, the count and k numbers are there for it. I am trying to erase unordered_map keys (lets call P) that have unordered_sets(containing neighbors, call N) which have lower than k sizes.
But since i delete the N entry from the P node, i also need to find the N entry from the outer map and find P and delete it there.
The following code is what i came up with so far (there is more but i don't want plagiarism or anything). During the debugging i noticed that somewhat cout<<nodes.size() never executes. I don't know what is the problem. Probably the inner while infinitely loops, and it is related with how iterators function with erase etc. but i am not sure. Hope it is clear.
EDIT : I have updated the code according to the suggestion, but there is a new problem: for k=1 the amount of nodes are right. But after k=2,3,4.. there is infinite loop of outermost loop. And the size stays constant (after taking out nodes with k=1)
while(nodes.size()!=0)
{
int count = 0;
while(stillLeft){
stillLeft = 0;
it = nodes.begin();
while(it != nodes.end()){
if(it->second.size()<=k){
stillLeft = 1;
++count;
for ( innerit = it->second.begin(); innerit != it->second.end();innerit++ ){
nodes.find(*innerit)->second.erase(it->first);
}
it = nodes.erase(it);
}
else{
++it;
}
}
}
cout << nodes.size() << endl;
kCoreNumbers.push_back(count);
++k;
}
You don't need to loop till while(nodes.size()!=0) i.e. till nodes is empty. After running the k-core algorithm, you might be left with nodes whose vertexes have a degree greater than k. You only need to loop till there are no more nodes that have a degree less than k.
Your initial code was in the right direction but with the problem of deleting a node in the map while traversing it. I solved it by just adding the vertices to be deleted to a vector while iterating the graph and then after each graph traversal just deleted all the nodes makred for deletion. Here's my version of code, based off yours with a few variable name changes to reflect what they are:
void runKCore(size_t k) {
bool nodesDeleted;
do {
// To keep track of how many times the loop needs to run
nodesDeleted = false;
// To keep track of the nodes to be deleted after one pass
std::vector<int> markDeleted;
for(auto const& node: graph) {
auto vertex = node.first;
auto const& neighbours = node.second;
// Pick vertex if it has less than k neighbours
if(neighbours.size() < k) {
for(auto neighbour: neighbours) {
// Get the neighbour's list of vertices
auto& neighBoursEdges = graph.at(neighbour);
// Remove vertex from this list
neighBoursEdges.erase(vertex);
}
// Mark this node as deleted
markDeleted.push_back(vertex);
}
}
// Update nodesDeleted if any nodes were marked for deletion
nodesDeleted = markDeleted.size() > 0;
for(auto node: markDeleted) {
// Erase the node and it's neighbours
graph.erase(node);
}
}while(nodesDeleted);
}
Here is the complete program.
For an initial graph
translating to initial graph
8: 6 5
7: 6 3 4
6: 7 3 8 5 4 2
5: 8 6 2 1
4: 7 3 6 2
3: 7 6 4 2
2: 6 3 4 5 1 0
1: 5 2 0
0: 2 1
the output of the program after running the k-core algo for k = 3 output is:
7: 6 3 4
6: 7 3 4 2
4: 7 3 6 2
3: 7 6 4 2
2: 6 3 4

cant find error in my applied logic

question:
Given an array of elements of length N, ranging from 0 to N-1, your task is to write a program that rearranges the elements of the array. All elements may not be present in the array, if element is not present then there will be -1 present in the array. Rearrange the array such that A[i] = i and if i is not present, display -1 at that place.
my code:
#include <iostream>
using namespace std;
int main()
{
long int n;
cin>>n;
long int a[n];
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for (int i=1;i<=n;i++)
{
while(a[i]==i&&a[i]==-1)
{
int temp=a[i];
a[i]=a[temp];
a[temp]=temp;
}
}
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
return 1;
}
output:
6
-1 4 2 3 -1 5
-1 4 2 3 -1 5
can anyone please help me in finding out my error in the logic apllied?
Thanks in advance.
for(int i=1;i<=n;i++)
Wrong, elements go from 0 to N-1, not 1 to N
while(a[i]==i&&a[i]==-1)
This will never happen, you are asking for a[i] to be equal to both i and -1, which means asking i to be equal to -1, which won´t happen in your loop.
For a simple answer, you need to sort the list and then process that. For an efficient answer, you will want to make a boolean array of size N and then iterate the array and check which values are present. Then you iterate the boolean array to write the number when it is present or -1 when its not.
The easiest way to solve this kind of problem is to get a pack of playing cards and lay them out on your desk, and then solve the problem by hand. Write down every step you take, and then write code that performs those steps.
Because cards start at 1, rather than 0, I use the 10 as a 0. Use the joker to indicate an empty space (-1 in your problem description).
Take five cards and lay them out in six spaces
2 10 4 J 3 1
Starting with position 0. Pull the 2 out and replace it with -1, so your cards look like this:
J 10 4 J 3 1
And you're holding the 2 in your hand.
Then, go to position 2, pull out the 4 and put the 2 there. Now you have
J 10 2 J 3 1
And you're holding 4 in your hand. Go to position 4 (where the 3 is). Replace the 3 with 4, you have:
J 10 2 J 4 1
And 3 in the hand. Position 3 contains a joker. So you put the 3 in that position and put the joker aside. You now have:
J 10 2 3 4 1
So you move to the next position, 1. Pick up the 10 and put a joker in that spot. The 10 goes to position 0, so take the joker from position 0, place the 10 there, and you have:
10 J 2 3 4 1
You don't have anything in your hand now, so you move forward, checking positions 2, 3, and 4, which already have a[i] == i. But position 5 contains a 1. So you pick it up, place a joker in that position, and then replacing the joker in position 1 with the value 1 that you just pulled from position 5. Your array now looks like this:
10 1 2 3 4 J
And you're done.
Do that a few times with different arrangements of cards, writing down the steps you took. After a few practice runs, you should be able to write down the general algorithm for solving the problem. Then you write a program to implement that solution.
The idea of this kind of problem is to help you develop these problem solving steps. Over time, you'll be able to go straight to code with the simpler problems, but you'll find that building a physical model is very useful with more complex problems. If you step away from the computer, you're not tempted to start programming before you've solved the problem. You'll find that doing things way will save you a lot of frustration.

2-D Array C++ Triangle

I am trying to create a program in c++ that takes in triangle pattern of numbers into a 2-D array.
Example:
1
3 4
5 9 2
9 4 6 1
The top row is one number(integer) and each row of the triangle has one more number than the row above it.
Once the triangle has been entered and/or examined via for loops, the program needs to traverse the triangle from top to bottom and record all possible sums of each path;
The path taken down the triangle must always be adjacent to the number in the row above it.
While traversing down the triangle each "path" should be stored in a new array so the path can be displayed.
After recording the sum for each path down the triangle the program should compare them and display the path with the smallest sum.
With the changes i made so far thanks to #Beta i have this so far:
int main()
{
int row = 0;
int col = 0;
int A[4][4] = {{2},{8,9},{3,4,5},{6,2,9,1}};
for (row = 0; row < 4; row++)
{
for (col = 0; col <= row; col++)
{
cout << A[row][col] << " ";
}
cout << endl;
My Output is so far is:
2
8 9
3 4 5
6 2 9 1
I think the trick you're looking for is this:
for (col = 0; col <= row; col ++)
I couldn't parse the last part of your question ("After that...").
EDIT:
The problem of making the triangle look symmetrical is a problem of printing spaces at the beginning of each line. With the trick above, you should be able to figure than one out.
As for considering all paths and displaying the one with the smallest sum, what have you tried? If you are not familiar with Breadth-First Search and Depth-First Search, copying arrays and arrays of pointers, you're probably not ready for this exercise.

possible combinations and loops

i have to make all possible combinations of a 2d array..for e.g. if i have a array of 4x3 ...i m using 4 loops,all runs up to 3.. to get all combinations...
for.e.g if i have a 4x3 array as given below..
1 2 3
4 5 6
7 8 9
10 11 12
i will have to make combinations like
1,4,7,10
1,4,7,11
1,4,7,12
1,4,8,10
1,4,8,11
1,4,8,12
1,4,9,10
1,4,9,11
1,4,9,12
1,5,8,10
1,5,8,11
1,5,8,12
...........
and so on....
in short all such combinations...the max number of possible combinations in this case will be 3 power 4....and if i have a array of nxm then maximum combinations will be m power n....can any one help creating it....i want help to solve it in generic .....i think recursive function shall be used...as i don't know the no of loop...it will be known during run time...
void buildArray(vector <int> build, vector< vector <int> > &arrays)
{
int position = build.size();
if (position == arrays.size()) { /* current build is one of the solutions*/}
else {
for (int i = 0; i < arrays[position].size(); i++)
{
build.push_back(arrays[position][i]);
buildArray(build, arrays);
build.pop_back();
}
}
}

C++ Matrix combinations

Firstly thanks for reading.I'm trying to make a "noob" program and i wanted to use a registration code.
For completing my encryption algorythm i need to generate all 4x4 matrices containing only numbers from 0 to 9 like in the following example:
4 4 6 8
5 2 4 3
8 5 2 9
2 7 2 6
I know there is a huge number of these combinations but it wont stop me.I tried myself to do it using "for" but i can't figure it out.
I would store the 4x4 digit matrix as char[16], interpreting the first four chars as the first row, the next four chars as the second row, etc. You can easily generate all possible values by recursion, with a for loop on each level.
void print_all_possible_matrices(char *matrix, int level) {
if(level == 16) {
print_matrix(matrix);
}
for(int i = 0; i < 10; ++i) {
matrix[level] = i;
print_all_possible_matrices(matrix, level + 1);
}
}
You would use this in the following way:
int main() {
char matrix[16];
print_all_possible_matrices(matrix, 0);
}
But this will take really loooong time to complete.