Related
I wanna create all possible 5 digit numbers that can be created from the numbers (0-7).
The code below achieves this, but is there any way to make this depend on user input?
The number of loops equals the number of digits I want and each individual loop must be:
for(1st number;condition<=last number;1st number++)
So, for five digits, I have:
for(i=0;i<8;i++){
for(j=0;j<8;j++){
for(k=0;k<8;k++){
for(m=0;m<8;m++){
for(n=0;n<8;n++){
printf("%d %d %d %d %d\n",i,j,k,m,n);
}
}
}
}
}
Keep iterators in an array and increment them manually.
#include <assert.h>
#include <stdio.h>
#include <string.h>
void callback(unsigned n, int i[n]) {
assert(n == 5);
printf("%d %d %d %d %d\n", i[0], i[1], i[2], i[3], i[4]);
}
void iterate(unsigned n, unsigned max, void (*callback)(unsigned n, int i[n])) {
// VLA, use *alloc in real code
int i[n];
memset(i, 0, sizeof(i));
while (1) {
for (int j = 0; j < n; ++j) {
// increment first number, from the back
++i[n - j - 1];
// if it didn't reach max, we end incrementing
if (i[n - j - 1] < max) {
break;
}
// if i[0] reached max, return
if (j == n - 1) {
return;
}
// if the number reaches max, it has to be zeroed
i[n - j - 1] = 0;
}
// call the callback
callback(n, i);
}
}
int main() {
// iterate with 5 numbers to max 8
iterate(5, 8, callback);
}
The beginning and ending of what the code prints:
0 0 0 0 0
0 0 0 0 1
...
...
7 7 7 7 6
7 7 7 7 7
If you want variable numbers of loops, you generally need to use recursion.
Say if you want n digits, with the ith digit be in the range of a[i],b[i], then you will do the following:
/* whatever */
int n;
int *a,*b,*number;
void recursion(int whichdigit){
if (whichdigit==n){
/* Say you managed to output number */
return;
}
for (int i=a[whichdigit];i<=b[whichdigit];i++){
number[whichdigit]=i;
recursion(whichdigit+1);
}
return;
}
int main(){
/* Say somehow you managed to obtain n */
a=malloc(n*sizeof(int));
b=malloc(n*sizeof(int));
number=malloc(n*sizeof(int))
if (!a||!b||!number){
/* unable to allocate memory */
}
/* Say somehow you managed to read a[i],b[i] for all i in 0..n-1 */
recursion(0);
return 0;
}
Warning: if you tries to have too many digits, you will likely get a segmentation fault or stack overflow error.
I need to write a function that subtracts digits.
If user inputs 2345, the output should be 111 (5-4, 4-3, 3-2); another example would be 683, where the output should be 25 (3-8(abs value is taken), 8-6).
I have wrote the following code which works only when the size of the array is declared.
int subtraction(int arr[], int size) {
int sub = 0;
for (int i = 0; i < size-1; i++) {
sub = sub * 10 + abs(arr[i] - arr[i+1]);
}
return sub;
}
However, the number that the user inputs is random and can have various digits, so I don't know what limit to put in the for loop.
For example:
int arr[] = {1, 2, 55, 56, 65, 135}, i;
subtraction(arr, 6);
for (i=0; i<6; i++)
printf("%d ", arr[i]);
expected output: 0 0 0 1 1 22
The function is supposed to subtract the second-to-last digit from the last one, by the way , / from right to left / from a random number that the user inputs ; for example if the input is 5789, the output is supposed to be 211 (9-8, 8-7, 7-5); if user inputs a negative number, the program should take it's absolute value and then do the subtracting. If user input is a one digit number the result should be 0.
The function I wrote only works when the size of the array is declared. I don't know how to make it work when the size is undeclared (pointers and malloc are required I believe, as that's what I managed to find out by googling for ages, but unfortunately, I don't know how to do it).
please help?
You are not actually changing any values, here is the line you need to look at.
sub = sub * 10 + abs(arr[i] - arr[i+1]);
As you are printing the array you actually need to store the calculated value in the array again.
#include <stdio.h>
#include <stdlib.h>
int subtract(int n)
{
int factor = 1;
int total = 0;
int lastPlace = n%10;
n /= 10;
while (n>0)
{
total += (factor * abs((n%10) - lastPlace));
factor *= 10;
lastPlace = n%10;
n /= 10;
}
return total;
}
void subtractArray(int* arr, unsigned int size)
{
for (int i=0; i<size; ++i)
{
if (arr[i] < 0)
arr[i] = abs(arr[i]);
arr[i] = subtract(arr[i]);
}
}
int main()
{
int arr[] = {1, 2, 55, 56, 65, 135};
int size = sizeof(arr)/ sizeof(arr[0]);
subtractArray(arr, size);
for (int i=0; i<size; ++i)
{
printf("%d ", arr[i]);
}
return 0;
}
Here is a simple code that solve your problem :)
#include <stdio.h>
#include <stdlib.h>
int *subtraction(int arr[], int size)
{
int *sub = calloc(sizeof(int*) , size), i = 0, rev; //allocating memory
for (i = 0; i < size; i++)
{
rev = 0;
arr[i] = abs(arr[i]);
for (int a = 0; arr[i] != 0; arr[i] /= 10)
rev = (rev * 10) + (arr[i] % 10);
for (i; (rev / 10) != 0; rev /= 10) //the loop ends when rev = 0
sub[i] = ((sub[i] * 10) + abs( (rev % 10) - ((rev / 10) % 10) )); //easy math => for example rev = 21 > sub[i] = (0 * 10) + ( (21 % 10) - ((21 / 10) %10)) = abs(1 - 2) = 1;
}
return sub;
}
int main()
{
int arr[] = {-9533, 7, -19173}, i;
int len = sizeof(arr)/sizeof(arr[0]); //size of arr
int *sub = subtraction(arr, len);
for(int i = 0; i < len; i++) //for test
printf("%d ", sub[i]);
return 0;
}
output for {1, 2, 55, 56, 65, 135}:
0 0 0 1 1 22
output for {987654321, 123456789, 111111111} :
11111111 11111111 0
output for {38279}:
5652
output for {-9533, 7, -19173}:
420 0 8864
Well as for the array of undefined size. What you probably want is a dynamically allocated array.
Here we get the number of array elements based on user input, within limits, of course.
first we're gonna get the number from the user using fgets() which will give us a string, then we'll use strtol() to convert the number part to scalar (int). you can use scanf("%d", &n) if you want.
Then we can count the digits from that number, and that value will be the number of elements of our array.
#include <stdio.h>
#include <stdlib.h> //for strtol(), malloc() and NULL guaranteed
//you may also want to add
#include <limits.h>
#include <errno.h>
#define MAX_STRLEN 12 // can hold all digits of INT_MAX plus '\0' and a posible, AND very likely, '\n'
#define DEC 10 // for strtol base argument
/*
* I'm lending you my old get_n_dits() function that I used to count decimal digits.
*/
int get_n_dits(int dnum) {
unsigned char stop_flag = 0; //we'll use to signal we're done with the loop.
int num_dits = 1, dpos_mult = 1; //num_dits start initialized as 1, cause we're pretty sure that we're getting a number with at least one digit
//dpos_mult stands for digital position multiplier.
int check_zresult; //we'll check if integer division yields zero.
/**
* Here we'll iterate everytime (dnum / dpost_mult) results in a non-zero value, we don't care for the remainder though, at least for this use.
* every iteration elevates dpost_mult to the next power of ten and every iteration yielding a non-zero result increments n_dits, once we get
* the zero result, we increment stop_flag, thus the loop condition is no longer true and we break from the loop.
*/
while(!stop_flag) {
dpos_mult *= 10;
check_zresult = dnum / dpos_mult;
(check_zresult) ? num_dits++ : stop_flag++;
}
return num_dits;
}
int main(void) {
int num, ndits; //we'll still using int as per your code. you can check against INT_MAX if you want (defined in limits.h)
int *num_array = NULL; //let's not unintentionally play with an unitialized pointer.
char *num_str = malloc(MAX_STRLEN); //or malloc(sizeof(char) * MAX_STRLEN); if there's any indication that (sizeof(char) != 1)
printf("please enter a number... please be reasonable... or ELSE!\n");
printf(">>> ");
if(!fgets(num_str, MAX_STRLEN, stdin)) {
fprintf(stderr, "Error while reading from STDIN stream.\n");
return -1;
}
num = (int)strtol(num_str, NULL, DEC); //convert the string from user input to scalar.
if(!num) {
fprintf(stderr, "Error: no number found on input.\n");
return -1;
}
ndits = get_n_dits(num);
if(ndits <= 0) {
fprintf(stderr, "Aw, crap!\n");
return -1;
}
printf("number of digits: %d\n", ndits);
num_array = malloc(sizeof(int) * ndits); //now we have our dynamically allocated array.
return 0;
}
I have 2 arrays, in parallel:
defenders = {1,5,7,9,12,18};
attackers = {3,10,14,15,17,18};
Both are sorted, what I am trying to do is rearrange the defending array's values so that they win more games (defender[i] > attacker[i]) but I am having issues on how to swap the values in the defenders array. So in reality we are only working with the defenders array with respect to the attackers.
I have this but if anything it isn't shifting much and Im pretty sure I'm not doing it right. Its suppose to be a brute force method.
void rearrange(int* attackers, int* defenders, int size){
int i, c, j;
int temp;
for(i = 0; i<size; i++){
c = 0;
j = 0;
if(defenders[c]<attackers[j]){
temp = defenders[c+1];
defenders[c+1] = defenders[c];
defenders[c] = temp;
c++;
j++;
}
else
c++;
j++;
}
}
Edit: I did ask this question before, but I feel as if I worded it terribly, and didn't know how to "bump" the older post.
To be honest, I didn't look at your code, since I have to wake up in less than 2.30 hours to go to work, hope you won't have hard feelings for me.. :)
I implemented the algorithm proposed by Eugene Sh. Some links you may want to read first, before digging into the code:
qsort in C
qsort and structs
shortcircuiting
My approach:
Create merged array by scanning both att and def.
Sort merged array.
Refill def with values that satisfy the ad pattern.
Complete refilling def with the remaining values (that are
defeats)*.
*Steps 3 and 4 require two passes in my approach, maybe it can get better.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char c; // a for att and d for def
int v;
} pair;
void print(pair* array, int N);
void print_int_array(int* array, int N);
// function to be used by qsort()
int compar(const void* a, const void* b) {
pair *pair_a = (pair *)a;
pair *pair_b = (pair *)b;
if(pair_a->v == pair_b->v)
return pair_b->c - pair_a->c; // d has highest priority
return pair_a->v - pair_b->v;
}
int main(void) {
const int N = 6;
int def[] = {1, 5, 7, 9, 12, 18};
int att[] = {3, 10, 14, 15, 17, 18};
int i, j = 0;
// let's construct the merged array
pair merged_ar[2*N];
// scan the def array
for(i = 0; i < N; ++i) {
merged_ar[i].c = 'd';
merged_ar[i].v = def[i];
}
// scan the att array
for(i = N; i < 2 * N; ++i) {
merged_ar[i].c = 'a';
merged_ar[i].v = att[j++]; // watch out for the pointers
// 'merged_ar' is bigger than 'att'
}
// sort the merged array
qsort(merged_ar, 2 * N, sizeof(pair), compar);
print(merged_ar, 2 * N);
// scan the merged array
// to collect the patterns
j = 0;
// first pass to collect the patterns ad
for(i = 0; i < 2 * N; ++i) {
// if pattern found
if(merged_ar[i].c == 'a' && // first letter of pattern
i < 2 * N - 1 && // check that I am not the last element
merged_ar[i + 1].c == 'd') { // second letter of the pattern
def[j++] = merged_ar[i + 1].v; // fill-in `def` array
merged_ar[i + 1].c = 'u'; // mark that value as used
}
}
// second pass to collect the cases were 'def' loses
for(i = 0; i < 2 * N; ++i) {
// 'a' is for the 'att' and 'u' is already in 'def'
if(merged_ar[i].c == 'd') {
def[j++] = merged_ar[i].v;
}
}
print_int_array(def, N);
return 0;
}
void print_int_array(int* array, int N) {
int i;
for(i = 0; i < N; ++i) {
printf("%d ", array[i]);
}
printf("\n");
}
void print(pair* array, int N) {
int i;
for(i = 0; i < N; ++i) {
printf("%c %d\n", array[i].c, array[i].v);
}
}
Output:
gsamaras#gsamaras:~$ gcc -Wall px.c
gsamaras#gsamaras:~$ ./a.out
d 1
a 3
d 5
d 7
d 9
a 10
d 12
a 14
a 15
a 17
d 18
a 18
5 12 18 1 7 9
The problem is that you are resetting c and j to zero on each iteration of the loop. Consequently, you are only ever comparing the first value in each array.
Another problem is that you will read one past the end of the defenders array in the case that the last value of defenders array is less than last value of attackers array.
Another problem or maybe just oddity is that you are incrementing both c and j in both branches of the if-statement. If this is what you actually want, then c and j are useless and you can just use i.
I would offer you some updated code, but there is not a good enough description of what you are trying to achieve; I can only point out the problems that are apparent.
I am trying to find a random number that has 1 to max digits (max < 10).
srand((int) time(NULL));
answer = ((rand() % max) + 1);
BUT:
0,...9 is only allowed to be used once.
I have found that waiting for the rand() to create such a number by chance takes too long, so I am assuming there must be a way to create a running total where each time a digit is added a comparison is made.
If you are looking for an integer with n digits drawn from 0 to 9 with no repeats (your question is hard to interpret), then the following will suffice.
The idea is to put all the digits from 0 to 9 in a hat and then draw them out one by one. Append each to the random integer value you're building.
The hat is an array initially set 0 to 9.
To draw a number when the hat has k elements in it, compute a random index j in the range [0..k-1] and get that element from the array. Then copy the last (k-1 th) element down to position j, which "erases" it. The remaining unpicked digits are now in [0..k-2], and you can repeat this process until done.
Appending a digit d to an integer value is the same as saying
val = 10 * val + d
Putting these ideas together, you have the following. Note this allows 0 in the first position, so the result may actually have one less than n digits when printed with no leading zeros.
unsigned random_unrepeated_digits(int n) {
int i, digits[] = { 0,1,2,3,4,5,6,7,8,9 };
unsigned val = 0;
for (i = 0; i < n; i++) {
int k = 10 - i, j = rand() % k;
val = 10 * val + digits[j];
digits[j] = digits[k - 1];
}
return val;
}
You can generate the each digit one by one. First, get a random integer from 0 to 9. For instance, if you get 5, then remove it from the array of all digits:
0 1 2 3 4 6 7 8 9
Next get a random integer from 0 to 8, if you get 8 this time, then the second digit is 9. Remove it and get the next digit repeatedly.
If you need to get 8 digits for instance, In the end you have only 4 digits left, for instance:
3 4 6 9
Then get a random integer from 0 to 3. If for instance, you get 0, then the last digit is 3 and the rest is discarded.
You can shuffle the digits {0, 1, 2, ..., 9}, being careful not to put 0 first, then construct the number from the appropriate number of initial digits. By doing this, while constructing the result as you go, and stopping shuffling once you've fixed the first ndig digits, you end up with code like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long long rand_digits(int ndig) {
int digits[10] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
long long res = 0;
for (int i = 0; i < ndig; i++) {
int r = i + rand() % (10 - i - (i == 0));
res = res * 10 + digits[r];
digits[r] = digits[i];
}
return res;
}
int main(int argc, char *argv[]) {
srand((unsigned)time(0));
for (int i = 0; i < 10; i++) {
printf("%-2d: %lld\n", i + 1, rand_digits(i + 1));
}
return 0;
}
You can use array of 10 digits, shuffle them each time and get the N first digits. Pseudo code:
void shuffle(char[] a) {
for(int i=0; i< 10; i++) {
pos = rand() % 10;
swap(a[i], a[pos]);
}
}
int main() {
char arr[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
# it prints endlessly random numbers of random length
while (1) {
shuffle(arr);
int N = rand() % 10 + 1; # how many digits to generate
for (int i=0; i<N; i++) {
printf(arr[i]);
}
}
printf("\n");
}
The possible issue in this way is when '0' comes the first digit, turning the number to gets less number than it is required. But you can add avoiding '0' at first position by fixing 'shuffle'(e.g, check if the first is '0' then generate random pos=rand()%9+1 and then swap(a[0], a[pos]) or getting numbers if you need it.
You could set up a function:
char * randstr(int len)
{
srand(0); //seed the generator
char * str = malloc(len); //allocate exactly len bytes
int i, x; //define some loop variables
char used = 0; //used is to check if the number has already been taken
char num; //a temp value
for (i = 0; i < len; i++)
{ //this loop runs through each character in the string
used = 1;
while (used) //basically, if we already used it, find another
{
used = 0;
num = rand() % 10 + 48; //48 = '8' //returns 0-9
for (x = 0; x < i; x++)
{ //this loop checks to see if its already been used
if (str[x] == num) used = 1;
}
}
}
return str;
}
This will return a char array, but not a null terminated one, though all of the numbers will be in ASCII form. For a null terminated string, simply modify it like so:
char * randstr(int len)
{
srand(0);
char * str = malloc(len + 1);
int i, x;
char used = 0;
char num;
for (i = 0; i < len; i++)
{
used = 1;
while (used)
{
used = 0;
num = rand() % 10 + 48; //48 = '8'
for (x = 0; x < i; x++)
{
if (str[x] == num) used = 1;
}
}
}
str[len - 1] = 0;
return str;
}
Hope this helps.
EDIT:
The way the function works, is it returns a string of size len, using only digits 1-9, with no repeats.
calling randstr(5) could return something like
12345
93751
73485
...
Do note, if there are no more numbers to use, the function will just sit there looping.
Comments are in the first function
Getting a random number of digits would be actually pretty simple. We just want a random number between 1 and 10. Done by
rand() % 10 + 1;
//so lets assign that to an int and call our function
int num = rand() % 10 + 1;
char * str = randstr(num); //assume this is the null terminated one
printf("The number was %s\n", str);
Well I have been studying a little C this winter break and in my adventures I stumbled upon an issue with a Dynamic Array.
It's a fairly simple program really. What I am trying to do is to create an array that holds the numbers of the Fibonacci series. Here is the code:
#include <stdio.h>
#include <stdlib.h>
int dynamic_arry_append(int* arry, int* number, int* size);
int main() {
int i, n, size = 3, *arry = NULL, fibarr[size];
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
i = 0;
// passing the first elements
fibarr[0] = 0;
fibarr[1] = 1;
fibarr[2] = 1;
while ( i < n ) {
printf("**%d\n",fibarr[0]);
dynamic_arry_append( arry, &fibarr[0], &size );
fibarr[0] = fibarr[1];
fibarr[1] = fibarr[2];
fibarr[2] = fibarr[1] + fibarr[0];
i++;
}
for ( i = 0 ; i < size ; i++)
printf("Element %d of the array: %d.\n", i, arry[i]);
return 0;
}
int dynamic_arry_append(int* arry, int* number, int* size) {
int i;
int bacon = *size; // first name i thought of
bacon++;
int *new_addr = realloc(arry, bacon * sizeof(int));
if( new_addr != NULL ) {
arry = new_addr;
arry[bacon-1] = *number;
// printf for easier debugging, or so i thought
for ( i = 0 ; i < bacon ; i++ )
printf("%d\t%d\n", i+1, arry[i]);
printf("\n");
*size = bacon;
} else {
printf("Error (re)allocating memory.");
exit (1);
}
return 0;
}
At least in my mind this works. However, in practice I get funny results:
Dynamic array, Fibonacci series.
Capture upto element: 5
**0 // next fibonacci number
1 5256368
2 5246872
3 1176530273
4 0
**1
1 5256368
2 5246872
3 1768053847
4 977484654
5 1
**1
1 5256368
2 5246872
3 1551066476
4 1919117645
5 1718580079
6 1
**2
1 5256368
2 5246872
3 977484645
4 1852397404
5 1937207140
6 1937339228
7 2
**3
1 5256368
2 5246872
3 1551071087
4 1953724755
5 842231141
6 1700943708
7 977484653
8 3
/* Code::Blocks output */
Process returned -1073741819 (0xC0000005) execution time : 17.886 s
Press any key to continue.
I am really baffled by this error, and after searching around I found no solution...Can anyone help? Thank you very much.
#include <stdio.h>
#include <stdlib.h>
int * dynamic_array_append(int * array, int size);
int main() {
int i, n, size=0, *array = NULL;
printf("Dynamic array, Fibonacci series. \n");
printf("Capture upto element: ");
scanf("%d", &n);
for (i=0 ; i<n ; i++)
array = dynamic_array_append(array, i);
for (i=0 ; i<n ; i++)
printf("array[%d] = %d\n", i, array[i]);
return 0;
}
int * dynamic_array_append(int * array, int size)
{
int i;
int n1, n2;
int new_size = size + 1;
int * new_addr = (int *) realloc(array, new_size * (int)sizeof(int));
if (new_addr == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
if (size == 0 || size == 1) {
new_addr[size] = size;
return new_addr;
}
n1 = new_addr[size-1];
n2 = new_addr[size];
new_addr[new_size-1] = new_addr[new_size-2] + new_addr[new_size-3];
return new_addr;
}
/*
Output:
Dynamic array, Fibonacci series.
Capture upto element: 10
array[0] = 0
array[1] = 1
array[2] = 1
array[3] = 2
array[4] = 3
array[5] = 5
array[6] = 8
array[7] = 13
array[8] = 21
array[9] = 34
*/
Points to note:
The newly (re)allocated array should be returned back to main and stored in a pointer-to-int (or) pass pointer-to-pointer-to-int and update it accordingly once after reallocing
The fibarr is not needed. It doesn't solve any problem.
You don't have to pass the size and the number. Just send the size and it will pick the n-1 and n-2 to calculate n.
This is considered to be highly inefficient. Because if you know the n then you can allocate memory for n integers in one shot and calculate the fib series.
The problem may be that the arry pointer variable is passed by value to the function dynamic_arry_append. That means, that changes that you make to the arry variable within that function will not be reflected by any variables outside of that function. For example:
int *a = NULL;
someFunc(a);
// a will still be NULL here no matter what someFunc does to it.
You should declare your fibarr as a pointer (so name it differently) not an array. And you should pass to your dynamic_arry_append the address of that pointer, like &fibarr. And you should initialize fibarr in your main with calloc. At last you should dynamically update (and keep, and pass) the size of the allocated array.
You are not returning the new address of the array... and you are reading/writing not your memory. Run the program with all error messages under debugger and you'll see the problem is in this line:
dynamic_arry_append( arry, &fibarr[0], &size );