find adjacent vertical elements in a grid - c++

I'm having trouble figuring out the thought process behind grabbing adjacent vertical elements in a grid. Say I have a 5x5 grid:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
I want to find all adjacent horizontal and vertical adjacent elements and place them into an array. The size of the array is given by the possible number of walls between each element (not counting the outside) e.g.
1 | 2 | 3
--- --- ---
4 | 5 | 6
A graph of 2x3 has 7 walls so the array would look like
1 2
2 3
4 5
5 6 //end of horizontal walls
1 4 //beginning of vertical walls
2 5
3 6
now I've figured out how to find all horizontal walls given rows and cols, where walls is the array I will be storing the result in:
//find all horizontal walls in grid
//2-d array to store the element between the wall (0 1) (1 2)
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols-1; c++){
int s = r > 0 ? -1*r : 0; //after first row always write over last space
walls[r*rows+c+s][0] = r*rows+c;
walls[r*rows+c+s][1] = r*rows+c+1;
}
}
but I'm just getting lost on figuring out how to determine all vertical walls, in a grid of 5x5 for example the vertical walls would be
0 5
5 10
10 15
15 20
1 6
6 11
etc...
here's what I'm currently trying:
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols; c++){
//just print the values at the moment, setting walls properly is easy
std::cout << r*rows+c*cols << " " << r*rows+c*cols+5 << std::endl;
}
}
only problem is this does not reset after the first column to 1, instead it continues on like:
0 5
5 10
10 15
15 20
20 25 //nope, should be 1 6
and suggestions? pseudo-code is much appreciated I would prefer an explanation over code

Ok, just figured out the solution so I'll post all I did:
the problem I had was rows did not recent back to 1 when the inner for loop left and started again, this was because I was still multiplying r by rows, this was actually a really simple fix:
r*rows+c*cols << " " << r*rows+c*cols+5 <<
becomes
r+c*cols << " " << r+c*cols+5 <<
I also was running the inner for loop one too many times so, changing
c < cols should become c < cols-1 and now my output is:
0 5
5 10
10 15
15 20
1 6
6 11
11 17
etc...

Related

Read to array from table in text file, while skipping specific column

I am trying to read the contents of a text file into 2D array in C++. The file contains 125 rows with 21 columns of integers (a table of integers). I'm to read this into an array that is 125 rows of 20 columns, skipping column 21 of the file.
I defined the size of the array with variables, but it just reads column 21 into the next row, ignoring the new line. I need it to start each row in the array at the start of the new line from the file but ignore the last item in the table.
I'm not sure if I'm looking for it to skip column 21, or if I'm looking for it to start reading each column at a new line (or both?)
Text file looks like (is this called a matrix?) and it's number separated by 1 space and \n at end.
(The text file was generated by a program to generate rows of 20 numbers and the sum.)
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 93
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 93
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 93
" etc
Other solutions I've found can be difficult for me to understand because people write their variables and functions non-descriptively. Some solutions require advanced methods I'm not supposed to use as well, such as vectors and string manipulation. I have currently learned everything before "pointers" so I can only use solutions I've learned in class. I've learned functions, arrays, search/sort, and basics like operators, loops, variables, etc. I'm not supposed to use vectors for this or string manipulation.
I will (eventually) have to sum the numbers in the array (after I extract the first 20 of each row from the file) so to compare the sum from the array final column to the last integer in each row of the file (which is a sum).
My function is (note: We are using namespace std)
void readArray() {
ifstream infile("tableofintegers.txt");
for (int rowcount = 0; rowcount < ROWS; rowcount++) // row loop
{
for (int colcount = 0; colcount < COLS; colcount++) // column loop
{
infile >> twoDArray[rowcount][colcount]; // read to array
}
}
}
These are variables:
const int ROWS = 125;
const int COLS = 20;
I tried this but got a runtime error
file >> array[row][col];
file.ignore(10, '\n');
The error when I tried file.ignore
C:\path\matrix.exe (process 27316) exited with code -2147483645.
Not only is there an error, but it still "wraps" the read starting line two with the sum (last digit) of line 1.) As you can imagine, as this iterates, it keeps pushing the data over further and further.
I expected for the program to stop reading when it reached the limit of the array columns (20) then continue at the next line, but it didn't. My brain tells me something's not logical about that expectation, yet I have a dissonance or something going on. I can't really wrap my head around it. I also tried file.ignore which I expected would ignore 10 characters after the 20th column up to new line, but it just kicked an error and still wrapped.
Note: I'm printing the array to the console. Here is my code for that.
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
{
cout << setw(5) << dataArray[row][col];
}
cout << endl;
}

Why is rand() % N sufficient for small distributions?

I've often heard that you should never mod the result of your random number generator if you want a uniform distribution. However, I've seen that using a std::uniform_int_distribution makes no difference for significantly small ranges.
Below is an example using both mod and uniform_int_distribution for values 0 - 15:
std::mt19937 gen;
gen.seed(0);
int ROWS = 6;
int COLS = 10;
std::cout << "mod: \n";
for (size_t i = 0; i < ROWS; ++i){
for (size_t j = 0; j < COLS; ++j){
std::cout << std::setw(2) << gen() % 16 << " ";
}
std::cout << "\n";
}
std::cout << "\n";
gen.seed(0);
std::uniform_int_distribution<> distrib(0, 15);
std::cout << "dist: \n";
for (size_t i = 0; i < ROWS; ++i){
for (size_t j = 0; j < COLS; ++j){
std::cout << std::setw(2) << distrib(gen) << " ";
}
std::cout << "\n";
}
results:
mod:
12 15 5 0 3 11 3 7 9 3
5 2 4 7 6 8 8 12 10 1
6 7 7 14 8 1 5 9 13 8
9 4 3 0 3 5 14 15 15 0
2 3 8 1 3 13 3 3 14 7
0 1 9 9 15 0 15 10 4 7
dist:
12 15 5 0 3 11 3 7 9 3
5 2 4 7 6 8 8 12 10 1
6 7 7 14 8 1 5 9 13 8
9 4 3 0 3 5 14 15 15 0
2 3 8 1 3 13 3 3 14 7
0 1 9 9 15 0 15 10 4 7
I guess it has something to do with 2 bytes? I'm just wondering how this is valid mathematically since its stepping through the random number generator and modding results. Does this mean mod creates a uniform distribution if the range is small enough? And why a 2 byte range and not more?
Using the modulo operator will frequently introduce a bias into the returned results when the number of unique values returned by your source of random bits is not a multiple of the divisor.
As a simple example, if your random source returns 4 bits (0-15) and you want values in the range 0-2, using gen() % N you'll get 6 0s, 5 1s, and 5 2s. This biases your results to the low side.
Using multiply-then-divide (gen() * N / RANGE) can still leave an imbalance in the specific number of each result returned, but the imbalance will be spread out evenly among the results which reduces or eliminates the low bias. It also has to contend with overflow in the multiplication. With the previous example, you'll get 5 0s, 6 1s, and 5 0s.
A third alternative would be to check the returned bits to see if the value is among the highest result (that would result in the bias) and regenerate the random bits if this is the case. This introduces a conditional in the code and the time to generate a random number is open ended (rather than fixed).

What does this vector array code do? (C++)

Having difficulty finding an explanation to this.
What does this code do? I understand it creates an array of vector but that's about it.
How can I print the vector array and access elements to experiment with it?
#define MAXN 300009
vector<int>dv[MAXN];
int main()
{
for(int i=1;i<MAXN;i++)
for(int j=i;j<MAXN;j+=i)
dv[j].push_back(i);
}
The code is easy enough to instrument. The reality of what it ends up producing is a very simple (and very inefficient) Sieve of Eratosthenes. Understanding that algorithm, you'll see what this code does to produce that ilk.
Edit: It is also a factor-table generator. See Edit below.
Instrumenting the code and dumping output afterward, and reducing the number of loops for simplification we have something like the following code. We use range-based-for loops for enumerating over each vector in the array of vectors:
#include <iostream>
#include <vector>
#define MAXN 20
std::vector<int>dv[MAXN];
int main()
{
for(int i=1;i<MAXN;i++)
{
for(int j=i;j<MAXN;j+=i)
dv[j].push_back(i);
}
for (auto const& v : dv)
{
for (auto x : v)
std::cout << x << ' ';
std::cout << '\n';
}
}
The resulting output is:
1
1 2
1 3
1 2 4
1 5
1 2 3 6
1 7
1 2 4 8
1 3 9
1 2 5 10
1 11
1 2 3 4 6 12
1 13
1 2 7 14
1 3 5 15
1 2 4 8 16
1 17
1 2 3 6 9 18
1 19
Now, note each vector that only has two elements (1 and an additional number). That second number is prime. In our test case those two-element vectors are:
1 2
1 3
1 5
1 7
1 11
1 13
1 17
1 19
In short, this is a very simple, and incredibly inefficient way of finding prime numbers. A slight change to the output loops to only output the second element of all vectors of length-two-only will therefore generate all the primes lower than MAXN. Therefore, using:
for (auto const& v : dv)
{
if (v.size() == 2)
std::cout << v[1] << '\n';
}
We will get all primes from [2...MAXN)
Edit: Factor Table Generation
If it wasn't obvious, each vector has an ending element (that not-coincidentally also lines up with the subscripts of the outer array). All preceding elements make up the positive factors of that number. For example:
1 2 5 10
is the dv[10] vector, and tells you 10 has factors 1,2,5,10. Likewise,
1 2 3 6 9 18
is the dv[18] vector, and tells you 18 has factors 1,2,3,6,9,18.
In short, if someone wanted to know all the factors of some number N that is < MAXN, this would be a way of putting all that info into tabular form.

Magic Square in Python Debugging

Problem originally is in this link. I wrote a Python code but I got 64 points (total points is 100) and this indicates that my code has some missing points. I passed 11 of 16 test cases but 5 test cases have problematic for me. Could you say where my code has some missing points and how can I fix it?
import math
m = int(raw_input())
liste = []
y_liste = []
md = 0
ad = 0
sum = 0
sum2 = 0
for k in range(m):
temp = str(raw_input())
liste.append(temp)
liste[k] = liste[k].split(" ")
liste[k] = [int(i) for i in liste[k]]
for k in range(m):
md += liste[k][k]
ad += liste[k][m-k-1]
if md == ad:
print 0
else:
for k in range(m):
for l in range(m):
sum2 += liste[l][k]
sum += liste[k][l]
if sum2 != md and -(k+1) is not y_liste:
y_liste.append(-(k+1))
if sum != md and (k+1) is not y_liste:
y_liste.append(k+1)
sum2 = 0
sum = 0
if md != ad:
y_liste.append(0)
print len(y_liste)
y_liste.sort()
for i in y_liste:
print i
Problem Statement
Magic Square
Johnny designed a magic square (square of numbers with the same sum for all rows, columns and diagonals i.e. both the main diagonal - meaning the diagonal that leads from the top-left corner towards bottom-right corner - and the antidiagonal - meaning the diagonal that leads from top-right corner towards bottom-left corner). Write a program to test it.
Task
Write a program that will check if the given square is magic (i.e. has the same sum for all rows, columns and diagonals).
Input
First line: N , the size of the square (1 <= N <= 600).
Next N lines: The square, N space separated integers pre line, representing the entries per each row of the square.
Output
First line: M , the number of lines that do not sum up to the sum of the main diagonal (i.e. the one that contains the first element of the square). If the Square is magic, the program should output 0.
Next M lines: A sorted (in incremental order ) list of the lines that do not sum up to the sum of the main diagonal. The rows are numbered 1,2,…,N; the columns are numbered -1,-2,…,-N; and the antidiagonal is numbered zero.
Note: There is a newline character at the end of the last line of the output.
Sample Input 1
3
8 1 6
3 5 7
4 9 2
Sample Output 1
0
Sample Input 2
4
16 3 2 13
5 10 11 8
6 9 7 12
4 15 14 1
Sample Output 2
3
-2
-1
0
Explanation of Sample Output 2
The input square looks as follows: http://i.stack.imgur.com/JyMgc.png
(Sorry for link but I cannot add image due to reputation)
The square has 4 rows (labeled from 1 to 4 in orange) and 4 columns (labeled from -1 to -4 in green) as depicted in the image above. The main diagonal and antidiagonal of the square are highlighted in red and blue respectively.
The main diagonal has sum = 16 + 10 + 7 +1 = 34.
The antidiagonal has sum = 13 + 11 + 9 + 4 = 37. This is different to the sum of the main diagonal so value 0 corresponding to the antidiagonal should be reported.
Row 1 has sum = 16 + 3 + 2 + 13 = 34.
Row 2 has sum = 5 + 10 + 11 + 8 = 34.
Row 3 has sum = 6 + 9 + 7 + 12 = 34.
Row 4 has sum = 4 + 15 + 14 + 1 = 34.
Column -1 has sum = 16 + 5 + 6 + 4 = 31. This is different to the sum of the main diagonal so value -1 should be reported.
Column -2 has sum = 3 + 10 + 9 + 15 = 37. This is different to the sum of the main diagonal so value -2 should be reported.
Column -3 has sum = 2 + 11 + 7 + 14 = 34.
Column -4 has sum = 13 + 8 + 12 + 1 = 34.
Based on the above, there are 3 lines that do not sum up to the sum of the elements of the main diagonal. Since they should be sorted in incremental order, the output should be:
3
-2
-1
0
Your explanation doesn't discuss this clause which is a potential source of error:
if md == ad:
print 0
else:
It says that if the main diagonal and antidiagonal add up to the same value, print just a 0 (no bad lines) indicating the magic square is valid (distinct from reporting a 0 in the list of bad lines). Consider this valid magic square:
9 6 3 16
4 15 10 5
14 1 8 11
7 12 13 2
If I swap 13 and 11, the diagonals still equal each other but the square is invalid. So the above code doesn't appear to be correct. In the else clause for the above if statement, you test:
if md != ad:
y_liste.append(0)
a fact you already know to be true from the previous/outer test so your code seems to be out of agreement with itself.

Why does my multidimensional vector only push_back 0 index?

I having a problem using push_back(), I can't figure out why only the first cols vector is just pushed over and over again.
Input
10 9 10 3 100 8 7 10 73 9 10 5 9 87 -1 8 3 7 10 92 6 10 6 83 9 11 8 8 77 -1 10 10 10 10 100 10 10 10 100 10 10 10 10 100 -1 DONE
C++
(...)
size = numbers.size();
counter = 0;
square = ceil(sqrt(size));
vector < vector <int> > rows;
vector<int> cols;
do {
for (int i = 0; i < square; ++i) {
cols.push_back(numbers[counter]);
cout << cols[i] << " ";
++counter;
}
rows.push_back(cols);
cout << endl;
} while (counter <= size);
(...)
Undesirable Output
0: 10 9 10 3 100 8 7
1: 10 9 10 3 100 8 7
2: 10 9 10 3 100 8 7
3: 10 9 10 3 100 8 7
4: 10 9 10 3 100 8 7
5: 10 9 10 3 100 8 7
6: 10 9 10 3 100 8 7
rows[1][2] should be 73, not 9. Where have I gone wrong?
You never reset cols. Instead you just keep adding on to it. I think you are printing rows out with magic number indices, which is why you do not spot the added portion. Either declare a temporary cols inside the loop or call clear after each push_back().
awesomeyi found your main problem. But your code has other issues too.
There is a buffer overflow. For example if size == 4 then square == 2
and we get:
after iter #1: counter == 2; continue since 2 <= 4
after iter #2: counter == 4; continue since 4 <= 4
iter #3: reads numbers[4] and numbers[5] - oops!
The loop condition should be:
while (counter + square <= size);
we need to make sure that the next iteration will complete without overflowing the vector. It would be smart to use .at() for vector access so that if you did make a miscalculation, then the error will behave nicely instead of going screwball.
The loop (minus the output) could actually be written as:
for (size_t counter = 0; counter + square <= size; counter += square )
{
std::vector<int> cols( numbers.begin() + counter, numbers.begin() + counter + square );
rows.push_back(cols);
}