I have an assigment to create a function that recieves a number, and return the reversed number.
E.G :
Input : 12343
Output : 34321
No loops allowed, and the input is only the number .
This is what I've tried :
long GetReverse(unsigned long n)
{
if (n < 10)
return n % 10;
else
return 10 * GetReverse(n / 10) + n % 10;
}
Though This is retuning me the same input and not reversing the number ( I know what is the problem here, I just can't think of a way to do it)
Any thoughts?
EDIT: This is the solution I came up with :
int numOfMulti(unsigned long num) {
if (num < 10)
return 1;
return 10 * numOfMulti(num / 10);
}
long GetReverse(unsigned long n)
{
if (n < 10)
return n % 10;
else
return n % 10 * numOfMulti(n) + GetReverse(n / 10) ;
}
Wasn't able to find a solution without a secondary function or static variables.
It's easy. Please try my solution. NO LOOPS, ONE PARAMETER.
long GetReverse(unsigned long n)
{
static unsigned long m = 0;
static int recursive_level = 0;
recursive_level++;
if (n < 10) {
recursive_level--;
m = m * 10 + n;
int temp = m;
if (recursive_level == 0) {
m = 0;
}
return temp;
}
m = m * 10 + (n % 10);
GetReverse(n / 10);
recursive_level--;
int temp = m;
if (recursive_level == 0) {
m = 0;
}
return temp;
}
You will need to pass 2 elements to the GetReverse function, because the last digit will have to be shifted on the left:
long GetReverse(unsigned long n, unsigned long m)
{
if (n < 10)
return 10 * m + n;
else
return GetReverse(n / 10, 10 * m + n % 10);
}
You can then call GetReverse(12343, 0) and get as expected 34321
This is silly and should not be used in real life, but complies with the requirements:
unsigned long GetReverse(unsigned long n)
{
if (n < 10)
return n;
else
return n % 10 * lround(pow(10,floor(log10(n)))) + GetReverse(n / 10);
}
Here's a solution that only takes one parameter, although you can only use the least significant 32 bits for your input:
uint64_t rev(uint64_t n)
{
uint32_t _n = n;
uint32_t _m = n >> 32;
return _n < 10
? 10 * _m + _n
: rev(_n / 10 + (uint64_t)(10 * _m + _n % 10) * 65536 * 65536)
;
}
int main(){
uint32_t n = 12345;
n = rev(n);
}
Essentially the coefficient is stored in the higher order bits of n. In many ways this is a terrible contrivance since all I'm doing is using a single parameter where there should be two parameters, and I'm relying on a (well-defined) narrowing unsigned conversion at the call site! But it does show the elegance of using the fixed width unsigned types.
How about this?
#include <stdio.h>
#include <math.h>
long GetReverse(unsigned long n){
if (n < 10){
return n;
} else {
unsigned long r = GetReverse(n / 10);
int p = snprintf(NULL, 0, "%lu", r);
return lround(pow(10, p)) * (n % 10) + r;
}
}
int main(void){
unsigned long n = 112233445566778899;
printf("%lu", GetReverse(n));
return 0;
}
To place the last digit first you need to multiply it by 10 once for each digit in the number:
#include <math.h>
long GetReverse(unsigned long n)
{
if (n < 10)
return n; // Removed the % 10 as it is not needed when n is < 10
else {
long digit = n%10;
long factor = (long) pow(10, (int)log(n));
return digit * factor + GetReverse(n / 10);
}
}
log and pow is used instead of loops to calculate the number of digits in n. Note that this may fail unless the implementation of pow is good enough. I did a test using gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16) and that combination produced correct results for integer powers of 10 for results that fit in a long.
No loops, no variables, no additional parameters!
#include <stdio.h>
unsigned long reverse(unsigned long num)
{
if (num < 10) return num;
if (num < 100) return 10 * (num %10) + reverse(num/10);
if (num < 1000) return 100 * (num %10) + reverse(num/10);
if (num < 10000) return 1000 * (num %10) + reverse(num/10);
if (num < 100000) return 10000 * (num %10) + reverse(num/10);
if (num < 1000000) return 100000 * (num %10) + reverse(num/10);
if (num < 10000000) return 1000000 * (num %10) + reverse(num/10);
if (num < 100000000) return 10000000 * (num %10) + reverse(num/10);
return 100000000 * (num %10) + reverse(num/10);
}
int main(int argc, char **argv)
{
unsigned long num, rev;
if (argc < 2) return 1;
sscanf(argv[1], "%lu", &num);
rev = reverse(num);
printf("%lu -->> %lu\n", num, rev );
return 0;
}
Or, using a helper function (not a variable)
[note: this has quadratic complexity(on the number of digits)]
unsigned long tencount(unsigned long num)
{
if (num < 10) return 1;
return 10 * tencount( num/10);
}
unsigned long reverse2(unsigned long num)
{
if (num < 10) return num;
return tencount(num) * (num %10) + reverse2(num/10);
}
Assuming a 32bit long you could do it without loops or recursion;
long GetReverse(unsigned long n)
{
unsigned long x = ((n/1000000000) +
((n/100000000)%10)*10 +
((n/10000000)%10)*100 +
((n/1000000)%10)*1000 +
((n/100000)%10)*10000 +
((n/10000)%10)*100000 +
((n/1000)%10)*1000000 +
((n/100)%10)*10000000 +
((n/10)%10)*100000000 +
((n)%10)*1000000000);
return (x/(9*(x%10==0)+1)/
(9*(x%100==0)+1)/
(9*(x%1000==0)+1)/
(9*(x%10000==0)+1)/
(9*(x%100000==0)+1)/
(9*(x%1000000==0)+1)/
(9*(x%10000000==0)+1)/
(9*(x%100000000==0)+1)/
(9*(x%1000000000==0)+1));
}
This is a solution:
int reverse(int i) {
static int p = 0;
if (i==0) { int r = p; p = 0; return r; }
p = 10*p+i%10;
return reverse(i/10);
}
Idea is to use a second argument, but as it is used only to store the partial result a static variable can be used. To be able to reuse the function you just need to reset the static at the end of the recursion.
Becareful as such a function is not an involution means that reverse(reverse(x)) not equals to x, think about x=1000. If you want involution then you need to define it over a C-string that represent the value.
C reverse a number recursively
I have an assignment to create a function that receives a number and return the reversed number.
No loops allowed, and the input is only the number .
Add a helper recursive function. #Art
No static variable, no floating point math needed.
The below meets the goals:
1) Recursion used.
2) Function receives a number and return the reversed number
3) No loops allowed, and the input is only the number
#include <stdio.h>
#include <stdlib.h>
static unsigned reverse_helper(unsigned x, unsigned *pow10) {
if (x < 10) {
*pow10 = 10;
return x;
}
unsigned y = reverse_helper(x / 10, pow10);
y += *pow10 * (x%10);
*pow10 *= 10;
return y;
}
unsigned reverse(unsigned x) {
unsigned pow10 = 1;
unsigned y = reverse_helper(x, &pow10);
printf("%10u %10u\n", x, y);
return y;
}
int main(void) {
reverse(0);
reverse(9);
reverse(10);
reverse(99);
reverse(100);
reverse(1234);
reverse(123456789);
}
Output
0 0
1 1
9 9
10 1
99 99
100 1
1234 4321
123456789 987654321
A solution like OP's yet uses 2 recursive functions.
Recurse function with 1 parameter, no floating-point, no static variables.
// return the great power-of-10 less than n
unsigned long p10(unsigned long n) {
if (n < 10) {
return 1;
}
return p10(n/10) * 10;
}
unsigned long GetReverse(unsigned long n) {
if (n < 10) {
return n;
}
// OPs code
//return 10 * GetReverse(n / 10) + n % 10;
// v----------------v------------------- scale by 1
// | | v-----------v--- scale by a power of 10 <= n
return GetReverse(n / 10) + p10(n)*(n%10);
}
What about calling a function like char* getReverse(int n) So you could use mod and concatenation to obtain the reverse. Then in the caller method int getReverse(int n) you parse the string to int. You could use recursion and then the single line to make the parsing. No loops needed and one parameter.
Here's my completely reentrant version, with no extra variable. It works by using ldiv( num / 10 ) to get quotient and remainder, then returns the remainder multiplied by 10^(num digits in quotient) added to the reverse of the quotient (code is formatted to remove the scroll bar - normally I'd have blank lines and more braces):
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
/* unsigned long power function */
unsigned long lpow( unsigned long base, unsigned long exp )
{
unsigned long result = 1UL;
while ( exp )
{
if ( exp & 1 )
result *= base;
exp >>= 1;
base *= base;
}
return( result );
}
/* count the number of decimal digits */
unsigned long numdigits( unsigned long num )
{
return( floor( log10( num ) ) + 1 );
}
unsigned long reverse( unsigned long in )
{
ldiv_t tmp = ldiv( in, 10UL );
if ( tmp.quot == 0 )
return( tmp.rem );
return( reverse( tmp.quot ) + tmp.rem * lpow( 10, numdigits( tmp.quot ) ) );
}
unsigned long lpow() function from https://stackoverflow.com/a/101613/4756299
unsigned long numdigits() function from https://stackoverflow.com/a/1068870/4756299
Called like this:
int main( int argc, char **argv )
{
for ( int ii = 1; ii < argc; ii++ )
{
unsigned long num = strtoul( argv[ ii ], NULL, 10 );
printf( "Reverse of %lu is %lu\n", num, reverse( num ) );
}
return( 0 );
}
For starters it is unclear why the return type is declared like long while the parameter has the type unsigned long.
long GetReverse(unsigned long n);
^^^^ ^^^^^^^^^^^^^
To have a more large of integers it is better to declare the parameter and the return type like unsigned long long int.
The function can be defined by using a local static variable that will keep the calculated reversed value.
Here it is.
unsigned long long int GetReverse(unsigned long long int n)
{
const unsigned long long int Base = 10;
static unsigned long long int reversed;
unsigned long long int tmp;
reversed = Base * reversed + n % Base;
return (n /= Base ) == 0 ? tmp = reversed, reversed = n, n = tmp, n
: GetReverse(n);
}
In the demonstrative program below there is shown how the function works.
#include <stdio.h>
unsigned long long int GetReverse(unsigned long long int n)
{
const unsigned long long int Base = 10;
static unsigned long long int reversed;
unsigned long long int tmp;
reversed = Base * reversed + n % Base;
return (n /= Base ) == 0 ? tmp = reversed, reversed = n, n = tmp, n
: GetReverse(n);
}
int main(void)
{
const unsigned long long int Base = 10;
for ( unsigned long long int i = 1, n = 0; i < Base; i++ )
{
n = Base * n + i;
printf( "%llu\n", n );
printf( "%llu\n", GetReverse( n ) );
putchar( '\n' );
}
return 0;
}
The program output is
1
1
12
21
123
321
1234
4321
12345
54321
123456
654321
1234567
7654321
12345678
87654321
123456789
987654321
Related
Write a function int* dec2bin(int N, int* n), which, given a natural number 0 ≤ N < 65535, computes and returns its representation in the binary numeral system. The program has to determine the coefficients ai ∈ {0,1}, i = 0,...,n − 1, such that N = (sum->n-1) ai2^i (n ≤ 16).
#include <stdio.h>
#include <math.h>
#include <assert.h>
int decimalToBinary(int N)
{
int B_Number = 0;
int c= 0;
int ctr=0;
while (N != 0) {
int rem = N % 2;
c = pow(10, ctr);
B_Number += rem * c;
N /= 2;
ctr++;
}
return B_Number;
}
int main()
{
int N;
scanf("%d", &N);
printf("%d", decimalToBinary(N));
return 0;
}
I know how to make a program that converts the numbers but I don't understand why the pointer is needed for and how to implement it.
Another way...
This was written to print the binary representation of a value (left-to-right). Instead of printing, you could simply assign the 0/1 (left-to-right) to a passed array (of 16 integers), then return the number of assigned integers to the calling function to print them from a loop.
int main() {
for( int i = 253; i <= 258; i++ ) {
printf( "Decimal %d: ", i );
unsigned int bitmask = 0;
bitmask = ~bitmask;
bitmask &= ~(bitmask >> 1); // High bitmask ready
// skip over leading 0's (optional)
while( bitmask && (bitmask & i) == 0 ) bitmask >>= 1;
// loop using bitmask to output 1/0, then shift mask
do {
putchar( (bitmask & i) ? '1' : '0' );
} while( (bitmask >>= 1) != 0 );
putchar( '\n' );
}
return 0;
}
Use an integer type capable of encoding the decimal number 1111_1111_1111_1111: use long long.
Do not use pow(), a floating point function for an integer problem. It may generate value just slightly smaller than the integer expected and is slow.
long long decimalToBinary_alt(int N) {
long long B_Number = 0;
long long power = 1;
while (N != 0) {
int rem = N % 2; // result: -1, 0, or 1
B_Number += rem * power;
N /= 2;
power *= 10; // Scale the power of 10 for the next iteration.
}
return B_Number;
}
Usage
printf("%lld\n", decimalToBinary(N));
Your function does not have the required parameters and return value.
int* dec2bin(int N, int* n)
{
unsigned uN = N;
for(int bit = 15; bit >= 0; bit--)
{
*(n + 15 - bit) = !!(uN & (1U << bit));
}
return n;
}
I have a function that is supposed to convert a decimal number into binary.
The thing is for some numbers it works like the output for:
27 = 00011011
but for 5015 it converts it into 82630143 instead 1001110010111
This is my function:
int dec(int num) {
long bNum = 0;
int remNum, i = 1, highNum = 32768;
while (num != 0) {
remNum = num / highNum;
remNum = num % 2;
num /= 2;
bNum = bNum + remNum * i;
i = i * 10;
}
return bNum;
}
Any help would be really appreciated.
As mch commented 1001110010111 is way to big for a integer. You can try to save it in a unsigned long long int variable, but actually the best way is to use a char-array or a char-pointer.
You should check which of your variables don't have enough
"space" for storing your numbers. I checked and see besides bNum your other variables like i don't have enough space:
unsigned long long int dec(int num) {
unsigned long long int bNum = 0,i = 1;// i should be unsigned long long
long int remNum, highNum = 32768;//highNum is better to be long int
while (num != 0) {
remNum = num / highNum;
remNum = num % 2;
num /= 2;
bNum = bNum + remNum * i;
i = i * 10;
}
return bNum;
}
and in your main check where you store returned number:
int main()
{
unsigned long long int r;
int a;
scanf("%d", &a);
r = dec(a);
}
I have a function that is supposed to convert a decimal number into binary.
The thing is for some numbers it works like the output for:
27 = 00011011
but for 5015 it converts it into 82630143 instead 1001110010111
This is my function:
int dec(int num) {
long bNum = 0;
int remNum, i = 1, highNum = 32768;
while (num != 0) {
remNum = num / highNum;
remNum = num % 2;
num /= 2;
bNum = bNum + remNum * i;
i = i * 10;
}
return bNum;
}
Any help would be really appreciated.
As mch commented 1001110010111 is way to big for a integer. You can try to save it in a unsigned long long int variable, but actually the best way is to use a char-array or a char-pointer.
You should check which of your variables don't have enough
"space" for storing your numbers. I checked and see besides bNum your other variables like i don't have enough space:
unsigned long long int dec(int num) {
unsigned long long int bNum = 0,i = 1;// i should be unsigned long long
long int remNum, highNum = 32768;//highNum is better to be long int
while (num != 0) {
remNum = num / highNum;
remNum = num % 2;
num /= 2;
bNum = bNum + remNum * i;
i = i * 10;
}
return bNum;
}
and in your main check where you store returned number:
int main()
{
unsigned long long int r;
int a;
scanf("%d", &a);
r = dec(a);
}
I am trying to make a recursive function in C that calculates the sum of digits in 2ⁿ, where n < 10⁷. I made something that works, but it's very slow (for n = 10⁵ it takes 19 seconds). The function must return the sum in maximum 1 second. My algorithm calculates 2ⁿ using arrays to store its digits and it's not using a recursive function.
Is there any way to compute this sum of digits without calculating 2ⁿ? Or a faster way to calculate 2ⁿ and its digits sum?
P.S.: The recursive function must get only the n parameter, i.e. int f(int n);
Late edit: I wrote a recursive solution; it is faster, but it doesn't work for n > 10⁵.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int sumOfDigits(int* num, int n) {
if (n == 0) {
int sum = 0;
for (int i = 1; i <= num[0]; ++i) {
while (num[i] > 0) {
sum += num[i] % 10;
num[i] /= 10;
}
}
return sum;
}
int carry = 0;
for (int i = 1; i <= num[0]; ++i) {
num[i] = num[i] * 2 + carry;
carry = num[i] / 1000000000;
num[i] %= 1000000000;
if (carry != 0 && i == num[0]) {
++num[0];
}
}
return sumOfDigits(num, n - 1);
}
int main (void) {
int n = 100000;
int size = (n*log10(2) + 1) / 9 + 2;
int* num = calloc(size, sizeof(int));
num[0] = 1;
num[1] = 1;
printf("\n%d", sumOfDigits(num, n));
free(num);
return 0;
}
It seems that the posted code is using an "implicit" arbitrary precision type (with "digits" in the range [0, 999999999]) to recursively calculate all the multiplication by 2, which means, for e.g. n = 100, to perform 100 times those expansive calculation.
It should be more efficient (O(log(n)) instead of O(n)) to perform each time a multiplication of the number by itself or by 2, based on whether the exponent is even or odd. E.g. 27 = 2 * (23 * 23).
Another approach would be to explicitly implement a Bing Int type, but with a binary underlying type (say a uint32_t). It would be trivial to calculate 2n, it'd be just an array of zeroes with a final power of two (again, just one non-zero bit).
Now, to get the sum of the (base 10) digits you need to transform that number in base, say 100000000 (like the OP did), and to do that, you have to implement a long subtraction between two Big Ints and a long division by 100000000, which will give you the remainder too. Use that remainder to calculate the partial sum of the digits and iterate.
The following is a minimal implementation, testable here.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#define D_BASE 1000000
#define MSB_MASK 1 << 31
typedef struct
{
uint32_t size;
uint32_t capacity;
uint32_t *digits;
} BigInt;
void divide_bigint(BigInt *n, uint32_t x, uint32_t *remainder);
BigInt *make_bigint_of_two_raised_to(uint32_t n)
{
BigInt *p = malloc(sizeof *p);
if (!p)
{
perror("Fatal error");
exit(1);
}
uint32_t pos = n / 32;
uint32_t remainder = n % 32;
uint32_t capacity = (remainder == 31) ? pos + 2 : pos + 1;
uint32_t *pp = calloc(capacity, sizeof *pp);
if (!pp)
{
perror("Error initializing a Big Int as a power of two");
free(p);
exit(1);
}
p->capacity = capacity;
p->size = capacity;
pp[pos] = 1u << remainder;
p->digits = pp;
return p;
}
void free_bigint(BigInt **p);
uint64_t sum_of_digits_of_two_raised_to_the_power(uint32_t n)
{
BigInt *power_of_two = make_bigint_of_two_raised_to(n);
uint32_t remainder;
uint64_t sum = 0;
while (!(power_of_two->size == 1 && power_of_two->digits[0] == 0))
{
divide_bigint(power_of_two, 1000000000, &remainder);
while (remainder)
{
sum += remainder % 10;
remainder /= 10;
}
}
free_bigint(&power_of_two);
return sum;
}
void test(uint32_t n)
{
uint64_t sum = sum_of_digits_of_two_raised_to_the_power(n);
printf("Sum of digits of 2^%d: %" PRIu64 "\n", n, sum);
}
int main(void)
{
test(5);
test(10);
test(1000);
test(10000);
test(100000);
test(1000000);
return 0;
}
void shrink_size(BigInt *n)
{
while ( n->size > 1 )
{
if ( n->digits[n->size - 1] == 0 && !(n->digits[n->size - 2] & MSB_MASK) )
--n->size;
else
break;
}
}
void divide_bigint(BigInt *n, uint32_t x, uint32_t *remainder)
{
uint64_t carry = 0;
uint32_t i = n->size;
while ( i-- > 0 )
{
carry <<= 32;
carry += n->digits[i];
if ( carry < x )
{
n->digits[i] = 0;
continue;
}
uint64_t multiplier = (carry / x);
carry -= multiplier * x;
n->digits[i] = (uint32_t)multiplier;
}
shrink_size(n);
*remainder = carry;
}
void free_bigint(BigInt **p)
{
if (p && *p)
{
free((*p)->digits);
free(*p);
*p = NULL;
}
}
2^8 = (2 * 2 * 2 * 2 * 2 * 2 * 2 * 2) = (2 * 2 * 2 * 2) * (2 * 2 * 2 * 2) = (2 * 2 * 2 * 2)^2 = ((2 * 2) * (2 * 2))^2 = ((2 * 2)^2)^2 = ((2^2)^2)^2
So, first you need to calculate log(2, n), to see how you can calculate effectively. If log(2, n) is an integer, then you can simply calculate the square of the square of the ... of the square with very few operations. If log(2, n) is not an integer, then calculate 2^((int)log(2, n)) and thus you will very effectively do a partial calculation and then do the same for the remainder until there is no longer remainder.
Unify your partial results into a number (possibly represented by an array) and calculate the sum of the digits. Calculating the sum of the digits is straight-forward. The actual calculation of the 2^n is what takes the most time.
If you do not reach the limits of a number format, then you can think about shift left, but with the domain you work with this is not really an option.
I have a number that I wish to sort. I know how to sort it in ascending and descending order, but what the question wants is to switch places value in the number.
try this
#include <stdio.h>
unsigned power(unsigned base, unsigned exp){
unsigned result = 1;
while(exp > 0){
if(exp & 1)
result = result * base;
base = base * base;
exp >>=1;
}
return result;//Overflow is not considered
}
int pow10(int exp){
return power(10, exp);
}
int get_num_at(int n, int pos){
int exp = pow10(pos);
return n / exp % 10;//Changed by advice of chux
}
int swap(int n, int pos1, int pos2){
if(pos1 == pos2)
return n;
int n1 = get_num_at(n, pos1);
int n2 = get_num_at(n, pos2);
return n - n1 * pow10(pos1) - n2 * pow10(pos2) + n1 * pow10(pos2) + n2 * pow10(pos1);
}
int length(int n){
int len = 1;
while(n /= 10)
++len;
return len;
}
int arrange(int v){
int len = length(v), half = len / 2;
return (len & 1) ? swap(v, 0, len-1) : swap(v, half-1, half);//0 origin
}
int main (void) {
int v;
scanf("%d", &v);
printf ("%d\n", arrange(v));
}
Continuing from my comment, to answer your question:
How would I modify the code below to get the above or do i have to start a new code?
I would start with a new approach. Why? While you could use a set of place-holders and set various conditions to manipulate the integer values to accomplish a mid-digit or end-digit swap depending on odd/even, it is far easier to simply convert your integer value to a string and then manipulate the characters.
Given you are working with integers, the longest integer you will have to address is INT_MIN (-2147483648), or 11-chars (+1 for the nul-terminating character). You can simply use a static character buffer of 12 chars and call sprintf to convert you integer to a string (while getting its length in the same call). A simple odd/even test and you know to either swap the middle characters or the end characters. To convert the resulting string back to integer, simply use strtol.
You can test for a negative value at the beginning, handle the positive form, and then multiply the resulting value by -1 for return if the value was negative. (note: you should also test for INT_MIN before assigning the positive form as -INT_MIN will not fit in an integer value. You must also check that the resulting integer after you swap digits will fit within an integer as well. -- that is left as an exercise for you).
Putting those pieces together, you can do something similar to:
#include <stdio.h>
#include <stdlib.h>
enum {BASE = 10, MAXS = 12}; /* constants */
int minswap (int v)
{
char buf[MAXS] = "";
int neg = v < 0 ? -1 : 1, /* flag negative numbers */
val = v * neg, /* handle as positive val */
len = sprintf (buf, "%d", val); /* conver to str, get len */
if (len % 2 == 0) { /* val is even */
int m = len / 2;
char tmp = buf[m - 1]; /* swap mid digits */
buf[m - 1] = buf[m];
buf[m] = tmp;
}
else {
char tmp = *buf; /* swap end digits */
*buf = buf[len - 1];
buf[len - 1] = tmp;
}
return (int)strtol (buf, NULL, BASE) * neg;
}
int main (void) {
int v1 = 264802,
v2 = 1357246;
printf (" %d => %d\n", v1, minswap(v1));
printf (" %d => %d\n", v2, minswap(v2));
return 0;
}
Example Use/Output
Using your test values:
$ ./bin/minswap
264802 => 268402
1357246 => 6357241
Look things over and let me know if you have any questions.
Without Library Function Usage
If you have a requirement to no use any of the C-library functions in your minswap function, you can easily replace them with loops with something similar to the following:
enum {BASE = 10, MAXS = 12}; /* constants */
int minswap (int v)
{
char buf[MAXS] = "";
int neg = v < 0 ? -1 : 1, /* flag negative numbers */
val = v * neg, /* handle as positive val */
len = 0;
while (len + 1 < MAXS && val) { /* convert to string get len */
buf[len++] = val % 10 + '0';
val /= 10;
}
/* (you should validate len > 0 here) */
if (len % 2 == 0) { /* val is even */
int m = len / 2;
char tmp = buf[m - 1]; /* swap mid digits */
buf[m - 1] = buf[m];
buf[m] = tmp;
}
else {
char tmp = *buf; /* swap end digits */
*buf = buf[len - 1];
buf[len - 1] = tmp;
}
while (len--) /* convert to int */
val = val * 10 + buf[len] - '0';
return val * neg;
}
(note: there is actually no need to convert to the character values with -/+ '0' since you are simply swapping the values at the mid or end positions, but for sake of completeness, that was included.)
Look things over and let me know if your have further questions.
Here is a solution without any standard library calls, arrays or strings, except for printing the result:
#include <stdio.h>
long long shuffle(int v) {
int i, n, x, d0, d1;
long long p;
/* compute the number of digits and the largest power of 10 <= v */
for (x = v, p = 1, n = 1; x > 9; x /= 10, p *= 10, n++)
continue;
if (n & 1) {
/* odd number of digits, swap first and last */
d0 = v % 10;
d1 = v / p;
return d0 * p + v % p - d0 + d1;
} else {
/* even number of digits, swap middle 2 digits */
for (i = 0, p = 1; i < n / 2 - 1; i++, p *= 10)
continue;
d0 = (v / p) % 10;
d1 = (v / p) / 10 % 10;
return v + p * (d0 - d1) * 9;
}
}
int main(void) {
printf("%d => %lld\n", 0, shuffle(0));
printf("%d => %lld\n", 1, shuffle(1));
printf("%d => %lld\n", 42, shuffle(42));
printf("%d => %lld\n", 24, shuffle(24));
printf("%d => %lld\n", 264802, shuffle(264802));
printf("%d => %lld\n", 1357246, shuffle(1357246));
return 0;
}
Output:
0 => 0
1 => 1
42 => 24
24 => 42
264802 => 268402
Notes:
I do not handle negative numbers
The reversed number might not fit in an int, so I used type long long, but on systems where int would have the same range as long long, you might still get an incorrect result.
Ive completed the assignment and my code is as below. It is a bit primitive, but it works thank you all for your contribution.
int swapvalues(int input, int digit)
{
int swapsort = 0; //initializes swapsort to 0
int lastdigit; //finds he last digit of input
int digits; //the total number of digits - 1
int firstdigit; //finds the first digit of the input
int middledigit; //finds the first middle digit in an even digit number
int secondmiddledigit; //finds the second middle digit in an even digit number
int firsthalf; //the first half of an even digit number
int firsthalf2; //the second half of an even digit number
int spacing; //the spacing between the output and the input
if(digit % 2 != 0)
{
lastdigit = input % 10;
digits = digit - 1;
firstdigit = (int)(input / pow(10, digits));
swapsort = lastdigit;
swapsort *= (int) pow(10, digits);
swapsort += input % ((int)pow(10, digits));
swapsort -= lastdigit;
swapsort += firstdigit;
}
else
{
firsthalf = input / pow(10, (digit / 2));
middledigit = firsthalf % 10;
firsthalf2 = input / pow(10, (digit / 2) - 1);
secondmiddledigit = firsthalf2 % 10;
spacing = (((secondmiddledigit * 10) + (middledigit)) - ((middledigit * 10) + (secondmiddledigit))) * pow(10, ((digit / 2) - 1));
swapsort = input + spacing;
}
return(swapsort);
}