Counting Sort displays a weird behavior - c

I have implemented a Counting Sort in an assignment given to us by a teacher but sometimes it doesn't work for large arrays.
Here is the code:
void countingSort(int *t, int n) {
int min = findMin(t, n);
int max = findMax(t, n);
int range = max - min + 1;
int *count, *output;
int i;
count = (int *)malloc(range * sizeof(int));
output = (int *)malloc(n * sizeof(int));
for (i = 0; i < range; i++) {
count[i] = 0;
}
for (i = 0; i < n; i++) {
count[t[i] - min]++;
}
for (i = 1; i < range; i++) {
count[i] += count[i - 1];
}
for (i = n - 1; i >= 0; i--) {
output[count[t[i] - min] - 1] = t[i];
count[t[i] - min]--;
}
for (i = 0; i < n; i++) {
t[i] = output[i];
}
}
What's wrong with my code?

Your code seems to work for small values of range, but might fail if min and max are too far apart, causing the computation of range to overflow the range of int and malloc() to fail.
You should check for overflow in range and check memory allocation success. Note too that calloc() is more appropriate than malloc() for the count array. Finally, you must free the allocated arrays.
Here is a modified version:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int findMax(const int *t, int n) {
int max = INT_MIN;
while (n-- > 0) {
if (max < *t) max = *t;
t++;
}
return max;
}
int findMin(const int *t, int n) {
int min = INT_MAX;
while (n-- > 0) {
if (min > *t) min = *t;
t++;
}
return min;
}
int countingSort(int *t, int n) {
int min, max, range, i;
int *count, *output;
if (n <= 0)
return 0;
min = findMin(t, n);
max = findMax(t, n);
if (min < 0 && max >= 0 && (unsigned)max + (unsigned)(-min) >= INT_MAX) {
fprintf(stderr, "countingSort: value range too large: %d..%d\n", min, max);
return -1;
}
range = max - min + 1;
if ((count = (int *)calloc(range, sizeof(int))) == NULL) {
fprintf(stderr, "countingSort: cannot allocate %d element count array\n", range);
return -1;
}
if ((output = (int *)malloc(n * sizeof(int))) == NULL) {
fprintf(stderr, "countingSort: cannot allocate %d element output array\n", n);
free(count);
return -1;
}
for (i = 0; i < n; i++) {
count[t[i] - min]++;
}
for (i = 1; i < range; i++) {
count[i] += count[i - 1];
}
for (i = n; i-- > 0;) {
output[count[t[i] - min] - 1] = t[i];
count[t[i] - min]--;
}
for (i = 0; i < n; i++) {
t[i] = output[i];
}
free(count);
free(output);
return 0;
}
You can avoid the cumbersome and potentially inefficient downward loop by replacing the second and third for loops with this:
/* compute the first index for each value */
int index = 0;
for (i = 0; i < range; i++) {
incr = count[i];
count[i] = index;
index += incr;
}
/* copy each value at the corresponding index and update it */
for (i = 0; i < n; i++) {
output[count[t[i] - min]++] = t[i];
}

Related

I want to store elements of maximum and minimum frequency in the arr2 array ? But not able to

I want to store elements of maximum and minimum frequency in the arr2 array if there are more than one element of same frequency then both the elements should be stored ? But it is showing wrong results and i am not able to find what is the err. Can anyone help me with this. Any kind of help would be greatly appreciated.
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int arr[n];
for (int i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
int arr2[n];
int prevcount = 0;
int k = 0;
// for finding max element
for (int i = 0; i < n; i++)
{
int count = 0;
//counting the number of times it has occured
for (int j = 0; j < n; j++)
{
if (arr[i] == arr[j])
{
count++;
}
}
// checking if the same element was not there in the new array
for (int i = 0; i < k; i++)
{
if (arr[i] == arr[k])
{
goto nextit;
}
}
//it will update the kth element if the count is greater than the prev count
if (prevcount < count)
{
arr2[k] = arr[i];
}
//if these both are same but the number is different then will iterate k by 1 and store that element as well
else if (prevcount == count)
{
k++;
arr2[k] = arr[i];
}
prevcount = count;
nextit:
}
// for finding min element
prevcount = 1000;
for (int i = 0; i < n; i++)
{
int count = 0;
for (int j = 0; j < n; j++)
{
if (arr[i] == arr[j])
{
count++;
}
}
// checking if the same element was not there in the new array if there is then go to the next iteration
for (int i = 0; i < k; i++)
{
if (arr[i] == arr[k])
{
goto nextit2;
}
}
if (prevcount > count)
{
arr2[k] = arr[i];
}
else if (prevcount == count)
{
k++;
arr2[k] = arr[i];
}
prevcount = count;
nextit2:
}
for (int i = 0; i < k; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
As #SparKot suggests, sorting the array makes the problem simple. Would you please try:
#include <stdio.h>
#include <stdlib.h>
// compare values numerically
int numeric(const void *a, const void *b)
{
return (*(int *)a < *(int *)b) ? -1 : (*(int *)a > *(int *)b);
}
int main()
{
int n, i, j;
int *arr; // input array
int *count; // count frequency: initialized to 0's by calloc
int min = 0; // minimum occurrences
int max = 0; // maximum occurrences
scanf("%d", &n);
if (NULL == (arr = malloc(n * sizeof(int)))) {
perror("malloc");
exit(1);
}
if (NULL == (count = calloc(n, sizeof(int)))) {
perror("calloc");
exit(1);
}
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
qsort(arr, n, sizeof(int), numeric);
// count the length of sequence of the same numbers
for (i = 0; i < n; i++) {
for (j = 0; i + j < n && arr[i] == arr[i + j]; j++) {
;
}
count[i] = j; // i'th element has length j
i += j - 1; // jump to next number
}
// find minimum and maximum frequencies
for (i = 0; i < n; i++) {
if (count[i]) {
if (min == 0 || count[i] < min) min = count[i];
if (max == 0 || count[i] > max) max = count[i];
}
}
// report the result
for (i = 0; i < n; i++) {
if (count[i] == min) {
printf("min frequency %d value %d\n", count[i], arr[i]);
}
if (count[i] == max) {
printf("max frequency %d value %d\n", count[i], arr[i]);
}
}
return 0;
}
Sample input (n=10):
6
1
2
5
1
2
3
1
3
6
Output:
max frequency 3 value 1
min frequency 1 value 5

modified version of selection sort in C

I'm trying to modify selection sort in such a way that it puts the biggest element at the end of the array and then repeats selection sort for n - 1 items until n is 0. My code compiles but the output is still an unsorted array, please help me out!
#include <stdio.h>
void selection_sort(int arr[], int n);
int main ()
{
int n;
scanf("%d", &n);
int arr[n];
for (int i = 0; i < n; i++)
scanf("%d", &arr[i]);
selection_sort(arr, n);
for(int i = 0; i < n; i++)
printf("%d\n", arr[i]);
return 0;
}
void selection_sort(int arr[], int n)
{
if(n <= 0)
return;
while(n > 0)
{
int max = 0;
int temp, x;
for(int i = 0; i < n; i++)
{
if(arr[i] >= max)
max = arr[i];
x = i;
}
temp = arr[n - 1];
arr[n - 1] = max;
arr[x] = temp;
selection_sort(arr, --n);
}
}
The part
if(arr[i] >= max)
max = arr[i];
x = i;
is wrong. You forgot to write {}, so x = i; is executed unconditionally and the swapping after the loop will always be done with the last element. This means that the swapping is done between the same element and it is effectively doing nothing.
Also note that doing both of loop while(n > 0) and recursion selection_sort(arr, --n); is wasteful. You will need only one of that.
Another note is initializing max with 0 will make it behave wrongly when all elements of the input array are negative.
Finally, you should format your code properly with consistent indentation.
Try this:
void selection_sort(int arr[], int n)
{
if(n <= 0)
return;
while(n > 0)
{
int max = arr[0];
int temp, x;
for(int i = 0; i < n; i++)
{
if(arr[i] >= max)
{
max = arr[i];
x = i;
}
}
temp = arr[n - 1];
arr[n - 1] = max;
arr[x] = temp;
--n;
}
}

Binary algorithm for calculating greatest common divisor of big integers

In order to calculate GCD of two Big Integers, I used binary algorithm and save big integers in arrays to calculate the GCD of two big integers efficiently.
Input
One line containing two integers, a and b, where 0 < a, b < 10^256
Output
Please output an integer representing gcd(a, b).
Time limits
1 s
Sample Input 1
20210208 80201202
Sample Output 1
6
Sample Input 2
987654321987654321987654321 123456789123456789123456789
Sample Output 2
9000000009000000009
I have tried worst case scenario like 10^256 - 1 and 1, which is can be calculated within 1 s. Also ,
I have passed sample test and some other test data. However, when I upload code down below to the judge system, most of the test data shows TLE and few even shows WA. What's the problem of my code? Is there any other worse scenario cases that I missed ?
pseudo code of Binary Algorithm
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define SIZE 256
void rev(char *string, int len);
bool zero(int *to_array, int size);
void divided_by_2(int *ptr, int size);
bool comparison(int *m, int *n, int size);
void substraction(int *m, int *n, int size);
void twice(int array[], int k, int size);
int main(void){
char string_1[SIZE], string_2[SIZE];
scanf("%s%s", string_1, string_2);
int len_a = strlen(string_1);
int len_b = strlen(string_2);
char string_a[len_a], string_b[len_b];
strcpy(string_a, string_1);
strcpy(string_b, string_2);
/*reverse the string*/
rev(string_a, len_a);
rev(string_b, len_b);
int max_size = len_a;
if (len_b > len_a)
max_size = len_b;
int a[max_size], b[max_size];
for (int i = 0; i < max_size; i++){
if (i >= len_a)
a[i] = 0;
else
a[i] = string_a[i] - '0';
}
for (int i = 0; i < max_size; i++){
if (i >= len_b)
b[i] = 0;
else
b[i] = string_b[i] - '0';
}
int k = 0; /* k for power*/
int *m = a, *n = b;
/*binary algorithm for GCD */
while(!zero(m, max_size) && !zero(n, max_size)){
if (m[0] % 2 == 0 && n[0] % 2 == 0){
k++;
divided_by_2(m, max_size);
divided_by_2(n, max_size);
}else if (m[0] % 2 == 0)
divided_by_2(m, max_size);
else if (n[0] % 2 == 0)
divided_by_2(n, max_size);
if (comparison(n, m, max_size)){
int *temp = n;
n = m;
m = temp;
}
substraction(m, n, max_size);
}
twice(n, k, max_size);
bool zero = true;
for (int i = (max_size - 1); i >= 0; i--){
if (n[i] != 0 && zero)
zero = false;
if (!zero)
printf("%d", n[i]);
}
return 0;
}
void rev(char string[], int len){
char rev[len];
for (int i = 0; i < len; i++){
rev[i] = string[len - i - 1];
}
for (int i = 0; i < len; i++){
string[i] = rev[i];
}
}
bool zero(int *to_array, int size){
for (int i = 0; i < size; i++){
if (to_array[i] != 0)
return false;
}
return true;
}
void twice(int *array, int k, int size){
int carry = 0;
for (int i = 0; i < k; i++)
for (int index = 0; index < size; index++){
int digit = array[index];
if (digit == 0 && carry == 0)
continue;
digit *= 2;
digit += carry;
if (digit >= 10){
array[index] = digit % 10;
carry = digit / 10;
}else{
array[index] = digit;
carry = 0;
}
}
}
void divided_by_2(int *ptr, int size){
int digit = ptr[0];
for (int index = 0; index < size; index++){
if (index == size - 1){
ptr[index] = digit / 2;
break;
}
int prev = ptr[index + 1];
if (prev % 2 == 0)
ptr[index] = digit / 2;
else{
ptr[index] = (digit + 10) / 2;
ptr[index + 1] -= 1;
}
digit = ptr[index + 1];
}
}
bool comparison(int *m, int *n, int size){
bool larger = false;
for (int index = 0; index < size; index++){
if (m[index] > n[index])
larger = true;
else if (n[index] > m[index]){
larger = false;
}
}
return larger;
}
void substraction(int *m, int *n, int size){
int borrow = 0;
for (int i = 0; i < size; i++){
int digit = m[i] - n[i];
digit -= borrow;
if (digit >= 0){
m[i] = digit;
borrow = 0;
}else{
m[i] = digit + 10;
borrow = 1;
}
}
}

The pointer variables overflows when they store integers larger than 1024 and some adresses seem to be locked.in C

How do I get to write to 2D pointers where I have pnumber[2%4][2%4] and how can I get pnumber with more than 3 ciphers to be displayed?
I'm making a program to write pascals triangle in C.
When the pointer pnumbers[i][j] have both i and j = 2 mod 4, except for when i and j = 2, then my program won't write to the address and give the error message:
pascals triangle: malloc.c:2406: sysmalloc: Assertion '{old_top == initial_top (av) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =7;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
/*
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
*/
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
When I avoid writing to these addresses and just print them out I get some seemingly random integer at these memory addresses.
Also when avoid these addresses and just print out so many rows that I get some spots with a higher integer with more than 3 siphers, it seems to overflow - and I don't see the logic behind it.
The result of running the second code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =20;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
/*
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
*/
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
But row number 13 is still quite messed up.
Code is experiencing int overflow and thus undefined behavior (UB).
With 32-bit int and int factorial(int p), p > 12 oveflows the int range.
Code could use a wider integer type (long long works up to p==20), but improvements can be made at NchooseM() to avoid overflow for higher values.
Something like the below. Works up to int n = 30;
int NchooseM(int n, int m) {
// return factorial(n)/(factorial(n-m)*factorial(m));
int nm = 1;
int den = 1;
for (int i = m+1; i <= n; i++) {
assert(INT_MAX/i >= nm);
nm *= i;
assert(nm % den == 0);
nm /= den++;
}
return nm;
}
Tried unsigned long long and works up to int n = 62;
Edit: Another bug:
I "fixed" by initializing all to 1, yet I suspect something remains amiss in /* Calculating the value of pnumbers[k][l] */ for (i = 0; i < n; i++) { code.
pnumbers[i] = malloc((i + 1) * sizeof pnumbers[i][0]);
for (int j = 0; j < i + 1; j++) {
pnumbers[i][j] = 1;
}
Aside: rather than pnumbers[i] = (int *) malloc((i+1) * sizeof(int));, consider below with no unneeded cast nor trying to match the right type.
pnumbers[i] = malloc(sizeof pnumbers[i][0] * (i+1));

My program for printing longest palindrome subsequence isn't working, When I run it,console windows stops working after taking input

#include <stdio.h>
#include <string.h>
int ai, aj; // ai and aj to store the value of i and j respectively
int maxx(int a, int b) { // to return max of the two numbers
return (a <= b) ? b : a;
}
void LongestPal(char a[], int n) { // to find longest palindrome
int i, j, max = 0;
int p[1000][1000] = { 0 };
for (j = 0; j < n; j++)
for (i = 0; i <= j; i++) {
if (i == j) { // for one string having only one character
p[i][j] = 1;
if (max < p[i][j]) {
max = p[i][j];
ai = i;
aj = j;
}
}
if (j == (i + 1)) { // for string having two characters
if (a[i] == a[j]) { // if the string is like "aa","bb" etc.
p[i][j] = 2;
if (max < p[i][j]) {
max = p[i][j];
ai = i;
aj = j;
}
} else { // if string like "ab","ba" etc.
p[i][j] = 1;
if (max < p[i][j]) {
max = p[i][j];
ai = i;
aj = j;
}
}
} else { // for all other type of strings
if (a[i] == a[j]) { // if a longer palindrome found
p[i][j] = p[i-1][j-1] + 2;
if (max < p[i][j]) {
max = p[i][j];
ai = i;
aj = j;
}
} else { // if no longer palindrome is present
p[i][j] = maxx(p[i+1][j], p[i][j-1]);
if (max < p[i][j]) {
max = p[i][j];
ai = i;
aj = j;
}
}
}
}
}
int main() {
int i, j, n;
char a[1000];
printf("Just enter the string hoss!\n");
scanf("%s", &a);
n = strlen(a);
LongestPal(a, n);
for (i = ai; i <= aj; i++)
printf("%c", a[i]);
return 0;
}
In this program I wanna find longest palindrome Subsequence, but unable to run program
I have written comments for each case
This program for printing longest palindrome subsequence isn't working, When I run it, the Windows console stops working after taking input.
Your program fails because it allocates too much data with automatic storage (aka on the stack). int p[1000][1000] uses 4MB, probably too much for your system default stack size. You can try and use less space by allocating this array as:
int p[n][n];
This is allowed in C99, but your compiler might not support C99.
Your algorithm is a little complicated. Why not enumerate all positions for i and j and just verify with an auxiliary function if you have a palindrome there and keep track of the longest one:
#include <stdio.h>
#include <string.h>
int isPalindrome(const char *a, int i, int j) {
for (; i < j; i++, j--) {
if (a[i] != a[j])
return 0;
}
return 1;
}
void getLongestPalindrome(const char *a, int n, int *ai, int *aj) {
int i, j, maxi, maxj;
for (maxi = maxj = i = 0; i < n; i++) {
for (j = n - 1; j > i + maxj - maxi; j--) {
if (isPalindrome(a, i, j)) {
maxi = i;
maxj = j;
break;
}
}
}
*ai = maxi;
*aj = maxj;
}
int main(void) {
char a[1000];
int i, j;
printf("Enter the string: ");
if (scanf("%999s", a) == 1) {
getLongestPalindrome(a, strlen(a), &i, &j);
printf("longest palindrome at %d..%d: %.*s\n", i, j, j - i + 1, a + i);
}
return 0;
}

Resources