I have to write a program that finds every number (except 0) which can be factored by numbers from 2-9.
For example first such a number would be number 2520 as it can be divided by every single number from 2 to 9.
It also has to be a number that contains only 1 type of digit of its own (no multiple digits in a number). So for example 2520 will not meet this requirement since there are two same digits (2). The example of a number that meets both requirements is number 7560. That is the point I don't how to do it. I was thinking about converting value in an array to string, and then putting this string in another array so every digit would be represented by one array entry.
#include <stdio.h>
#include <math.h>
int main() {
int i, n, x, flag, y = 0;
scanf("%d", &n);
double z = pow(10, n) - 1;
int array[(int)z];
for (i = 0; i <= z; i++) {
flag = 0;
array[i] = i;
if (i > 0) {
for (x = 2; x <= 9; x++) {
if (array[i] % x != 0) {
flag = 1;
}
}
if (flag == 0) {
y = 1;
printf("%d\n", array[i]);
}
}
}
if (y == 0) {
printf("not exist");
}
return 0;
}
This should give you a base:
#include <stdio.h>
#include <string.h>
int main()
{
char snumber[20];
int number = 11235;
printf("Number = %d\n\n", number);
sprintf(snumber, "%d", number);
int histogram[10] = { 0 };
int len = strlen(snumber);
for (int i = 0; i < len; i++)
{
histogram[snumber[i] - '0']++;
}
for (int i = 0; i < 10; i++)
{
if (histogram[i] != 0)
printf("%d occurs %d times\n", i, histogram[i]);
}
}
Output:
Number = 11235
1 occurs 2 times
2 occurs 1 times
3 occurs 1 times
5 occurs 1 times
That code is a mess. Let's bin it.
Theorem: Any number that divides all numbers in the range 2 to 9 is a
multiple of 2520.
Therefore your algorithm takes the form
for (long i = 2520; i <= 9876543210 /*Beyond this there must be a duplicate*/; i += 2520){
// ToDo - reject if `i` contains one or more of the same digit.
}
For the ToDo part, see How to write a code to detect duplicate digits of any given number in C++?. Granted, it's C++, but the accepted answer ports verbatim.
If i understand correctly, your problem is that you need to identify whether a number is consisted of multiple digits.
Following your proposed approach, to convert the number into a string and use an array to represent digits, i can suggest the following solution for a function that implements it. The main function is used to test the has_repeated_digits function. It just shows a way to do it.
You can alter it and use it in your code.
#include <stdio.h>
#define MAX_DIGITS_IN_NUM 20
//returns 1 when there are repeated digits, 0 otherwise
int has_repeated_digits(int num){
// in array, array[0] represents how many times the '0' is found
// array[1], how many times '1' is found etc...
int array[10] = {0,0,0,0,0,0,0,0,0,0};
char num_string[MAX_DIGITS_IN_NUM];
//converts the number to string and stores it in num_string
sprintf(num_string, "%d", num);
int i = 0;
while (num_string[i] != '\0'){
//if a digit is found more than one time, return 1.
if (++array[num_string[i] - '0'] >= 2){
return 1; //found repeated digit
}
i++;
}
return 0; //no repeated digits found
}
// test tha function
int main()
{
int x=0;
while (scanf("%d", &x) != EOF){
if (has_repeated_digits(x))
printf("repeated digits found!\n");
else
printf("no repeated digits\n");
}
return 0;
}
You can simplify your problem from these remarks:
the least common multiple of 2, 3, 4, 5, 6, 7, 8 and 9 is 2520.
numbers larger than 9876543210 must have at least twice the same digit in their base 10 representation.
checking for duplicate digits can be done by counting the remainders of successive divisions by 10.
A simple approach is therefore to enumerate multiples of 2520 up to 9876543210 and select the numbers that have no duplicate digits.
Type unsigned long long is guaranteed to be large enough to represent all values to enumerate, but neither int nor long are.
Here is the code:
#include <stdio.h>
int main(void) {
unsigned long long i, n;
for (n = 2520; n <= 9876543210; n += 2520) {
int digits[10] = { 0 };
for (i = n; i != 0; i /= 10) {
if (digits[i % 10]++)
break;
}
if (i == 0)
printf("%llu\n", n);
}
return 0;
}
This program produces 13818 numbers in 0.076 seconds. The first one is 7560 and the last one is 9876351240.
The number 0 technically does match your constraints: it is evenly divisible by all non zero integers and it has no duplicate digits. But you excluded it explicitly.
Related
I need to build a program, that would write all numbers from 0 to 100, but will place an * instead of any number that contains the digit 3 or can be divided by 3. This is what I have so far. How can I make it work?
#include <stdio.h>
main() {
int i, c;
c = 100;
for (i = 0; i <= c; i++) {
if (i % 3 == 0) {
printf("*");
}
if (i)
printf("%d\n", i);
}
}
place an * instead of any number that contains the digit 3 or can be divided by 3.
OP's code took care of the "can be divided by 3" with i % 3 == 0.
How about a little divide and conquer for the "contains the digit 3"? Put a function in there.
if (contains_the_digit(i, 3) || (i % 3 == 0)) {
printf("*\n");
} else {
printf("%d\n", i);
}
Now what is left is to define contains_the_digit(int i, int digit)
Mathematically (nice and efficient):
bool contains_the_digit_via_math(int i, int digit) {
do {
if (abs(i % 10) == digit) { // Look at the least digit, abs() to handle negative `i`
return true;
}
i /= 10; // Now look at the upper decimal digits
} while (i);
return false;
}
Or textually:
bool contains_the_digit_via_string(int i, int digit) {
char buf[30]; // Something certainly big enough
sprintf(buf, "%d", i);
return strchr(buf, digit + '0') != NULL;
}
Or use your imagination for other ideas.
The key is to take your problems and reduce them to smaller ones with helper functions: divide and conquer.
Concert the number to a string
Replace '3' with '*' within that string
i.e.
int to_be_converted =12345612343242432; // Or summat else
char num[100]; // Should be more than enough
sprintf(num, "%d", to_be_converted);
for (int i =0; num[i]; i++) {
if (num[i] -- '3') num[i] = '*';
}
printf("Here you go %s", num);
That should do the trick
Just ad the bit to go through the numbers and check if divisible by 3. I leave that to the reader.
Seeing you forgot to add the return type int to your int main(), I think this is a good time to learn to write your own function!
In this case, you want a function that can check whether the last digit of a number is a 3 when you represent that number as base-10. That's easy! The function should look like (you need to #include <stdbool.h> at the beginning of your file, too):
bool ends_in_decimal_3(int number) {
// figure out a way to find the difference
// between number, rounded to multiples of 10
// and the original number. If that difference==3,
// then this ends in 3 and you can `return true;`
}
Armed with that function, you can see whether your i itself ends in 3, or whether i/10 ends in 3 and so on. Remembering that division / in C between ints always rounds down is a good trick to do that, and also an important hint on how to implement your rounding in ends_in_decimal_3.
I am writing a program that will take any number of integers. The program will end when the terminal 0 has been entered. It will then output the number closest to 10 (except for the terminal character). If there are several numbers closest to 10 then it should output the last number entered.
My current code does read the numbers from the input stream, but I don't know how to implement the logic so that the program will give me the number that is closest to 10.
I know, that I need to keep track of the minimum somehow in order to update the final result.
#include <stdio.h>
int main() {
int n = 1;
int number = 1;
int numberArray[n];
int resultArray[n];
int min;
int absMin;
int result;
int finalResult;
while (number != 0) {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
for (int i = 0; i < n; i++) {
min = 10 - numberArray[i];
if (min < 0) {
absMin = -min;
}
else {
absMin = min;
}
resultArray[i] = absMin;
result = resultArray[0];
if (resultArray[i] < result) {
finalResult = resultArray[i];
}
}
printf("%d\n", finalResult);
return 0;
}
here's a simple code I wrote
One thing I must say is you can't simply declare an array with unknown size and that's what you have done. Even if the no. of elements can vary, you either take input the number of elements from the user OR (like below) create an array of 100 elements or something else according to your need.
#include <stdio.h>
#define _CRT_NO_WARNINGS
int main() {
int n = 0;
int number = 1;
int numberArray[100];
int resultArray[100];
int minNumber;
int *min;
do {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
while (number != 0);
resultArray[0] = 0;
min = &resultArray[0];
minNumber = numberArray[0];
for (int i = 0; i < n-1; i++) {
if(numberArray[i]>=10){
resultArray[i] = numberArray[i] - 10;
}
if(numberArray[i]<10){
resultArray[i] = 10 - numberArray[i];
}
if(resultArray[i] <= *min){
min = &resultArray[i];
minNumber = numberArray[i];
}
}
printf("\n%d",minNumber);
return 0;
}
I have improved your script and fixed a few issues:
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int n;
int number;
int numberArray[n];
while (scanf("%d", &number) && number != 0) {
numberArray[n++] = number;
}
int currentNumber;
int distance;
int result;
int resultIndex;
int min = INT_MAX; // +2147483647
for (int i = 0; i < n; i++) {
currentNumber = numberArray[i];
distance = fabs(10 - currentNumber);
printf("i: %d, number: %d, distance: %d\n", i, currentNumber, distance);
// the operator: '<=' will make sure that it will update even if we already have 10 as result
if (distance <= min) {
min = distance;
result = currentNumber;
resultIndex = i;
}
}
printf("The number that is closest to 10 is: %d. It is the digit nr: %d digit read from the input stream.\n", result, resultIndex + 1);
return 0;
}
Reading from the input stream:
We can use scanf inside the while loop to make it more compact. Also, it will loop one time fewer because we don't start with number = 1 which is just a placeholder - this is not the input - we don't want to loop over that step.
I used the shorthand notation n++ it is the post-increment-operator. The operator will increase the variable by one, once the statement is executed (numberArray entry will be set to number, n will be increased afterwards). It does the same, in this context, as writing n++ on a new line.
Variables:
We don't need that many. The interesting numbers are the result and the current minimum. Of course, we need an array with the inputs as well. That is pretty much all we need - the rest are just helper variables.
Iteration over the input stream:
To get the result, we can calculate the absolute distance from 10 for each entry. We then check if the distance is less than the current minimum. If it is smaller (closer to 10), then we will update the minimum, the distance will be the new minimum and I have added the resultIndex as well (to see which input is the best). The operator <= will make sure to pick the latter one if we have more than one number that has the same distance.
I have started with the minimum at the upper bound of the integer range. So this is the furthest the number can be away from the result (we only look at the absolute number value anyway so signed number don't matter).
That's pretty much it.
I'm a bit stuck on one of my problems not because I don't know, but because I can't use more complex operations.(functions and multiple arrays)
So I need to make a program in C that ask for an input of an array(max 100 elements) and then program needs to sort that matrix by numbers with same digits.
So I made everything that I know, I tested my program with sorting algorithm from minimum to maximum values and it works, only thing that I can't understand is how should I test if the number have same digits inside the loop? (I can't use functions.)
So I know the method of finding if the number have the same digits but I don't know how to compare them. Here is an example of what I need.
This is what I have for now this sorts numbers from min to max.
#include <stdio.h>
int main() {
int matrix[100];
int i,j;
int temp,min;
int elements_number=0;
printf("Enter the values of matrix-max 100 elements-type -1 to end: ");
for(i=0;i<100;i++){
scanf("%d",&matrix[i]);
elements_number++;
if(matrix[i]==-1){
elements_number--;
break;
}
}
for (i=0; i<elements_number; i++) {
min=i;
for (j=i+1; j<elements_number; j++) {
if (matrix[j] < matrix[min])
min = j;
}
temp = matrix[i];
matrix[i] = matrix[min];
matrix[min] = temp;
}
for(i=0;i<elements_number;i++){
if(i!=elements_number-1){
printf("%d,",matrix[i]); }
else printf("%d.",matrix[i]);
}
return 0;
}
I need this output for these numbers:
INPUT :
1 22 43 444 51 16 7 8888 90 11 -1
OUTPUT:
1,22,444,7,8888,11,43,51,16,90.
Integers with 1 digit count as "numbers with same number of digits" like 7 and 1 in this example.
Hope that you can help.
After processing the array, the single-digit numbers should all be in the left part of the array, the other numbers in the right part. Within each part, the original order of the elements should be preserved. This is called a stable partition. It is different from sorting, because the elements are only classified into two groups. Sorting means that there is a clear relationship between any two elements in the array.
This can be done by "filtering" the array for single-digit numbers and storing the other numbers that were filtered out in a temporary second array. Then append the contents of that second array to the (now shorter) first array.
Here's how that could work:
#include <stdlib.h>
#include <stdio.h>
void print(const int *arr, int n)
{
for (int i = 0; i < 10; i++) {
if (i) printf(", ");
printf("%d", arr[i]);
}
puts(".");
}
int is_rep_digit(int n)
{
int q = n % 10;
n /= 10;
while (n) {
if (n % 10 != q) return 0;
n /= 10;
}
return 1;
}
int main()
{
int arr[10] = {1, 22, 43, 444, 51, 16, 7, 8888, 90, 11};
int aux[10]; // auxliary array for numbers with several digits
int i, j, k;
print(arr, 10);
j = 0; // number of single-digit numbers
k = 0; // number of other numbers
for (i = 0; i < 10; i++) {
if (is_rep_digit(arr[i])) {
arr[j++] = arr[i]; // pick single-digit number
} else {
aux[k++] = arr[i]; // copy other numbers to aux
}
}
k = 0;
while (j < 10) { // copy aux to end of array
arr[j++] = aux[k++];
}
print(arr, 10);
return 0;
}
Edit: I've just seen your requirement that you can't use functions. You could use Barmar's suggestion to test divisibility by 1, 11, 111 and so on. The tricky part is to find the correct divisor, however.
Anyway, the point I wanted to make here is that you don't need a full sorting algorithm here.
#include <stdio.h>
#include <stdlib.h>
#define TEN 10
int main ()
{
int number = 0;
int digit = 0;
int last_digit = 0;
int digit_sum = 0;
int i = 0;
while (i == 0)
{
printf("Please Enter A Positive Number! \n"); //explaining
scanf("%d",&number);
if (number > 0)
{
i++;
}
}
while (number > 0)
{
digit = number % TEN; //breaking number into digits
number /= TEN;
if (last_digit != digit) //comparing digits
{
last_digit = digit;
digit_sum += digit;
}
}
printf("The Sum Of The Digits Is : %d",digit_sum);
return 0;
}
the code will divide the number into digits and check if there are duped digits, in case there are, only one of them will be calculated for exmple: 3211
3+2+1, but my problem is thats the code wont work with numbers like 31211 Im thankful for any kind of help.
The code doesn't work because there is no guarantee that duplicate's will appear consecutive manner. your code handles that not the other ways. That's why it fails.
A simple solution would be to consider a 10 element array where you will keep count of which element appeared and which didn't.
The idea is to map the digits to the array indices of the 10 element array. Intialized with 0.
...
int digitAppeared[10]={0};
while (number)
{
digit = number % TEN; //breaking number into digits
number /= TEN;
digit_sum += (1 - digitAppeared[digit]) * digit;
digitAppeared[digit] = 1;
}
...
To give you a clear idea this line basically checks whether the element appeared or not and as per the result it will add the digit.
If digit D appeared then digitAppeared[D]=1
and if it didn't then digitAppeared[D]=0.
We will add it to digitsum if it appears first time. That's why the (1-digitAppeared[D]) will tell us whether to add it or not.
digit_sum += (1 - digitAppeared[digit]) * digit;
Convert the number to string use itoa() . sort it and then walk through it , looking for unique number and do your calculation
You can mark which digits were already added by using setting logical flags as represented by done in program below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEN 10
int main ()
{
int number = 0;
int digit = 0;
int last_digit = 0;
int digit_sum = 0;
int i = 0;
int done[10];
while (i == 0)
{
printf("Please Enter A Positive Number! \n"); //explaining
scanf("%d",&number);
if (number > 0)
{
i++;
}
}
memset(done,0,sizeof(done));
while (number > 0)
{
digit = number % TEN; //breaking number into digits
number /= TEN;
if(done[digit] == 0)
{
digit_sum += digit;
done[digit] = 1;
}
}
printf("The Sum Of The Digits Is : %d",digit_sum);
return 0;
}
Hello guys i am trying to implement a program which is finding the happy numbers were between two numbers A and B.
Summing the squares of all the digits of the number, we replace the number with the outcome, and repeat the process. If after some steps the result is equal to 1 (and stay there), then we say that the number N is **<happy>**. Conversely, if the process is repeated indefinitely without ever showing the number 1, then we say that the number N is **<sad>**.
For example, the number 7 is happy because the procedure described above leads to the following steps: 7, 49, 97, 130, 10, 1, 1, 1 ... Conversely, the number 42 is sad because the process leads to a infinite sequence 42, 20, 4, 16, 37, 58, 89, 145, 42, 20, 4, 16, 37 ...
I try this right down but i am getting either segm faults or no results.
Thanks in advance.
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
void happy( char * A, int n);
int numPlaces (long n);
int main(void)
{
long A,B;
int npA;
char *Ap;
printf("Give 2 Numbers\n");
scanf("%li %li",&A,&B);
npA = numPlaces(A);
Ap = malloc(npA);
printf("%ld %d\n",A,npA);
//Search for happy numbers from A to B
do{
sprintf(Ap, "%ld", A);
happy(Ap,npA);
A++;
if ( npA < numPlaces(A) )
{
npA++;
Ap = realloc(Ap, npA);
}
}while( A <= B);
}
//Finds happy numbers
void happy( char * A, int n)
{
//Basic Condition
if ( n == 1)
{
if (A[0] == 1 || A[0] == 7)
printf("%c\n",A[0]);
printf("%s\n",A);
return;
}
long sum = 0 ;
char * sumA;
int nsum;
int Ai;
//Sum the squares of the current number
for(int i = 0 ; i < n;i++)
{
Ai = atoi(&A[i]);
sum = sum + (Ai*Ai);
}
nsum = numPlaces (sum);
sumA = malloc(nsum);
sprintf(sumA, "%li", sum);
happy(sumA,nsum);
free(sumA);
}
//Count digits of a number
int numPlaces (long n)
{
if (n < 0) return 0;
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}
Thanks for your time.
by the definition of your program sad numbers will cause your program to run forever
Conversely, if the process is repeated indefinitely
You need to add a stopping condition, like if I have looped for 1000 times, or if you hit a well known non terminating number (like 4) (is there a definite list of these? I dont know)
I find this solution tested and working..
Thanks for your time and I am sorry for my vagueness.
Every advice about this solution would be welcome
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
void happy( char * A, int n);
int numPlaces (long n);
int happynum = 0;
int main(void)
{
long A,B;
int npA;
char *Ap;
printf("Give 2 Numbers\n");
scanf("%li %li",&A,&B);
npA = numPlaces(A);
Ap = malloc(npA);
//Search for happy numbers from A to B
do{
sprintf(Ap, "%ld", A);
happy(Ap,npA);
if (happynum ==1)
printf("%s\n",Ap);
A++;
if ( npA < numPlaces(A) )
{
npA++;
Ap = realloc(Ap, npA);
}
}while( A <= B);
}
//Finds happy numbers
void happy( char * A, int n)
{
//Basic Condition
if ( n == 1)
{
if (A[0] == '3' || A[0] == '6' || A[0] == '9')
{
happynum = 0;
}
else
{
happynum = 1;
}
return;
}
long sum = 0;
char * sumA;
int nsum;
int Ai;
//Sum the squares of the current number
for(int i = 0 ; i < n;i++)
{
Ai = (int)(A[i]-48);
sum = sum + (Ai*Ai);
}
nsum = numPlaces (sum);
sumA = malloc(nsum);
sprintf(sumA, "%li", sum);
happy(sumA,nsum);
free(sumA);
}
//Count digits of a number
int numPlaces (long n)
{
if (n < 0) return 0;
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}
Your code uses some questionable practices. Yoe may be misguided because you are concerned about performance and memory usage.
When you allocate memory for the string, you forget to allocate one character for the null terminator. But you shouldn't be allocating, re-allocating and freeing constantly anyway. Dynamic memory allocation is expensive compared to your other operations.
Your limits are long, which may be a 32-bit or 64-bit signed integer, depending on your platform. The maximum number that can be represented with e 64-bit signed integer is 9,223,372,036,854,775,807. This is a number with 19 digits. Add one for the null terminator and one for a possible minus sign, so that overflow won't hurt, you and use a buffer of 21 chars on the stack.
You probably shouldn't be using strings inthe first place. Use the basic code to extract the digits: Split off the digit by taking the remainder of a division by 10. Then divide by 10 until you get zero. (And if you use strings with a fixed buffer size, as described above, you don't have to calculate the difits separately: sprintf returns the number of characters written to the string.
Your functions shouldn't be recursive. A loop is enough. As pm100 has noted, you need a termination criterion: You must keep track of the numbers that you have already visited. Each recursive call creates a new state; it is easier to keep an array, that can be repeatedly looked at in a loop. When you see a number that you have already seen (other than 1, of course), your number is sad.
Happy and sad numbers have this property that when your sum of squares is a number with a known happiness, the original number has this happiness, too. If you visit a known das number, the original number is sad. If you visit a known happy number, the original number is happy.
The limits of your ranges may ba large, but the sum of square digits is not large; it can be at most the number of digits times 81. In particular:
type max. number number of max. square sum dss
int 2,147,483,647 1,999,999,999 730
uint 4,294,967,295 3,999,999,999 738
long 9,223,372,036,854,775,807 8,999,999,999,999,999,999 1522
ulong 18,446,744,073,709,55,1616 9,999,999,999,999,999,999 1539
That means that when you take the sum of digit squares of an unsigned long, you will get a number that is smaller than 1540. Create an array of 1540 entries and mark all known happy numbers with 1. Then you can reduce your problem to taking the sum of digit squares once and then looking up the happiness of the number in this array.
(You can do the precalculation of the array once when you start the program.)