Custom Sorting algorithm (C) [closed] - c

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
Our teacher asked us today to make a custom sorting algorithm, and he gave us some instructions, however I wasn't able to solve it:
First you get the smallest number from a randomly generated array and assign it to a separate array. Then you get the second smallest number the array and assign it to the next position in the separate array.
I was able to build this, but it doesn't fully work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ANZAHL 5
int main() {
srand(time(0));
int zfeld[ANZAHL], zfeld1[ANZAHL] = {}, zfeld2[ANZAHL] = {}, i, d, ug, og, kl = ANZAHL + 1;
printf("Gib die untere und obere grenze an");
scanf("%d%d", &ug, &og);
for (i = 0; i < ANZAHL; i++) {
zfeld[i] = rand() % ((og - ug) - 1) + ug + 1;
}
for (d = 0; d < ANZAHL; d++) {
for (i = 0; i < ANZAHL; i++) {
if (zfeld[i] < kl && zfeld[i] != zfeld2[d - 1]) {
kl = zfeld[i];
}
}
zfeld2[d] = kl;
}
return 0;
}

Several issues:
kl=ANZAHL+1: the length of the original array has nothing to do with values. It would make more sense to do kl = og. But still, the place where you do this assignment is wrong. Once you have found the first minimum value, kl will be too small to detect the next smallest value: you need to reset it each time you iterate in the outer loop.
The inner loop should not iterate over all elements when you have already identified a few small values. You try to avoid to pick the same one twice, but just comparing with the previously identified value (zfeld[i] != zfeld2[d-1]) is not going to work. First, because when d is zero, this is an invalid reference, and second: there are in general more values in zfeld2 which you also don't want to select again. Instead consider that the first array should become "shorter". You can do this by moving the last value of the array into the slot where you found the smallest value. Then you can consider that the array became one unit smaller without losing any information. To make that work, you need to know the index where you find the smallest value.
So here is the corrected code for the loops:
for(d=0; d<ANZAHL; d++)
{
// Reset the index, and just consider the first value to the the smallest so far
int indexOfSmallest = 0;
// Each time you move one value, we look at one value less in this loop:
for(i=1; i<ANZAHL - d; i++)
{
if(zfeld[i] < zfeld[indexOfSmallest])
{
indexOfSmallest = i;
}
}
zfeld2[d] = zfeld[indexOfSmallest];
// Move last value in the slot that opens up:
zfeld[indexOfSmallest] = zfeld[ANZAHL - d - 1];
}
NB: this is a variant to selection sort. Selection sort does not use a second array, as it reuses the space that is liberated in the first array to store the sorted values.
I would also suggest to use better variable names. Names like kl, ug, og are maybe clear to you, but it is better practice to just use full names: kleinste, untereGrenze, ...etc.

Related

Cycling through interval in C efficiently

I have dynamically allocated array consisting of a lot of numbers (200 000+) and I have to find out, if (and how many) these numbers are contained in given interval. There can be duplicates and all the numbers are in random order.
Example of numbers I get at the beginning:
{1,2,3,1484984,48941651,489416,1816,168189161,6484,8169181,9681916,121,231,684979,795641,231484891,...}
Given interval:
<2;150000>
I created a simple algorithm with 2 for loops cycling through all numbers:
for( int j = 0; j <= numberOfRepeats; j++){
for( int i = 0; i < arraySize; i++){
if(currentNumber == array[i]){
counter++;
}
}
currentNumber++;
}
printf(" -> %d\n", counter);
}
This algorithm is too slow for my task. Is there more efficient way for me to implement my solution? Could sorting the arrays by value help in this case / wouldn't that be too slow?
Example of working program:
{ 1, 7, 22, 4, 7, 5, 11, 9, 1 }
<4;7>
-> 4
The problem was simple as the single comment in my question answered it - there was no reason for second loop. Single loop could do it alone.
My changed code:
for(int i = 0; i <= arraySize-1; i++){
if(array[i] <= endOfInterval && array[i] >= startOfInterval){
counter++;
}
This algorithm is too slow for my task. Is there more efficient way for me to implement my solution? Could sorting the arrays by value help in this case / wouldn't that be too slow?
Of course, it is slow. A single pass algorithm to count the number of elements that are in the set should suffice, just count them in a single pass if they pass the test (be n[i] >= lower bound && be n[i] < upper bound or similar approach) will do the work.
Only in case you need to consider duplicates (e.g. not counting them) you will need to consider if you have already touched them or no. In that case, the sorting solution will be faster (a qsort(3) call is O(nlog(n)) against the O(nn) your double loop is doing, so it will run in an almost linear, then you make a second pass over the data (converting your complexity to O(nlog(n) + n), still lower than O(nn) for the large amount of data you have.
Sorting has the advantage that puts all the repeated key values together, so you have to consider only if the last element you read was the same as the one you are processing now, if it is different, then count it only if it is in the specified range.
One final note: Reading a set of 200,000 integers into an array to filter them, based on some criteria is normally a bad, non-scalable way to solve a problem. Your problem (select the elements that belong to a given interval) allow you for a scalable and better solution by streaming the problem (you read a number, check if it is in the interval, then output it, or count it, or whatever you like to do on it), without using a large amount of memory to hold them all before starting. That is far better way to solve a problem, as it allows you to read a true unbounded set of numbers (coming e.g. from a file) and producing an output based on that:
#include <stdio.h>
#define A (2)
#define B (150000)
int main()
{
int the_number;
size_t count = 0;
int res;
while ((res = scanf("%d", &the_number)) > 0) {
if (the_number >= A && the_number <= B)
count++;
}
printf("%zd numbers fitted in the range\n", count);
}
on this example you can give the program 1.0E26 numbers (assuming that you have an input file system large enough to hold a file this size) and your program will be able to handle it (you cannot create an array with capacity to hold 10^26 values)

Backtracking maze in C, with obstacles

I need to solve a maze using backtracking method.
My maze has 0 listed as a wall, 1 listed as an empty cell, 2 is for visited, 3 for dragon.
Dragons are basically obstacles that I can go through BUT I need to choose the path with the LEAST dragons.
So far I can solve the maze and mark a path, but I can't seem to think of a relatively simple way of finding the path with the least dragons.
Do note we just started coding with C in my uni (so far I've only done java/bash/a bit of python), so I'm really new to C and algorithms in general.
Code is below.
#include <stdio.h>
#define IMPOSSIBLE (N*N+1)
int counter=0;
enum {WALL,EMPTY,VISITED,DRAGON,N};
int printMaze(int maze[N][N])
{
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
printf("%d ",maze[i][j]);
}
printf("\n");
}
}
int solveMaze(int maze[N][N], int i, int j)
{
if (maze[i][j] == WALL){ return 0; } // If [i][j] are currently a wall (0).
if (maze[i][j] == VISITED) { return 0; } // If [i][j] are currently a mark (2).
if (maze[i][j] == DRAGON) { counter++; }
maze[i][j] = VISITED; // Mark current spot with (2).
if (i==N-1 && j==N-1) { return 1; } // reached the end (N-1,N-1) - (3,3) incase N is 4.
if ( ((i < N-1) && solveMaze(maze,i+1,j)) || ((i > 0) && solveMaze(maze,i-1,j)) || ((j < N-1) && solveMaze(maze,i,j+1)) || ((j > 0) && solveMaze(maze,i,j-1)) ) { // checking index-out-bounds + recursively going around the maze
return 1;
}
maze[i][j] = EMPTY;
return 0;
}
int main() {
int maze[N][N] = { {1,1,3,3},
{3,0,1,1},
{3,0,0,1},
{1,3,3,1} };
int solved = solveMaze(maze, 0, 0);
if (solved)
{
printMaze(maze);
printf("Amount of dragons passed through in the maze: %d\n",counter);
}
else
{
printf("No solution, %d\n",IMPOSSIBLE);
}
}
I tried creating a counter that counts the amount of dragons on the way, but I guess I'm not fluent enough in recursions to make it go in every available path and choose the best one.
You seem to understand the idea of recursively traversing the tree with backtracking. The issue is that you need to find not just a path, but the one with the least cost -- that is, the fewest dragons. That means that in general, you can't stop with the first path you find. You need to keep going until you can be sure that there's no better path.
Here's one way to do it:
Maintain a variable to track the number of dragons along the best path discovered so far. Initialize it to something larger than the value that can appear along any path -- your IMPOSSIBLE, for example, or INT_MAX. This is separate from the number of dragons so far encountered along the path you are currently exploring.
Perform a recursive traversal much like you are already doing, except
Fix the example code's problems with restoring state (node contents and counter value) when you backtrack out of a dragon node.
Stop exploring any given path when the number of dragons encountered along it equals the number along the best path discovered so far.
In light of the previous, you can be certain that whenever you discover a path that reaches the exit, that path has fewer dragons than the best path previously discovered, if any. Update the variable tracking the best number of dragons accordingly. Note that this does not necessarily end the search, but it may reduce the search space that remains to be explored.
A way to solve this is to imagine the maze as a 3 dimensional graph instead of 2D. You have the triplet (i, j, number_of_dragons) define the nodes of the graph. Note that this may in extreme case mean the number of nodes are N^4. Thus you will need an array with size [N][N][N*N] to store if the given node is visited (note that dragons and walls can still be stored in a [N][N] array). To get the minimal path from source to target, simply iterate over the the values of [target.x][target.y][i] and return the minimum i for which you have visited the node.
I can suggest a better solution using min path graph algorithm like Dijkstra, but it seems this is out of scope for the question.

Getting unexpected result when trying to remove element from array in C [closed]

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 6 years ago.
Improve this question
I'm new to C and I'm trying to work through a function within a program that would remove the integer 5 from an array of varying length, also shortening the array afterwards to accommodate. a[0] is the element in the array that determines that array's length. v is the element that would be removed from the array. Within the remaining code, as well as all the other details, this is taken into account.
The following is the code I have written for the function:
void delete_set(int v, int a[])
{
int i;
int j;
for (i = 0; i < a[0]; i++)
if (a[i] == v)
{
for(j = i; j < a[0]; j++)
a[j] = a[j + 1];
a[0] = a[0] - 1;
}
}
So, I'm unsure if you would need to see the rest of the code outside of this function for it to make sense, but my problem is this. Whatever I set a[i] == to (in the if statement), if the length of the array read in is exactly that number, I get an unexpected answer. However, for any other read in array's length, I get expected (correct) results. Any change in coding would have to be done within the function, as that is how this problem was presented to me.
Thanks, and sorry for the lengthy post (if it is). I'm not too used to using forums.
You need to skip the element holding the length, it should be:
for (i = 1; i <= a[0]; i++)
It looks like your outer loop is looking at a[0] as if it were an actual element of your array (and not the length). Try:
for (i = 1; i <= a[0]; i++) ...
Notice also that I used <= there because if you have three elements, they would be in a[1], a[2], and a[3]. If you don't do this, you will have trouble removing the element which happens to be last in your array.
If a[0] is the length of the array, should you remove it? Without saving it first? Also, shouldn’t you be shifting all the elements of the original array? Only once?
You should try refactoring your algorithm. Hint: you need only one loop with a current index and the number of elements removed.
The inner loop also has a problem as it goes off the end of the array. You need to swap the placement of changing the number of elements with the for loop that copies the elements. Assuming that a[0] is the length of the array which includes a[0] then we have the following:
for (int i = 1; i < a[0]; ++i) {
if (a[i] == v) {
a[0] = a[0] - 1;
for (int j = i; j < a[0]; ++j) {
a[j] = a[j + 1];
}
}
}

Devising an algorithm in C for all possible permutations, including zero [closed]

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 8 years ago.
Improve this question
I am trying to devise and code an algorithm, in C, to come up with a table listing varying percentages of 5 different components. I need to end up with a table looking something like this:
sugar(50%).....salt(20%)....pepper(10%)....chili(10%)....cayenne(10%)
sugar(50%).....salt(50%)....pepper(00%)....chili(00%)....cayenne(00%)
sugar(00%).....salt(100%)...pepper(00%)....chili(00%)....cayenne(00%)
sugar(10%).....salt(00%)....pepper(90%)....chili(00%)....cayenne(00%)
I need to capture all the possible permutations, and note that 0% is a valid permutation, as can be seen above. The sum of all the permutations must always be 100%.
I realize that to list all the possible permutations with a granularity of 1% would mean a huge number of permutations, so I'd like to be able to pass a variable to my function that would define the level of granularity; the higher the granularity, the lower the number of table entries.
I've looked at many of the questions on SO similar to this, but I could not find one that dealt with situations where 1) the order is not important 2) items could be excluded (in my case, this means an item would have a value of 0); and 3) the example was in C.
[PS: I've simplified things by using food, but this is not homework...see my other posts.]
So, my question is, how can I cod this? I have in fact tried to code this by using a recursive loop:
int variations[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
char names[][10] = { "sugar", "spice", "pepper", "cayenne", "salt", "" );
int componentCount = 5;
for (int i = 0; i < componentCount; ++i)
for (int j = 1; j < componentCount; ++j)
for (int k = 2; k < compoentCount; ++k)
for (int l = 3; l < componentCount; ++l)
for (int m = 4; m < componentCount; ++m)
for (int x = 0; x < componentCount; ++x)
printf("%s=%d", names[x], variations[x]);
But this doesn't do what I need it to do in terms of capturing all the variations, and I did not post this earlier because I assume I need to take a completely different approach, hence my question: how can this be done?
You can solve this problem with recursion. Remember that every recursive function has the following pattern:
Am I in a simple case? If so, solve the simple problem.
Am I in a more complicated case? If so, break the problem into one or more simpler problems.
Solve each simpler problem recursively.
Now combine the solutions to the simpler problems into a solution to the harder problem.
Always start with the simplest possible problem. What's your simplest problem?
I have one item which must make up x% of the total.
The solution is: that item makes up x% of the total.
Now suppose you have n items that must make up x% of the total. How do you do it? Break it into simpler problems:
Suppose item 1 made up 0% of the total. Now I have n-1 items that make up x% of the total. List all the ways of doing that.
Suppose item 1 made up 5% of the total. Now I have n-1 items that make up x-5% of the total. List all the ways of doing that.
...
Suppose item 1 made up x% of the total. Now I have n-1 items that make up 0% of the total. List all the ways of doing that.
And you're done.
Now translate that into code.
Let us reformulate it in terms of granularity: what you want is essentially enumerate the ways to express N as a sum of K nonnegative integers. Here, N is the granularity (for 5% increments, N would be 100% / 5% = 20) and K is the number of items.
In such formulation, all it takes is a recursive function with parameters k (index from 0 to K-1) and n (what's left of N), in C-like pseudocode:
int a [MAX_K];
void fun (int k, int n)
{
int i;
if (k < 0)
{
if (n == 0)
{
<print - or otherwise use - array a>
}
return;
}
for (i = 0; i <= n; i++)
{
a[k] = i; // run the branch where k-th item gets i/N of the total sum
fun (k - 1, n - i);
}
}
...
<call it as "fun (K - 1, N)">
You can bring a pointer to array a with you in the recursion if a global variable is not an option.
The only sensible way to define the level of granularity is as 1/n, where n is a positive integer. I.e. you want to split up the percentages into multiples of 1/n for some n. Otherwise if you merely want all positive percentages to be greater than 1/n you get infinitely many possibilities. Look up the "stars and bars" construction for how to split up an integer n into k non-negative parts. You will see that the answer for the number of possibilities is (n+k-1 choose k-1) and see how each choice of k-1 numbers from the range 1 to n+k-1 leads to a unique assignment of percentages in the combinations you are trying to generate. There are also references online for how to generate all combinations of a particular size from a set.

Grid containing apples

I found this question on a programming forum:
A table composed of N*M cells,each having a certain quantity of apples, is given. you start from the upper-left corner. At each step you can go down or right one cell.Design an algorithm to find the maximum number of apples you can collect ,if you are moving from upper-left corner to bottom-right corner.
I have thought of three different complexities[in terms of time & space]:
Approach 1[quickest]:
for(j=1,i=0;j<column;j++)
apple[i][j]=apple[i][j-1]+apple[i][j];
for(i=1,j=0;i<row;i++)
apple[i][j]=apple[i-1][j]+apple[i][j];
for(i=1;i<row;i++)
{
for(j=1;j<column;j++)
{
if(apple[i][j-1]>=apple[i-1][j])
apple[i][j]=apple[i][j]+apple[i][j-1];
else
apple[i][j]=apple[i][j]+apple[i-1][j];
}
}
printf("\n maximum apple u can pick=%d",apple[row-1][column-1]);
Approach 2:
result is the temporary array having all slots initially 0.
int getMax(int i, int j)
{
if( (i<ROW) && (j<COL) )
{
if( result[i][j] != 0 )
return result[i][j];
else
{
int right = getMax(i, j+1);
int down = getMax(i+1, j);
result[i][j] = ( (right>down) ? right : down )+apples[i][j];
return result[i][j];
}
}
else
return 0;
}
Approach 3[least space used]:
It doesn't use any temporary array.
int getMax(int i, int j)
{
if( (i<M) && (j<N) )
{
int right = getMax(i, j+1);
int down = getMax(i+1, j);
return apples[i][j]+(right>down?right:down);
}
else
return 0;
}
I want to know which is the best way to solve this problem?
There's little difference between approaches 1 and 2, approach 1 is probably a wee bit better since it doesn't need the stack for the recursion that approach 2 uses since that goes backwards.
Approach 3 has exponential time complexity, thus it is much worse than the other two which have complexitx O(rows*columns).
You can make a variant of approach 1 that proceeds along a diagonal to use only O(max{rows,columns}) additional space.
in term of time the solution 1 is the best because there is no recursie function.
the call of recursive function takes time
Improvement to First Approach
Do you really need the temporary array to be N by M?
No.
If the initial 2-d array has N columns, and M rows, we can solve this with a 1-d array of length M.
Method
In your first approach you save all of the subtotals as you go, but you really only need to know the apple-value of the cell to the left and above when you move to the next column. Once you have determined that, you don't look at those previous cells ever again.
The solution then is to write-over the old values when you start on the next column over.
The code will look like the following (I'm not actually a C programmer, so bear with me):
The Code
int getMax()
{
//apple[][] is the original apple array
//N is # of columns of apple[][]
//M is # of rows of apple[][]
//temp[] is initialized to zeroes, and has length M
for (int currentCol = 0; currentCol < N; currentCol++)
{
temp[0] += apple[currentCol][0]; //Nothing above top row
for (int i = 1; i < M; i++)
{
int applesToLeft = temp[i];
int applesAbove = temp[i-1];
if (applesToLeft > applesAbove)
{
temp[i] = applesToLeft + apple[currentCol][i];
}
else
{
temp[i] = applesAbove + apple[currentCol][i];
}
}
}
return temp[M - 1];
}
Note: there isn't any reason to actually store the values of applesToLeft and applesAbove into local variables, and feel free to use the ? : syntax for the assignment.
Also, if there are less columns than rows, you should rotate this so the 1-d array is the shorter length.
Doing it this way is a direct improvement over your first approach, as it saves memory, and plus iterating over the same 1-d array really helps with caching.
I can only think of one reason to use a different approach:
Multi-Threading
To gain the benefits of multi-threading for this problem, your 2nd approach is just about right.
In your second approach you use a memo to store the intermediate results.
If you make your memo thread-safe (by locking or using a lock-free hash-set) , then you can start multiple threads all trying to get the answer for the bottom-right corner.
[// Edit: actually since assigning ints into an array is an atomic operation, I don't think you would need to lock at all ].
Make each call to getMax choose randomly whether to do the left getMax or above getMax first.
This means that each thread works on a different part of the problem and since there is the memo, it won't repeat work a different thread has already done.

Resources