So I want to start by saying that I already solved the problem, but there is something that is bugging me,
Here is the code first:
#include <stdio.h>
int flag = 1;
int controlNumber(int);
int main() {
int array[10] = { 233, 45, 777, 81, 999999, 36, 90, 88, 11, 61 };
int i;
int c;
for (i = 0; i < 10; i++) {
printf("%d >> ", array[i]);
c = controlNumber(array[i]);
if (c == 1) {
printf("all digits are equal\n");
} else {
printf("not all digits are equal\n");
}
}
return 0;
}
int controlNumber(int a) {
int q = a;
int r = a % 10;
int temp;
while (q != 0) {
temp = q % 10;
if (temp == r) {
q = q / 10;
} else {
flag = 0;
return flag;
}
}
return flag;
}
The code works only if the global variable flag is made local inside the scope of the function controlNumber with a value of 1, and I can't really figure out why that is the case since the logic should still be the same.
Also, I'm still a beginner to some extend so I apologize for any indentation errors.
For starters it is a very bad idea to define a function that depends on a global variable. In fact it is the reason of the bug of your program. You forgot to reset the global variable flag to 1 each time before calling the function.
The function can be defined the following way without any redundant global variable
int controlNumber( int n )
{
const int Base = 10;
int digit = n % Base;
while ( ( n /= Base ) && ( n % Base == digit ) );
return n == 0;
}
Here is a demonstrative program.
#include <stdio.h>
int controlNumber( int n )
{
const int Base = 10;
int digit = n % Base;
while ( ( n /= Base ) && ( n % Base == digit ) );
return n == 0;
}
int main(void)
{
int array[] = { 233, 45, 777, 81, 999999, 36, 90, 88, 11, 61 };
const size_t N = sizeof( array ) / sizeof( *array );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d >> ", array[i] );
if ( controlNumber( array[i] ) )
{
printf( "all digits are equal\n");
}
else
{
printf( "not all digits are equal\n" );
}
}
return 0;
}
The program output is
233 >> not all digits are equal
45 >> not all digits are equal
777 >> all digits are equal
81 >> not all digits are equal
999999 >> all digits are equal
36 >> not all digits are equal
90 >> not all digits are equal
88 >> all digits are equal
11 >> all digits are equal
61 >> not all digits are equal
If for example you will change the constant Base in the function and make it equal to 8
int controlNumber( int n )
{
const int Base = 8; //10;
int digit = n % Base;
while ( ( n /= Base ) && ( n % Base == digit ) );
return n == 0;
}
then you will get the following result.
233 >> not all digits are equal
45 >> all digits are equal
777 >> not all digits are equal
81 >> not all digits are equal
999999 >> not all digits are equal
36 >> all digits are equal
90 >> not all digits are equal
88 >> not all digits are equal
11 >> not all digits are equal
61 >> not all digits are equal
In this case for example the number 45 has the same digits in the octal representation because in the octal representation the number is written like 055.
Global variables retain their value. In your case, if flag is global, once set to 0 (within controlNumber) it will keep that value. There is no other place in the code to make it 1 again.
Making it a local variable to the function will cause it to initialize to 1 every time the function is called.
Edit: if you want to have it as global, you could set it to 1 every time controlNumber returns 0, i.e., before or after printf("not all digits are equal\n");.
Related
I've gotta count how many times a certain digit is repeated in each number in a range. For example, in the numbers between 0 and 20, there is only one occurrence of 1 being repeated twice (11). I originally did this by converting the int to a str and iterating over it, but I would like to be able to solve this in an arithmetic way. Any ideas?
here is a general solution that you can use , your problem didn't contain much information so I assumed that you want to count the number of repeating of each digit in each number.
so what I did is like hashing where the digits in each number will never cross the value 9 , so they are from 0 to 9 so I made that hash table called arr, so what I did is to come to every single digit in number and increment the position of that digit in arr
for example , number 554 will cause arr[5]++; twice and arr[4]++; only once , simple idea of using hash tables.
and then at the end I iterate over the hash array printing the number of occurrence of each digit in each number.
and here is the code :
#include <stdio.h>
#include <math.h>
int main()
{
int arr[6] = {5555, 12112, 14, -3223, 44, 10001};
int tempArr[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for (int i = 0; i < 6; i++) {
int temp1 = arr[i];
// get the number of occurrences of each digit in each number
do{
tempArr[(abs(temp1) % 10)]++;
temp1 /= 10;
}while(temp1 != 0);
// loop over the array to know how many times each digit occurred
printf("the number of occurrences in number called %d\n", arr[i]);
for (int j = 0; j < 10; j++) {
if(tempArr[j] > 1)
printf("number %d occurred %d times\n", j, tempArr[j]);
// resetting that position of the array
tempArr[j] = 0;
}
}
return 0;
}
and here is the output :
the number of occurrences in number called 5555
number 5 occurred 4 times
the number of occurrences in number called 12112
number 1 occurred 3 times
number 2 occurred 2 times
the number of occurrences in number called 14
the number of occurrences in number called -3223
number 2 occurred 2 times
number 3 occurred 2 times
the number of occurrences in number called 44
number 4 occurred 2 times
the number of occurrences in number called 10001
number 0 occurred 3 times
number 1 occurred 2 times
You can divide your number multiple times by 10:
int number = 72;
int rest;
while(number)
{
rest = number % 10;
printf("%d\n", rest);
number /= 10;
}
Here rest contains '2' and then '7'
how many times a certain digit is repeated in each number in a range.
Pseudo code*1
Get the range: imin, imax (any int pair where imin <= imax)
Get the digit: digit 0 to 9
Iterate m from imin to imax, inclusive
.... Print m
.... Set digit_count = 0
.... Repeat
....... Last digit ld of m is abs(m%10).
....... If ld == digit, increment digit_count.
........ Divide m by 10
.... Until m == 0
.... Print digit_count
Done
*1 As OP did not provide code, seemed best to not provide a code answer.
Riffing on the answer provided by #Abdo Salm presented only to demonstrate a slightly alternative approach. All credit to Abdo.
EDIT: Going beyond single, arbitrary numbers to generating ascending contiguous sequence of numbers to be evaluated.
#include <stdio.h>
#include <string.h>
#include <limits.h>
void process( int n, int cnts[] ) {
// count occurences of each digit (right to left)
while( n )
cnts[ abs(n % 10) ]++, n /= 10;
}
void report( int cnts[], int thresh ) {
char *sep = "";
for( int j = 0; j < 10; j++ )
if( cnts[ j ] > thresh )
printf( "%s%dx%d", sep, cnts[ j ], j ), sep = ", ";
if( !*sep )
printf( "no digit occurred multiple times" );
putchar( '\n' );
}
int main() {
#ifndef PROVE
int tests[] = {
0, 11, 121, 5555, 12112, 14,
-3223, 44, 1223334444,
INT_MIN, INT_MAX,
};
// proof of concept: run through multiple arbitrary test values
for( int i = 0; i < sizeof tests/sizeof tests[0]; i++ ) {
// counter for each digit, all init'd to zero
int cnts[ 10 ];
memset( cnts, 0, sizeof cnts );
process( tests[ i ], cnts );
// report only digits appearing multiple times
printf( "%11d: ", tests[ i ] );
report( cnts, 1 );
}
#else // with "ranges" instead of arbitrary test cases
int ranges[][2] = {
{ 0, 10, },
{ 0, 22, },
{ 110, 133, },
{ 447, 448, },
};
for( int r = 0; r < sizeof ranges/sizeof ranges[0]; r++ ) {
int metacnts[10];
memset( metacnts, 0, sizeof metacnts );
for( int i = ranges[r][0]; i <= ranges[r][1]; i++ ) {
int cnts[ 10 ];
memset( cnts, 0, sizeof cnts );
process( i, cnts );
for( int j = 0; j < 10; j++ )
if( cnts[ j ] > 1 )
metacnts[ j ]++;
}
// report only digits appearing multiple times in numbers between min & max
printf( "Range %3d-%3d (incl) ", ranges[r][0], ranges[r][1] );
report( metacnts, 0 );
}
#endif
return 0;
}
/*
Output from arbitrary sequence:
0: no digit occurred multiple times
11: 2x1
121: 2x1
5555: 4x5
12112: 3x1, 2x2
14: no digit occurred multiple times
-3223: 2x2, 2x3
44: 2x4
1223334444: 2x2, 3x3, 4x4
-2147483648: 3x4, 2x8
2147483647: 3x4, 2x7
Output from arbitrary ranges:
Range 0- 10 (incl) no digit occurred multiple times
Range 0- 22 (incl) 1x1, 1x2
Range 110-133 (incl) 12x1, 1x2, 1x3
Range 447-448 (incl) 2x4
*/
Random numbers are printed in "numbers.txt". "numbers.txt" exists as a single line. The values here will be taken as two digits and assigned to the queue. I'm having trouble with the while part.
When the numbers in the Numbers.txt file are separated by two digits, I want to make the 0 in the tens digit a 1.
Example
numbers.txt :
839186660286459132876040232609
Output:
two-digit
83 91 86 66 2 86 45 91 32 87 60 40 23 26 9.
As you can see 02 and 09 written as 2 and 9. i want to 12 and 19.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 30
typedef struct stack
{
int value;
} Stack;
int *first, *last, *queue;
void kuyrukList()
{
printf("\nKuyruktaki Elemeanlar\n");
int *temp = first;
while (temp < last)
{
printf("%d ", *temp);
temp++;
}
}
void insert(int value)
{
*last = value;
last++;
}
int main()
{
//Random number.
srand(time(NULL));
int text[30] = {0};
FILE *dosyaYaz = fopen("numbers.txt", "w");
printf("\nOlusturulan number degeri:\n");
for (int i = 0; i < SIZE; i++)
{
text[i] = (rand() % 10);
printf("%d", text[i]);
fprintf(dosyaYaz, "%d", text[i]);
}
fclose(dosyaYaz);
printf("\n ");
//***********************************
char ch;
int number = 0;
int counter = 1;
queue = (int *)malloc(sizeof(int) * SIZE);
first = queue;
last = queue;
FILE *dosyaAc = fopen("numbers.txt", "r");
if (dosyaAc == NULL)
{
printf("\nDosya bulunamadi.\n");
exit(0);
}
while ((ch = fgetc(dosyaAc)) != -1)
{
if (counter % 2 == 1)
{
number += (ch - '0') * 10;
}
if (counter % 2 == 0)
{
number += (ch - '0');
insert(number);
number = 0;
}
counter++;
}
fclose(dosyaAc);
kuyrukList();
return 0;
}
So you are creating random numbers, but afterwards you modify them when they are smaller than 10? The easiest solution is to create random numbers who only vary from 10 to 99. This can be done as follows:
Imagine that double rand() generates a random number from 0 to 1 (both never being generated).
Then, 90 * rand() generates a random number from 0 to 90 (both never being generated).
Then, 10 + 90 * rand() generates a random number from 10 to 100 (both never being generated).
Then, (int)(10 + 90 * rand()) generates a random natural number, from 10 to 99 (both might be generated because of the rounding mechanism).
It appears from your stated goals that an array of 15 numbers ranging from 10 - 99 is the need. If that is true, skip writing to a file, and reading them back as a intermediate step and just create an array of 15, two digit numbers directly.
To do this, consider using a function to accept range and offset parameters (upper and lower values) and an array sized for each of the values to use with configuring rand(),.
The following can serve as the core of what you are doing by generating an array of pseudo randoms in the range you specify:
//generate an array of pseudo random values between lower and upper values
void gen_rand(int lower, int upper, int count, int *arr)
{
int i;
for (i = 0; i < count; i++)
{
arr[i] = (rand() % (upper - lower + 1)) + lower;
}
}
int main(void)
{
int arr[15];
srand(time(NULL));
gen_rand(10, 99, 15, arr);
return 0;
}
why the result of " (num >> i)& 1 " is 1 for the second loop?
main() {
char num = 5 ;
int i , count = 0 ;
for(i=0;i<8;i++){
if ((num >> i)& 1 )
count++;
}
printf("%d", count);
}
For starters pay attention to that the variable num itself is not being changed within the for loop
for(i=0;i<8;i++){
if ((num >> i)& 1 )
count++;
}
Its binary representation is
00000101
(Note take into account that the declaration
char num = 5 ;
differs from the declaration
char num = '5' ;
end note.)
In the first iteration of the loop when i is equal to 0 the shift operator has no effect so the if statement evaluates to logical true and the variable count will be incremented.
The variable count also will be incremented when i is equal to 2.
So as a result you will get that count is equal to 2 because in the internal representation of the variable num only two bits are set..
To make it more clearer rewrite the program the following way
#include <stdio.h>
int main(void)
{
char num = 5 ;
int count = 0 ;
for ( int i = 0; i < 8; i++ )
{
int result = (num >> i)& 1;
printf( "i = %d, result = %d\n", i, result );
if ( result ) count++;
}
printf( "\ncount = %d\n", count );
}
The program output is
i = 0, result = 1
i = 1, result = 0
i = 2, result = 1
i = 3, result = 0
i = 4, result = 0
i = 5, result = 0
i = 6, result = 0
i = 7, result = 0
count = 2
In fact the output from top to bottom shows the internal representation of the variable num starting from its less significant bit to the most significant bit.
This question already has answers here:
How to create a random permutation of an array?
(3 answers)
Closed 6 years ago.
i am doing a homework. i put rand function in a loop.
int counter = 1;
while ( counter <= 10 ){
variable1 = rand() % 5 + 1;
printf("%d", variable);
counter = counter + 1;
In this code, rand function assigns different value to variable called variable1 but sometimes it assigns same value because range of rand function is narrow. how can i perform that rand function assign different number to variable at the time when loop returns every time.
While rand() is not the greatest random function it should do the trick for many jobs and certainly for most homework. It is perfectly valid to have the same number returned twice in a row from a random function -- as the function should not have any memory of what values were previously returned.
The best way to understand this, is with an example of a coin-toss. Every coin toss is random, and the coin has no memory of the previous toss, so it is possible to flip a coin 32 times in a row and they all comes up head -- if every coin toss is a bit in a 32 bit integer you have created the binary value of integer zero.
However human tend to think (intuition) that having the same value returned more than once is "wrong" for a random function -- but our intuition is wrong on this account.
If you for some reason do want to not repeat the number from one loop to the next, then you will need to program that regardless of which random functions you use -- since any random function would be capable of returning the same values twice.
So something like this would do it;
int counter = 1;
int prevValue = -1;
while ( counter <= 10 ){
do {
variable1 = rand();
} while (variable1 == prevValue);
prevValue = variable1;
variable1 = variable1 % 5 + 1;
printf("%d", variable);
counter = counter + 1;
}
Note that this is still capable of printing the same value twice, since 10 and 15 would be different values before the %5 but would be the same after. If you want the %5 to be taken into account, so the printf never print the same value twice in a row, you would need to move the %5 inside the loop.
In your code snippet i can't find which instruction is the last one inside while. If you want to get different numbers every program run you should use srand() function before while.
But as you mentioned before. Your range (1 - 5) is to narrow to get 10 unique values every time.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
int counter = 1;
int variable1 = 0;
srand(time(NULL));
while ( counter <= 10 ) {
variable1 = rand() % 5 + 1;
printf("%d ", variable1);
counter = counter + 1;
}
putchar('\n');
return 0;
}
how can i perform that rand function assign different number to variable at the time when loop returns every time?
I take this to mean OP does not want to generate the same number twice in a row.
On subsequent iterations, use %(n-1)
int main(void) {
int counter;
int variable;
for (counter = 1; counter <= 10; counter++) {
// First time in loop
if (counter <= 1) {
variable = rand() % 5 + 1;
} else {
int previous = variable;
variable = rand() % (5 - 1) + 1;
if (variable >= previous) variable++;
}
printf("%d\n", variable);
}
return 0;
}
In order to generate a unique list of random numbers, you must check each number generated against the list of numbers previously generated to insure there is no duplicate. The easiest way is to store your previously generated numbers in an array to check against. Then you simply iterate over the values in the array, and if your most recent number is already there, create a new one.
For example, you can use a simple flag to check if your are done. e.g.
while (counter < MAXI){
int done = 0;
while (!done) { /* while done remains 0 (not done) */
done = 1;
tmp = rand() % MAXI + 1; /* generate radom number */
for (i = 0; i < counter; i++) /* check again previous */
if (tmp == array[i]) /* if num already exists */
done = 0; /* set as (not done) */
}
array[counter++] = tmp; /* assign random value */
}
Or you can use the old faithful goto to do the same thing:
while (counter < MAXI) {
gennum:
tmp = rand() % MAXI + 1;
for (i = 0; i < counter; i++)
if (tmp == array[i])
goto gennum;
array[counter++] = tmp;
}
Whichever makes more sense to you. Putting together a full example, you could do:
#include <stdio.h>
#include <stdlib.h> /* for rand */
#include <time.h> /* for time */
enum { MAXI = 10 };
int main (void) {
int array[MAXI] = {0}, counter = 0, i, tmp;
srand (time (NULL)); /* initialize the semi-random number generator */
while (counter < MAXI){
int done = 0;
while (!done) { /* while done remains 0 (not done) */
done = 1;
tmp = rand() % MAXI + 1; /* generate radom number */
for (i = 0; i < counter; i++) /* check again previous */
if (tmp == array[i]) /* if num already exists */
done = 0; /* set as (not done) */
}
array[counter++] = tmp; /* assign random value */
}
for (i = 0; i < MAXI; i++)
printf (" array[%2d] = %d\n", i, array[i]);
return 0;
}
(note: the number your mod (%) the generated number by must be equal to or greater than the number of values you intend to collect -- otherwise, you cannot generate a unique list.)
Example Use/Output
$ ./bin/randarray
array[ 0] = 8
array[ 1] = 2
array[ 2] = 7
array[ 3] = 9
array[ 4] = 1
array[ 5] = 4
array[ 6] = 3
array[ 7] = 10
array[ 8] = 6
array[ 9] = 5
A Shuffled Sequence
Given the discussion in the comments, a good point was raised concerning whether your goal was to create unique set of random numbers (above) or a random set from a sequence of numbers (e.g. any sequence, say 1-50 in shuffled order). In the event you are looking for the latter, then an efficient method to create the shuffled-sequence is using a modified Fisher-Yates shuffle knows as The "inside-out" algorithm.
The algorithm allows populating an uninitialized array with a shuffled sequence from any source of numbers (whether the source can be any manner of generating numbers). Essentially, the function will swap the values within an array at the current index with the value held at a randomly generated index. An implementation would look like:
/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
int i, val;
for (i = 0; i < n; i++) {
val = i ? randhq (i) : 0;
if (val != i)
a[i] = a[val];
a[val] = i; /* i here can be any source, function, etc.. */
}
}
(where randhq is any function that generates a random value (0 <= val < n))
A short example program that uses the function above to generate a shuffled array of value from 0 - (n-1) is shown below. The example generates a shuffled sequence of values in array using the inside-out algorithm, and then confirms the sequence generation by sorting the array:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void insideout_fill (int *a, int n);
int randhq (int max);
void prnarray (int *a, size_t n, size_t strd, int wdth);
int intcmp (const void *a, const void *b);
int main (int argc, char **argv) {
srand (time (NULL));
int arrsz = argc > 1 ? (int)strtol (argv[1], NULL, 10) : 50;
int array[arrsz];
insideout_fill (array, arrsz);
printf ("\n array initialized with inside-out fill:\n\n");
prnarray (array, arrsz, 10, 4);
qsort (array, arrsz, sizeof *array, intcmp);
printf ("\n value confirmation for inside-out fill:\n\n");
prnarray (array, arrsz, 10, 4);
return 0;
}
/** fill an uninitialized array using inside-out fill */
void insideout_fill (int *a, int n)
{
int i, val;
for (i = 0; i < n; i++) {
val = i ? randhq (i) : 0;
if (val != i)
a[i] = a[val];
a[val] = i; /* i here can be any source, function, etc.. */
}
}
/** high-quality random value in (0 <= val <= max) */
int randhq (int max)
{
unsigned int
/* max <= RAND_MAX < UINT_MAX, so this is okay. */
num_bins = (unsigned int) max + 1,
num_rand = (unsigned int) RAND_MAX + 1,
bin_size = num_rand / num_bins,
defect = num_rand % num_bins;
int x;
/* carefully written not to overflow */
while (num_rand - defect <= (unsigned int)(x = rand()));
/* truncated division is intentional */
return x/bin_size;
}
/** print array of size 'n' with stride 'strd' and field-width 'wdth' */
void prnarray (int *a, size_t n, size_t strd, int wdth)
{
if (!a) return;
register size_t i;
for (i = 0; i < n; i++) {
printf (" %*d", wdth, a[i]);
if (!((i + 1) % strd)) putchar ('\n');
}
}
/** qsort integer compare */
int intcmp (const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
Example Use/Output
$ ./bin/array_io_fill
array initialized with inside-out fill:
40 15 35 17 27 28 20 14 32 39
31 25 29 45 4 16 13 9 49 7
11 23 8 33 48 37 41 34 19 38
24 26 47 44 5 0 6 21 43 10
2 1 18 22 46 30 12 42 3 36
value confirmation for inside-out fill:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
Look it over and let me know if you have any questions.
How to count total number of digits from a given positive number without looping in C?
For integers, take the log10 of the number, round down, and add one.
TEST:
#include <math.h>
#include <stdio.h>
int
num_digits(unsigned long number)
{
return (int)(floor(log10((double)number)) + 1.0);
}
int
main(int argc, char **argv)
{
unsigned long test_numbers[] = {
1, 9, 10, 99, 100, 999, 1000, 9999, 10000, 99999, 100000, 999999,
123456789ul,
999999999ul,
0
};
unsigned long *ptr;
for(ptr = test_numbers; *ptr; ptr++)
{
printf("Number of digits in %lu: %d\n", *ptr, num_digits(*ptr));
}
return 0;
}
Output:
Number of digits in 1: 1
Number of digits in 9: 1
Number of digits in 10: 2
Number of digits in 99: 2
Number of digits in 100: 3
Number of digits in 999: 3
Number of digits in 1000: 4
Number of digits in 9999: 4
Number of digits in 10000: 5
Number of digits in 99999: 5
Number of digits in 100000: 6
Number of digits in 999999: 6
Number of digits in 123456789: 9
Number of digits in 999999999: 9
One possible solutions, assuming 16-bit integer values and logical expressions evaluating to 0 or 1. You could replace the conditions with (u > 99) ? 1 : 0 if you're worried about portability.
int digits( unsigned u)
{
return 1 + (u > 9) + (u > 99) + (u > 999) + (u > 9999);
}
Two solutions for you!
int digit_count(unsigned int n)
{
if (n < 10)
return 1;
else
return (1 + digit_count(n / 10));
}
and
unsigned int n = 50;
int i = 0;
HACK:
i++;
if (n < 10)
{
printf("Digits: %d\n", i);
}
else
{
n /= 10;
goto HACK;
}
Don't hate me for the last one :(
return snprintf(0, 0, "%d", num);