finding how many times number2 is showing in number1 - c

I am solving an exercise in C and I got stuck. I don't know the logic of the code to get to my solution. For example we enter 2 numbers from input let the numbers be 123451289 and 12 and I want to see how many times number 2 is showing at number 1 (if this is confusing let me know). For the numbers earlier the program outputs 2. I tried solving it here is my code:
#include <stdio.h>
int main() {
int num1, num2, counter = 0;
scanf("%d%d", num1, num2);
if (num1 < num2) {
int temp = num1;
num1 = num2;
num2 = temp;
}
int copy1 = num1;
int copy2 = num2;
while (copy2 > 0) {
counter++; // GETTING THE LENGHT OF THE SECOND NUMBER
copy2 /= 10;
// lastdigits = copy1 % counter //HERE I WANT TO GET THE LAST DIGITS OF THE FIRST NUMBER
// But it does not work
}
}
My question is how can I get the last digits of the first number according to the second one for example if the second number have 3 digits I want to get the last 3 digits of the first number. For the other part I think I can figure it out.
I must solve this problem WITHOUT USING ARRAYS.

The problem: find all the needles (e.g. 12) in a haystack (e.g. 123451289).
This can be done simply without arrays using a modulus of the needle. For 12, this is 100. That is, 12 is two digits wide. Using the modulus, we can
isolate the rightmost N digits of the haystack and compare them against the needle.
We "scan" haystack repeatedly by dividing by 10 until we reach zero.
Here is the code:
#include <stdio.h>
int
main(void)
{
int need, hay, counter = 0;
scanf(" %d %d", &hay, &need);
// ensure that the numbers are _not_ reversed
if (hay < need) {
int temp = need;
need = hay;
hay = temp;
}
// get modulus for needle (similar to number of digits)
int mod = 1;
for (int copy = need; copy != 0; copy /= 10)
mod *= 10;
// search haystack for occurences of needle
// examine the rightmost "mod" digits of haystack and check for match
// reduce haystack digit by digit
for (int copy = hay; copy != 0; copy /= 10) {
if ((copy % mod) == need)
++counter;
}
printf("%d appears in %d exactly %d times\n",need,hay,counter);
return 0;
}
UPDATE:
I'm afraid this does not work for 10 0. –
chqrlie
A one line fix for to the modulus calculation for the 10/0 case. But, I've had to add a special case for the 0/0 input.
Also, I've added a fix for negative numbers and allowed multiple lines of input:
#include <stdio.h>
int
main(void)
{
int need, hay, counter;
while (scanf(" %d %d", &hay, &need) == 2) {
counter = 0;
// we can scan for -12 in -1237812
if (hay < 0)
hay = -hay;
if (need < 0)
need = -need;
// ensure that the numbers are _not_ reversed
if (hay < need) {
int temp = need;
need = hay;
hay = temp;
}
// get modulus for needle (similar to number of digits)
int mod = need ? 1 : 10;
for (int copy = need; copy != 0; copy /= 10)
mod *= 10;
// search haystack for occurences of needle
// examine the rightmost "mod" digits of haystack and check for match
// reduce haystack digit by digit
for (int copy = hay; copy != 0; copy /= 10) {
if ((copy % mod) == need)
++counter;
}
// special case for 0/0 [yecch]
if ((hay == 0) && (need == 0))
counter = 1;
printf("%d appears in %d exactly %d times\n", need, hay, counter);
}
return 0;
}
Here is the program output:
12 appears in 123451289 exactly 2 times
0 appears in 10 exactly 1 times
0 appears in 0 exactly 1 times
UPDATE #2:
Good fixes, including tests for negative numbers... but I'm afraid large numbers still pose a problem, such as 2000000000 2000000000 and -2147483648 8 –
chqrlie
Since OP has already posted an answer, this is bit like beating a dead horse, but I'll take one last attempt.
I've changed from calculating a modulus of needle into calculating the number of digits in needle. This is similar to the approach of some of the other answers.
Then, the comparison is now done digit by digit from the right.
I've also switched to unsigned and allow for the number to be __int128 if desired/supported with a compile option.
I've added functions to decode and print numbers so it works even without libc support for 128 bit numbers.
I may be ignoring [yet] another edge case, but this is an academic problem (e.g. we can't use arrays) and my solution is to just use larger types for the numbers. If we could use arrays, we'd keep things as strings and this would be similar to using strstr.
Anyway, here's the code:
#include <stdio.h>
#ifndef NUM
#define NUM long long
#endif
typedef unsigned NUM num_t;
FILE *xfin;
int
numget(num_t *ret)
{
int chr;
num_t acc = 0;
int found = 0;
while (1) {
chr = fgetc(xfin);
if (chr == EOF)
break;
if ((chr == '\n') || (chr == ' ')) {
if (found)
break;
}
if ((chr >= '0') && (chr <= '9')) {
found = 1;
acc *= 10;
chr -= '0';
acc += chr;
}
}
*ret = acc;
return found;
}
#define STRMAX 16
#define STRLEN 100
const char *
numprt(num_t val)
{
static char strbuf[STRMAX][STRLEN];
static int stridx = 0;
int dig;
char *buf;
buf = strbuf[stridx++];
stridx %= STRMAX;
char *rhs = buf;
do {
if (val == 0) {
*rhs++ = '0';
break;
}
for (; val != 0; val /= 10, ++rhs) {
dig = val % 10;
*rhs = dig + '0';
}
} while (0);
*rhs = 0;
if (rhs > buf)
--rhs;
for (char *lhs = buf; lhs < rhs; ++lhs, --rhs) {
char tmp = *lhs;
*lhs = *rhs;
*rhs = tmp;
}
return buf;
}
int
main(int argc,char **argv)
{
num_t need, hay, counter;
--argc;
++argv;
if (argc > 0)
xfin = fopen(*argv,"r");
else
xfin = stdin;
while (1) {
if (! numget(&hay))
break;
if (! numget(&need))
break;
counter = 0;
// we can scan for -12 in -1237812
if (hay < 0)
hay = -hay;
if (need < 0)
need = -need;
// ensure that the numbers are _not_ reversed
if (hay < need) {
num_t temp = need;
need = hay;
hay = temp;
}
// get number of digits in needle (zero has one digit)
int ndig = 0;
for (num_t copy = need; copy != 0; copy /= 10)
ndig += 1;
if (ndig == 0)
ndig = 1;
// search haystack for occurences of needle
// starting from the right compare digit-by-digit
// "shift" haystack right on each iteration
num_t hay2 = hay;
for (; hay2 != 0; hay2 /= 10) {
num_t hcopy = hay2;
// do the rightmost ndig digits match in both numbers?
int idig = ndig;
int match = 0;
for (num_t need2 = need; idig != 0;
--idig, need2 /= 10, hcopy /= 10) {
// get single current digits from each number
int hdig = hcopy % 10;
int ndig = need2 % 10;
// do they match
match = (hdig == ndig);
if (! match)
break;
}
counter += match;
}
// special case for 0/0 et. al. [yecch]
if (hay == need)
counter = 1;
printf("%s appears in %s exactly %s times\n",
numprt(need), numprt(hay), numprt(counter));
}
return 0;
}
Here's the program output:
12 appears in 123451289 exactly 2 times
123 appears in 123451289 exactly 1 times
1234 appears in 123451289 exactly 1 times
1 appears in 123451289 exactly 2 times
0 appears in 10 exactly 1 times
0 appears in 0 exactly 1 times
1000000000 appears in 1000000000 exactly 1 times
2000000000 appears in 2000000000 exactly 1 times

This looks along the lines of what you're attempting.
You can use the pow() function from math.h to raise 10 to the power of how many digits you need for your modulus operation.
Compile with -lm or make your own function to calculate 10^num_digits
#include <stdio.h>
#include <math.h>
int main() {
int x = 123456789;
double num_digits = 3.0;
int last_digits = x % (int)pow(10.0, num_digits);
printf("x = %d\nLast %d Digits of x = %d\n", x, (int)num_digits, last_digits);
return 0;
}
Outputs:
x = 123456789
Last 3 Digits of x = 789

I think you are trying to ask :- if number1 = 1234567 and number2 = 673, then, length of number2 or number2 has 3 digits, so, you now want the last 3 digits in number1, i.e, '456', if I'm not wrong.
If that is the case, then, what you did to find the number of digits in num2 is correct, i.e,
while (copy2>0) {
counter++; // GETTING THE LENGHT OF THE SECOND NUMBER
copy2/=10;
}
you can do the same for number1 and find out its number of digits, then you can compare whether the number of digits in number2 is less than that in number1. Ex, 3 is less than number of digits in number1, so you can proceed further. Let's say number of digits in number1 is 7 and you want the last 3 digits, so you can do iterate over the digits in number1 till count of digits in number2 and pop out each last digit and store them in an array.
The code:
#include <stdio.h>
int main()
{
int num1,num2;
int count1 = 0, count2 = 0;
scanf("%d",&num1);
scanf("%d",&num2);
if(num1<num2){
int temp = num1;
num1 = num2;
num2 = temp;
}
int copy1 = num1;
int copy2 = num2;
while (copy1>0)
{
count1++;
copy1/=10;
}
while (copy2>0)
{
count2++;
copy2/=10;
}
// printf("num1 has %d digits and num2 has %d digits\n", count1, count2);
if (count1 >= count2)
{
int arr[count2];
int x = count2;
int p = num1;
int i = 0;
while (x > 0)
{
arr[i++] = p%10;
x --;
p/=10;
}
for (int j = 0; j < i; j++)
{
printf("%d ", arr[j]);
}
}
return 0;
}
output : 8 7 6
let's say, num1 = 12345678, num2 = 158, then arr = {8,7,6}.

You must determine the number of digits N of num2 and test if num1 ends with num2 modulo 10N.
Note these tricky issues:
you should not sort num1 and num2: If num2 is greater than num1, the count is obviously 0.
num2 has at least 1 digit even if it is 0.
if num1 and num2 are both 0, the count is 1.
if num2 is greater then INT_MAX / 10, the computation for mod would overflow, but there can only be one match, if num1 == num2.
it is unclear whether the count for 1111 11 should be 2 or 3. We will consider all matches, including overlapping ones.
to handle larger numbers, we shall use unsigned long long instead of int type.
Here is a modified version:
#include <limits.h>
#include <stdio.h>
int main() {
int counter = 0;
unsigned long long num1, num2;
if (scanf("%llu%llu", &num1, &num2) != 2) {
printf("invalid input\n");
return 1;
}
if (num1 == num2) {
/* special case for "0 0" */
counter = 1;
} else
if (num1 > num2 && num2 <= ULLONG_MAX / 10) {
unsigned long long copy1 = num1;
unsigned long long mod = 10;
while (mod < num2) {
mod *= 10;
}
while (copy1 > 0) {
if (copy1 % mod == num2)
counter++;
copy1 /= 10;
}
}
printf("count=%d\n", counter);
return 0;
}
Note that leading zeroes are not supported in either number: 101 01 should produce a count of 1 but after conversion by scanf(), the numbers are 101 and 1 leading to a count of 2. It is non trivial to handle leading zeroes as well as numbers larger than ULLONG_MAX without arrays.

This was the answer that i was looking for but thank you all for helping :)
#include <stdio.h>
#include <math.h>
int main(){
int num1,counter1,counter2,num2,temp,digit,copy1,copy2;
scanf("%d%d",&num1,&num2);
if(num1<num2){
temp = num1;
num1 = num2;
num2 = temp;
}
copy1 = num1;
copy2 = num2;
counter1 = counter2 = 0;
while (copy2>0) {
counter1++;
copy2/=10;
}
counter1 = pow(10,counter1);
if(num1> 1 && num2>1)
while (copy1>0) {
digit = copy1%counter1;
if(digit==num2){
counter2++;
}
copy1/=10;
} else{
if(num2<1){
while (copy1>0) {
digit = copy1%10;
if(digit==copy2){
counter2++;
}
copy1/=10;
}
}
}
printf("%d",counter2);
}

Related

A function that takes an integer and inserts zeros between its digits

The function should take the address of the integer and modify it by inserting zeros between its digits. For example:
insert_zeros(3) //3
insert_zeros(39) //309
insert_zeros(397) //30907
insert_zeros(3976) //3090706
insert_zeros(39765) //309070605
My code:
#include <stdio.h>
#include <math.h>
void insert_zeros(int* num);
int main() {
int num;
printf("Enter a number:");
scanf("%d", num);
insert_zeros(&num);
printf("Number after inserting zeros: %d", num);
return 0;
}
void insert_zeros(int* num){
int count = 0;
int tmp = *num;
//Count the number of digits in the number
while(tmp != 0){
tmp /= 10;
count++;
}
//calculating the coefficient by which I will divide the number to get its digits one by one
int divider = (int)pow(10, count-1);
int multiplier;
tmp = *num;
*num = 0;
/*
The point at which I'm stuck
Here I tried to calculate the degree for the number 10
(my thought process and calculations are provided below)
*/
(count >= 3)? count += (count/2): count;
//the main loop of assembling the required number
while (count >= 0){
multiplier = (int)pow(10, count); //calculating a multiplier
*num += (tmp / divider) * multiplier; //assembling the required number
tmp %= divider; //removing the first digit of the number
divider /= 10; //decreasing divider
count -= 2; //decreasing the counter,
//which is also a power of the multiplier (witch is 10)
}
}
My idea consists of the following formula:
For number "3" I shold get "30" and it will be:
30 = (3 * 10^1) - the power is a counter for number "3" that equals 1.
For number "39" it will be "309":
309 = (3 * 10^2) + (9 * 10^1)
For number "397" it will be "30907":
30907 = (3 * 10^4) + (9 * 10^2) + (7 * 10^0)
For number "3976" it will be "3090706":
3090706 = (3 * 10^6) + (9 * 10^4) + (7 * 10^2) + (6 * 10^0) - with each iteration power is decreasing by 2
For number "39765" it will be "309070605":
309070605 = (3 * 10^8) + (9 * 10^6) + (7 * 10^4) + (6 * 10^2) + (5 * 10^0)
And so on...
For a 3-digit number, the start power should be 4, for a 4-digit number power should be 6, for a 5-digit it should be 8, for 6-digit it should be 10, etc.
That algorithm works until it takes a 5-digit number. It outputs a number like "30907060" with an extra "0" at the end.
And the main problem is in that piece of code (count >= 3)? count += (count/2): count;, where I tried to calculate the right power for the first iterating through the loop. It should give the right number to which will be added all the following numbers. But it only works until it gets a 5-digit number.
To be honest, so far I don't really understand how it can be realized. I would be very grateful if someone could explain how this can be done.
As noted in comments, your use of scanf is incorrect. You need to pass a pointer as the second argument.
#include <stdio.h>
#include <math.h>
int main(void) {
int num;
scanf("%d", &num);
int num2 = 0;
int power = 0;
while (num > 0) {
num2 += (num % 10) * (int)pow(10, power);
num /= 10;
power += 2;
}
printf("%d\n", num2);
return 0;
}
There's an easy recursive formula for inserting zeros: IZ(n) = 100*IZ(n/10) + n%10.
That gives a very concise solution -- here the test cases are more code than the actual function itself.
#include <stdio.h>
#include <stdint.h>
uint64_t insert_zeros(uint64_t n) {
return n ? (100 * insert_zeros(n / 10) + n % 10) : 0;
}
int main(int argc, char **argv) {
int tc[] = {1, 12, 123, 9854, 12345, 123450};
for (int i = 0; i < sizeof(tc)/sizeof(*tc); i++) {
printf("%d -> %lu\n", tc[i], insert_zeros(tc[i]));
}
}
Output:
1 -> 1
12 -> 102
123 -> 10203
9854 -> 9080504
12345 -> 102030405
123450 -> 10203040500
Adapting some code just posted for another of these silly exercises:
int main() {
int v1 = 12345; // I don't like rekeying data. Here's the 'seed' value.
printf( "Using %d as input\n", v1 );
int stack[8] = { 0 }, spCnt = -1;
// Peel off each 'digit' right-to-left, pushing onto a stack
while( v1 )
stack[ ++spCnt ] = v1%10, v1 /= 10;
if( spCnt == 0 ) // Special case for single digit seed.
v1 = stack[ spCnt ] * 10;
else
// multiply value sofar by 100, and add next digit popped from stack.
while( spCnt >= 0 )
v1 = v1 * 100 + stack[ spCnt-- ];
printf( "%d\n", v1 );
return 0;
}
There's a ceiling to how big a decimal value can be stored in an int. If you want to start to play with strings of digits, that is another matter entirely.
EDIT: If this were in Java, this would be a solution, but the problem is in C, which I'm not sure if this can convert to C.
This may be a lot easier if you first convert the integer to a string, then use a for loop to add the zeros, then afterward reconvert to an integer. Example:
int insert_zeros(int num) {
String numString = Integer.toString(num);
String newString = "";
int numStringLength = numString.length();
for (int i = 0; i < numStringLength; i++) {
newString += numString[i];
// Only add a 0 if it's not the last digit (with exception of 1st digit)
if (i < numStringLength - 1 || i == 0) newString += '0';
}
return Integer.parseInt(newString);
}
I think this should give you your desired effect. It's been a little bit since I've worked with Java (I'm currently doing JavaScript), so I hope there's no syntax errors, but the logic should all be correct.

Armstrong number program in C returns wrong value

I am writing a program to see if a user entered number is Armstrong or not, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(){
int x = 0;
printf("Enter a natural number: ");
scanf("%d", &x);
int ans = x;
// Digit Counter
int counter = 0; //Variable for number of digits in the user entered number
int b = x; //For each time number can be divided by 10 and isnt 0
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
++counter;
//Digit Counter
int sum = 0;
// Digit Finder
int D;
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
if (sum == ans){
printf("%d is a Armstrong number! :)", ans);
}else
printf("%d is not an Armstrong number :(", ans);
//Digit Finder
return 0;
}
My problem is that the program works fine apart from one point, when the program is given a Armstrong number which does not start with 1 then it behaves normally and indicates if it is an Armstrong number or not, but when i input a Armstrong number which start with 1 then it will print out the Armstrong number but -1.
For example: If i input something such as 371 which is an Armstrong number it will show that it is an Armstrong number. However if i input 1634 it will output 1633 which is 1 less than 1634.
How can i fix this problem?, also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
How can I fix this problem.
You know the number of iterations you want to make once you have calculated the digit count. So instead of looping till you reach the value of x:
for (int j = 1; j <= x; j++){
use the digit counter instead:
for (int j = 1; j <= counter; j++) {
also by the way could someone comment on my code and tell me if it seems good and professional/efficient because i am a beginner in C and would like someone else's opinion on my code.
There's a number of things you can do to improve your code.
First and foremost, any piece of code should be properly indented and formatted. Right now your code has no indenting, which makes it more difficult to read and it just looks ugly in general. So, always indent your code properly. Use an IDE or a good text editor, it will help you.
Be consistent in your code style. If you are writing
if (some_cond) {
...
}
else
//do this
It is not consistent. Wrap the else in braces as well.
Always check the return value of a function you use, especially for scanf. It will save you from many bugs in the future.
if (scanf("%d", &x) == 1)
//...all OK...
else
// ...EOF or conversion failure...
exit(EXIT_FAILURE);
Your first for loop will iterate x times uselessly. You can stop when you know that you have hit 0:
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b == 0){
break;
}
counter += 1;
}
C has ++ operator. Use that instead of doing counter += 1
int D; you create this, but don't initialize it. Always initialize your variables as soon as possible
C has const qualifier keyword, which makes a value immutable. This makes your code more readable, as the reader can immediately tell that this value will not change. In your code, you can change ans variable and make it a const int because it never changes:
const int ans = x;
Use more descriptive names for your variables. ans, D don't tell me anything. Use proper names, so that the reader of your code can easily understand your code.
These are some of the things that in my opinion you should do and keep doing to improve your code and coding skills. I am sure there can be more things though. Keep your code readable and as simple as possible.
The condition in this loop
for (int i = 1; i <= x; i++){ // Then counter variable is incremented by 1
b /= 10;
if (b != 0){
counter += 1;
}
}
does not make sense because there will be numerous redundant iterations of the loop.
For example if x is equal to 153 that is contains only 3 digits the loop will iterate exactly 153 times.
Also additional increment of the variable counter after the loop
++counter;
makes the code logically inconsistent.
Instead of the loop you could write at least the following way
int counter = 0;
int b = x;
do
{
++counter;
} while ( b /= 10 );
This loop iterates exactly the number of times equal to the number of digits in a given number.
In this loop
for (int j = 1; j <= x; j++){
D = x % 10; //Shows remainder of number (last digit) when divided by 10
sum += pow(D, counter); //Raises Digit found by counter and adds to sum
printf("%d\n", sum);
x /= 10; // Divides user entered number by 10 to get rid of digit found
}
it seems you did not take into account that the variable x is decreased inside the body of the loop
x /= 10; // Divides user entered number by 10 to get rid of digit found
So the loop can interrupt its iterations too early. In any case the condition of the loop again does not make great sense the same way as the condition of the first loop and only adds a bug.
The type of used variables that store a given number should be unsigned integer type. Otherwise the user can enter a negative number.
You could write a separate function that checks whether a given number is an Armstrong number.
Here you are.
#include <stdio.h>
int is_armstrong( unsigned int x )
{
const unsigned int Base = 10;
size_t n = 0;
unsigned int tmp = x;
do
{
++n;
} while ( tmp /= Base );
unsigned int sum = 0;
tmp = x;
do
{
unsigned int digit = tmp % Base;
unsigned int power = digit;
for ( size_t i = 1; i < n; i++ ) power *= digit;
sum += power;
} while ( ( tmp /= Base ) != 0 && !( x < sum ) );
return tmp == 0 && x == sum;
}
int main(void)
{
unsigned int a[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407,
1634, 8208, 9474, 54748, 92727, 93084, 548834
};
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
printf( "%u is %san Armstrong number.\n", a[i], is_armstrong( a[i] ) ? "": "not " );
}
return 0;
}
The program output is
0 is an Armstrong number.
1 is an Armstrong number.
2 is an Armstrong number.
3 is an Armstrong number.
4 is an Armstrong number.
5 is an Armstrong number.
6 is an Armstrong number.
7 is an Armstrong number.
8 is an Armstrong number.
9 is an Armstrong number.
153 is an Armstrong number.
370 is an Armstrong number.
371 is an Armstrong number.
407 is an Armstrong number.
1634 is an Armstrong number.
8208 is an Armstrong number.
9474 is an Armstrong number.
54748 is an Armstrong number.
92727 is an Armstrong number.
93084 is an Armstrong number.
548834 is an Armstrong number.
Please remove j++ from 2nd loop for (int j = 1; j <= x; j++)
I tried this:
void armstrong(int x)
{
// count digits
int counter = 0, temp = x, sum = 0;
while(temp != 0)
{
temp = temp/10;
++counter; // Note: pre increment faster
}
// printf("count %d\n",counter);
temp = x;
while(temp != 0)
{
sum += pow(temp % 10, counter);
temp = temp/10;
}
// printf("sum %d\n",sum);
if(x == sum)
{
printf("Armstrong\n");
}
else
{
printf("No Armstrong\n");
}
}
int main(){
armstrong(371);
armstrong(1634);
return 0;
}
Let's take this and add the ability to handle multiple numeric bases while we're at it. Why? BECAUSE WE CAN!!!! :-)
#include <stdio.h>
#include <math.h>
double log_base(int b, double n)
{
return log(n) / log((double)b);
}
int is_armstrong_number(int b, /* base */
int n)
{
int num_digits = trunc(log_base(b, (double)n)) + 1;
int sum = 0;
int remainder = n;
while(remainder > 0)
{
sum = sum + pow(remainder % b, num_digits);
remainder = (int) (remainder / b);
}
return sum == n;
}
int main()
{
printf("All the following are valid Armstrong numbers\n");
printf(" 407 base 10 - result = %d\n", is_armstrong_number(10, 407));
printf(" 0xEA1 base 16 - result = %d\n", is_armstrong_number(16, 0xEA1));
printf(" 371 base 10 - result = %d\n", is_armstrong_number(10, 371));
printf(" 1634 base 10 - result = %d\n", is_armstrong_number(10, 1634));
printf(" 0463 base 8 - result = %d\n", is_armstrong_number(8, 0463));
printf("All the following are NOT valid Armstrong numbers\n");
printf(" 123 base 10 - result = %d\n", is_armstrong_number(10, 123));
printf(" 0x2446 base 16 - result = %d\n", is_armstrong_number(16, 0x2446));
printf(" 022222 base 8 - result = %d\n", is_armstrong_number(8, 022222));
}
At the start of is_armstrong_number we compute the number of digits directly instead of looping through the number. We then loop through the digits of n in base b, summing up the value of the digit raised to the number of digits in the number, for the given numeric base. Once the remainder hits zero we know there are no more digits to compute and we return a flag indicating if the given number is an Armstrong number in the given base.

Print a different result than actual answer (Ciel and A-B Problem)

Input:
An input contains 2 integers A and B.
Output:
Print a wrong answer of A-B. Your answer must be a positive integer containing the same number of digits as the correct answer, and exactly one digit must differ from the correct answer. Leading zeros are not allowed. If there are multiple answers satisfying the above conditions, anyone will do.
Code:
#include <stdio.h>
int no_of_zeroes(int x);
int main()
{
int a, b;
int res1, res2;
int n1, n2;
scanf("%d",&a);
scanf("%d",&b);
res1 = a - b;
res2 = res1 + 10;
n1 = no_of_zeroes(res1);
n2 = no_of_zeroes(res2);
if(res1 < 9) printf("%d",res1 + 1);
else if(res1 == 9) printf("%d",res1-1);
else if((n1 == n2) && (res1 > 9)) printf("%d",res2);
else if((n2 > n1) && (res1>9))
{
res2 = res2 - 20;
printf("%d",res2);
}
}
int no_of_zeroes(int x)
{
int count = 0;
while(x>0)
{
x = x / 10;
count++;
}
return count;
}
Error:
What different should i do, basically else if blocks are creating trouble.
Your answer must be a positive integer containing the same number of digits as the correct answer
So the answer should be a-b. But the statement also says
exactly one digit must differ from the correct answer
Since it didn't specify the position of the digit, changing the last digit only should give us the correct answer to this problem. And so counting the number of digits of the difference is redundant.
Now the issue is - how to change the last digit? It's simple. We add 1 to the difference.
But there is a catch! If the difference is 99 and we add 1 to it, the result will be 100. Here, not only we're changing more than one digit, but also the number of digits.
And so, all we have to do is subtract 1 from the difference if the last digit of the difference is 9.
And so, the if-else block should look something like this:
int diff = a - b;
if(diff%10 == 9) {
diff--;
}
else {
diff++;
}
Here's my full code:
#include <stdio.h>
int main(void) {
int a, b;
scanf("%d%d", &a, &b);
int diff = a - b;
if(diff%10 == 9) {
diff--;
}
else {
diff++;
}
printf("%d\n", diff);
return 0;
}
On a different note, the function no_of_zeroes(int x) will return 0 if x=0. But, it should return 1 under general circumstances. And so the function should be something like this:
int no_of_digits(int x)
{
/* Adding the following line should fix the issue */
if(x==0) return 1;
int count = 0;
while(x>0)
{
x = x / 10;
count++;
}
return count;
}
I think you are making this much more complicated than needed. All you need is to check the last digit of the correct result and then change it.
For 0 and positive numbers:
last digit is 0 : add 1
last digit is 1 : add 1
...
last digit is 8 : add 1
last digit is 9 : subtract 1
For negative numbers, you simply change the sign and handle it as the positive number. This can be done because -123 has the same digits as 123.
So the code can be:
void wrongCalc(int a, int b)
{
int res = a - b; // Calculate result
if (res < 0) res = -res; // Change sign if negative
int lastDigit = res % 10; // Find last digit
if (lastDigit == 9)
{
--res; // Subtract 1
}
else
{
++res; // Add 1
}
printf("%d - %d = %d (correct result is %d)\n", a, b, res, a-b);
}
Limitations:
1) The program doesn't handle the possible integer overflow in a-b
2) The program doesn't handle the possible integer overflow in res = -res;
3) The program doesn't handle the case where the correct result is INT_MAX

Validating card credit numbers

I've been trying to create a program that can check if a credit card number is valid or not based on Hans Peter Luhn's algorithm. However, I can only get it to work for some inputs.
// Loop through every digit in the card number
for ( int i = 0; i < intlen (num); ++i )
{
nextDigit = getDigit (num, i);
// If every other number...
if ( i % 2 )
{
nextDigit *= 2;
// ...times by two and add the individual digits to the total
for ( int j = 0; j < intlen (nextDigit); ++j )
{
total += getDigit (nextDigit, j);
}
}
else
{
total += nextDigit;
}
}
When I use the AMEX card number 378282246310005 it works fine and tells the user it's valid. However, once I try the VISA card number 4012888888881881 it says it's invalid. I tried to do a sanity check and do it manually to see if my program was wrong but I deduced the same result. These card number were taken from the Paypal test credit card numbers page so I know they are valid.
So what am I doing wrong?
To clarify the details by the program, if total modulo 10 == 0 then the card number is valid.
Functions called:
// Function to return length (number of digits) of an int
int intlen (long long n)
{
int len = 1;
// While there is more than 1 digit...
while ( abs (n) > 9 )
{
// ...discard leading digits and add 1 to len
n /= 10;
++len;
}
return len;
}
// Function to return a digit in an integer at a specified index
short getDigit (long long num, int index)
{
// Calculating position of digit in integer
int pos = intlen (num) - index;
// Discard numbers after selected digit
while ( pos > 1 )
{
num /= 10;
--pos;
}
// Return right-most digit i.e. selected digit
return num % 10;
}
You'll want to change i % 2 to i % 2 == intlen (num) % 2 or similar; you should double every second digit, but starting from the right; i.e. excluding the final check digit:
From the rightmost digit, which is the check digit, moving left, double the value of every second digit; …
The reason the AMEX number you tried validated anyway is because it's an odd number of digits; the same digits get doubled regardless of whether you skip from the front or the back.
While I was looking at this to find the bug, I re-wrote the program to make it a bit simpler. As a side-effect this will be much faster.
We need to grab digits from the right anyway. We don't even need to count the digits; just keep pulling off the right-most digit until the number becomes 0. If the number starts out as 0, the checksum is trivially 0 and the code is still correct.
I grabbed all the numbers from the test page. This seems to be correct, except for one number: 76009244561 (listed as "Dankort (PBS)" in the test page). I tried this number with the Python code from the Wikipedia page, and again this number is rejected. I don't know why this number is different from the others.
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
bool check_one(long long num)
{
int checksum = 0;
int i = 1;
for (int i = 1; num; num /= 10, ++i)
{
int d = num % 10;
if (i % 2 == 0)
{
// even digit: double and add digits of doubled value
d *= 2;
if (d < 10)
{
// only one digit: we doubled a 0-4 so number is 0-8
checksum += d;
}
else
{
// two digits: we doubled a 5-9 so number is 10-18
checksum += (d % 10);
checksum += (d / 10);
}
}
else
{
// odd digit: just add
checksum += d;
}
}
return (checksum % 10) == 0;
}
static long long const valid_nums[] =
{
378282246310005,
371449635398431,
378734493671000,
5610591081018250,
30569309025904,
38520000023237,
6011111111111117,
6011000990139424,
3530111333300000,
3566002020360505,
5555555555554444,
5105105105105100,
4111111111111111,
4012888888881881,
4222222222222,
76009244561,
5019717010103742,
6331101999990016,
};
static size_t len_valid_nums = sizeof(valid_nums) / sizeof(valid_nums[0]);
static long long const non_valid_nums[] =
{
378282246310006, // add 1 to valid
371449635398432,
378734493671001,
5610591081018205, // swap last two digits
30569309025940,
38520000023273,
601111111111111, // delete last digit
601100099013942,
353011133330000,
};
static size_t len_non_valid_nums =
(sizeof(non_valid_nums) / sizeof(non_valid_nums[0]));
main()
{
bool f;
for (int i = 0; i < len_valid_nums; ++i)
{
long long num = valid_nums[i];
f = check_one(num);
if (!f)
{
printf("Number %lld considered invalid but should be valid\n", num);
}
}
for (int i = 0; i < len_non_valid_nums; ++i)
{
long long num = non_valid_nums[i];
f = check_one(num);
if (f)
{
printf("Number %lld considered valid but should be invalid\n", num);
}
}
}

Extracting individual digits from a long in C

I'm doing a homework assignment for my course in C (first programming course).
Part of the assignment is to write code so that a user inputs a number up to 9 digits long, and the program needs to determine whether this number is "increasing"/"truly increasing"/"decreasing"/"truly decreasing"/"increasing and decreasing"/"truly decreasing and truly increasing"/"not decreasing and not increasing". (7 options in total)
Since this is our first assignment we're not allowed to use anything besides what was taught in class:
do-while, for, while loops, else-if, if,
break,continue
scanf, printf ,modulo, and the basic operators
(We can't use any library besides for stdio.h)
That's it. I can't use arrays or getchar or any of that stuff. The only function I can use to receive input from the user is scanf.
So far I've already written the algorithm with a flowchart and everything, but I need to separate the user's input into it's distinct digits.
For example, if the user inputs "1234..." i want to save 1 in a, 2 in b, and so on, and then make comparisons between all the digits to determine for example whether they are all equal (increasing and decreasing) or whether a > b >c ... (decreasing) and so on.
I know how to separate each digit by using the % and / operator, but I can't figure out how to "save" these values in a variable that I can later use for the comparisons.
This is what I have so far:
printf("Enter a positive number : ");
do {
scanf ("%ld", &number);
if (number < 0) {
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
while (number < 0) {
a = number % 10;
number = number - a;
number = number / 10;
b = a;
}
Why not scan them as characters (string)? Then you can access them via an array offset, by subtracting the offset of 48 from the ASCII character code. You can verify that the character is a digit using isdigit from ctype.h.
EDIT
Because of the incredibly absent-minded limitations that your professor put in place:
#include <stdio.h>
int main()
{
int number;
printf("Enter a positive number: ");
do
{
scanf ("%ld", &number);
if (number < 0)
{
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
int a = -1;
int b = -1;
int c = -1;
int d = -1;
int e = -1;
int f = -1;
int g = -1;
int h = -1;
int i = -1;
while (number > 0)
{
if (a < 0) a = number % 10;
else if (b < 0) b = number % 10;
else if (c < 0) c = number % 10;
else if (d < 0) d = number % 10;
else if (e < 0) e = number % 10;
else if (f < 0) f = number % 10;
else if (g < 0) g = number % 10;
else if (h < 0) h = number % 10;
else if (i < 0) i = number % 10;
number /= 10;
}
/* Printing for verification. */
printf("%i", a);
printf("%i", b);
printf("%i", c);
printf("%i", d);
printf("%i", e);
printf("%i", f);
printf("%i", g);
printf("%i", h);
printf("%i", i);
return 0;
}
The valid numbers at the end will be positive, so those are the ones you validate to meet your different conditions.
Since you only need to compare consecutive digits, there is an elegant way to do this without arrays:
int decreasing = 2;
int increasing = 2;
while(number > 9)
{
int a = number % 10;
int b = (number / 10) % 10;
if(a == b)
{
decreasing = min(1, decreasing);
increasing = min(1, increasing);
}
else if(a > b)
decreasing = 0;
else if(a < b)
increasing = 0;
number /= 10;
}
Here, we walk through the number (by dividing by 10) until only one digit remains. We store info about the number up to this point in decreasing and increasing - a 2 means truly increasing/decreasing, a 1 means increasing/decreasing, and a 0 means not increasing/decreasing.
At each step, a is the ones digit and b is the tens. Then, we change increasing and decreasing based on a comparison between a and b.
At the end, it should be easy to turn the values of increasing and decreasing into the final answer you want.
Note: The function min returns the smaller of its 2 arguments. You should be able to write your own, or replace those lines with if statements or conditionals.
It's stupid to ask you to do loops without arrays --- but that's your teacher's fault, not yours.
That being said, I would do something like this:
char c;
while (1) {
scanf("%c", &c);
if (c == '\n') /* encountered newline (end of input) */
break;
if (c < '0' || c > '9')
break; /* do something to handle bad characters? */
c -= '0';
/*
* At this point you've got 0 <= c < 9. This is
* where you do your homework :)
*/
}
The trick here is that when you type numbers into a program, you send the buffer all at once, not one character at a time. That means the first scanf will block until the entire string (i.e. "123823" or whatever) arrives all at once, along with the newline character ( '\n' ). Then this loop parses that string at its leisure.
Edit For testing the increasing/decreasing-ness of the digits, you may think you need to store the entire string, but that's not true. Just define some additional variables to remember the important information, such as:
int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far;
etc. etc.
Let us suppose you have this number 23654
23654 % 10000 = 2 and 3654
3654 % 1000 = 3 and 654
654 % 100 = 6 and 54
54 % 10 = 5 and 4
4
This way you can get all the digits. Of course, you have to know if the number is greater than 10000, 1000, 100 or 10, in order to know the first divisor.
Play with sizeof to get the size of the integer, in order to avoid a huge if...else statement
EDIT:
Let us see
if (number>0) {
// Well, whe have the first and only digit
} else if (number>10) {
int first_digit = number/10;
int second_digit = number % 10;
} else if (number>100) {
int first_digit = number/100;
int second_digit = (number % 100)/10;
int third_digit = (number % 100) % 10;
} ...
and so on, I suppose
// u_i is the user input, My homework asked me to extract a long long, however, this should also be effective for a long.
int digits = 0;
long long d_base = 1;
int d_arr[20];
while (u_i / d_base > 0)
{
d_arr[digits] = (u_i - u_i / (d_base * 10) * (d_base * 10)) / d_base;
u_i -= d_arr[digits] * d_base;
d_base *= 10;
digits++;
}
EDIT: the extracted individual digit now lives in the int array d_arr. I'm not good at C, so I think the array declaration can be optimized.
Here's a working example in plain C :
#include <stdio.h>
unsigned long alePow (unsigned long int x, unsigned long int y);
int main( int argc, const char* argv[] )
{
int enter_num, temp_num, sum = 0;
int divisor, digit, count = 0;
printf("Please enter number\n");
scanf("%d", &enter_num);
temp_num = enter_num;
// Counting the number of digits in the entered integer
while (temp_num != 0)
{
temp_num = temp_num/10;
count++;
}
temp_num = enter_num;
// Extracting the digits
printf("Individual digits in the entered number are ");
do
{
divisor = (int)(alePow(10.0, --count));
digit = temp_num / divisor;
temp_num = temp_num % divisor;
printf(" %d",digit);
sum = sum + digit;
}
while(count != 0);
printf("\nSum of the digits is = %d\n",sum);
return 0;
}
unsigned long alePow(unsigned long int x, unsigned long int y) {
if (x==0) { return 0; }
if (y==0||x==1) { return 1; }
if (y==1) { return x; }
return alePow(x*x, y/2) * ((y%2==0) ? 1 : x);
}
I would suggest loop-unrolling.
int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits
int count = 0; //for number of digits in the given number
if(number>0) {
i=number%10;
number/=10;
count++;
}
if(number>0) {
h=number%10;
number/=10;
count++;
}
if(number>0) {
g=number%10;
number/=10;
count++;
}
....
....
/* All the way down to the storing variable a */
Now, you know the number of digits (variable count) and they are stored in which of the variables. Now you have all digits and you can check their "decreasing", "increasing" etc with lots of if's !
I can't really think of a better soltion given all your conditions.

Resources