Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am writing a very simple program, yet I can not seem to get it to work properly. I want to start with an array with numbers from 1-69 and then randomly select 5 numbers from this array without repeating. And I do not want to just shuffle the array and take the first 5 numbers. I want it to resemble more of a darwing numbers out of a hat with the probability being the way it should be.
For Example:
Array1[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
Array2[]
// I want it to randomly choose an element from Array1, remove it from Array1, and place it in Array2. Then repeat the process until I have 5 randomly pulled numbers from Array1 without repeating.
Any help is greatly appreciated! Thank You!
P.s. I am writing this project in C.
Pseudo-code:
Create 69-element array A[] with values [1 ... 69]. Length = 69;.
Randomly create an index index = rand()%Length;
Swap that indexed element A[index] with array element A[Length-1].
Decrement: Length--
Repeat steps 2-4 four more times.
The last five elements of A[] are the desired set - no repeats.
Note: code is not shuffling the complete array - which would be a waste of time.
You can't simply "remove" a cell in a C array; if you really want to do it that way, the best you can do is:
select the element with rank n (from array A) and do whatever you want with it
move elements n+1, n+2, etc. (from array A) one cell left (backward) with something like memcpy
remember the new size of the array A (because the allocated memory will remain the same during the whole process)
You absolutely need to just "try something", post your work, and ask questions about what you've tried. Especially if this is a homework assignment, we can't "do your work for you" :(
There are many ways you can approach this.
Some example options:
a) Fill the array with "legal" numbers, select five numbers from five random positions, then mark those positions "taken" (so they won't be selected again).
b) Randomly fill the array with legal numbers, and choose five at a time, starting with position "0". Increment current position by "five" each time.
c) Etc.
"I want it to resemble more of a darwing numbers out of a hat." That is exactly how you can implement this:
Create a hat array with all lottery ticket in it.
Pick a random ticket from the array, store it and remove the ticket from the hat.
Repeat until you have as many tickets as you need.
Deletions from arrays require the tail of the array being shifted, but you don't need that here: The order of the items in the hat isn't important, so you can move the last element to the gap the drawn ticket has left in the array and decrement the array length.
So:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
int hat[70]; // pool of numbers
size_t n = 70; // size of pool
size_t i;
// get pseudo-random-number generator underway
srand(time(NULL));
// fill pool with all numbers
for (i = 0; i < n; i++) hat[i] = i;
// pick five numbers and print them
for (i = 0; i < 5; i++) {
size_t pick = rand() % n;
printf("%d\n", hat[pick]);
hat[pick] = hat[--n];
}
return 0;
}
In your case, the number of drawn numbers is small in comparison to the pool, so you might actually look at things the other way: Instead of restricting the items that you draw, you could look at the items you have already drawn and draw a ticket until you get one that you haven't seen yet. But the method above is genneral.
Related
I'm totally new here but I heard a lot about this site and now that I've been accepted for a 7 months software development 'bootcamp' I'm sharpening my C knowledge for an upcoming test.
I've been assigned a question on a test that I've passed already, but I did not finish that question and it bothers me quite a lot.
The question was a task to write a program in C that moves a character (char) array's cells by 1 to the left (it doesn't quite matter in which direction for me, but the question specified left). And I also took upon myself NOT to use a temporary array/stack or any other structure to hold the entire array data during execution.
So a 'string' or array of chars containing '0' '1' '2' 'A' 'B' 'C' will become
'1' '2' 'A' 'B' 'C' '0' after using the function once.
Writing this was no problem, I believe I ended up with something similar to:
void ArrayCharMoveLeft(char arr[], int arrsize, int times) {
int i;
for (i = 0; i <= arrsize ; i++) {
ArraySwap2CellsChar(arr, i, i+1);
}
}
As you can see the function is somewhat modular since it allows to input how many times the cells need to move or shift to the left. I did not implement it, but that was the idea.
As far as I know there are 3 ways to make this:
Loop ArrayCharMoveLeft times times. This feels instinctively inefficient.
Use recursion in ArrayCharMoveLeft. This should resemble the first solution, but I'm not 100% sure on how to implement this.
This is the way I'm trying to figure out: No loop within loop, no recursion, no temporary array, the program will know how to move the cells x times to the left/right without any issues.
The problem is that after swapping say N times of cells in the array, the remaining array size - times are sometimes not organized. For example:
Using ArrayCharMoveLeft with 3 as times with our given array mentioned above will yield
ABC021 instead of the expected value of ABC012.
I've run the following function for this:
int i;
char* lastcell;
if (!(times % arrsize))
{
printf("Nothing to move!\n");
return;
}
times = times % arrsize;
// Input checking. in case user inputs multiples of the array size, auto reduce to array size reminder
for (i = 0; i < arrsize-times; i++) {
printf("I = %d ", i);
PrintArray(arr, arrsize);
ArraySwap2CellsChar(arr, i, i+times);
}
As you can see the for runs from 0 to array size - times. If this function is used, say with an array containing 14 chars. Then using times = 5 will make the for run from 0 to 9, so cells 10 - 14 are NOT in order (but the rest are).
The worst thing about this is that the remaining cells always maintain the sequence, but at different position. Meaning instead of 0123 they could be 3012 or 2301... etc.
I've run different arrays on different times values and didn't find a particular pattern such as "if remaining cells = 3 then use ArrayCharMoveLeft on remaining cells with times = 1).
It always seem to be 1 out of 2 options: the remaining cells are in order, or shifted with different values. It seems to be something similar to this:
times shift+direction to allign
1 0
2 0
3 0
4 1R
5 3R
6 5R
7 3R
8 1R
the numbers change with different times and arrays. Anyone got an idea for this?
even if you use recursion or loops within loops, I'd like to hear a possible solution. Only firm rule for this is not to use a temporary array.
Thanks in advance!
If irrespective of efficiency or simplicity for the purpose of studying you want to use only exchanges of two array elements with ArraySwap2CellsChar, you can keep your loop with some adjustment. As you noted, the given for (i = 0; i < arrsize-times; i++) loop leaves the last times elements out of place. In order to correctly place all elements, the loop condition has to be i < arrsize-1 (one less suffices because if every element but the last is correct, the last one must be right, too). Of course when i runs nearly up to arrsize, i+times can't be kept as the other swap index; instead, the correct index j of the element which is to be put at index i has to be computed. This computation turns out somewhat tricky, due to the element having been swapped already from its original place. Here's a modified variant of your loop:
for (i = 0; i < arrsize-1; i++)
{
printf("i = %d ", i);
int j = i+times;
while (arrsize <= j) j %= arrsize, j += (i-j+times-1)/times*times;
printf("j = %d ", j);
PrintArray(arr, arrsize);
ArraySwap2CellsChar(arr, i, j);
}
Use standard library functions memcpy, memmove, etc as they are very optimized for your platform.
Use the correct type for sizes - size_t not int
char *ArrayCharMoveLeft(char *arr, const size_t arrsize, size_t ntimes)
{
ntimes %= arrsize;
if(ntimes)
{
char temp[ntimes];
memcpy(temp, arr, ntimes);
memmove(arr, arr + ntimes, arrsize - ntimes);
memcpy(arr + arrsize - ntimes, temp, ntimes);
}
return arr;
}
But you want it without the temporary array (more memory efficient, very bad performance-wise):
char *ArrayCharMoveLeft(char *arr, size_t arrsize, size_t ntimes)
{
ntimes %= arrsize;
while(ntimes--)
{
char temp = arr[0];
memmove(arr, arr + 1, arrsize - 1);
arr[arrsize -1] = temp;
}
return arr;
}
https://godbolt.org/z/od68dKTWq
https://godbolt.org/z/noah9zdYY
Disclaimer: I'm not sure if it's common to share a full working code here or not, since this is literally my first question asked here, so I'll refrain from doing so assuming the idea is answering specific questions, and not providing an example solution for grabs (which might defeat the purpose of studying and exploring C). This argument is backed by the fact that this specific task is derived from a programing test used by a programing course and it's purpose is to filter out applicants who aren't fit for intense 7 months training in software development. If you still wish to see my code, message me privately.
So, with a great amount of help from #Armali I'm happy to announce the question is answered! Together we came up with a function that takes an array of characters in C (string), and without using any previously written libraries (such as strings.h), or even a temporary array, it rotates all the cells in the array N times to the left.
Example: using ArrayCharMoveLeft() on the following array with N = 5:
Original array: 0123456789ABCDEF
Updated array: 56789ABCDEF01234
As you can see the first cell (0) is now the sixth cell (5), the 2nd cell is the 7th cell and so on. So each cell was moved to the left 5 times. The first 5 cells 'overflow' to the end of the array and now appear as the Last 5 cells, while maintaining their order.
The function works with various array lengths and N values.
This is not any sort of achievement, but rather an attempt to execute the task with as little variables as possible (only 4 ints, besides the char array, also counting the sub function used to swap the cells).
It was achieved using a nested loop so by no means its efficient runtime-wise, just memory wise, while still being self-coded functions, with no external libraries used (except stdio.h).
Refer to Armali's posted solution, it should get you the answer for this question.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
**This is for Homework
I have a project coming up (A game of scrabble) and I have a couple questions. In scrabble certain letters can only appear a certain number of times. EX: E has an occurrence of 12, A has an occurrence of 9, ect. My first question is how would I make this possible without creating a gigantic array. So instead of
char arr['A' , 'A' , 'A'.....]
how would I just type
char arr['A' , 'B' , 'C']
(Type every letter once then somehow set a frequency for each letter.
My second question is how would I create a score counter for the program. In scrabble there are letters that have score values. I figured one way was to loop a ton of switch statements, but I was wondering if there's a more efficient way to do it.
I don't need any code made for me because that would take away from the whole point of learning programming, but examples would be appreciated or even an explanation of more efficient ways to create letter frequencies and score calculators. I figure that if I figure out how to do these things efficiently this early on, It would help me in the future.
Thanks for any help!
This code will have to be written in C
Okay the thing is first answer is seemingly easy if you think of using the ascii value.
What if I say that use the ASCII value as an index to an array. Any idea came?
Wait I will hint a bit more. A = 65...That means you can easily map to A using the index value 65 in your array.
Now you may wonder that for this you need a large array? Nope. Just use the offset appropriately. So now you think 65->A->0 then 66->B->1.
Second question:
Yes you can use an array here also the same way. If you need to store more data than just a score you can use array of structures. That will let you store other data also along with scores.
Things that may help you?
You can store the frequency of occurrences of characters by just incrementing the frequency array at correct position.
Design the code so that you understand where you store scores and how you handle it. Try to keep the scores in an array and or array of structures and manipulate them when needed.
To get a good design idea you can challenge yourself to store the game logic and game playing in different modules and interact with them accordingly.
Clarification
Suppose this is a char array.
char s[] = "ABCD";
for(int i = 0; i<4;i++)
Frequency[s[i]-'A']++;
This way here we are basically converting ascii value to an index of array. Here instead of directly using 65 I have subtracted that value so that every frequency is stored from index position 0.
If you consider that a character like A is actually an integral value representing the ASCII-Code of A (which is 65 in this case), then you could use this ASCII-value to index an integer array holding the maximum value for the specific letter (and the same for the actual count). See the following code illustrating this. Hope it helps:
int main() {
// ASCII, assuming character st A B C D E F, ...
char maxOccurrences[256]= { 12, 3, 4, 5, 9, 1 }; // ...
char actualOccurrences[256] = { 0 };
char *testInput = "AAABBBBCDEEEFF";
for(char *p=testInput;*p;p++) {
int charIndex = *p - 'A';
if (charIndex < 0 || charIndex > 26) {
printf("invalid character %c.\n", *p);
}
else if (actualOccurrences[charIndex] >= maxOccurrences[charIndex]) {
printf("maximum of %d for %c reached.\n",maxOccurrences[charIndex], *p);
}
else {
actualOccurrences[charIndex]++;
}
}
}
For the first question: Since you know there are exactly 27 different tiles in Scrabble (counting blanks), you can store just the frequency of each letter in an array of length 27.
For the second, you can take a similar approach and store the score of each letter in a constant array.
You then need to map each letter to the appropriate index, e.g. A should map to 0, B to 1, etc.; a clever way to do this would be to cast the character as an integer and subtract the appropriate amount.
So the second would work roughly like this, to score a = ['w','o','r',d']:
s = 0
First iteration: index of 'w' is 23, so
s += letter_scores[22]
letter_freqs[22] -= 1
Second iteration... and so on
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 5 years ago.
Improve this question
I'm trying to write John Conway's Game of Life in C, but I'm having trouble adding living cells to the board. The function I wrote to handle it is extremely slow.
Thought process: I want to add n living cells to the board randomly, so while cells left to set alive, get a random (x, y) pair, and if it's dead, make it living. That way I can guarantee n cells become alive.
Is my understanding of the problem incorrect, or am I just being inefficient? Why is it so slow, and how can I make it faster?
void add_cells( int board[BOARD_WIDTH][BOARD_HEIGHT], int n )
{
// Randomly set n dead cells to live state.
while ( n )
{
int randX = rand() % BOARD_WIDTH;
int randY = rand() % BOARD_HEIGHT;
if( board[randX][randY] == 0 )
{
board[randX][randY] = 1;
n--;
}
}
}
If let's say 70% of cells are alive, then it means that your program will have to find an other cell 7 times out of 10, which makes unecessary repetitions.
You could pop the selected cell out from a "remaining cells" array when you set it alive, and select your cell randomly in this array. I suggest to use a dynamicaly resizable container so you don't have to manipulate your entire "remaining cells" array each time you pop out a cell. This should help save you more time.
There are several issues that might explain some slowness in your problem:
Is the board initialized to 0 before calling add_cells()? If the board has random contents, finding dead cells might take an arbitrary long time, or potentially take forever if fewer than n cells are dead.
Are you sure the board is correctly defined? The 2D array seems more natural with y being the first dimension and x the second: using int board[BOARD_HEIGHT][BOARD_WIDTH] and swapping the index values for randX and randY.
Testing for (n > 0) would protect against an infinite loop if add_cells() is ever called with a negative n.
If n is large, finding dead cells can take a long time as shooting at random has a small chance of hitting one.
If n is larger than BOARD_WIDTH * BOARD_HEIGHT or if there are fewer than n dead cells, the loop will iterate forever.
If n is large or if the board has only a few dead cells, it would be more efficient to enumerate the dead cells and chose the target cells at random from the dead cells only. The drawback is such a method would be slower if n is small and the board has many dead cells.
The time complexity for n small compared to the number of dead cells is O(n), which is hard to beat and should be very fast on current hardware, but it tends towards O(n * BOARD_WIDTH * BOARD_HEIGHT) if n is large or close to the number of dead cells, which is much less efficient, and the function never finishes if n is greater than the number of dead cells.
If the board is known to be empty when add_cells() is called, if n is larger than BOARD_WIDTH * BOARD_HEIGHT / 2, it would be more efficient to set all cells alive and chose n cells to kill.
If the board is not necessarily empty, passing this function the number of live cells would help decide which approach is better and if there are at least n dead cells without the need for a lengthy loop to enumerate the dead cells.
If your board is contiguous in memory, you don't have to call rand() twice. You can just use rand() % (BOARD_WIDTH * BOARD_HEIGHT).
void add_cells(uint8_t board[BOARD_WIDTH][BOARD_HEIGHT], int n)
{
std::mt19937 eng;
uniform_int_distribution<int> dist(0, BOARD_WIDTH * BOARD_HEIGHT - 1);
while(n)
{
int index = dist(eng);
uint8_t* cell = (uint8_t*)board + index;
if(*cell == 0)
{
*cell = 1;
--n;
}
}
}
The modulo function is pretty slow, try (float)rand()/RAND_MAX*BOARD_WIDTH + 0.5
You can also use a faster rand, see here
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have an exercise (please take a look at picture):
Problem
The problem:
You input any number (number is integer) then the program will find numbers in binary tree has 4 levels. The top is your number you input, and the pair of 2 numbers at lower level will be added together and 2 times the parent number above. And the numbers must be used only once.
Here my code, but it still doesn't work properly. Please figure out for me what is my mistake here.
#include <stdio.h>
#include <stdbool.h>
#define MAX 15
int data[MAX]; // binary tree with 4 levels
void init_Data(){
int i=0;
for(i=0; i<=MAX; i++){
data[i] = -1;
}
}
void BackTracking(int index){
int c1, c2; // c1 and c2 are a pair that is added and equal 2 times the parent number
for(c1=1; c1<data[index]; c1++){
c2 = 2*data[index] - c1;
if(!Search(c1) && !Search(c2)){ // checking c1 and c2 is used or not
data[2*index+1] = c1; // put c1 into data
data[2*index+2] = c2; // put c2 into data
if(index == MAX/2) // the stop condition
print_Data(); // print out
else
BackTracking(index+1);
}
}
}
bool Search(int number){
int i=0;
for(i=0; i<MAX; i++){
if(number == data[i])
return true;
}
return false;
}
int main(int argc, char const *argv[]) {
int n = 0;
init_Data();
printf("Enter your number: ");
scanf("%d\n", &n);
data[0] = n;
BackTracking(0);
return 0;
}
I've got working code for this exercise, but since it is an exercise, I'll just give some primers.
How do you solve the problem? One way to find a valid configuration (of Sudoku grids, of eight non-attacking queens on a chess board or of numbers in a tree) is backtracking: You prober various possible solutions and when you find that it is invalid, you revert to a previous partial solution that is still valid.
One way to implement backtracking is to use recursion, where each step in the solution (put a number in the Sudoku grid, placing a queen, assigning a pait of numbers in your problem) is one level of recursion. Backracking then means to return to previous levels in the recursion.
How do you represent the tree? Your picture shows a binary tree. You can represent such a tree as a linear array:
0
1 2
3 4 5 6
7 8 9 10 11 12 13 14 15
For a node with the array index i, you get:
parent(i) == (i - 1) / 2
left(i) == 2*i + 1
right(i) == 2*i + 2
You need the array to print the solution once you have found it.
How do you traverse the tree? There are many ways to traverse a tree. Here, you can use many ways as long as you have assigned a value to the parent node before visiting it.
In your case, the easiest way is to do a level-wise iteration that follows the linear array. You can use the fact that the two numbers you need to find for each parant node are adjacent. Start with index i = 1 and if you can find two valid numbers, advace to i + 2.
That way to iterate also provides a nice terminating condition: When you reach the fifth level, you have found a valid solution.
How do you find out whether a number has been used? The straightforward solution is to look at all numbers up to the current index. This method will become slow the deeper you go in your tree, though. (But that shouldn't be a concern for a tree of 4 levels.)
If you choose your numbers such that the smaller number if always to the right, you have a binary search tree. You can use that to find whether a number has been used in (O log n), that is you have to visit each level of the tree once instead of visiting each node once.
There are other ways to keep track of which numbers have been used like bit sets or hashes, but these have to be implemented in C.
Edit: You've got the basics of the code right, but:
The termination criterion should be checked for the next step, so index + 1 == MAX/2. Alternatively, you can check index before (and instead of) entering the loop. (I prefer the latter, because it puts the termination criterion at the top of the function, but the former is closer to your existing code.)
In Search, you check the whole range of elements. That's okay, because the unused elements are −1. There is one problem, though: You don't reset the used elements, so that the check is against values from solutions that you have backtracked from. You can reset these values to −1 before backtracking. A better approach might be to check only the values that you have already entered. (Not resetting the values means that you will find fewer solutions. The first value for which there are solutions is 8, but without resetting, it won't find a solution here.)
Currently, you print all solutions. (Well, all solutions for which the left bracnch has the smaller number.) Depending on the value, there will be a lot of solutions. If you just want to print one solution, you can stop backtracking short by returning early.
You should provide prototypes of the functions before you use them, so that the compiler can make sure you are passing the correct arguments.
Here's a corrected version:
void BackTracking(int index){
int c1, c2;
for(c1=1; c1<data[index]; c1++){
c2 = 2*data[index] - c1;
if(!Search(c1) && !Search(c2)){
data[2*index+1] = c1;
data[2*index+2] = c2;
if(index + 1 == MAX/2)
print_Data();
else
BackTracking(index+1);
data[2*index+1] = -1;
data[2*index+2] = -1;
}
}
}
I think you can solve it using dynamic programming, if you do not care about number of computations, then you can also use combination algorithms.
your input = 10
for first level there could be X possible pair of numbers {n1,n2} = 2*10
for each of the pairs above pick one and use recursion to check further
run(input,tree)
for n1 from 0 to input:
for n2 from n1+1 to input:
if n1+n2 = 2*input:
pairs.add(n,input-n)
//if no pairs staisfy our condition
if pairs ==null:
return false
//check each pair
foreach pair in pairs:
run(pair.numbers, tree)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to complete a sudoku solution checker program in c. I'm still trying to understand the steps in building this program before I start coding it. I found this example online http://practicecprogram.blogspot.com/2014/10/c-program-to-find-out-if-solved-sudoku.html
There are a few questions I still don't understand.
1 For my program I am given a text file with the first number being a number that says how many sets of sudoku solutions it contains. I am almost understanding how to check just one solution but having to do it for N solutions and making the program work for multiple sudoku solutions confuses me. Especially in making my 2d arrays for the values. My ouput is supposed to only be Yes or No on a new line for however many N sets.
2 Is checking that all rows and columns have sums of 45 and that the values are >0, <10 enough to prove that the solution is valid? I'm assuming since every puzzle only has one solution I don't have to check each 3x3 grid to make it doesn't contain duplicates if each row and column sum to 45.
1) simple:
/// Read the number of puzzles;
...
for (i = 0; i < number_of_puzzless; i++) {
// Read Data for a puzzle
...
// Process puzzle data
...
// Print result
...
}
2) The sum or all cells in a row/column is equal to 45 and all numbers are in a range from 1 to 9. Is this enough to check only rows and columns to state that the whole puzzle is valid?
Yes it is. Even if you try to fool your checker and would give it a row that, say, has two sixes and two nines and no sevens and eights, this would break the checks on some columns.
Your problem statement is missing an input. The sample assumes that the solution for each game is typed in, but in #1 you state that the only input is the number of games to solve. There has to be a source of data for each game solution. Let's assume there is another file for each game. Your program needs to read in each game solution, verify the solution, and simply report pass or fail as the result. The sample code needs to be re-coded to accept a file-based input but it does not need to retain all solutions in memory at once.
Another rule for Sudoku is that each digit in a row or column may only appear once. Just calculating a total for each row or column won't catch duplicates.
1) Handle each puzzle one at a time. Read the puzzle into the array. Check it. Then read the next puzzle into the same array. If you only want a single yes/no for all the puzzles collectively you can print no and exit as soon as any check fails. If you make it to the end without any failed checks, then print yes. If you need to print whether individual puzzles passed, then answer before moving on to the next puzzle.
2)No! Absolutely not. One simple example is a sudoku filled with all 5s. This will give a 45 sum for every block, row, and column, but obviously is incorrect. It is also not sufficient to only check the presence of each digit along the rows and columns. For example consider one filled with 1 - 9 on the first row. Each successive row is a left rotate of the previous row. This would give all digits in each row and each column, but the blocks would be wrong e.g. block 0,0 would be 123,234,456.
One (maybe the best) way to check for each number is to set up an array of flags. Each index represents that number in the puzzle. Scan the line (or row or block) and set the flag for each number when you reach it. Then check to make sure all the flags are set. For checking a row:
int i,col;
int flags[9];
//zero the flags
for(i 0 1; i < 9; i++)
flags[i] = 0;
//check row
for(col = 0; col < 9; col++)
flags[data[row][col] - '1'] = 1;
//check flags
for(i 0 1; i < 9; i++)
if( 0 == flags[i] )
fail = true;