Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm stuck on an basic algorithmic issue and I can't figure out how to solve it.
Basically I wanna list all numbers that are proper descendants of an integer. That is to say, if my number is 21, I want to use its binary representation (10101) and list all numbers which have at least one common bit of value 1 with 21 and are lower than 21. The result here should be 10100, 10001, 10000, 101, 100, 1.
The mathematical definition of proper descendants is as follows:
Let h be a nonnegative number less than 2^m. h = d0 + d1*2^1 + ... + dm-1*2^(m-1) where di = 0 or 1.
Let h' be another nonnegative such as h' = d0' + d1'*2^1 + ... + dm-1'*2^(m-1) where di' = 0 or 1.
h' is a descendant of h if di'<=di for 0<=i<m
I've tried many implementations in both Python and C and tried the old pen and paper technique, but all of them failed. I know it's rather simple but I can't seem to figure it out. I'm coding in C so if you find a solution that works in C that would be ideal, but I'd take anything right now.
Here is a very simple approach: enumerate all integers between n-1 and 1 and print those that are strictly included in n, ie: (i & n) == i.
void list_descendants(int n) {
printf("descendants of %d:", n);
for (int i = n; i --> 1;) {
if ((i & n) == i)
printf(" %d", i);
}
printf("\n");
}
Ok so I finally came up with a code in C that is far from good looking and probably horribly optimised but still works as intended. There are probably much simpler solutions but here is mine for knowledge purposes :
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
unsigned int pui(unsigned int a, unsigned int b)
{
if (b == 0)
return 1;
if (b == 1)
return a;
if (b % 2 == 0)
return pui(a * a, b / 2);
else
return pui(a * a, (b - 1) / 2);
}
unsigned int testBit(unsigned int h, unsigned int offset)
{
unsigned int mask = 1 << offset;
return (h & mask);
}
bool isInList(unsigned int x, unsigned int *output_size, unsigned int **output)
{
for (int i = 0; i < *output_size; i++)
{
if (*(*output + i) == x)
{
return true;
}
}
return false;
}
void listDescendants(unsigned int h, unsigned int *output_size, unsigned int **output, int *currently_processing)
{
unsigned int max_offset = 0;
unsigned int temp_h = h;
unsigned int initial_output_size = *output_size;
while (temp_h > 0)
{
max_offset++;
temp_h /= 2;
}
unsigned int h_radix2[max_offset];
for (int i = 0; i < max_offset; i++)
{
if (testBit(h, i))
{
if (h > pui(2, i) && !isInList(h - pui(2, i), output_size, output))
{
*(*output + *output_size) = h - pui(2, i);
*output_size += 1;
}
}
}
if (*currently_processing < (int)*output_size)
{
*currently_processing += 1;
listDescendants(*(*output + *currently_processing), output_size, output, currently_processing);
}
}
int main()
{
int currently_processing = -1;
unsigned int size = 0;
unsigned int *output = malloc(300 * sizeof(unsigned int));
listDescendants(21, &size, &output, ¤tly_processing);
printf("size = %u\n", size);
for (int i = 0; i < size; i++)
{
printf("%u ", output[i]);
}
printf("\n");
return 0;
}
You can use a recursive solution, such as the following one.
I'm a bit lazy, so I didn't put the numbers in a list but simply printed them, and I also printed 0 and the given number.
I believe you can easily adjust the code so it will do what you desire.
#include <stdio.h>
#define CHAR_BIT 8
void ProperDescendantsRecursive(unsigned int num, unsigned int bit_index)
{
if (CHAR_BIT * sizeof(unsigned int) - 1 == bit_index)
{
printf("%u\n", num);
}
else
{
unsigned int mask = 1U << bit_index;
if (num & mask)
{
/* with the bit at index bit_index is off */
ProperDescendantsRecursive(num ^ mask, bit_index + 1);
/* with the bit at index bit_index is on */
ProperDescendantsRecursive(num, bit_index + 1);
}
else
{
ProperDescendantsRecursive(num, bit_index + 1);
}
}
}
void ProperDescendants(unsigned int num)
{
ProperDescendantsRecursive(num, 0);
}
int main(void)
{
ProperDescendants(21);
return 0;
}
compiling and running results this output:
0
16
4
20
1
17
5
21
Related
I have a task to convert decemiacal number to 8-binary. from 1 to 100, i don't know how to reverse dights in right order/ i use recursive, i mean
output is: 3 4 1, what it should be 1 3 4/ How to reverse a few numbers)
#include <math.h>
#include <stdio.h>
int bit8(int n) {
int x = n;
if (n == 100) {
return 1;
}
int mass[100];
int b;
int i = 0;
printf("%d: ", n);
while (x >= 8) {
b = x % 8;
x = x / 8;
}
if (x < 8) {
printf("%d ", x);
i++;
}
bit8(n + 1);
}
int main() {
int n = 1;
bit8(n);
}
to convert decemiacal number to 8-binary
Suggest starting over.
Typical recursion first tests before maybe recursing.
To print an n-bit integer number:
void print_n_bit(unsigned value, unsigned bit_count) {
if (bit_count > 0) {
if (bit_count > 1) {
// Print the other, more significant, bits first.
print_n_bit(value >> 1, bit_count-1); // Recursive call
}
// Now print the least significant bit
putchar((value & 1) + '0');
}
}
Usage example:
int main(void) {
unsigned n = 1;
unsigned bits_to_print = 8;
print_n_bit(n, bits_to_print);
}
I am writing a small C program to count the number of bits which need to be flipped to make one number equal to another.
The program works very fine but i observe abnormal behaviour (Program hangs) when i pass ULONG_MAX as an argument. Why is this happening? See code below
#include <stdio.h>
#include <limits.h>
#include <stddef.h>
/**
* flip_bits - Count the number of bits to flip to equalize two numbers
* #n: First number
* #m: Second number
*
* Return: the number of bits to flip
*/
unsigned int flip_bits(unsigned long int n, unsigned long int m)
{
unsigned long int diff, count;
int i;
diff = n ^ m;
count = 0;
i = 0;
while (diff >> i)
{
if (diff >> i & 1)
count++;
i++;
}
return (count);
}
/**
* main - check the code
*
* Return: Always 0.
*/
int main(void)
{
unsigned int n;
n = flip_bits(1024, 1);
printf("%u\n", n);
n = flip_bits(402, 98);
printf("%u\n", n);
n = flip_bits(1024, 3);
printf("%u\n", n);
n = flip_bits(ULONG_MAX, 0);
printf("%u\n", n);
return (0);
}
Be explicit with signedness and size of all relevant types involved. Don't use bitwise arithmetic on signed numbers. You can simplify this whole code quite a bit by using a readable for loop instead:
#include <stdint.h>
uint32_t count_diff32 (uint32_t x, uint32_t y)
{
uint32_t diff = x ^ y;
uint32_t count = 0;
for(size_t i=0; i<32; i++)
{
if (diff & (1u<<i))
{
count++;
}
}
return count;
}
As a new learner of C, I managed to go this far in this little exercice, the code works (kind of). It doesn't work for the second time, the output just adds up.
int i = 0;
void inverse(unsigned int n) {
int reste;
if (n != 0) {
reste = n % 10;
i = (i * 10) + reste;
inverse(n / 10);
} else {
printf("%d \n", i);
}
}
void main() {
inverse(1589);
inverse(42);
}
Output:
9851
985124
Your approach fails because i is not cleared before each new case. You could clear i after the printf, but a better approach is to avoid global variables. You can modify inverse for this purpose by removing the recursion:
#include <stdio.h>
void inverse(unsigned int n) {
unsigned int i = 0;
while (n != 0) {
unsigned int reste = n % 10;
i = i * 10 + reste;
n = n / 10;
}
printf("%u\n", i);
}
int main() {
inverse(1589);
inverse(42);
return 0;
}
Note these remarks:
you must include <stdio.h> to use printf()
main return type is int.
for consistency, i should have type unsigned int.
Some numbers will produce incorrect output as their inverse exceeds the range of unsigned int eg: 1000000009. You can remove this shortcoming by printing the digits instead of combining them as a number:
void inverse(unsigned int n) {
while (n > 9) {
putchar('0' + n % 10);
n = n / 10;
}
putchar('0' + n);
putchar('\n');
}
You need to reset i at some point. The most straight forward and horrible way is to simply do it after the printf().
But you should better redesign the recursion to work without global variables. Which is not easily done with any similarity to the shown code.
This is (I realised a little late) more or less what luk2302 recommended in a comment on a deleted answer.
#include <stdio.h>
int i = 0;
void inverse(unsigned int n){
int reste;
if (n != 0) {
reste = n % 10;
i = (i * 10) + reste;
inverse(n / 10);
}
else {
printf("%d \n", i);
i=0;
}
}
void inverse2(int number, int reversed)
{
if (number < 1)
{
printf("%d \n",reversed);
} else
{
inverse2(number/10, reversed*10+number%10);
}
}
void main(){
inverse(1589);
inverse(42);
inverse(123);
inverse2(1589,0);
inverse2(42,0);
inverse2(123,0);
}
Output:
9851
24
321
9851
24
321
I am trying to make a very simple 64 bit operating system, and so far have done really well, but since I am not very familiar with C I have been having some problems with it, and this one stumped me. The output would count like normal (1 2 3 4 5 6 7 8 9 10 11 12 etc.) but it would stop printing at 65. I know that "print.h" works because I have tested it many times, but I am not so sure on my method of converting the numbers to a character array. Any help at all would be much appreciated. Here's my code:
#include "print.h"
int getLen(int x) {
unsigned int n = x;
int count = 0;
while(n!=0)
{
n=n/10;
count++;
}
return count;
}
char ITC(unsigned int x) {
char ret;
unsigned int n = x;
if(n==0){
ret='0';
}
if(n==1){
ret='1';
}
if(n==2){
ret='2';
}
if(n==3){
ret='3';
}
if(n==4){
ret='4';
}
if(n==5){
ret='5';
}
if(n==6){
ret='6';
}
if(n==7){
ret='7';
}
if(n==8){
ret='8';
}
if(n==9){
ret='9';
}
return ret;
}
void kernel_main(){
print_clear();
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
char out[512];
int onOut = 0;
for (int i = 0; i < 100; i++)
{
onOut++;
unsigned int n = i;
while (n != 0) {
out[onOut + getLen(n)] = ITC(n%10);
n /= 10;
}
out[onOut + getLen(i) + 1] = '\n';
onOut += getLen(i) + 1;
}
for (int i = 0; i < 512; i++)
{
print_char(out[i]);
}
}
The issue is with the algorithm rather then perhaps familiarity with C. Your indexing into the unitialised out array was leaving gaps so outputting junk that happened to be in the array.
Consider the following - the parts I changed annotated - not all are part of the solution; just good practice:
char out[512] = {0}; // <<< Good idea to initialise
int onOut = 0;
for (int i = 1; i < 100; i++) // Start form 1 not zero
{
int n = i; // <<< Type agreement with i
int numlen = getLen(n) ; // <<< Get the length of the initial number
// Don't unnecessarily calculate in the loop
// when you know it decrements by 1 on each
// iteration
for( int j = onOut + numlen; // <<< Start from the end position
(n!=0) && j >= onOut; // <<< toward the start position
j-- ) // <<< backward
{
out[j - 1] = ITC(n % 10); // <<< Insert digit, starting from index zero
n /= 10;
}
onOut += numlen ; // <<< Move to end of newly inserted number
out[onOut++] = '\n'; // <<< Add the newline
}
Note that you have over-complicated this code somewhat; especially w.r.t. to ITC() if you code like that habitually your "operating system" will run very slowly. ITC() can be reduced to a simple look-up thus:
char ITC(unsigned int x)
{
static const char digits[] = "0123456789" ;
return digits[x] ;
}
Or in any likely character set where digits are contiguous and in order, arithmetically thus:
char ITC(unsigned int x)
{
return '0' + x ;
}
I'd give two pieces of advice for success in this project and programming in general.
Comment your code. If you have to explain it to yourself, you are more likely to find the flaws. But also later maintainers or people assisting you with debugging will have an idea of your intended semantics.
Use a debugger. I used a debugger to figure out were your code was going wrong because it was quicker and more direct that other methods. Certainly quicker than posting questions of StackOverflow!
I don't understand why you make that one function so complicated, what's wrong with this?
char ITC(unsigned int x) {
return (char)((int)'0' + n);
}
Some of the above comments are correct, plus you also need to terminate your string with a null character... and NOT print all 512 characters of a non-initialized array. Something like this should work much better (though you should also include the contents of print.h so we can see if there are any problems there):
#include "print.h"
int getLen(unsigned int x)
{
int count = 0;
while (n != 0) {
n = n / 10;
count++;
}
return count;
}
char ITC(unsigned int x)
{
return (x <= 9) ? x + '0' : '?';
}
void kernel_main()
{
char out[512];
int onOut = 0;
print_clear();
print_set_color(PRINT_COLOR_GREEN, PRINT_COLOR_BLACK);
for (int i = 0; i < 100; i++) {
unsigned int len = getLen(i);
unsigned int n = i;
unsigned int offs = len;
while (n != 0) {
out[onOut + offs--] = ITC(n % 10);
n /= 10;
}
out[onOut + len + 1] = '\n';
onOut += len + 1;
}
out[onOut + 1] = 0;
for (int i = 0; out[i] != 0; i++) {
print_char(out[i]);
}
}
There are several fast algorithms to calculate prime numbers up to a given number n. But, what is the fastest implementation to list all the numbers r relatively prime to some number n in C? That is, find all the elements of the multiplicative group with n elements as efficiently as possible in C. In particular, I am interested in the case where n is a primorial.
The n primorial is like the factorial except only prime numbers are multiplied together and all other numbers are ignored. So, for example 12 primorial would be 12#=11*7*5*3*2.
My current implementation is very naive. I hard code the first 3 groups as arrays and use those to create the larger ones. Is there something faster?
#include "stdafx.h"
#include <stdio.h> /* printf, fgets */
#include <stdlib.h> /* atoi */
#include <math.h>
int IsPrime(unsigned int number)
{
if (number <= 1) return 0; // zero and one are not prime
unsigned int i;
unsigned int max=sqrt(number)+.5;
for (i = 2; i<= max; i++)
{
if (number % i == 0) return 0;
}
return 1;
}
unsigned long long primorial( int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k];
}
return answer;
}
unsigned long long EulerPhi(int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k]-1;
}
return answer;
}
int gcd( unsigned long long a, unsigned long long b)
{
while (b != 0)
{
a %= b;
a ^= b;
b ^= a;
a ^= b;
}
//Return whethere a is relatively prime to b
if (a > 1)
{
return false;
}
return true;
}
void gen( unsigned long long *Gx, unsigned int primor, int *G3)
{
//Get the magic numbers
register int Blocks = 30; //5 primorial=30.
unsigned long long indexTracker = 0;
//Find elements using G3
for (unsigned long long offset = 0; offset < primor; offset+=Blocks)
{
for (int j = 0; j < 8;j++) //The 8 comes from EulerPhi(2*3*5=30)
{
if (gcd(offset + G3[j], primor))
{
Gx[indexTracker] = offset + G3[j];
indexTracker++;
}
}
}
}
int main(int argc, char **argv)
{
//Hardcoded values
int G1[] = {1};
int G2[] = {1,5};
int G3[] = {1,7,11,13,17,19,23,29};
//Lazy input checking. The world might come to an end
//when unexpected parameters given. Its okey, we will live.
if (argc <= 1) {
printf("Nothing done.");
return 0;
}
//Convert argument to integer
unsigned int N = atoi(argv[1]);
//Known values
if (N <= 2 )
{
printf("{1}");
return 0;
}
else if (N<=4)
{
printf("{1,5}");
return 0;
}
else if (N <=6)
{
printf("{1,7,11,13,17,19,23,29}");
return 0;
}
//Hardcoded for simplicity, also this primorial is ginarmous as it is.
int Primes[50] = {0};
int counter = 0;
//Find all primes less than N.
for (int a = 2; a <= N; a++)
{
if (IsPrime(a))
{
Primes[counter] = a;
printf("\n Prime: : %i \n", a);
counter++;
}
}
//Get the group size
unsigned long long MAXELEMENT = primorial(Primes, counter);
unsigned long long Gsize = EulerPhi(Primes, counter);
printf("\n GSize: %llu \n", Gsize);
printf("\n GSize: %llu \n", Gsize);
//Create the list to hold the values
unsigned long long *GROUP = (unsigned long long *) calloc(Gsize, sizeof(unsigned long long));
//Populate the list
gen( GROUP, MAXELEMENT, G3);
//Print values
printf("{");
for (unsigned long long k = 0; k < Gsize;k++)
{
printf("%llu,", GROUP[k]);
}
printf("}");
return 0;
}
If you are looking for a faster prime number check, here is one that is reasonably fast and eliminates all calls to computationally intensive functions (e.g. sqrt, etc..)
int isprime (int v)
{
int i;
if (v < 0) v = -v; /* insure v non-negative */
if (v < 2 || !((unsigned)v & 1)) /* 0, 1 + even > 2 are not prime */
return 0;
for (i = 2; i * i <= v; i++)
if (v % i == 0)
return 0;
return 1;
}
(note: You can adjust the type as required if you are looking for numbers above the standard int range.)
Give it a try and let me know how it compares to the once you are currently using.