In this method I am looking to see if a string appears in word search. Since a string can appear in any direction I have methods like the following which check those directions:
Currently my code is giving a segmentation fault when run. This is happening because the first if statement in my method is being skipped according to gdb.
The grid I am working with looks like this:
a r e o
o n l y
o d d a
The values of x, y and str at runtime (just before segfault) are:
x = 0;
y = 0;
str = "add"
Now strlen(str) evaluates to 3 and x - 3 evaluates to -3.
-3 < 0 would evaluate true and quits my method. Unfortunately the if statement at the start of the method is skipped at run time. Anyone know what is going on?
Furthermore I'll add that if I change the first line of my grid to:
q r e o
I get proper results.
Here is the method:
bool checkNorth (int x, int y, string str) {
//Deal with trival case and avoid array out of bounds/checking silly things
if (x-strlen(str) < 0){
return false;
}
//for each character in str
for (int i = 0; i < (strlen(str)); i++){
//If the character above in the grid is the next character in the string
if (grid[x-i][y].letter == str[i]){
//keep going
continue;
}else{
//It ain't north
return false;
}
}
//It's north
return true;
}
Since strlen() returns a value of type size_t, which is unsigned, then you compute x - 3 the computation is done on unsigned values, and with unsigned arithmetic, 0 - 3 is a large positive value, and is never less than zero. In fact, since the comparison is for an unsigned quantity less than 0, but unsigned quantities can never be negative, the compiler can optimize the entire if test and the following return completely away.
You can fix the problem by changing:
if (x-strlen(str) < 0){
to:
if (x < strlen(str)) {
Note that your loop is somewhat inefficient. You have:
for (int i = 0; i < (strlen(str)); i++){
This recomputes strlen(str) on each iteration. You could write:
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
This guarantees that the length is only computed once, which is sufficient unless you're modifying the string somewhere in the function, or one of the functions it calls.
Related
EDIT:
I forgot to mention that I do not want to allocate another temporarily array.
I am trying to solve a problem in C, which is:
Suppose you were given an array a and it's size N. You know that all of the elements in the array are between 0 to n-1. The function is supposed to return 0 if there is a missing number in the range (0 to n-1). Otherwise, it returns 1. As you can understand, duplicates are possible. The thing is that its supposed to run on O(n) runtime.
I think I managed to do it but i'm not sure. From looking at older posts here, it seems almost impossible and the algorithm seems much more complicated then the algorithm I have. Therefore, something feels wrong to me.
I could not find an input that returns the wrong output yet thou.
In any case, I'd appreciate your feedback- or if you can think of an input that this might not work for. Here's the code:
int missingVal(int* a, int size)
{
int i, zero = 0;
for (i = 0; i < size; i++)
//We multiply the element of corresponding index by -1
a[abs(a[i])] *= -1;
for (i = 0; i < size; i++)
{
//If the element inside the corresponding index is positive it means it never got multiplied by -1
//hence doesn't exist in the array
if (a[i] > 0)
return 0;
//to handle the cases for zeros, we will count them
if (a[i] == 0)
zero++;
}
if (zero != 1)
return 0;
return 1;
}
Just copy the values to another array placing each value in its ordinal position. Then walk the copy to see if anything is missing.
your program works and it is in O(N), but it is quite complicated and worst it modify the initial array
can be just that :
int check(int* a, int size)
{
int * b = calloc(size, sizeof(int));
int i;
for (i = 0; i != size; ++i) {
b[a[i]] = 1;
}
for (i = 0; i != size; ++i) {
if (b[i] == 0) {
free(b);
return 0;
}
}
free(b);
return 1;
}
This problem is the same as finding out if your array has duplicates. Here's why
All the numbers in the array are between 0 and n-1
The array has a size of n
If there's a missing number in that range, that can only mean that another number took its place. Which means that the array must have a duplicate number
An algorithm in O(n) time & O(1) space
Iterate through your array
If the sign of the current number is positive, then make it negative
If you found a negative this means that you have a duplicate. Since all items are originally greater (or equal) than 0
Implementation
int missingVal(int arr[], int size)
{
// Increment all the numbers to avoid an array with only 0s
for (int i = 0; i < size; i++) arr[i]++;
for (int i = 0; i < size; i++)
{
if (arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
return 0;
}
return 1;
}
Edit
As Bruno mentioned if we have an array with all zeros, we could have run into a problem. This is why I included in this edit an incrementation of all the numbers.
While this add another "pass" into the algorithm, the solution is still in O(n) time & O(1) space
Edit #2
Another great suggestion from Bruno which optimizes this, is to look if there's more than one zero instead of incrementing the array.
If there's 2 or more, we can directly return 0 since we have found a duplicate (and by the same token that not all the numbers in the range are in the array)
To overcome the requirement that excludes any extra memory consumption, the posted algorithm changes the values inside the array by simply negating their value, but that would leave index 0 unchanged.
I propose a different mapping: from [0, size) to (-1 - size, -1], so that e.g. {0, 1, 2, 3, 4, ...} becomes {-1, -2, -3, -4, -5, ...}. Note that, for a two's complement representation of integers, INT_MIN = -INT_MAX - 1.
// The following assumes that every value inside the array is in [0, size-1)
int missingVal(int* a, int size) // OT: I find the name misleading
{
int i = 0;
for (; i < size; i++)
{
int *pos = a[i] < 0
? a + (-a[i] - 1) // A value can already have been changed...
: a + a[i];
if ( *pos < 0 ) // but if the pointed one is negative, there's a duplicate
break;
*pos = -1 - *pos;
}
return i == size; // Returns 1 if there are no duplicates
}
If needed, the original values could be restored, before returning, with a simple loop
if ( i != size ) {
for (int j = 0; j < size; ++j) {
if ( a[j] < 0 )
a[j] = -a[j] - 1;
}
} else { // I already know that ALL the values are changed
for (int j = 0; j < size; ++j)
a[j] = -a[j] - 1;
}
I have got an assignment and i'll be glad if you can help me with one question
in this assignment, i have a question that goes like this:
write a function that receives an array and it's length.
the purpose of the function is to check if the array has all numbers from 0 to length-1, if it does the function will return 1 or 0 otherwise.The function can go through the array only one.
you cant sort the array or use a counting array in the function
i wrote the function that calculate the sum and the product of the array's values and indexes
int All_Num_Check(int *arr, int n)
{
int i, index_sum = 0, arr_sum = 0, index_multi = 1, arr_multi = 1;
for (i = 0; i < n; i++)
{
if (i != 0)
index_multi *= i;
if (arr[i] != 0)
arr_multi *= arr[i];
index_sum += i;
arr_sum += arr[i];
}
if ((index_sum == arr_sum) && (index_multi == arr_multi))
return 1;
return 0;
}
i.e: length = 5, arr={0,3,4,2,1} - that's a proper array
length = 5 , arr={0,3,3,4,2} - that's not proper array
unfortunately, this function doesnt work properly in all different cases of number variations.
i.e: length = 5 , {1,2,2,2,3}
thank you your help.
Checking the sum and product is not enough, as your counter-example demonstrates.
A simple solution would be to just sort the array and then check that at every position i, a[i] == i.
Edit: The original question was edited such that sorting is also prohibited. Assuming all the numbers are positive, the following solution "marks" numbers in the required range by negating the corresponding index.
If any array cell already contains a marked number, it means we have a duplicate.
int All_Num_Check(int *arr, int n) {
int i, j;
for (i = 0; i < n; i++) {
j = abs(arr[i]);
if ((j >= n) || (arr[j] < 0)) return 0;
arr[j] = -arr[j];
}
return 1;
}
I thought for a while, and then i realized that it is a highly contrained problem.
Things that are not allowed:
Use of counting array.
Use of sorting.
Use of more than one pass to the original array.
Hence, i came up with this approach of using XOR operation to determine the results.
a ^ a = 0
a^b^c = a^c^b.
Try this:
int main(int argc, char const *argv[])
{
int arr[5], i, n , temp = 0;
for(i=0;i<n; i++){
if( i == 0){
temp = arr[i]^i;
}
else{
temp = temp^(i^arr[i]);
}
}
if(temp == 0){
return 1;
}
else{
return 0;
}
}
To satisfy the condition mentioned in the problem, every number has to occour excatly once.
Now, as the number lies in the range [0,.. n-1], the looping variable will also have the same possible range.
Variable temp , is originally set to 0.
Now, if all the numbers appear in this way, then each number will appear excatly twice.
And XORing the same number twice results in 0.
So, if in the end, when the whole array is traversed and a zero is obtained, this means that the array contains all the numbers excatly once.
Otherwise, multiple copies of a number is present, hence, this won't evaluate to 0.
hoping for some help with bitwise operators. The exercise reads as following:
Write a function called bitpat_search() that looks for the occurence of a specified pattern of bits inside an unsigned int. The function should take three arguments, and should be called as such:
bitpat_search (source, pattern, n)
The function searches for the integer "source", starting at the leftmost bit, to see if the rightmost n bits of "pattern" occur in "source". If the pattern is found, have the function return the number of the bit at which the pattern begins, where the leftmost bit is number 0. If the pattern is not found, then have the function return -1. So, for example, the call
index = bitpat_search (0xe1f4, 0x5, 3);
causes the bit_pat(search() function to search the number 0xe1f4 (= 1110 0001 1111 0100 binary) for the occurence of the three-bit pattern 0x5 (= 101 binary). The function returns 11 to indicate that the pattern was found in the "source" beginning with bit number 11.
Make certain that the function makes no assumptions about the size of an int.
I've got a few problems getting this working:
1- The numbers don't actually make much sense to me... I've tried all kinds of printf() functions after each itiration, and it looks like the 0x5 number gets read as 100 binary, which would be four. If I try other numbers they just come fairly random, but often as 000, so.... not very helpful. Am I counting them wrong? Does the right shift change it somehow?
2 - it's returning the wrong position (19 rather than 11), but while I'm messing up the numbers as my q1 above, it's not really going to work, is it?
Sorry if this is obvious to all you lovely people, I just can see it. (I'm just trying to learn from the book btw, it's not homework from school).
Thanks
#include <stdio.h>
int int_size(unsigned int num);
int bit_test(unsigned int word, int position, int size);
int bitpat_search(unsigned int source, unsigned int pattern, int n);
int main(void)
{
int index;
index = bitpat_search(0xe1f4, 0x5, 3);
printf(" Pattern found in position %i\n", index);
return 0;
}
int bitpat_search(unsigned int source, unsigned int pattern, int n)
{
int i, j, tempSource, tempPat, count;
int size = int_size(~0);
for (i = 0; i < size;)
{
count = 0;
for (j = 0; j < n; j++)
{
tempSource = bit_test(source, i, size);
tempPat = bit_test(pattern, j, size);
i++;
count++;
if (tempSource != tempPat)
break;
}
if (count == n)
return i - n;
}
return 0;
}
int bit_test(unsigned int word, int position, int size)
{
if( (word >> (size - position)) & 0x1) // shift bits in word 31 minus n spaces right, and AND word with hexadecimal 1
return 1; // if above is true (1 & 1) return 1
else
return 0;
}
int int_size(unsigned int num)
{
int size = 0;
while (num)
{
size++;
num >>= 1;
}
return size;
}
for (i = 0; i < size;)
{
count = 0;
for (j = 0; j < n; j++)
{
tempSource = bit_test(source, i, size);
tempPat = bit_test(pattern, j, size);
Here, you're checking a bit at position i in the source against a bit at position j in the pattern. That needs to be i+j in the source, otherwise you compare a pattern against one bit, rather than a pattern against a number of bits, in the source. Since the pattern 101 contains ones and a zero, you'll never find anything.
Side note: you can replace the int_size function by sizeof(int)*8. That assumes 8-bit bytes, but computers for which that assumption does not hold haven't been made since the early eighties, so that should be a fairly safe assumption.
1- The numbers don't actually make much sense to me... I've tried all kinds of printf() functions after each itiration, and it looks like the 0x5 number gets read as 100 binary, which would be four. If I try other numbers they just come fairly random, but often as 000, so.... not very helpful. Am I counting them wrong?
I can't comment on code you've not presented, but of course hex 0x5 is binary 101. I'm inclined to suppose that in your tests you printed different values than you thought you were printing, or that your mechanism for printing them was flawed.
Does the right shift change it somehow?
Shift operators leave their operands unchanged. Of course, if the right-hand operand of a conforming shift operation is non-zero then the result differs from the left-hand operand. If the left-hand operand is drawn from a variable, then you might conceivably overwrite that variable's value afterward.
2 - it's returning the wrong position (19 rather than 11), but while I'm messing up the numbers as my q1 above, it's not really going to work, is it?
I don't think your main problem is "messing up the numbers". Your implementation is problematic. Consider the key loop nest in your code:
for (i = 0; i < size;)
{
count = 0;
for (j = 0; j < n; j++)
{
tempSource = bit_test(source, i, size);
tempPat = bit_test(pattern, j, size);
i++;
count++;
Observe that you increment the outer loop's control variable on each iteration of the inner loop. As a result, you test the pattern only against every nth starting index in the source string. That is, you test non-overlapping sets of the source bits. You should instead test the whole pattern starting at every possible starting position.
Note also that you test starting positions where an n-bit pattern cannot possibly start, on account of there being fewer than n bits between that position and the end of the source string. In this case you will end up invoking undefined behavior by using an invalid right-hand operand to a shift operator.
In the proposed algorithm, except the revealed issue by #WouterVerhelst, it exists other issues causing a wrong result.
Issue 1 - In the function bit_test(), the tested-bit is not the expected one.
To test a bit from the leftmost side, replace (size - position) by
(size - (position + 1)).
int bit_test(unsigned int word, int position, int size)
{
if( (word >> (size - (position + 1))) & 0x1) //
return 1; // if above is true (1 & 1) return 1
else
return 0;
}
Issue 2 - To be tested as the same size of source, the pattern shall be aligned to left.
In the bitpat_search(), before for-loop, shift-left of (size-n)
bits.
int size = int_size(source);
pattern = pattern << (size-n);
Issue 3 - To have the correct count to be compared with n, the comparison of bits with the break; should be done before count++.
if (tempSource != tempPat)
break;
count++;
Issue 4 - The index result returned would be i instead of i - n (linked with Issue 5).
if (count == n)
return (i); // instead of (i - n);
Issue 5 - As #WouterVerhelst suggests, the comparison between source and pattern should be done for each bit.
for (i = 0; i < size;i++) // each bit ==> i++
{
count = 0;
for (j = 0; j < n; j++)
{
tempSource = bit_test(source, i+j, size);
tempPat = bit_test(pattern, j, size);
// not here i++;
if (tempSource != tempPat)
break;
count++;
}
if (count == n)
return (i);
}
Issue 6 - And the result in case of 'pattern not found' is -1.
return (-1); // Instead of (0);
so my requirements are
REQUIRES: n >= 1. Elements a[0] ... a[n-1] exist.
PROMISES
The return value is 1 if n == 1.
If n > 1, the return value is 1 if a[0] ... a[n-1] form
an arithmetic sequence.
PROMISES
Otherwise, the return value is 0.
my function so far is
int is_arith_seq(const int *a, int n)
{
assert(n >= 1);
if (n == 1)
return 1;
int i;
int initaldif = a[1]-a[0];
int currentdif,result;
for (i=0;i<n;i++)
{
currentdif = a[i+1]-a[i];
if(initaldif!=currentdif)
return 0;
}
return 1;
}
My code does not work,as I am completely stuck now, what can I do to correct it.
If array has n elements your for loop will cause a segmentation fault. It goes all the way to n-1 but you are accessing a[i+1]. a[n] is out of bounds. Modify like this :
for (i = 0; i < n - 1; i++)
{
currentdif = a[i+1]-a[i];
if (initaldif != currentdif)
return 0;
}
Problem is here
currentdif = a[i+1]-a[i];
What do you think will happen to this code during n-1 th iteration?
i = n-1 + 1 = n
Therefore the function either returns 1 if n=1 or returns 0 due to the error!
Off-by-one errors are one of the most common programming mistakes. A good way to quickly track many of these down is to look at the very first and last iterations of your loops.
Your intent is that your loop computes the differences
a[1]-a[0] a[2]-a[1] ... a[n-1]-a[n-2]
The first iteration has i=0 and computes a[1]-a[0], and the last iteration has i=n-1 and computes a[n]-a[n-1]. Whoops, that's wrong! Need to adjust the loop.
Your arithmetic sequence test should set the initialdif as you have done, but then predict what the next element is throughout the sequence. If any term fails, the string of numbers is not an arithmetic sequence:
int initaldif = a[1]-a[0];
for (i = 2; i < n; i++)
if (a[i] != a[i-1] + initaldif)
return 0;
return 1;
EDIT: Originally I had transcribed i++ not i--
The code now is as it was, and the code in the code block compiles and works.
Why, if unsigned int i; is used instead of int i; in the code snippet below, does using the function result in a segfault?
void insertion_sort_int_array(int * const Ints, unsigned int const len) {
unsigned int pos;
int key;
int i;
for (pos = 1; pos < len; ++pos) {
key = Ints[pos];
for (i = (pos - 1); (i >= 0) && Ints[i] > key; i--) {
Ints[i + 1] = Ints[i];
}
Ints[i + 1] = key;
}
}
THe posted code will fail in either case (possibly with a segfault, possibly only corrupting memory).
The inner loop starts at pos-1 and scans upwards in memory until some random condition is met - it does not check if it has passed the end of the array, so will run merrily on until it crashes or the end condition happens to be met by the (undefined) contents of the memory it is corrupting.
You probably meant to scan downwards in memory (using i-- in the loop), in which case it would fail because the loop will reach 0. Subtracting 1 from 0 gives you a very large positive number in an unsigned, so the loop will never end (i>=0 is always true) and it will access some memory somewhere in the region of Pluto.
insertionSort(array A)
begin
for x := 1 to length[A]-1 do
begin
value := A[x];
i := x - 1;
while i >= 0 and A[i] > value do
begin
A[i + 1] := A[i];
i := i - 1;
end;
A[i + 1] := value;
end;
end;
The only difference between the standard insertion sort algorithm and your code is that you're incrementing i instead of decrementing. That's your problem. I bet that in the code you're actually compiling and running, you have i-- instead of i++ in the inner loop. That's why the unsigned i makes a difference - it cannot be negative, so the inner loop will never end. Did you copy the code wrong when you posted?
EDIT:
Well, now that you changed the posted code, it all makes sense, right? An unsigned i will simply underflow to INT_MAX when you decrement it past 0, which will cause you to access memory outside of the array bounds.
What keeps i+1 within the bounds of your array 'ints'? It looks like badly formed data in your array will cause you to index into areas of memory which you shouldn't be in.
Why, if unsigned int i; is used
instead of int i; in the code snippet
below, does using the function result
in a segfault?
Because for unsigned int i, i >= 0 is always true, so your for loop is unlikely to terminate when you want.
You should always be extremely careful when looping backwards (from high to low) if your counter is unsigned.
i will [wraparound] causing access beyond the array limits.
Importing limits and comparing to UINT_MAX instead of the previous (i >= 0) fixes the issue:
#include <limits.h>
void insertion_sort_int_array(int * const Integers, unsigned int const N)
{
unsigned int o;
int target;
unsigned int i;
for (o = 1; o < N; o++) {
target = Integers[o];
for (i = (o - 1); (i != UINT_MAX) && (Ints[i] > target); i--) {
Integers[i + 1] = Integers[i];
}
Integers[i + 1] = key;
}
}