So all I'm trying to do is take an input from the user of how many cards to use and then randomly assign each card to a different index in an array. I'm having extensive issues getting the rand function to work properly. I've done enough reading to find multiple different ways of shuffling elements in an array to find this one to be the easiest in regards to avoiding duplicates. I'm using GCC and after I input the amount of cards I never get the values from the array back and if I do they're all obscenely large numbers. Any help would be appreciated.
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
void main(){
srand(time(NULL));
int d, c, i, z, l, r;
printf("Enter the deck length: ");
scanf("%d\n ", &c);
int deck[c];
int swap[c];
z = c;
for(l=0; l<c; l++){
swap[l] = l;
}
for(i=z; i=0; i--){
r = rand() / i
deck[i] = swap[r];
for(r; r=(c-1); r++){
swap[r] = swap[(r+1)];
}
}
for(d = 0; d < c; d++){
printf("%d ", deck[d]);
}
return;
}
I can spot one major problem here:
for(i=z; i=0; i--)
^^^
This loop will never execute since you are using assignment(=) and setting i to 0 therefore the condition will always be false, although using equality(==) will still be false in this case, you probably want:
for(i=z; i!=0; i--)
This means you will be using deck unitialized which is undefined behavior. Once you fix that you have a similar problems here:
for(r; r=(c-1); r++){
main has to return int and your return at the end needs to provide a value.
Turning on warning should have allowed you to find most of these issues, for example using -Wall with gcc gives me the following warning for both for loops:
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
Note, see How can I get random integers in a certain range? for guidelines on how to use rand properly.
You basically need to be able to generate 52 numbers pseudo-randomly, without repeating. Here is a way to do that...
First, loop a random number generator 52 times, with a method to ensure none of the random numbers repeat. Two functions in addition to the main() will help to do this:
#include <ansi_c.h>
int NotUsedRecently (int number);
int randomGenerator(int min, int max);
int main(void)
{
int i;
for(i=0;i<52;i++)
{
printf("Card %d :%d\n",i+1, randomGenerator(1, 52));
}
getchar();
return 0;
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
while(trying)
{
srand(clock());
random = (rand()/32767.0)*(max+1);
((random >= min)&&(NotUsedRecently(random))) ? (trying = 0) : (trying = 1);
}
return random;
}
int NotUsedRecently (int number)
{
static int recent[1000];//make sure this index is at least > the number of values in array you are trying to fill
int i,j;
int notUsed = 1;
for(i=0;i<(sizeof(recent)/sizeof(recent[0]));i++) (number != recent[i]) ? (notUsed==notUsed) : (notUsed=0, i=(sizeof(recent)/sizeof(recent[0])));
if(notUsed)
{
for(j=(sizeof(recent)/sizeof(recent[0]));j>1;j--)
{
recent[j-1] = recent[j-2];
}
recent[j-1] = number;
}
return notUsed;
}
Related
Im in the process of learning C and the basis of the class is C primer plus(6th edition). We use Eclipse as an IDE.
For an project we have to create to arrays. One array that takes numbers in a loop and another array that display the cumulative value. So if array 1 has values 1, 5 and 3(out of 10 inputs total) then the resulting input in array 2 should be 9(on the 3th input because of the 3 inputs in array 1).
Im having trouble getting started the right way - anyone here has ideas how I could proceed?
So far I have this for starters but forgive me for it it very weak:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
void doublearrays (double usernumber);
int main(void)
{
double usernumbers = 0.0;
int loop1 = 1;
while(loop1)
{
printf("Type numbers as doubles. \n");
fflush(stdout);
loop1 = scanf("%lf", &usernumber);
if(loop1)
{
doublearrays(usernumber);
}
}
return 0;
}
All the text in a homework assignment shall be read:
For a project we have to create two arrays... 10 inputs total...
Why on earth do not you declare them?... You already have defined SIZE so
double usernumbers[SIZE];
double cumulnumbers[SIZE];
Next do yourself a favour and handle one problem at a time:
One array that takes numbers in a loop...
Ok, so write a loop up to 10 reading floats directly into the array and note how many numbers were received
int n;
for(n=0; n<SIZE; n++) {
if (scanf("%lf", &usernumbers[n]) != 1) break;
}
// ok we now have n number in the first array
Let us go on
and another array that display the cumulative value.
Ok cumul is initially 0. and is incremented on each value from the first array:
double cumul = 0.;
for(int i=0; i<n; i++) {
cumul += usernumbers[i];
cumulnumbers[i] = cumul;
}
(your current code isn't what you need... delete it and then...)
anyone here has ideas how I could proceed?
Well the first step would be to actually define some arrays.
double input[SIZE];
double cum[SIZE];
The next step would be a loop to read input.
for (int i = 0; i < SIZE; ++i)
{
if (scanf("%lf", &input[i]) != 1)
{
// Input error - add error handling - or just exit
exit(1);
}
}
The next step is to add code for calculating the the cumulative value.
I'll leave that for you as an exercise.
The last step is to print the array which I also will leave to you as an exercise.
The straight forward way of doing this, which would also use two arrays and a loop construct would be to create something like this.. I've changed the doubles to integers. (and i am also ignoring any errors from scanf()).
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
static void
print_array(int *arr, const char *arr_name)
{
int i;
printf("%s = [");
for (i = 0; i < SIZE; i++)
printf("%d%s", arr[i], i < SIZE -1 ? ",":"");
printf("]\n");
}
int main(int argc, char **argv)
{
int i;
int input[SIZE];
int cumsum[SIZE];
for (i = 0; i < SIZE; i++)
{
int _input;
printf("Give me numbers!\n");
fflush(stdout);
scanf("%d", &_input); /* assuming integer */
input[i] = _input;
cumsum[i] = i > 0 ? cumsum[i-1] + _input : _input;
}
print_array(input, "input");
print_array(cumsum, "cumulative");
return 0;
}
or If you'd like to play around with pointers and have a bit more compact version.. perhaps this could be something to study to help you understand pointers, it does the same thing as my code above
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
static int data[SIZE*2];
int main(int argc, char *argv[])
{
int *input_p = &data[0];
int *cumsum_p = &data[0] + SIZE;
for (; input_p != &data[0] + SIZE; input_p++, cumsum_p++)
{
printf("Give me numbers!\n");
scanf("%d", input_p);
*cumsum_p = input_p == &data[0] ? *input_p : *(cumsum_p-1) + *input_p;
}
}
I am trying to find the number of distinct numbers from input which are not equal to 0. n is in 1-100 range. The numbers in the array are in the 0-600 range.
http://codeforces.com/problemset/problem/937/A
For this question, I wrote a code:
#include <stdio.h>
#include <string.h>
int main(void)
{
int n, count = 0, i;
scanf("%d", &n);
int ar[n], ar2[601];
memset(ar2, 0, 600 * sizeof(int));
for (i = 0; i < n; i++) {
scanf("%d ", &ar[i]);
if (ar2[ar[i]] == 0)
ar2[ar[i]] = 1;
}
for (i = 1; i < 601; i++) {
if (ar2[i] != 0)
count++;
}
printf("%d",count);
return 0;
}
for the first test case (4 1 3 3 2) , it outputs the right answer 3 in ideone.com 's gcc 6.3, but outputs 4 in gcc 5.1 which is used at codeforces.
Why does this happen, and how can I prevent this ?
(I think it's because of memset, but I'm not sure.)
You are defining an array of size n before the value of n has beed determined (note that you scanf the value of n later). This is undefined behaviour, such that different compilers may give different results, and even starting your program on your machine may give different results (including crashes).
instead of
int n, count = 0, i;
int ar[n];
...
write
int n, count = 0, i;
scanf("%d", &n);
int ar[n], ar2[601] = { 0 };
At least the malformed array should then be solved, and ar2 is completely initialized with 0. You can get rid of your memset, which initialized only 600 items (instead of 601) anyway.
Here is a quicker solution to the problem
#include <stdio.h>
int main()
{
bool seen_number_before[601] = { false };
int count = 0;
seen_number_before[0] = true;
int n;
scanf("%d", &n); // Should do error checking here
for (int i = 0; i < n; ++i) {
int v;
scanf("%d", v); // More error checking
if (!seen_number_before[v]) // Not seen it before
seen_number_before[v] = true; // Mark it as seen
++count; // Add to the count
}
}
printf("%d\n", count);
return 0;
}
}
There are some errors in your code, from a[n] when n is not defined.
To check errors try compiling with some useful options:
gcc -Wall code.c -o code -g
the -Wall is for Warning all and the -g is used for debug on valgrind (useful tool to check memory leak and other errors).
Also I suggest you to name properly every var in your code, could helpful for a large size of code base.
This is my solution,
#include <stdio.h>
#include <stdlib.h>
int main(){
int n, count = 0;
scanf("%d", &n);
int *a = malloc(n * sizeof(int));
int hash[600] = { 0 };
for(int i=0; i<n; i++){
scanf("%d ", &a[i]);
if(a[i] != 0){
hash[a[i]] = 1;
}
}
for(int i=0; i<600; i++){
printf("%d ", hash[i]);
if(hash[i] == 1) ++count;
}
printf("\n\n%d\n", count);
return 0;
}
it can be optimized in time, using only one for, and/or in memory by creating an hashset of int, and every int can store 32 bit and do some bitwise operations, so if the nth bit is 1, count++, otherwise don't do nothing.
I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.
My program should take a number from the user, and find the two numbers in an array such that the sum of their squares equals the user input squared. However, I'm having trouble doing this, as well as understanding all the errors I'm getting.
Here's my current attempt:
#include <stdio.h>
int numberaa;
scanf("%d",&numberaa);
int main()
{
int i,j;
int array[9] = {2,-4,6,3,9,0,-1,-9};
for (i = 0; i <= 8; i++)
for (j = 0; j <= 8; J++0)
firstone==i*i
secondone==j*j
if {
firstone+secondone=numberaa;
printf("The Numbers are %d and %d",j,i,numberaa);
return 0
};
Change
firstone+secondone=numberaa;
to
numberaa = firstone + secondone;
Ah! You need to grab a basic C book. For this time I am posting a correct code for you. Hope you will learn something.
#include <stdio.h>
int main()
{
int i,j;
int array[9] = {2,-4,6,3,9,0,-1,-9};
int numberaa;
scanf("%d",&numberaa);
for (i = 0; i <= 8; i++){
for (j = 0; j <= 8; J++0){
firstone = i*i
secondone = j*j
if(numberaa == firstone + secondone)
printf("The Numbers are %d and %d",j,i,numberaa);
}
}
return 0
}
You need to read through at least the introductory chapter of a book on C and work through the examples. That means typing them out (no, don't copy and paste), compiling them, and running them to understand what makes them work and what breaks them.
When you write your own code, always compile with warnings enabled, e.g. gcc -Wall -o my_executable_name my_code.c, and pay attention to the line numbers referenced in compiler errors and warnings.
I'll point out some locations of errors in your code below:
#include <stdio.h>
int numberaa; // Currently you're declaring this as a global. NO! not what you want.
scanf("%d",&numberaa); // This isn't going to happen out here. NO! NO NO NO!
int main() // Specify your parameters. int main(void)
{
int i,j;
int array[9] = {2,-4,6,3,9,0,-1,-9}; // why specify an array of 9 but store just 8 elements??
for (i = 0; i <= 8; i++) // These are the correct limits for array[9].
for (j = 0; j <= 8; J++0) // j and J are not the same. What is J++0 ????!! Also, read about "blocks" and try a for-loop example with more than one line.
firstone==i*i // WTF?? Have you even tried to compile this?
secondone==j*j // See line above.
if { // Likewise
firstone+secondone=numberaa; // Likewise again.
printf("The Numbers are %d and %d",j,i,numberaa); // How many formatting flags does your first argument have, and how many are to be inserted?
return 0 }; // again, have you tried to compile this?
Short version:
Semicolons
Assignment vs. equality
Scope of variables
Blocks, brace usage
syntax of if statements
You also aren't squaring the user input.
Efficiency: you only need to calculate firstone = i * i once for each i value, so take it outside the j loop.
I have a task to do a program that rolls 2 dices x amount of times and then print out the result for each number (2-12). This is how far I've come, but as you can see I am stuck. I don't know how to get the array from the throw_dice function to the print_result function. Nor do I know how to calculate and print out the actual percentages of each individual number. I am not asking for someone to complete the code for me, but some tips!
Thnx in advance.
#include <stdio.h>
#include <time.h>
int array[11];
int count=0;
int get_no_of_throws()
{
int throws;
printf("How many throws? ");
scanf("%i", &throws);
return throws;
}
int throw_dice(int throws)
{
int dice1;
int dice2;
int sum=0;
srand(time(NULL));
for(count=0;count<11;count++)
{
array[count]=0;
}
for(count=0;count<throws; count++)
{
dice1=rand()%6+1;
dice2=rand()%6+1;
sum=dice1+dice2;
++array[count];
}
return array[count];
}
void print_results(array)
{
?????
}
int main()
{
int throws;
get_no_of_throws();
throw_dice(throws);
print_results(array);
return 0;
}
Use the sum as the array index.
dice1 = rand()%6 + 1;
dice2 = rand()%6 + 1;
sum = dice1 + dice2;
array[sum-2]++;
To print, loop through the array and ...
printf("%d %0.1f%%\m", count + 2, array[count]*100.0/throws);
Nice touch to consider adding: Print the percentage of the expected results. Also someplace print throws.
Check input result and make sure you return a known value. Current code returns junk if user entered "ABC". Consider fgets()/sscanf().
if (1 != scanf("%i", &throws)) ComplainToUserAboutInput();
return array[count]; is bad. Simple return 0 or make function return void.
Move int count=0; in from global to function scope. I'd move array form global to and put it in main(), then pass it to various functions. BTW: consider another name for array like dice_occurrence[]. More descriptive than "array".
// int count=0;
int throw_dice(int throws) {
int count;
...
for(count=0; count<11; count++)
...
for(count=0; count<throws; count++)
...
}
Minor: Consider making variable more local as in
// int dice1;
// int dice2;
// int sum=0;
...
for(count=0;count<throws; count++) {
int dice1 = rand()%6 + 1;
int dice2 = rand()%6 + 1;
int sum = dice1 + dice2;
array[sum-2]++;
}
Let the space character to be your friend.
// dice1=rand()%6+1;
dice1 = rand()%6 + 1;
srand(time(NULL)); is good for production. You may want to comment out during debug to get repeatable results.
Other simplifications or features possible. For me, I'd create a 6x6 array and just do dice[rand()%6][rand()%6]++; then later add up pairs like dice[2][1] and dice[1][2]. One could also assess things like how close are dice[2][1] and dice[1][2] to each other and such.
Good luck.