Checking the frequency of numbers throughout an array - c

I have the following code which I'm trying to use to show how many times a certain number appears throughout the array. I want it to print out how many times it counted a specific number. (all numbers range from 0-20, with an index of 0 - 99).
void count_frequency(int *number) {
int i;
int j;
int len = sizeof number / sizeof(int);
printf("%i\n", len);
printf("reached here");
for(i = 0; i < 99; i++){ //index{
int c = 0;
for(j = 0; j < 99; j++){
if(number[j] == number[i]){
c++;
}else{
continue;
}
}
printf("%i\n", c);
//printf("%i\n", number[i]);
}
}
int main(){
int i;
int table[MAX];
int len = sizeof table / sizeof(int);
printf("%ireached before loop\n", len);
for(i = 0; i < len; i++){
table[i] = random_in_range(0, 20);
}
count_frequency(table);
//printf("%i", sizeof(table) / sizeof(int));
return 0;
}

int len = sizeof number / sizeof(int);
will not going to give you what you are expecting. number is a pointer variable not an array. Change your function to
void count_frequency(int *number, int len) {
int i;
int j;
int index[21] = {0};
printf("%i\n", len);
printf("reached here");
for(i = 0; i < len; i++){ //index{
index[number[i]%21]++;
}
for(i = 0; i < 21; i++)
printf("%d", index[i]);
}
and your function call should be
count_frequency(table, len);

Here you are. Honestly there was some magical thinking in your code. This works - it's not "the best" but an improvement on what you had. Let me know if this isn't clear. My definition of rand_in_range is not completely accurate - it will bias very slightly towards lower numbers.
include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define random_in_range(a,b) ( rand() % ((b) - (a) + 1) + (a) )
void count_frequency(int *table, int *output, int n1, int n2) {
// n1 = number of elements in table
// n2 = number of elements in output
int i;
// int len = sizeof number / sizeof(int); <<<< meaningless!
// printf("%i\n", len);
// printf("reached here");
for(i = 0; i < n1; i++) { // loop over the elements in the table
output[table[i] %n 2]++; // using % n2 so we don't go outside bounds of array.
}
}
int main(){
int i;
int table[MAX];
int counts[21]={0}; // <<<< need a place to put the result
int len = sizeof table / sizeof(int);
for(i = 0; i < len; i++){
table[i] = random_in_range(0, 20);
}
count_frequency(table, counts, MAX, 21);
for(i = 0; i < 21; i++) {
printf("number %d - frequency %d\n", i, counts[i]);
}
return 0;
}
Output:
number 0 - frequency 3
number 1 - frequency 5
number 2 - frequency 3
number 3 - frequency 6
number 4 - frequency 6
number 5 - frequency 7
number 6 - frequency 3
number 7 - frequency 5
number 8 - frequency 6
number 9 - frequency 9
number 10 - frequency 4
number 11 - frequency 2
number 12 - frequency 6
number 13 - frequency 8
number 14 - frequency 3
number 15 - frequency 4
number 16 - frequency 5
number 17 - frequency 6
number 18 - frequency 6
number 19 - frequency 3
number 20 - frequency 0

So you're saying you have an array of 100 numbers, each ranging from 0-20, and you want to count the occurrences of a SINGLE number within that array? Then this should do:
size_t count_occurrences(int interesting_num, int* array, size_t array_size) {
size_t i, occurrences = 0;
for (i=0; i < array_size; ++i) {
if (array[array_size] == interesting_num) {
++occurrences;
}
}
return occurrences;
}
Technically, you could replace those "size_t"s with unsigned chars, for the number ranges you're talking about, but given the dynamic calculation of len that you attempted, and the use of "MAX", I suspect you may want to increase those ranges at some point. So, I'm erring on the side of a safer, more general implementation.

Related

How to convert each number in a num String to an int in C

I've been trying to do this problem on Project Euler
This is what I've done so far -
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char nums[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
int64_t sum = 1, new_sum = 0;
int num;
for(int i = 0; i < 988; i+= 13){
sum = 1
for(int j = 0; j < 13; ++j){
//Converting nums[i] to int and storing it to num here
sum *= num;
}
if(sum > new_sum){
new_sum = sum;
}
}
printf("%lld", new_sum);
}
I don't know how to convert each charNum in the String to an integer, I've tried atoi and sscanf and both of them ask for a char pointer.
I get these errors respectively
passing argument to parameter here
int atoi(const char *); //sum *= atoi(nums[i])
format specifies type 'int *' but the argument has type 'int' [-Wformat]
sscanf(nums[i], "%d", num);
Any help is appreciated.
Just converting a character representing a digit to the digit itself is simply done by
int digit = nums[position] - '0';
C language guarantees for any character set that the digits 0-9 are succeeding one another in exactly that order (which is not necessarily the case for alphabetic characters, see e.g. (in-?) famous EBCDIC).
As I read the problem the maximum can be at any location, not only multiples of 13. For this speaks as well that the maximum of four subsequent digits is found at a location where the number of digits preceding is not a multiple of four.
Apart from, unless the number if digits is a multiple of 13, your loops would exceed array bounds of nums, so undefined behaviour (if not a multiple of 13, then for last iteration of i there are less than 13 digits left, but j still tries to iterate over all 13 digits).
Fixing both:
size_t sequenceLength = 13; // could be a function parameter
size_t len = strlen(nums); // sizeof would include the terminating 0 character!
if(len < sequenceLength)
{
return 0; // if within a function, else whatever appropriate error handling
}
uint64_t max = 1; // can't have negative values anyway...
for(size_t i = 0; i < sequenceLength; ++i)
{
max *= nums[i] - '0'; // see above
}
// now we found first possible maximum: the product of first 13 digits
uint64_t num = max;
for(size_t i = sequenceLength; i < len; ++i)
{
// for next product, we have already included the first 12 digits
// within the previous product!
// but there is one surplus digit contained we need to eliminate:
num /= nums[i - sequenceLength] - '0';
// now we can include the yet missing one:
num *= nums[i] - '0';
// or as a one-liner:
num = num / (nums[i - sequenceLength] - '0') * (nums[i] - '0');
// TODO: update maximum, if need be, just as in your code
}
Would you please try the following:
#include <stdio.h>
#include <stdlib.h>
#define N 13
int main() {
char nums[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int64_t prod = 1, max_prod = 0;
int num;
int pos;
for (int i = 0; i < sizeof nums; i += N) {
prod = 1;
for (int j = 0; j < N; j++){
// Converting nums[i] to int and storing it to num here
num = nums[i + j] - '0';
prod *= num;
}
if (prod > max_prod) {
max_prod = prod;
pos = i;
}
}
printf("max product = %ld at %.*s\n", max_prod, N, nums + pos);
}
Output:
max product = 6270566400 at 4355766896648
BTW as the variable name sum is misleading, I've changed it to prod for product.
I assume that you want a nuber for each digit (i.e., range 0 to 9)
If yes, the below code should be not too far from what you need:
char nums[] = "73167176531330624919225119674426574742355349194934969835203... (so long)...";
char *p;
long lTheTotalCount, lTheNumber;
lTheTotalCount = 0;
for (p=nums ; *p ; p++) {
lTheNumber = (long)(*p - '0');
lTheTotalCount += lTheNumber;
};

Counting and deleting repeated digits of array elements

I need to write a program that allows user to enter an array of integers, finds the digit that appears most often in all entered numbers, and removes it from the elements of the array. If several digits appear the same number of times, the smallest of them should be deleted. If all digits of the element of the array are deleted, that element should become zero. In the end, such a modified array is printed.
Example of input and output:
Enter number of elements of the array: 5
Enter the array: 3833 8818 23 33 1288
After deleting, the array is: 8 8818 2 0 1288
Explanation: The numbers 3 and 8 appear the same number of times (6 times each), but 3 is less, so it was removed it from all members of the array. Element 33 consists exclusively of the digits 3, so that it becomes 0.
#include <stdio.h>
int main() {
int i,n,arr[100]; n;
printf("Enter number of elements of the array: ");
scanf("%d", &n);
printf("Enter the array: ");
for(i=0;i<n;i++) {
scanf("%d", &arr[i]);
}
return 0;
}
EDIT: I'm beginner to programming, and this task should be done using only knowledge learned so far in my course which is conditionals, loops, and arrays. This shouldn't be done with strings.
Divide the problem into separate tasks.
Write the code
In the code below I do not treat 0 as having digit 0. It is because it is not possible to remove 0 from 0. You can easily change this behaviour by changing while(){} loop to do{}while()
int removeDigit(int val, int digit)
{
int result = 0;
unsigned mul = 1;
int sign = val < 0 ? -1 : 1;
digit %= 10;
while(val)
{
int dg = abs(val % 10);
if(dg != digit)
{
result += dg * mul;
mul *= 10;
}
val /= 10;
}
return sign * result;
}
void countDigits(int val, size_t *freq)
{
while(val)
{
freq[abs(val % 10)]++;
val /= 10;
}
}
int findMostFrequent(const size_t *freq)
{
size_t max = 0;
for(size_t i = 1; i < 10; i++)
{
if(freq[i] > freq[max]) max = i;
}
return (int)max;
}
int main(void)
{
int table[20];
size_t freq[10] = {0,};
int mostfreq = 0;
srand(time(NULL));
for(size_t i = 0; i < 20; i++)
{
table[i] = rand();
printf("Table[%zu] = %d\n", i, table[i]);
countDigits(table[i], freq);
}
mostfreq = findMostFrequent(freq);
printf("Most frequent digit: %d\n", mostfreq);
for(size_t i = 0; i < 20; i++)
{
table[i] = removeDigit(table[i], mostfreq);
printf("Table[%zu] = %d\n", i, table[i]);
}
}
https://godbolt.org/z/PPj9s341b

for loop unexpectedly jumping down in value

Goldbach's conjecture states that every even integer over 4 is the sum of two primes, I am writing a program in C to find these pairs. To do this it first finds all the primes less than a user given number. I have a for loop to iterate from 4 to the user given number and find the pairs within the loop body. When that loop gets to about around 40, suddenly jumps back down by about 30 and then continues to iterate up (with user input 50 it jumped from 38 to 9, with input 60 it jumped from 42 to 7). I can't figure out why this is happening. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <unistd.h>
struct pair{
int a;
int b;
}pair_t;
int main(){
int N;
int numPrimes = 1;
int *primes = malloc(100*sizeof(int));
int isPrime = 1;
primes[0] = 2;
int timesRealloc = 0;
int availableSlots = 100;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
struct pair pairs[N/2 + 4];
int j = 0;
int i;
for (i = 3; i <= N; i+=2){
j = 0;
isPrime = 1;
while (primes[j] <= sqrt(i)) {
if (i%primes[j] == 0) {
isPrime = 0;
break;
}
j++;
}
if (isPrime == 1){
primes[numPrimes] = i;
numPrimes++;
}
if (availableSlots == numPrimes){
timesRealloc++;
availableSlots += 100;
primes = realloc(primes, availableSlots*sizeof(int));
}
}
printf("The largest prime I found was %d\n", primes[(numPrimes-1)]);
int k;
for (i=4; i<=N; i+=2){
printf("i is %d, N is %d\n", i, N);
if (i > N){ break; }
for (j=0; j<numPrimes; j++){
for (k=0; k<numPrimes; k++){
int sum = primes[j] + primes[k];
if(sum == i){
pairs[i].a = primes[j];
pairs[i].b = primes[k];
}
}
}
}
for (i=4; i<=N; i+=2){
printf("%d is the sum of %d and %d\n", i, pairs[i].a, pairs[i].b);
}
return 0;
}
You attempt to be space efficient by compressing the pairs array to just hold every other (even) number and start from 4 instead of zero. However, you miscalculate its size and then when you go to use it, you treat it like it hasn't been compressed and that there's a slot for every natural number.
The code suffers from having the prime array calculation in main() along with the other code, this is best separated out. And when it looks for pairs, it doesn't quit when it finds one, nor when it starts getting sums greater than the target. My rework below attempts to address all of these issues:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define INITIAL_SLOTS (100)
struct pair {
int a;
int b;
} pair_t;
int compute_primes(int limit, unsigned **primes, int size) {
int numPrimes = 0;
(*primes)[numPrimes++] = 2;
for (int i = 3; i <= limit; i += 2) {
bool isPrime = true;
for (int j = 0; (*primes)[j] <= i / (*primes)[j]; j++) {
if (i % (*primes)[j] == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
(*primes)[numPrimes++] = i;
}
if (numPrimes == size) {
size *= 2;
*primes = realloc(*primes, size * sizeof(unsigned));
}
}
return numPrimes;
}
int main() {
int N;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
unsigned *primes = calloc(INITIAL_SLOTS, sizeof(unsigned));
int numPrimes = compute_primes(N, &primes, INITIAL_SLOTS);
printf("The largest prime I found was %d\n", primes[numPrimes - 1]);
struct pair pairs[(N - 4) / 2 + 1]; // compressed data structure
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
bool found = false;
for (int j = 0; ! found && j < numPrimes; j++) {
for (int k = 0; ! found && k < numPrimes; k++) {
int sum = primes[j] + primes[k];
if (sum == i) {
pairs[offset].a = primes[j];
pairs[offset].b = primes[k];
found = true;
} else if (sum > i) {
break;
}
}
}
}
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
printf("%d is the sum of %d and %d\n", i, pairs[offset].a, pairs[offset].b);
}
free(primes);
return 0;
}
OUTPUT
> ./a.out
Please enter the largest even number you want to find the Goldbach pair for:
10000
The largest prime I found was 9973
4 is the sum of 2 and 2
6 is the sum of 3 and 3
8 is the sum of 3 and 5
10 is the sum of 3 and 7
12 is the sum of 5 and 7
14 is the sum of 3 and 11
...
9990 is the sum of 17 and 9973
9992 is the sum of 19 and 9973
9994 is the sum of 53 and 9941
9996 is the sum of 23 and 9973
9998 is the sum of 31 and 9967
10000 is the sum of 59 and 9941
>

how can I make this programme faster? [duplicate]

This question already has answers here:
Algorithm to find all the exact divisors of a given integer
(7 answers)
Closed 5 years ago.
The assignment was to write a program which reads in an integer k, and prints out the number of positive integers
between 1 and 100000 (inclusive) which have exactly k divisors. As an example, the number 24 has 8 divisors:
1, 2, 3, 4, 6, 8, 12, and 24.
I have a running programme, but is there anyway i could make the search faster??
#include <stdio.h>
#include <math.h>
int main(void)
{ int a; //user input//
int divisors; //running total of number of divisors//
int sum; //running total of numbers with the required number of divisors//
printf("Enter the target number of divisors:");
scanf("%d", &a);
printf("\n");
int i;
for (i=1; i<=100000; i++)
{
divisors=2;
int p;
for(p=2; p<i; p++)
{if (i%p==0)
divisors++;}
if (divisors==a)
sum++;}
printf("There are %d numbers between 1 and 100000 inclusive which have exactly %d divisors.", sum, a);
return 0;
}
Example code. Moved declarations for i and p to be compatible with old C type compilers (I'm using Microsoft / Visual Studio). Uses ceil(sqrt(i)) outer loops. The code handles an input of 1 (only the number 1 has 1 divisor). An input of 2 will output the number of prime numbers less than 100,000 (there are 9592 prime numbers less than 100,000).
This method takes a bit over 21 million iterations. Number of iterations ~= .67 n sqrt(n).
#include <stdio.h>
int main(void)
{
int a; /* user input */
int divisors; /* total number of divisors */
int sum; /* count of numbers with required number of divisors */
int i; /* moved here for C compiler */
int p; /* moved here for C compiler */
int sqrti; /* ceil(sqrt(i)) */
printf("Enter the target number of divisors: ");
scanf("%d", &a);
printf("\n");
sum = 0; /* init sum */
sqrti = 1; /* init sqrti */
for (i = 1; i <= 100000; i++)
{
divisors = 0; /* init number of divisors */
if(sqrti*sqrti < i) /* update sqrti as needed */
sqrti += 1;
for(p = 1; p < sqrti; p++)
if(i%p == 0) /* if p is a divisor, count it and i/p */
divisors += 2;
if(p*p == i) /* if p*p == i, count it */
divisors += 1;
if (divisors == a) /* if i has a divisors, increment sum */
sum += 1;
}
printf("There are %d numbers from 1 to 100000 inclusive which have exactly %d divisors.\n", sum, a);
return 0;
}
If an array can be used similar to sieve method for primes, this method takes a bit over 1 million iterations. Number of iterations ~= n ln(n).
#include <stdio.h>
#define n 100000
int main(void)
{
int * cnt = (int *)calloc(n+1, sizeof(int));
int d;
printf("Enter the target number of divisors: ");
scanf("%d", &d);
/* time complexity O(n log(n)) */
{
int i, j;
for (i = 1; i <= n; i++) {
for(j = i; j <= n; j += i) {
cnt[j]++;
}
}
}
{
int i;
int sum = 0;
for (i = 1; i <= n; i++)
sum += (cnt[i] == d) ? 1 : 0;
printf("excactly %d numbers have %d divisors\n", sum, d);
}
free(cnt);
return 0;
}
Rather than checking for the value of p uptil i we can optimize by checking until sqrt(i) and instead of incrementing divisors by 1, we increament it by 2, one for the number say k divided by i and second for the number i/k.
n=1000000;
for (i=1; i<=10000; i++)
{
divisors=2;
int p;
for(p=2; p<=sqrt(i); p++)
{
if (i%p==0)
{
if(p != (i/p)
divisors = divisors + 2;
else
divisors++;
}
}
if (divisors==a)
sum++;
}

Dynamic arrays C

So I am creating array and I need to find the number with highest divisors count, print the number, the count and divisors in decline order, if I create array with only 1 number my function works properly, but if I create it with 2 or more some divisors are changed into incorrect ones.
void calculate(int *data, int size){
int max;
int divisors[size][size];
int divisorssize[size];
//Checking for the divisors
for (int i = 0; i < size; i++){
divisorssize[i] = 0;
for (int j = data[i]; j >= 1; j--) {
if (data[i] % j == 0) {
divisorssize[i]++;
divisors[i][divisorssize[i]] = j;
}
}
}
//Searching for the number in the array with the highest divisors count
max = 0;
for (int i = 0; i < size; i++){
if (divisorssize[max] < divisorssize[i]){
max = i;
}
}
//divisors Output
printf("Max divisors: %d\n", data[max]);
printf("divisors count: %d\n", divisorssize[max]);
printf("divisors list: ");
for (int i = 1; i <= divisorssize[max]; i++){
printf("%d ", divisors[max][i]);
}
}
Function usage :
calculate(data, size);
So when I create array with size = 1; And input number 56 it shows all divisors: 56 28 14 8 7 4 2 1, but if for example the size is 2 and I input 56 and 1, it changes the divisors into this 56 28 1 8 7 4 2 1.
The problem is with your array sizes.
For example, with size 2
int arr[size][size];
Will be
int arr[2][2];
That is fine, as long as no number has more than two divisors...
The size of the second dimension needs to be big enough for any divisor count.
For example, find the largest number in *data, and use that
int array[size][max_number];

Resources