C: Different value every time program is run - c

I have a simple function in C to get whether an array is sorted, but I seem to be getting different values every time. Sometimes I get 3 tests passed and sometimes I get 2 tests passed and am unsure what the problem is.
int is_sorted(int a[], int n)
{
for(int i = 0; i < n; i++)
{
if(a[i] > a[i + 1])
{
return 0;
}
}
return 1;
}
int main()
{
int a[] = {2, 4, 9, 8, 12};
int b[] = {-5, -2, 0, 8, 11, 15};
int aa[] = {2, 18, 12, 9, 1, 2, 8, 11, 16, 3};
int c[] = {4, 6, 8, 10};
npassed = 0;
if(!is_sorted(a, 5))
{
npassed++;
}
if(is_sorted(b, 6))
{
npassed++;
}
if(!is_sorted(aa, 10))
{
npassed++;
}
if(is_sorted(c, 5))
{
npassed++;
}
printf("number passed is_sorted : %i\n", npassed);
}

your function accepts two arguments:
a: the array
n: the arrays size
to check if it is sorted you iterate over all elements and see if its next element is bigger than itself. To do that, you count with i from zero (the lowest possible index) to n-1 (the highest possible index).
But you always check if i is greater than i+1. And what happens if you reach the last possible index for i? Then i+1 is equal to n and therefore outside the array. And what's outside your array is random data.

Related

move duplicates to the end of array in c while preserving order - nlogn

I am stuck in this question for long time.
the question is - to move duplicates to the end of the array while preserving the order(time complexity must be O(nlogn)).
limitation:
order must be preserved.
can use only 1 helper array
the range of values in the array are not known and can be really large from n(which is the size fo the array).
values are positives.
time complexity - nlogn
example:
arr = {7, 3, 1, 2, 7, 9, 3, 2, 5, 9, 6, 2}, n = 12
result:
arr = {7, 3, 1, 2, 9, 5, 6, 2, 9, 2, 3, 7}
this what i did right now but i am stuck from thier:
copied original array to temp array
sort the temp array using quick sort
move duplicate to the end in temp array
i know that i need to do some comparison with the original array but this the part that i am stuck.
code:
int findDulpilcatesV2(int* arr, int n) {
int i, * tempArr, j = 0, countNonRepeatEl = 0, searchKeyIndex, elIndex;
tempArr = (int*)calloc(n, sizeof(int));
assert(tempArr);
// Saving original array in temp array
for (i = 0; i < n; i++)
{
tempArr[i] = arr[i];
}
// Sorting temp array
quickSort(tempArr, 0, n - 1);
// Move duplicates to the end
for (i = 0; i < n; i++)
{
if (tempArr[i] != tempArr[i+1])
{
swap(&tempArr[j], &tempArr[i]);
countNonRepeatEl++;
j++;
}
}
free(tempArr);
tempArr = NULL;
return countNonRepeatEl;
}

Displaying the values of an n-dimension array as a string

Provided that we have an integer array of arbitrary depth, how would we traverse through it in order to build a string that represents the array as a C-style initialization?
For instance:
int arr3D[2][3][2] = { {{0, 1}, {2, 3}, {4, 5}}, {{6, 7}, {8, 9}, {10, 11}} };
We only know:
the total number of values (in this case 12)
the number of "dimensions" (in this case 3)
each of the dimension indexes (in this case 2,3,2)
the values 0,1,2,3,4,5,6,7,8,9,10,11
How can we make a string out of that, that looks like this:
"{{{0,1},{2,3},{4,5}},{{6,7},{8,9},{10,11}}}" ?
Evidently, this can be done with a nested nested loop, but that would only work with a definite set of dimensions (3). What if we have 10 dimensions? That made me think I can use recursion, but then it became confusing when and how to put { } characters. I am currently thinking about a single linear scan that intelligently inserts { and } characters in the string 0,1,2,3,4,5,6,7,8,9,10,11 but I feel like the real-world approach would be something like an indefinite n-tree branch traversing algorithm.
As you mentioned there are no need for the ndim nested for loops; what you could do is to use concepts like stride. Like then in how many count you change a dimension and then you can build you string.
Since you have not written any example code, I will write pseudo code to show how this could be done. In final case, dimensions should be input and stride calculated dynamically. Also, it is better to build a string and print it at the end, but for exposition, I'll output character by character using printf().
void print_mat(int* ptr, int ndims, int* dims){
int *stride = malloc(sizeof(int)* ndims); // TODO: null check
// create stride array same size of dims
stride[ndims -1] = dims[ndims - 1];
for(int j = ndims - 2 ; j >= 0; j--)
stride[j] = dims[j] * stride[j + 1];
// loop over all elements, stride[0] has the length
for(int idx = 0 ; idx < stride[0]; idx++){
// print open { for each start dimension
for(int i = 0; i < ndims; i++)
if (idx % stride[i] == 0){printf("{");}
printf("%d", ptr[idx]);
// print close } for each end dimension
for(int i = 0; i < ndims; i++)
if ((idx + 1) % stride[ndims - i - 1] == 0){printf("}");}
printf(", "); // comma after each element
}
printf("\b\b \n"); // clear extra , at end (may not support in all terminals)
free(stride);
}
int main()
{
int arr3D[2][3][2] = { {{0, 1}, {2, 3}, {4, 5}}, {{6, 7}, {8, 9}, {10, 11}} };
int dims[3] = {2, 3, 2};
print_mat(&arr3D[0][0][0], 3, dims);
// same as
// print_mat((int *) arr3D, 3, dims);
return 0;
}
This produces the desired output:
{{{0, 1}, {2, 3}, {4, 5}}, {{6, 7}, {8, 9}, {10, 11}}}

Selection Sort Explanation

I've been working on a recursive function in C which takes an int array and its size and does a selection sort where the array should now be ordered from least to greatest:
void selection_sort(int integers[], size_t size)
{
if (size == 0) {
return;
}
int largest = 0;
int largest_index = 0;
int temp;
for (int i = 0; i < size; ++i) {
if (integers[i] > integers[largest_index]) {
largest_index = i;
}
}
temp = integers[largest_index];
integers[largest_index] = integers[size - 1];
integers[size - 1] = temp;
selection_sort(integers, size - 1);
}
So if integers contains 17, 8, 14, 25, and 11, after calling selection_sort, it will now contain 8, 11, 14, 17, and 25. The code works as it should, however, I was trying to trace the logic out on paper and I don't think I'm thinking of it correctly because I'm not getting the numbers that I should. I was wondering if someone could thoroughly explain the logic of the function step-by-step. Any help would be appreciated!
Lets break out your code to understand its workflow.
your function takes two arguments one is array and other is size of the array
selection_sort(int integers[], size_t size)
Second part, if size of the array is zero then return
if (size == 0) {
return;
}
Third part, define variables
int largest = 0; //this variable is not used
int largest_index = 0; //this is index for largest array value
int temp; //temporary variable for swapping
Fourth part finding the largest value index in array
for (int i = 0; i < size; ++i) { //Iterate array from 0 to size
if (integers[i] > integers[largest_index]) { /*check if current index value is greater than largest value index */
largest_index = i; /* if value is greater than current index value add index in largest_index variable */
}
In first iteration for array [17, 8, 14, 25, 11] largest_index will be 3 (25).
Fifth part, Swap highest value and last element of the array
[17, 8, 14, 25, 11] will become [17, 8, 14, 11, 25]
temp = integers[largest_index]; //take 25 in temp
integers[largest_index] = integers[size - 1];
integers[size - 1] = temp; //swap 11 with 25
Last part, call the function recursively with array of reduced size by 1 element
Example in first iteration array will [17, 8, 14, 11] and second iteration [11, 8, 14], it will keep decreasing array size till it returns(size becomes zero)
selection_sort(integers, size - 1);

How to Write a function that will return the value of the array element which does not have a matching pair?

I'd like to ask for a help regarding the function which has to return a value of the array element which does not have a matching pair.
For instance,
a) In the array [1, 1, 2, 3, 4, 3, 4], the element without a pair is 2.
b) In the array [1, 1, 2, 4, 3, 4, 2, 3, 4], the element without a pair is 4.
So far I come up with the code below. So basically it checks for the repetitive numbers, and thus works for the b) case; yet it doesn't works for the a) case. Any help regarding how to fix this code, so that it works for a) and b) cases, is welcome.
#include <stdio.h>
int ft_unmatch(int *tab, int length)
{
int i;
int j;
int count;
i = 0;
while (i < length)
{
j = i + 1;
count = 0;
if (tab[i] == tab[j])
{
count++;
while (j < length)
{
if (tab[i] == tab[j])
count++;
j++;
}
if (count % 2 != 0)
return (tab[i]);
}
i++;
}
return (tab[i]);
}
int main(void)
{
//some additional arrays to check the function
int tab[9] = {1, 1, 2, 4, 3, 4, 2, 3, 4};
//int tab[11] = {1, 1, 2, 4, 3, 1, 4, 2, 4, 3, 4};
// int tab[7] = {1, 1, 2, 3, 4, 3, 4};
printf("%d\n", ft_unmatch(tab, 9));
return (0);
}
Assuming that all elements in the array are integer numbers and have a matching pair except one, just keep XORing the elements until the last one. Your result at the end of the scan will be the unmatched element.
The reason why this works is that:
XOR is commutative (so a XOR b = b XOR a)
for every a, a XOR a = 0
for every a, 0 XOR a = a
Every element will be cancelled out by their matching pair except one: the one you are looking for.
example:
int result=0;
for (i = 0; i < length; i++) {
result = result ^ tab[i];
}
return result;
Then handle edge cases as you wish.
Many problems in this code:
You compare every number with all of the following ones. So in a), you compare the first 1 with all the other numbers and count two 1s, but then you count the second 1 again and won't find another, so you code returns 1.
Also, you are missing curly brackets following the if tab[i] == tab[j]) and you only get to the while(j<length)-loop if the first if(tab[i] == tab[j]is true.
One possible solution would be to remove the numbers that were already counted from the array, so you don't count them again, or sort the array and count until each increment. If you are only working with small numbers you could also iterate over every possible number and count how often it appears, although that would be less elegant.

Remove elements from a given array

I am doing an problem on Leetcode. The question is that given an array and a value, remove all instances of that value in place and return the new length.
Or you can read it here:
int removeElement(int* nums, int numsSize, int val) {
int *nums_copy;
int count = 0;
int actual_count = 0;
while (actual_count < numsSize) {
if (nums[actual_count] != val) {
nums_copy[count] = nums[actual_count];
count++;
nums_copy = realloc(nums_copy, sizeof(int)* count);
}
actual_count++;
}
nums = nums_copy;
return actual_count;
}
When I tried to test it with [1, 2, 2, 3], 2, the output is [1, 2, 2, 3] while the expected output is [1, 3].
Firstly, you don't need to realloc, the problem says to remove the value in place. Secondly, what you need to do is to simply walk through the array and shift it one position to the left when you encounter the searched value. And decrement the resulted count.
The problem does not need to memory allocation. All that is needed is to have the matching elements towards the end of the list. Here is an example.
array = 3, 2, 5, 2, 7, 2
len = 6
val = 2
We want to achieve something like
array = 3, 7, 5, 2, 2, 2
newlength = 3
SOLUTION One approach is the following
Repeat:
Start with two marker (either index or pointer) one pointing to the leftmost and one pointing to the rightmost element
3, 2, 5, 2, 7, 2
L R
Move the left marker to the right if it matches to 'val'. Do it until the matching stops or it reaches the right marker.
3, 2, 5, 2, 7, 2
L R
(Opposite for right marker.) Move the right marker to the left if it matches to 'val'. Do it until the matching stops or it reaches the left marker.
3, 2, 5, 2, 7, 2
L R
Swap the elements corresponding to the left and right markers.
3, 7, 5, 2, 2, 2
L R
Go to Repeat.
Apparently, you have not specified how much memory you want to allocate after int *nums_copy. Use malloc from stdlib to allocate variable amount of memory on heap, or alloca to allocate on stack, but bear this in mind.
Here this should work:
int removeElement(int* nums, int numsSize, int val) {
int countNums = 0;
int countCpy = 0;
while (countNums < numsSize) {
if (nums[countNums] != val) {
// Copy the number.
nums[countCpy] = nums[countNums];
++ countCpy;
}
++ countNums;
}
return countCpy;
}
As for why this output you got was [1, 2, 2, 3], I don't really understand. As you're trying to set nums_copy[0] before having allocated nums_copy, you should be getting a segfault. I suppose it's due to the platform you're coding on.
The given code uses std::vector, so why not use its build-in functions?
int removeElement(vector<int>& nums,int val){
vector<int> newNums();
for (int i=0; i<nums.size(); i++){
if (nums[i]!=val){
newNums.push_back(nums[i]);
}
}
return newNums.size();
}
int removeElement(int* nums, int numsSize, int val) {
int i, j;
for(i = 0, j = 0 ; i < numsSize ; i++){
if( nums[i] == val ) continue;
nums[ j ] = nums[ i ]; // blind copy
j++;
}
/*
nums = realloc( nums, j * sizeof( int ) );
*/
return j; //actual_count
}

Resources