What is wrong with my 2-D array bordering algorithm? - c

I have a 2-D array in which I have to calculate the sum of the neighbours of each element, wrapping around margins and corners.
So, if we had the matrix:
1 2 3
4 5 6
7 8 9,
computing the sum of the neighbours of the last element at position (2, 2):
neighSum(A[2][2]) = 8 + 5 + 6 + 4 + 7 + 1 + 3 + 2
The way I want to implement this is by adding outside borders to the matrix. There's no point in explaining because it would take a lot longer than a visual example, so building upon the previous one, the matrix becomes:
7 8 9
3 1 2 3 1
6 4 5 6 4
9 7 8 9 7
1 2 3
For the corners, there is a catch however. The matrix is considered to be a toroid, which is a geometric shape that has the form of a donut. Think of it as taking the original matrix, wrapping it around a vertical cylinder, and then wrapping it around a horizontal cylinder. This operation makes all the corners be neighbours and we just have to fill in what is left after adding borders.
9 7 8 9 7
3 1 2 3 1
6 4 5 6 4
9 7 8 9 7
3 1 2 3 1
So far I have come up with this algorithm, which pretty much works fine, except for the rightmost column, or so I think. It is behaving strangely, sometimes overwriting some of the values in the right border, sometimes the ones in the left border as well
/* Copy the original matrix to the bordered one */
for (i = 1; i < N + 1; i++)
{
for (j = 1; j < M + 1; j++)
{
B[i][j] = A[i][j];
}
}
/* Add the left and right borders */
for(i = 1; i < M + 1; i++)
{
B[0][i] = B[N][i];
B[N+1][i] = B[1][i];
}
/* Add the top and down borders */
for(j = 1; j < N+1; j++)
{
B[i][0] = B[i][M];
B[i][M+1] = B[i][1];
}
/* Mirror the corners */
B[0][0] = B[N][M];
B[M+1][N+1] = B[1][1];
B[N+1][0] = B[1][M];
B[0][M+1] = B[N][1];

Your last loop iterator is 'j' but you use 'i' to index elements.

Related

How to create a Sudoku grid with the following pattern in C without arrays?

I have to create a Sudoku grid with the following pattern in C:
1 2 3 4
3 4 1 2
2 3 4 1
4 1 2 3
The first number in the top left corner (here: 1) must be an editable variable for a start value. There is another variable to create the grid with by the square size, in this example the square size is 2 and the 1 2 3 4 are in one square. 3 4 1 2 are in another square and so on...
If the start value is e.g. 3, the grid looks like this:
3 4 1 2
1 2 3 4
4 1 2 3
2 3 4 1
I noticed that there is a pattern: If the row number is odd, the new start value of the next row is the second last one. If the row number is even, the new start value of the next row is the last one. I tried to do it in C, but the even rows are cloning themselves. Note that arrays and pointers are not allowed here, only loops and other control-structures.
I tried the following approach, but the even rows are cloning themselves:
#include <stdio.h>
const int intSquareSize = 2;
const int intFieldLength = intSquareSize * intSquareSize;
int intStartValue = 3;
int main() {
int a = 0;
int b = 0;
int m = 0;
for (int intRowCounter = 1; intRowCounter <= intFieldLength; intRowCounter++) {
m = intFieldLength - 1;
for (int intColumnCounter = 1; intColumnCounter <= intFieldLength; intColumnCounter++) {
a = intStartValue + (intColumnCounter - 1);
b = a;
if (a > intFieldLength) {
a = intFieldLength - m;
m--;
}
if (intRowCounter % 2 == 0 && intColumnCounter == intFieldLength) {
intStartValue = a;
} else if (intRowCounter % 2 == 1 && intColumnCounter == (intFieldLength - 1)) {
intStartValue = b;
}
printf("%d\t", a);
}
printf("\n");
}
return 0;
}
What did I wrong and how can I fix it?
If the row number is odd, the new start value of the next row is the second last one. If the row number is even, the new start value of the next row is the last one.
I don't think it is helpful to think in terms of odd and even. The involved numbers are just symbols, and one could even replace them with distinct colors (for example). Odd/even is not a significant thing here, and it would certainly not play the same role in other board sizes.
The pattern I see is this:
In the first intSquareSize rows, the values shift horizontally (compared to the previous row) by intSquareSize. For example with intSquareSize=3 the first three rows could be:
3 4 5 6 7 8 9 1 2
6 7 8 9 1 2 3 4 5
9 1 2 3 4 5 6 7 8
Notice the shift of 3 positions to the left at each next row.
Then the pattern for the next chunks of intSquareSize rows would be the same, but with one shift. So the complete 9x9 sudoku would look like this:
3 4 5 6 7 8 9 1 2
6 7 8 9 1 2 3 4 5
9 1 2 3 4 5 6 7 8
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
1 2 3 4 5 6 7 8 9
5 6 7 8 9 1 2 3 4
8 9 1 2 3 4 5 6 7
2 3 4 5 6 7 8 9 1
This is just one possible pattern you could follow. There could be others. But the following code will apply the above logic. Note I used your variables, but I prefer to use 0-based logic, so loop variables start at 0, and the value of a is also 0-based. Only at the time of printing 1 is added to that value, so it becomes 1-based:
int a = intStartValue - 1; // Move from 1-based to 0-based
for (int intBlockCounter = 0; intBlockCounter < intSquareSize; intBlockCounter++) {
for (int intRowCounter = 0; intRowCounter < intSquareSize; intRowCounter++) {
for (int intColumnCounter = 0; intColumnCounter < intFieldLength; intColumnCounter++) {
printf("%d\t", (a + 1)); // back to 1-based
a = (a + 1) % intFieldLength;
}
printf("\n");
a = (a + intSquareSize) % intFieldLength; // Shift within a block
}
a = (a + 1) % intFieldLength; // Shift between blocks
}

Implementing shellsort algorithm in C

void shellsort(int v[], int n)
{
int gap, i, j, temp;
for (gap = n/2; gap > 0; gap /= 2)
for (i = gap; i < n; i++){
for (j=i-gap; j>=0 && v[j]>v[j+gap]; j-=gap) {
temp = v[j];
v[j] = v[j+gap];
v[j+gap] = temp;
}
}
}
}
In this shellsort() function, we've j-=gap. Assuming n = 10, the gap is always 5 and j increments from 0,1,2,3,4....
It means the first 5 times this inner for loop runs, it will return a negative value to j (e.g. 0-5=-5), and thus since j will not be greater than or equal to 0, it will only run once.
It works because that is exactly what we want. We don't want to swap more than once, because if we did, we would only be swapping the same two values over again, thus causing unnecessary redundancy.
So, I was thinking why can't we just omit j-=gap from the loop as it doesn't seem to affect the functioning at all. Is there any special reason why j-=gap is included?
Am I missing something here?
It might help to take a look at insertion sort as a reference to see where this comes from. In insertion sort, we scan from left to right, swapping each element backwards until it's greater than the element that comes before it (or it gets back to the start of the array). The pseudocode for that algorithm is shown here:
for (int i = 1; i < n; i++) {
for (int j = i - 1; j > 0 && A[j + 1] > A[j]; j--) {
swap(A[j], A[j - 1]);
}
}
The outer loop ranges over all elements of the array, saying "put each one in place." The inner loop says "keep swapping the current element with the one that comes before it as long as there is an element that comes before it and that element is greater than it." Here, the use of +1, ++, -1, and -- are because we're constantly looking at the element that comes immediately before the current element.
In shellsort, we run multiple passes of this algorithm over the array, except that we don't use a step size of one. Instead, we use a step size of some amount called the gap amount. Shellsort therefore looks something like this:
for (each gap size) {
for (int i = gap; i < n; i += gap) {
for (int j = i - gap; j > 0 && A[j + gap] > A[j]; j -= gap) {
swap(A[j], A[j - 1]);
}
}
}
The idea is that each element should be continuously compared against the element that's gap elements before it. If it's less than that number, we want to swap it with the preceding element, but then need to repeatedly compare it with the new element that precedes it.
As an example, suppose we are shellsorting this array of length 6:
6 5 4 3 2 1
After the first pass of shellsort (gap = 3), the array looks like this:
3 2 1 6 5 4
Now, imagine that we do the second pass of shellsort with gap = 1. The inner loop currently says "repeatedly swap every element backwards toward the front until it comes to rest." If you remove the j -= gap step from that loop, then every element is just compared against the one directly before it. That would result in the following. In each of these snapshots, the carats refer to where the swaps are looking:
3 2 1 6 5 4 -> 2 3 1 6 5 4
^ ^
2 3 1 6 5 4 -> 2 1 3 6 5 4
^ ^
2 1 3 6 5 4
^ ^
2 1 3 6 5 4 -> 2 1 3 5 6 4
^ ^
2 1 3 5 6 4 -> 2 1 3 5 4 6
^ ^
Notice that the resulting array is not sorted. However, if we put back the j -= gap code into the mix, then the following will happen instead:
3 2 1 6 5 4 -> 2 3 1 6 5 4
^ ^
2 3 1 6 5 4 -> 2 1 3 6 5 4 -> 1 2 3 6 5 4
^ ^ ^ ^
1 2 3 6 5 4
^ ^
1 2 3 6 5 4 -> 1 2 3 5 6 4
^ ^
1 2 3 5 6 4 -> 1 2 3 5 4 6 -> 1 2 3 4 5 6
^ ^ ^ ^
As you can see, now everything gets sorted properly.

Need help with logic (C)

I need to swap first n elements from two non repeating sequences(arrays), where n is a random integer.
Seq1: 1 4 5 6 9 8 2 3 7
Seq2: 3 9 1 2 8 7 4 5 6
If n = 4
Seq1: 3 9 1 2 | 9 8 2 3 7
Seq2: 1 4 5 6 | 8 7 4 5 6
Now i need to repair the sequence by replacing the repeated numbers after '|'.
How to do this?
This is my effort..
for(left1 = 0; left1<pivot; left1++)
{
for(right1 = pivot; right1 < no_jobs; right1++)
{
if(S1->sequence[left1] == S1->sequence[right1])
{
for(left2 = 0; left2<pivot; left2++)
{
for(right2 = pivot; right2<no_jobs; right2++)
{
if(S2->sequence[left2] == S2->sequence[right2])
{
swap_temp = S1->sequence[right1];
S1->sequence[right1] = S2->sequence[right2];
S2->sequence[right2] = swap_temp;
break;
}
}
}
}
}
}
Swapping the first n elements is straightforward using a single for loop.
for(int i = 0; i < n; i++){
int tmp = array1[i];
array1[i] = array2[i];
array2[i] = tmp;
}
Now you need to find what has changed in the arrays. You can do this by comparing the parts you swapped.
int m1 = 0, m2 = 0;
int missing_array1[n];
int missing_array2[n];
for(int i = 0; i < n; i++){
bool found = false;
for(int j = 0; j < n; j++){
if(array1[i] == array2[j]){
found = true;
break;
}
}
if(!found){
missing_array2[m2++] = array1[i];
}
}
for(int i = 0; i < n; i++){
bool found = false;
for(int j = 0; j < n; j++){
if(array2[i] == array1[j]){
found = true;
break;
}
}
if(!found){
missing_array1[m1++] = array2[i];
}
}
missing_array2 now contains the numbers that are missing from array2. These are all the numbers that will be duplicated in array1. The same goes for missing_array1. Next you need to scan both arrays and replace the duplicates with the missing numbers.
while(m1 >= 0){
int z = 0;
while(missing_array1[m1] != array2[n + z]){
z++;
}
array2[n + z] = missing_array2[m1--];
}
while(m2 >= 0){
int z = 0;
while(missing_array2[m2] != array1[n + z]){
z++;
}
array1[n + z] = missing_array1[m2--];
}
In summary, you compare the parts you swapped to find the values that will be missing from each array. These value are also the values that will be duplicated in the opposite array. Then you scan each of the arrays and replace the duplicate values with one of the missing values (I assume you don't care which of the missing values, as long as all the values are unique.
If the swapped portions of the sequences contain the same values, then there would be no repeats - performing the swap would just shuffle the first n elements. So the values you need to repair are the values which occur in one of the swapped sequences
Firstly, I'd create a histogram of the n swapped elements, with those from sequence 1 counting as bit 0, and those from sequence 2 as bit 1. If any members of the histogram are non-zero, then they occur in one or the other sequence only.
If there are values requiring repair, then you can construct a look-up table of the values which require rewriting. This should map i to i unless i is one of the asymmetric values in the histogram, in which case it needs to map to the another asymmetric value.
Seq1: 1 4 5 6 9 8 2 3 7
Seq2: 3 9 1 2 8 7 4 5 6
If n = 4
Seq1: 3 9 1 2 | 9 8 2 3 7
Seq2: 1 4 5 6 | 8 7 4 5 6
histogram
value 1 2 3 4 5 6 7 8 9
count 3 1 1 2 2 2 0 0 1
mapping for sequence 1 ( while histogram [S1[i]] & 1, replace[S1[i]] with S2[i] )
value 1 2 3 4 5 6 7 8 9
replace 1 6 5 4 5 6 7 8 4
apply mapping to sequence 1 for i > n
Seq1: 3 9 1 2 | 9 8 2 3 7
replace - - - - | 4 8 6 5 7
result 3 9 1 2 | 4 8 6 5 7
mapping for sequence 2 ( while histogram [S2[i]] & 2, replace[S2[i]] with S1[i] )
value 1 2 3 4 5 6 7 8 9
replace 1 2 3 9 3 2 7 8 9
apply mapping to sequence 1 for i > n
Seq2: 1 4 5 6 | 8 7 4 5 6
replace - - - - | 8 7 9 3 2
result 1 4 5 6 | 8 7 9 3 2
Alternatively, replace with the next value with the other bit set in the histogram (the iterated replace will also need to check for replacing a value with itself); I'm assuming it doesn't really matter what value is used as the replacement as long as the values in the result are unique.

Formula needed: Sort array to array-"zig-zag"

I have the following array:
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
I use it for some visual stuff like this:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now I want to sort the array like this to have a "zig-zag" when rendering later.
// rearrange the array according to this schema
1 3 6 10
2 5 9 13
4 8 12 15
7 11 14 16
// the original array should look like this:
a = [1,5,2,9,6,3,13,10,7,4,14,11,8,15,12,16]
// the second index to draw should be the first index in the second row,
// which is represent by 5 in the original 1D Array
Yeah, now I'm looking for a smart formula to do that
ticker = 0;
rows = 4; // can be n
cols = 4; // can be n
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
newArray = [];
while(ticker < originalArray.length)
{
//do the magic here
ticker++;
}
You can leave it sorted in the original order, you just have to step through it differently. EDIT: Turns out that my naive implementation didn't account for the differing step size based on the diagonal. The code below does and has been tested in C#.
var diagonals = new [] { 1, 2, 3, 4, 4, 3, 2, 1 };
for (int i = 0, m = 0; m < 4; i = i + m, ++m) {
for (int j = m, k = 0; k < 4; j = j + diagonals[m+k+1], ++k) {
Console.Write( i+j+1 );
Console.Write( " " );
}
Console.WriteLine();
}
Obviously, you could use this algorithm to fill a new array if you needed to keep that ordering around. It should also scale -- you just need to change the termination conditions to the square root of the array size and automate the generation of the diagonals.
Look at the structure of your matrix:
1 3
| / /
| / /
|/ / ...
2 / 5
/ /
/ /
4
The 1st row starts at 1
The 2nd row starts at 2 = 1 + 1 (# elements in 1st zig)
The 3rd row starts at 4 = 1
+ 1 (# elements in 1st zig)
+ 2 (# elements in 2nd zig)
...
The 3rd row ends at 6 = start of 3rd row + row num
= 4 + 3 = 7
You can derive a closed form formula for the ith row and go ahead.

If I'm using a 1d array to represent a square board, how can I take my index and check the squares above, below and to its sides?

If I have a 4x4 gameboard which I'm representing in my program as a 1d integer array of size 16.
How can I get the indexs of the squares above, below, to the left and to the right any given index?
So, for example:
A = { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 }
Which represents this board
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
Lets say I am currently on index #8 in the board (value = 7). How can I get the index for 4 (value = 3) , 5 (value = 6), 10 (value = 11) and realize that there is no right square because it is on the right hand edge of the board.
I know I need to use some modulus math but I'm failing to come up with the right way to get the indexes for adjacent squares.
I'm thinking something like...
if ((i % 4) + 1 < 3) right = i + 1;
if ((i % 4) - 1 > 0) left = i - 1;
if ((i % 4) + 4 < 15) bottom = i + 4;
if ((i % 4) - 4 > 0 ) top = i - 4;
Does this seem like it is the right approach?
To get row,column from your index, use the following:
row = index/num_columns;
column = index % num_columns;
to get back to the index, use
index = row * num_columns + column;
One you're in rows and columns, it's easy to get the surrounding positions.
above = (row-1, column)
left = (row, column-1)
etc...

Resources