Fast / efficient identification of two 2D arrays for sameness in C - c

I'm working on a search algorithm project, finding the solution for the 16 puzzle.
I have two lists of structs that contain a 2D array board[N][N]
The numbers in the list are unique in a range of 0-15, the difference is their order.
BoardA = 0 1 2 3 BoardB = 4 1 2 3
4 5 6 7 0 5 6 7
8 9 10 11 8 9 10 11
12 13 14 15 12 13 14 15
As you can see, the only difference between boards will be the order of the numbers.
Obviously it is possible to iterate through each board checking if
BoardA[i][j] == BoardB[i][j]
However, if there are hundreds or thousands of boards on a list, comparing them this way is undesirable.
Is there a way to quickly or efficiently compare two boards for sameness?

The elements of a two-dimensional array are located in a contiguous memory block. So to compare two arrays, you are just comparing two memory blocks. The fastest way to do it is with memcmp(). You did not specify what type each array element is, so I will use int and you can replace it with another type if your elements are not ints.
if (memcmp(BoardA, BoardB, sizeof(int) * N * N) == 0) {
/* equal */
} else {
not /* equal */
}

You might save a few cycles with tricks like memcmp(), but really the simple, straightforward comparisons will optimize well. If you exit early on failure, then it will only compare all elements in the case where the arrays are equal, in which case every comparison is needed anyway, even with memcmp().
So keep it simple:
int equals(int (*a)[4], int (*b)[4]) {
for (int i = 0; i < 4; i += 1) {
for (int j = 0; i < 4; j += 1) {
if (a[i][j] != b[i][j]) return 0;
}
}
return 1;
}

Related

Store rows of numbers from a list into arrays without leaving empty cells

I want to read rows of numbers from a file and store each of the rows into separate array to then sort and find the median of each array. The problem I'm having is that each row can have a different amount of numbers in it. I though about using a 2D array that would have enough space to fit the largest row in my file. The problem I see with this is that shorter rows in my file would have empty cells in the array and that could cause errors in the sorting and median.
Is there anyway to store each row of the list without having empty cells in the 2D array?
Here's an example of the number list
1 2 3 4 5
5 2 8 5 7 4 3
3 2 5 4 6 5
2 3 1 6 5
9 6 4 6 5 0
Yes you certainly can.
Use dynamic memory allocation for that. This is where it can be useful.
int *p[5];
p[0]= malloc( sizeof(int)*10);
if( p[0]== NULL)
{
fprintf(stderr,"Error in malloc");
exit(1);
}
p[1]= malloc( sizeof(int)*5);
if( p[1]== NULL)
{
fprintf(stderr,"Error in malloc");
exit(1);
}
..
free(p[0]);
free(p[1]);
This way now you have created an array of different sizes. Now to remmeber the sizes you can mention another array sizeArr which will hold the sizes of different arrays.
What I mean is sizeArr[0]=10 and sizeArr[1]=5 denoting the number of elements in p[0] and p[1].
Inputting and outputting the elements of p[0] and p[1] will be similar to that of an array.
if (scanf("%d", &p[0][0]) == 1)
// work with p[0][0];
else
...EOF or conversion failure...
Looping and printing would be similar to
for(size_t arrIndex = 0; arrIndex < 5; arrIndex++)
for(size_t i = 0; i< sizeArr[arrIndex]; i++ )
printf("%d", p[arrIndex][i]);
Here the benefit will be you will not have to worry about unused memory locations. You will allocate whatever memory you need. Also you can change then as you need using realloc() etc.
Note: In this case don't forget to free the memory dynamically allocated after you are done working with it.

C program to subtract differing numbers from an array

I want to crate a program that will subtract a decreasing set of numbers. or in other words:
I an array i have the numbers {20,23,67,3,67,12,24}
There are 7 elements in the array so therefore i want to to this:
20 - 7
23 - 6
67 - 5
3 - 4
67 - 3
12 - 2
24 - 1
I would assume I need to use a loop but am not sure of how to do this.
In C there is no specific count of items for arrays, length is fixed. If do you know the size 7 and create the array with the fixed length you can use the below code. You can use pointers for dynamic length arrays, but it is complicated.
int a[7] = {20,23,67,3,67,12,24};
int i;
for(i=7;i>0;i--) {
printf("%d - %d \n", a[i-1], i);
}
You can start a counter at 0 and go through the array until you hit the null terminator and it will print your array in a the order in which it is stored as.

dynamic array with unknown size

I want to write a program in C where the user types in 2 numbers a and b.
0 < a < INT_MAX
a < b < INT_MAX
The program checks how many Prime numbers are in between a and b and saves all of them in a dynamic array.
For the malloc function I need the size of the array, which means I have to first check all numbers if they are prim numbers just to get the size of the array,
then use malloc(),
and then check all numbers again to fill the array.
Is there any possibility to make this run faster and not doing the same thing twice?
for (int i = a; i <= b; i++)
{
if (check_if_prime(i) == 0)
size++;
}
primze_numbers = malloc(size*sizeof(int));
int j = 0;
for (int i = a; i <= b; i++)
{
if(check_if_prime(i) == 0)
{
prime_numbers[j] = i;
j++;
}
}
Since the size is unknown in the beginning, allocating the space for the size of one more element is inefficient.
One possible solution is: reallocate the space(Use realloc) twice the size of the previous size whenever the size is not enough.
Real size - Space size
0 0
1 1
2 2
3 4
4 4
5 8
6 8
7 8
8 8
9 16
10 16
... ...
This way, the times of reallocation is not much, and you don't waste much space.
If you are able to use c++ - you can use std::vector which solves your problem.

Find pairs that sum to X in an array of integers of size N having element in the range 0 to N-1

It is an interview question. We have an array of integers of size N containing element between 0 to N-1. It may be possible that a number can occur more than two times. The goal is to find pairs that sum to a given number X.
I did it using an auxiliary array having count of elements of primary array and then rearranging primary according auxiliary array so that primary is sorted and then searched for pairs.
But interviewer wanted space complexity constant, so I told him to sort the array but it is nlogn time complexity solution. He wanted O(n) solution.
Is there any method available to do it in O(n) without any extra space?
No, I don't believe so. You either need extra space to be able to "sort" the data in O(n) by assigning to buckets, or you need to sort in-place which will not be O(n).
Of course, there are always tricks if you can make certain assumptions. For example, if N < 64K and your integers are 32 bits wide, you can multiplex the space required for the count array on top of the current array.
In other words, use the lower 16 bits for storing the values in the array and then use the upper 16 bits for your array where you simply store the count of values matching the index.
Let's use a simplified example where N == 8. Hence the array is 8 elements in length and the integers at each element are less than 8, though they're eight bits wide. That means (initially) the top four bits of each element are zero.
0 1 2 3 4 5 6 7 <- index
(0)7 (0)6 (0)2 (0)5 (0)3 (0)3 (0)7 (0)7
The pseudo-code for an O(n) adjustment which stores the count into the upper four bits is:
for idx = 0 to N:
array[array[idx] % 16] += 16 // add 1 to top four bits
By way of example, consider the first index which stores 7. That assignment statement will therefore add 16 to index 7, upping the count of sevens. The modulo operator is to ensure that values which have already been increased only use the lower four bits to specify the array index.
So the array eventually becomes:
0 1 2 3 4 5 6 7 <- index
(0)7 (0)6 (1)2 (2)5 (0)3 (1)3 (1)7 (3)7
Then you have your new array in constant space and you can just use int (array[X] / 16) to get the count of how many X values there were.
But, that's pretty devious and requires certain assumptions as mentioned before. It may well be that level of deviousness the interviewer was looking for, or they may just want to see how a prospective employee handle the Kobayashi Maru of coding :-)
Once you have the counts, it's a simple matter to find pairs that sum to a given X, still in O(N). The basic approach would be to get the cartestian product. For example, again consider that N is 8 and you want pairs that sum to 8. Ignore the lower half of the multiplexed array above (since you're only interested in the counts, you have:
0 1 2 3 4 5 6 7 <- index
(0) (0) (1) (2) (0) (1) (1) (3)
What you basically do is step through the array one by one getting the product of the counts of numbers that sum to 8.
For 0, you would need to add 8 (which doesn't exist).
For 1, you need to add 7. The product of the counts is 0 x 3, so that gives nothing.
For 2, you need to add 6. The product of the counts is 1 x 1, so that gives one occurrence of (2,6).
For 3, you need to add 5. The product of the counts is 2 x 1, so that gives two occurrences of (3,5).
For 4, it's a special case since you can't use the product. In this case it doesn't matter since there are no 4s but, if there was one, that couldn't become a pair. Where the numbers you're pairing are the same, the formula is (assuming there are m of them) 1 + 2 + 3 + ... + m-1. With a bit of mathematical widardry, that turns out to be m(m-1)/2.
Beyond that, you're pairing with values to the left, which you've already done so you stop.
So what you have ended up with from
a b c d e f g h <- identifiers
7 6 2 5 3 3 7 7
is:
(2,6) (3,5) (3,5)
(c,b) (e,d) (f,d) <- identifiers
No other values add up to 8.
The following program illustrates this in operation:
#include <stdio.h>
int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 4, 4, 4, 4};
#define SZ (sizeof(arr) / sizeof(*arr))
static void dumpArr (char *desc) {
int i;
printf ("%s:\n Indexes:", desc);
for (i = 0; i < SZ; i++) printf (" %2d", i);
printf ("\n Counts :");
for (i = 0; i < SZ; i++) printf (" %2d", arr[i] / 100);
printf ("\n Values :");
for (i = 0; i < SZ; i++) printf (" %2d", arr[i] % 100);
puts ("\n=====\n");
}
That bit above is just for debugging. The actual code to do the bucket sort is below:
int main (void) {
int i, j, find, prod;
dumpArr ("Initial");
// Sort array in O(1) - bucket sort.
for (i = 0; i < SZ; i++) {
arr[arr[i] % 100] += 100;
}
And we finish with the code to do the pairings:
dumpArr ("After bucket sort");
// Now do pairings.
find = 8;
for (i = 0, j = find - i; i <= j; i++, j--) {
if (i == j) {
prod = (arr[i]/100) * (arr[i]/100-1) / 2;
if (prod > 0) {
printf ("(%d,%d) %d time(s)\n", i, j, prod);
}
} else {
if ((j >= 0) && (j < SZ)) {
prod = (arr[i]/100) * (arr[j]/100);
if (prod > 0) {
printf ("(%d,%d) %d time(s)\n", i, j, prod);
}
}
}
}
return 0;
}
The output is:
Initial:
Indexes: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Counts : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Values : 3 1 4 1 5 9 2 6 5 3 5 8 9 4 4 4 4
=====
After bucket sort:
Indexes: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Counts : 0 2 1 2 5 3 1 0 1 2 0 0 0 0 0 0 0
Values : 3 1 4 1 5 9 2 6 5 3 5 8 9 4 4 4 4
=====
(2,6) 1 time(s)
(3,5) 6 time(s)
(4,4) 10 time(s)
and, if you examine the input digits, you'll find the pairs are correct.
This may be done by converting the input array to the list of counters "in-place" in O(N) time. Of course this assumes input array is not immutable. There is no need for any additional assumptions about unused bits in each array element.
Start with the following pre-processing: try to move each array's element to the position determined by element's value; move element on this position also to the position determined by its value; continue until:
next element is moved to the position from where this cycle was started,
next element cannot be moved because it is already on the position corresponding to its value (in this case put current element to the position from where this cycle was started).
After pre-processing every element either is located at its "proper" position or "points" to its "proper" position. In case we have an unused bit in each element, we could convert each properly positioned element into a counter, initialize it with "1", and allow each "pointing" element to increase appropriate counter. Additional bit allows to distinguish counters from values. The same thing may be done without any additional bits but with less trivial algorithm.
Count how may values in the array are equal to 0 or 1. If there are any such values, reset them to zero and update counters at positions 0 and/or 1. Set k=2 (size of the array's part that has values less than k replaced by counters). Apply the following procedure for k = 2, 4, 8, ...
Find elements at positions k .. 2k-1 which are at their "proper" position, replace them with counters, initial value is "1".
For any element at positions k .. 2k-1 with values 2 .. k-1 update corresponding counter at positions 2 .. k-1 and reset value to zero.
For any element at positions 0 .. 2k-1 with values k .. 2k-1 update corresponding counter at positions k .. 2k-1 and reset value to zero.
All iterations of this procedure together have O(N) time complexity. At the end the input array is completely converted to the array of counters. The only difficulty here is that up to two counters at positions 0 .. 2k-1 may have values greater than k-1. But this could be mitigated by storing two additional indexes for each of them and processing elements at these indexes as counters instead of values.
After an array of counters is produced, we could just multiply pairs of counters (where corresponding pair of indexes sum to X) to get the required counts of pairs.
String sorting is n log n however if you can assume the numbers are bounded (and you can because you're only interested in numbers that sum to a certain value) you can use a Radix sort. Radix sort takes O(kN) time, where "k" is the length of the key. That's a constant in your case, so I think it's fair to say O(N).
Generally I would however solve this using a hash e.g.
http://41j.com/blog/2012/04/find-items-in-an-array-that-sum-to-15/
Though that is of course not a linear time solution.

c beginner, vectors

I'm a c beginner and i've a problem (as usual). I wrote this simple program:
#include <stdio.h>
#define SIZE 10
main()
{
int vettore[9];
int contatore1,contatore2;
for(contatore1 = 0; contatore1 <= 9; ++contatore1)
{
vettore[contatore1] = contatore1*2;
}
printf("%d\n\n", vettore[9]);
for(contatore2 = 0; contatore2 < 10; ++contatore2)
{
printf("%d\n", vettore[contatore2]);
}
printf("\n%d\n", vettore[9]);
return 0;
}
The output of this program is:
18
0
2
4
6
8
10
12
14
16
9
10
Why the value of vettore[9] changes 3 times? And why it has the correct value only on the first line of the output? thank you :)
C arrays are zero based so valid indexes for a 9 element array are [0..8]. You are writing beyond the end of your array. This has undefined results but is likely corrupting the next stack variable.
In more detail... vettore has 9 elements, which can be accessed using vettore[0] ... vettore[8]. The final iteration of your first loop writes to vettore[9]. This accesses memory beyond the end of your array. This results in undefined behaviour (i.e. the C standard does not specify expected outcome here) but it is likely that the address of vettore[9] is the same as the address of contatore2, meaning that the latter variable is written to.
You have a similar problem in the next loop which prints more elements than vettore contains.
You can fix this by changing your loops to
for(contatore1 = 0; contatore1 < 9; ++contatore1)
for(contatore2 = 0; contatore2 < 9; ++contatore2)
Note that it would be safer if you changed to calculating the size of the array instead, by using sizeof(vettore)/sizeof(vettore[0]) in the exit test of your loops in place of hard-coding 9.
Your array vettore has 9 elements, but by referencing vettore[9], you're actually referencing the 10th element (since element indexing starts from 0). So it's some random location on the stack, without a well-defined value.
The solution is to index only up to vettore[8], or define vettore to have size 10.
check this out:
for(contatore2 = 0; contatore2 < 10; ++contatore2)
{
printf("%d\n", vettore[contatore2]);
}
you are displaying 11 elements of the vettore array (which is defined as a 9 ints array). I think that the error is in the random allocation on the stack
the vettore size as you defined is 9
int vettore[9];
and in your loop you start from 0 till 9 so you are playing with 10 elements of the array and not 9 (size of the array)
you should define the array with size 10
int vettore[10];
Arrays (i.e. "vectors") start at index zero NOT one; it's contents may be, for example, 5 but it will occupy index locations of 0,1,2,3,4....
[1][2][3][4][5] <- Five items
0 1 2 3 4 <- Their respective locations in the array
Same goes for visualizing characters in strings.....(technically the location in memory contains ASCII value-- look into that for fun ;) )
['c']['a']['t'] <- Three items
0 1 2 <- Their index location in the array
I suggest Kochan's C Programming book; great for starting out!!!

Resources