Is it possible to remove digits from an integer? - c

Is it possible to remove a digit from an integer?
For example if I want to remove all
even digits from 123658 and be left with
135 how could I do that?
This is for an assignment, I can't use arrays, character variables
or Math.h functions.
Here is the code I have written so far
uint32_t phaseInt(uint32_t N, enum ProcessChoice Choice) {
uint32_t phaseInt = 0;
uint32_t tempVar = N;
if (tempVar == 0){
phaseInt = 0;
}
if (tempVar != 0 && Choice == Even){
while(tempVar != 0)
{
tempVar % 10;
tempVar /= 10;
if ( tempVar % 2 == 0)
{
doSomeAction(tempVar);
}
}
}

I don't see the need to use recursion here, it only complicates stuff -feels good though-, you can use a simple while loop with and if statement:
int digit,input,output = 0,currentFactor=1;
//read input
while(input!=0)
{
digit = input % 10; //read digit
input = input / 10; //remove digit from input
if(digit % 2 == 1) //if digit is odd
{
output += digit*currentFactor; //add digit to output at the position determined by factor
currentFactor *= 10; //move the position by one digit (multiply factor by 10)
}
}
return output;

For example if I want to remove all even digits from 123658 and be left with
135 how could I do that?
... can't use arrays, character variables or Math.h functions.
OP's code is somewhat close.
phaseInt = 0; reminds me of BASIC. In C, return the value instead.
I am sure a non-recursive solution, something like OP's can be written, yet recursion is so tight here.
Pseudo recursion code to not give it all away
uint32_t PhaseInt_SansEven(uint32_t n) {
if (has_a_small_value_that_needs_no_recursion_and_can_return_0(n)) {
return 0;
}
uint32_t msdigits = all_digits_except_the_least(n);
uint32_t lsdigit = the_least_digit(n);
// If odd digit
if (test_for_oddness(lsdigit) {
// How to "append" the left digits and the 1 right one
return PhaseInt_SansEven(msdigits) * TBD1 + lsdigit;
} else {
// How to "append" the left digits and ""
return PhaseInt_SansEven(msdigits) + TBD2;
}
}
As #BLUEPIXY commented, an all even digit number needs to return an empty number. Hope 0 is OK.
Or non-recursive
uint32_t PhaseInt_SansEven(uint32_t n) {
uint32_t odds = 0;
uint32_t pow10 = TBD1; // Think ones place
while (n) {
uint32_t least_digit = the_least_digit_think_mod(n);
n = shift_one_decimal_digit_right_think_divide(n);
if (least_digit%2) {
odds += pow10 * least_digit;
pow10 *= TBD; // Make 10x larger
}
}
return odds;
}

Related

C: Decimal Value

Can any one help me sort out one problem, i have to reverse a number without using array(int/char) for storing them.
input1 = 123
output1 = 321
input2 = 2300
output2 = 0032
I am trying to find the solution but 0 got erased while printing so i thought of octal conversion but still no solution, so i went with the decimal places and i made the 23 to 0.0032. Now my problem is how can i extract the 0032 from that part.
Is there any possible way to achieve this without using array(int/char), with that it will be easy.
#include<stdio.h>
#include<math.h>
int main()
{
int number =3200;
int temp;
while (number >0)
{
temp= number%10;
printf("%d",temp);
number = number/10;
}
return 0;
}
you could use recursion to solve this problem, without using any array in fact u could also reverse a string without using any array using recursion. This code works for both numbers and strings and it has no arrays:
char reverse(int a)
{
char c,d;
if(a=='\n')
return 0;
c=getchar();
d=reverse(c);
putchar(a);
return (c);
}
int main()
{
char c;
scanf("%c",&c);
reverse(c);
}
for a start try this.
int n, l;
char nBuf[126];
n = 1230010;
l = sprintf(nBuf, "%d", n );
while( l >= 0 )
printf("%c", nBuf[l--] );
Though if you are taking input from stdin take it as string rathar than as int or long.
Edit - for not using array
int n = 123;
while(n) {
printf("%d", n%10);
n/=10;
}
I am assuming to get a value of this sort "output2 = 0032" it is better of being a string, else formatting complications turns up with input value length and format left space with zeros etc etc.
This becomes fairly easy if you know that you can represent numbers like so:
x = a_0 + a_1 * b^1 + a_2 * b^2 + ...
a_i are the digits
b is the base
To extract the lowest digit, you can use the remainder: x % b
Dividing by the base "removes" the last digit. That way you can get the digits in order lowest to highest.
If you reverse the digits then the lowest becomes the highest. Looking at below transformation it's easy to see how to incrementally build up a number when the digits come in order highest to lowest:
x = a_0 + b * (a_1 + b * (a_2 + ...
You start of with 0, and for each digit you multiply with the base and then add the digit.
In pseudo code:
output = 0
while input != 0
digit = input % base
input = input / base ;; integer division
output = output * base + digit
end
If you want to store leading zeros, then you need to either store the digits in an array, or remember for how many steps of above loop the output remained zero:
output = 0
zeros = 0
while input != 0
digit = input % base
input = input / base ;; integer division
output = output * base + digit
if output == 0
zeros = zeros + 1
end
end
To print that you obviously need to print zeros zeros and then the number.
Live example here, relevant code:
unsigned reverse(
unsigned input,
unsigned const base,
unsigned * const zeros) {
unsigned output = 0;
unsigned still_zero = 0;
for (; input != 0; input/=base) {
output *= base;
output += input % base;
if (output == 0) {
++still_zero;
}
}
if (zeros != NULL) {
*zeros = still_zero;
}
return output;
}
void print_zeros(unsigned zeros) {
for (; zeros != 0; --zeros) {
printf("0");
}
}
Recursion allows for a simple solution. A small variation on #vishu rathore
void rev_dec(void) {
int ch = getchar();
if (isdigit(ch)) {
rev_dec();
}
if (ch >= 0) putchar(ch);
}
int main(void) {
rev_dec();
return 0;
}
input
0123456789012345678901234567890123456789
output
9876543210987654321098765432109876543210

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.

How can I get my program to do anything when a "multidigit number with all digits identical" appears?

my program generates random numbers with up to 6 digits with
int number = arc4random % 1000000;
I want that my program do something when a number like 66 or 4444 or 77777 appears (multidigit number with all digits identical). I could manual write:
switch (number) {
case 11: blabla...;
case 22: blabla...;
(...)
case 999999: blabla;
}
That would cost me many program code. (45 cases...)
Is there an easy way to solve the problem.
Here's one way to check that all digits are the same:
bool AllDigitsIdentical(int number)
{
int lastDigit = number % 10;
number /= 10;
while(number > 0)
{
int digit = number % 10;
if(digit != lastDigit)
return false;
number /= 10;
}
return true;
}
As long as you use the mod operator (sorry I do not know objective C) but I'm quite certain there must be a mod operator like % and modding it based on 1's.
For instance:
66%11
You know it is the same number of digits because mod returned 0 in this case.
Same here:
7777%1111
You could figure out how many digits, then divide a six-digit number by 111111, 5-digit number by 11111, etc, and see if the result is an integer.
Excuse me if I don't suggest any Objective-C code, I don't know that language.
convert the number to a string, check the length to get the number of digits, then mod by the appropriate number. pseudocode follows where num_to_check is the number you start out with (i.e. 777)
string my_num = (string)num_to_check;
int num_length = my_num.length;
int mod_result;
string mod_num = "1";
int mod_num_int;
for(int i = 1; i < num_length - 1; i++)
{
mod_num = mod_num + "1";
}
mod_num_int = (int)mod_num;
mod_result = num_to_check % mod_num_int;
//If mod_result == 0, the number was divisible by the appropriate 111... string with no remainder
You could do this recursively with the divide and multiply operator (a divide with remainder could simplify it though)
e.g.
bool IsNumberValid(int number)
{
if(number > 10)
{
int newNumber = number / 10;
int difference = number - newNumber * 10;
number = newNumber;
do
{
newNumber = number / 10;
if((number - newNumber * 10) != difference)
{
// One of the number didn't match the first number, thus its valid
return true;
}
number = newNumber;
} while(number);
// all of the numbers were the same, thus its invalid
return false;
}
// number was <= 10, according to your specifications, this should be valid
return true;
}
Here's a recursive version, just for larks. Again, not the most efficient way, but probably the shortest codewise.
bool IsNumberValid (int number) {
if (number < 10) return true;
int n2 = number / 10;
// Check if the last 2 digits are same, and recurse in to check
// other digits:
return ((n2 % 10) == (number % 10)) && IsNumberValid (n2);
}
Actually, this is tail recursion, so a decent compiler ought to generate pretty efficient code.
Convert to a string and check if each char in the string, starting at position 1, is the same as the previous one.
Assuming Objective-C has a 'bool' type analogous Standard C99:
#include <assert.h>
#include <stdbool.h>
extern bool all_same_digit(int number); // Should be in a header!
bool all_same_digit(int number)
{
static const struct
{
int lo_range;
int divisor;
} control[] =
{
{ 100000, 111111 },
{ 10000, 11111 },
{ 1000, 1111 },
{ 100, 111 },
{ 10, 11 },
};
static const int ncontrols = (sizeof(control)/sizeof(control[0]));
int i;
assert(number < 10 * control[0].lo_range);
for (i = 0; i < ncontrols; i++)
{
if (number > control[i].lo_range)
return(number % control[i].divisor == 0);
}
return(false);
}
You can probably work out a variation where the lo_range and divisor are each divided by ten on each iteration, starting at the values in control[0].
#include <stdlib.h>
#include <stdio.h>
int main() {
int a = 1111;
printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
a = 143;
printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
a = 1;
printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
a = 101;
printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
return 0;
}
int are_all_equal(int what) {
int temp = what;
int remainder = -1;
int last_digit = -1;
while (temp > 0) {
temp = temp/10;
remainder = temp%10;
if (last_digit != -1 && remainder != 0) {
if (last_digit != remainder) return 0;
}
last_digit = remainder;
}
return 1;
}
Similar, but not exactly equal to the other answers (which I didn't notice were there).
digitsequal = ( ((number < 1000000) && (number > 111110) && (number % 111111 == 0)) ||
...
((number < 1000) && (number > 110) && (number % 111 == 0)) ||
((number < 100) && (number > 10) && (number % 11 == 0))
);
Thanks to boolean operations that shortcut, this should be a good enough solution regarding the average number of comparisons, it requires at most only one modulo operation per number, it has no loop, it can be nicely formatted to look symmetric, and it is obvious what it tests. But of course, premature optimization, you know, but since a lot of other solutions are already given... ;)

Having trouble with a Collatz Conjecture test in C

I am trying to create a code that will take the number 2 to 100, and test each for the collatz conjecture.
The goal is that for each number, if it is even, divide it by two, and if it is odd, then multiply it by 3 and add 1.
It prints each step, and each number should stop testing if it reaches 1. Why doesn't it work?
#include <stdio.h>
int main()
{
int number, position;
position == 2;
number == 2;
while (position <= 100)
{
while (number != 1)
{
if (number % 2 == 0)
{
number = number/2;
printf("%d\n", number);
}
else if (number % 2 != 0)
{
number = number*3;
number = number + 1;
printf("%d\n", number);
}
}
position = position + 1;
number = position;
}
}
It prints recurring Os
Fix the == vs =:
position = 2;
number = 2;
Also, the else if is unnecessary. The opposite of even is odd, so a plain else will suffice :-)
You have set position and number with a double equal == (Comparision Operator) instead of using single equal = (Assignment Operator) so that the algorithm is comparing them instead of assigning a value.
The assignment should look like this:
position = 2;
number = 2;
Also you can do it when you first define them:
int number=2, position=2;
Apart from that the code is correct, the only thing to highlight is that you don´t need to use else if because it can just be even or odd so a single else would be enough.
Hope I´ve helped :-)

Resources