I have been working on an algorithm to find all permutations of the elements of a char array for a few days now and well it just doesn't seem to work.
The char array is an **array, which I iterate through based on the number entered by the user and I then malloc space for each word(40 chars each). The number entered by the user is the length of the array, and it is the number they expect to enter. This part works as expected.
What I am having trouble with is iterating through the char array and calculating the permutation of the entire set(**array). I then want to have another char array consisting of all permutations of the set. Now just permutations of the unit indices's of **array, not each indices's individual characters.
Does anybody have any tips on how to successfully do this, regardless of the size of the initial set? I assume it would be much easier if the set size where static.
My starting array looks like this as an example
char *array[] = {
"Hello",
"Calculator",
"Pencil",
"School Bus"
};
Which would be held in **array, with "Hello" in array[0] and "School Bus" in array[3], with '\0' at the end of each.
I want the permutation to be on the indices, not the characters.
So
"Hello"
.
.
.
"School BusSchool BusSchool BusSchool Bus"
Here's a dumb permutation generator (up to N=32... or 64).
#include <stdio.h>
const int N = 5;
int x[N];
int main( void ) {
int i,j;
x[0]=-1;
unsigned mask = -1; // unused numbers
for( i=0;; ) {
for( j=x[i]+1; j<N; j++ ) { // check remaining numbers
if( (mask>>j)&1 ) { // bit j is 1 -> not used yet
x[i] = j; // store the number
mask ^= (1<<x[i]); // mask used
// try going further, or print the permutation
if( ++i>=N ) { for( j=0; j<N; j++ ) printf( "%3i", x[j] ); printf( "\n" ); }
else x[i]=-1; // start next cell from 0
break;
}
}
// go back if there's no more numbers or cells
if( (j>=N) || (i>=N) ) {
if( --i<0 ) break;
mask ^= (1<<x[i]);
}
}
}
By your edit, I am taking that you have an array of four elements. Your desired output is a combination of these elements and is the concatenation of between one and four elements. The output may contain an input element more than once. Is this a correct summary?
If so, think of your output in four cases: for output generated from one, two, three, or four elements. For output generated from n elements, you have n^n possibilities. For all four of these cases combined, this gives you 1^1 + 2^2 + 3^3 + 4^4 = 288 possible outputs.
Your 1-element output permutations are simply: 0, 1, 2, 3
Your 2-element output permutations can be generated by the pseudo-code:
for i = 0 to 3 {
for j = 0 to 3 {
next_permutation = {i, j}
}
}
For 3- and 4-element output, permutations can be generated using three and four nested loops, respectively. For some arbitrary number of input elements x, you can generate permutations using the same technique with x number of nested loops. Be warned that the number of loops requires grows exponentially with the number of input elements, so this can get ugly fairly fast.
You can use the numbers from these permutations as indices into your initial array in order to generate the output as strings (as in your sample).
Update: Here's a recursive pseudo-code function that can generate these pseudo-permutations:
int output_array[dimension] = {0};
generate_combinations (unsigned dimension, int index) {
for i = 0 to (dimension-1) {
output_array[index] = i;
if index == 0
next_permutation = output_array
else
generate_combinations(dimension, index-1)
endif
}
}
You would use this with dimension set to the number of elements in your input array and index = dimension - 1. Hopefully, your input dimensionality won't be so large that this will recurse too deeply for your CPU to handle.
Here's one solution. Remember that the time complexity is factorial, and that if you're storing all the permutations then the space required is also factorial. You're not going to be able to do very many strings.
void CalculatePermutations(unsigned long permSize, const char** candidates, const char** currentPerm, unsigned long currentPermIdx, const char** ouputBuffer, unsigned long* nextOutputIdx)
{
//base case (found a single permutation)
if(currentPermIdx >= permSize){
unsigned long i = 0;
for(i = 0; i < permSize; ++i){
ouputBuffer[*nextOutputIdx] = currentPerm[i];
(*nextOutputIdx)++;
}
return;
}
//recursive case
unsigned long i = 0;
for(i = 0; i < permSize; ++i){
if(candidates[i]){
currentPerm[currentPermIdx] = candidates[i]; //choose this candidate
candidates[i] = NULL; //mark as no longer a candidate
CalculatePermutations(permSize, candidates, currentPerm, currentPermIdx + 1, ouputBuffer, nextOutputIdx);
candidates[i] = currentPerm[currentPermIdx]; //restore this as a possible candidate
}
}
}
int main(int argc, char** argv)
{
const char* allStrings[8] = {"0", "1", "2", "3", "4", "5", "6", "7"};
static const char* allPermutations[322560]; // = fact(8) * 8
const char* permBuffer[8];
unsigned long nextOutputIdx = 0;
CalculatePermutations(8, allStrings, permBuffer, 0, allPermutations, &nextOutputIdx);
for(unsigned long i = 0; i < 322560; ++i){
printf("%s", allPermutations[i]);
if(i % 8 == 7){
printf("\n");
} else {
printf(", ");
}
}
return 0;
}
here my code that give us the r-permutation of a n! possible permutations. Code works with all kind of size (I only check with 3!, 4!, 5! and 8! and always works correct, so I suppouse that works right):
#include <stdio.h>
#include <stdint.h>
enum { NPER = 4, };
static const char *DukeQuote[NPER] = {
"Shake it, baby!",
"You wanna dance?",
"Suck it down!",
"Let's rock!",
};
void fill(const uint32_t, uint32_t * const);
void fact(const uint32_t, uint32_t * const);
void perm(uint32_t, const uint32_t, const uint32_t * const, uint32_t * const);
int main(void)
{
uint32_t f[NPER+1];
uint32_t p[NPER];
uint32_t r, s;
/* Generate look-up table for NPER! factorial */
fact(NPER, f);
/* Show all string permutations */
for(r = 0; r < f[NPER]; r++)
{
perm(r, NPER, f, p);
for(s = 0; s < NPER; s++)
printf("%s, ", DukeQuote[p[s]]);
printf("\n");
}
return 0;
}
/* Generate look-up table for n! factorial.
That's a trick to improve execution */
void fact(const uint32_t n, uint32_t * const f)
{
uint32_t k;
for(f[0] = 1, k = 1; k <= n; k++)
f[k] = f[k-1] * k;
}
/* Fill the vector starting to 0 up to n-1 */
void fill(const uint32_t n, uint32_t * const p)
{
uint32_t i;
for(i = 0; i < n; i++)
p[i] = i;
}
/* Give us the r-permutation of n! possible permutations.
r-permutation will be inside p vector */
void perm(uint32_t r, const uint32_t n, const uint32_t * const f, uint32_t * const p)
{
uint32_t i, j;
fill(n, p);
for(i = n-1; i > 0; i--)
{
uint32_t s;
j = r / f[i];
r %= f[i];
s = p[j];
for(; j < i; j++)
p[j] = p[j+1];
p[i] = s;
}
}
For instance, if you want the first permutation of 4! possibles then:
perm(0, 4, f, p)
where p will have:
p = [3, 2, 1, 0]
Take care, 0 is 1th, 1 is 2th, and so on.
You can use p[i] like indices in your string array, how I've used in DukeQuote array.
PD1: This code implements the correct definition of a permutation (A r-permutation is a bijection. The cardinal of the set of all bijections N_n to N_n is exactly n!)
PD2: I hope that my mistakes in my poor English doesn't influence in the goal of my explanation.
Related
I have a recursive function that I wrote in C that looks like this:
void findSolutions(int** B, int n, int i) {
if (i > n) {
printBoard(B, n);
} else {
for (int x = 1; x <= n; x++) {
if (B[i][x] == 0) {
placeQueen(B, n, i, x);
findSolutions(B, n, i + 1);
removeQueen(B, n, i, x);
}
}
}
}
The initial call is (size is an integer given by user and B is a 2D array):
findSolutions(B, size, 1);
I tried to convert it into a iteration function but there is another function called removeQueen after findSolutions. I got stuck on where to put this function call. How to solve this problem? Stack is also fine but I'm also having trouble doing that.
I'm going to assume that placeQueen(B, n, i, x) makes a change to B and that removeQueen(B, n, i, x) undoes that change.
This answer shows how to approach the problem generically. It doesn't modify the algorithm like Aconcagua has.
Let's start by defining a state structure.
typedef struct {
int **B;
int n;
int i;
} State;
The original code is equivalent to the following:
void _findSolutions(State *state) {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = 1; x <= state->n; ++x) {
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
findSolutions(state2);
}
}
}
State_free(state); // Frees the board too.
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
Now, we're in position to eliminate the recursion.
void _findSolutions(State *state) {
StateStack *S = StateStack_new();
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(&state));
StateStack_free(S);
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
We can eliminate the helper we no longer need.
void findSolutions(int** B, int n, int i) {
StateStack *S = StateStack_new();
State *state = State_new(B, n, i); // Deep clones B.
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(S, &state));
StateStack_free(S);
}
Functions you need to implement:
StateStack *StateStack_new(void)
void StateStack_free(StateStack *S)
void StateStack_push(StateStack *S, State *state)
int StateStack_pop(StateStack *S, State **p)
State *State_new(int **B, int n, int i) (Note: Clones B)
State *State_clone(const State *state) (Note: Clones state->B)
void State_free(State *state) (Note: Frees state->B)
Structures you need to implement:
StateStack
Tip:
It would be best if you replaced
int **B = malloc((n+1)*sizeof(int*));
for (int i=1; i<=n; ++i)
B[i] = calloc(n+1, sizeof(int));
...
for (int x = 1; x <= n; ++x)
...
B[i][x]
with
char *B = calloc(n*n, 1);
...
for (int x = 0; x < n; ++x)
...
B[(i-1)*n+(x-1)]
What you get by the recursive call is that you get stored the location of the queen in current row before you advance to next row. You will have to re-produce this in the non-recursive version of your function.
You might use another array storing these positions:
unsigned int* positions = calloc(n + 1, sizeof(unsigned int));
// need to initialise all positions to 1 yet:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
}
I reserved a dummy element so that we can use the same indices...
You can now count up last position from 1 to n, and when reaching n there, you increment next position, restarting with current from 1 – just the same way as you increment numbers in decimal, hexadecimal or octal system: 1999 + 1 = 2000 (zero based in this case...).
for(;;)
{
for(unsigned int i = 1; i <= n; ++i)
{
placeQueen(B, n, i, positions[i]);
}
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
}
for(unsigned int i = 1; i <= n; ++i)
{
if(++positions[i] <= n)
// break incrementing if we are in between the numbers:
// 1424 will get 1431 (with last position updated already before)
goto CONTINUE;
positions[i] = 1;
}
// we completed the entire positions list, i. e. we reset very
// last position to 1 again (comparable to an overflow: 4444 got 1111)
// so we are done -> exit main loop:
break;
CONTINUE: (void)0;
}
It's untested code, so you might find a bug in, but it should clearly illustrate the idea. It's the naive aproach, always placing the queens and removing them again.
You can do it a bit cleverer, though: place all queens at positions 1 initially and only move the queens if you really need:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
placeQueen(B, n, i, 1);
}
for(;;)
{
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
++positions[i]
if(++positions[i] <= n)
{
placeQueen(B, n, i, positions[i]);
goto CONTINUE;
}
placeQueen(B, n, i, 1);
positions[i] = 1;
}
break;
CONTINUE: (void)0;
}
// cleaning up the board again:
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, 1);
}
Again, untested...
You might discover that now the queens move within first row first, different to your recursive approach before. If that disturbs you, you can count down from n to 1 while incrementing the positions and you get original order back...
At the very end (after exiting the loop), don't forget to free the array again to avoid memory leak:
free(positions);
If n doesn't get too large (eight for a typical chess board?), you might use a VLA to prevent that problem.
Edit:
Above solutions will print any possible combinations to place eight queens on a chess board. For an 8x8 board, you get 88 possible combinations, which are more than 16 millions of combinations. You pretty sure will want to filter out some of these combinations, as you did in your original solution as well (if(B[i][x] == 0)), e. g.:
unsigned char* checks = malloc(n + 1);
for(;;)
{
memset(checks, 0, (n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[positions[i]] != 0)
goto SKIP;
checks[positions[i]] = 1;
}
// place queens and print board
SKIP:
// increment positions
}
(Trivial approach! Including the filter in the more elaborate approach will get more tricky!)
This will even be a bit more strict than your test, which would have allowed
_ Q _
Q _ _
_ Q _
on a 3x3 board, as you only compare against previous column, whereas my filter wouldn't (leaving a bit more than 40 000 boards to be printed for an 8x8 board).
Edit 2: The diagonals
To filter out those boards where the queens attack each other on the diagonals you'll need additional checks. For these, you'll have to find out what the common criterion is for the fields on the same diagonal. At first, we have to distinguish two types of diagonals, those starting at B[1][1], B[1][2], ... as well as B[2][1], B[3][1], ... – all these run from top left to bottom right direction. On the main diagonal, you'll discover that the difference between row and column index does not differ, on next neighbouring diagonals the indices differ by 1 and -1 respectively, and so on. So we'll have differences in the range [-(n-1); n-1].
If we make the checks array twice as large and shift all differences by n, can re-use do exactly the same checks as we did already for the columns:
unsigned char* checks = (unsigned char*)malloc(2*n + 1);
and after we checked the columns:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[n + i - positions[i]] != 0)
goto SKIP;
checks[n + i - positions[i]] = 1;
}
Side note: Even if the array is larger, you still can just memset(checks, 0, n + 1); for the columns as we don't use the additional entries...
Now next we are interested in are the diagonals going from bottom left to top right. Similarly to the other direction, you'll discover that the difference between n - i and positions[i] remains constant for fields on the same diagonal. Again we shift by n and end up in:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[2 * n - i - positions[i]] != 0)
goto SKIP;
checks[2 * n - i - positions[i]] = 1;
}
Et voilà, only boards on which queens cannot attack each other.
You might discover that some boards are symmetries (rotational or reflection) of others. Filtering these, though, is much more complicated...
The question at hand is:
Q8. Given an unsorted array A[]. The task is to print all unique pairs in the unsorted array with equal sum. Consider the Input: A[] = {6, 4, 12, 10, 22, 54, 32, 42, 21, 11}
Explain the approach of solving the above problem, and write the code in any one programming language C/C++/Python/Java. What is the time complexity of the above problem?
Here is my solution to the above problem (in C) :
#include <stdio.h>
int main(){
int arr[]={6,4,12,10,22,54,32,42,21,11};
int len=sizeof(arr)/sizeof(arr[0]);
for(int i=0;i<len;i++)
for(int j=i+1;j<len;j++)
for(int k=i+1;k<len;k++)
for(int l=k+1;l<len;l++)
if(arr[i]+arr[j]==arr[l]+arr[k])
printf("(%d,%d),(%d,%d)\n",arr[i],arr[j],arr[k],arr[l]);
return 0;
}
My logic is to take one element at a time, and take its sum with every other element, and for each such iteration, compare the sum of two other unique pair of elements to it.
For example, when i=0, j=3, arr[i]+arr[j]=16. When k=1,l=2, arr[k]+arr[l]=16. Since the pairs are unique (6,10) and (4,12) and their sum is equal, I print them.
Note that the pairs are assumed to be unordered pairs so that (a,b) is the same as (b,a) and so we don't need to repeat that, as they have to be unique.
My question is : I know that my code is almost O(n^4). How can I improve/optimise it further?
FIrst you precompute the sum of each pair and keep the result in a matrix PAIRSUM.
PAIRSUM(0, 0) = 12
PAIRSUM(0, 1) = 10 a s o
Next, you loop over the PAIRSUM and see where 2 entries are similar.
So you reduced the big problem to a smaller one, in which you check the equality of 2 numbers, not of 2 sums of numbers.
For this you keep a vector PAIR in which at index X you keep the entries in PAIRSUM where the sum was X.
For example, PAIR(10) = { {0, 1} }.
You can also consider in PAIRSUM only the matrix above the diagonal, so for which the indexes (i,j) have i>j.
It would be easier in C++, Python, or Java because those languages provide high level containers. In Python, you could use a defaultdict(list) where the key would be the sums and the value a list of pairs giving that sum.
Then you only have to process unique pairs (N2 / 2)
result = collections.defaultdict(list)
for i, a in enumerate(A):
for b in A[i+1:]:
result[a+b].append((a,b))
It will be slightly more complex in C because you do not have the high-level direct access dict. If you can waste some memory and only have small numbers like here, you can say that the highest sum will be less than twice the biggest number in the input array, and directly allocate an array of that size. That way you ensure direct access from a sum. From there, you just use a linked list of pairs and that is all. As a bonus you even get a sorted list of sums.
I you cannot assume that numbers are small you will have to build a direct access container. A hash type container using N*N/2 as size (N being the length of A) and sum%size as hash function should be enough.
For completeness, here is a possible C code not doing the small numbers assumption (this code displays all pairs not only the ones with duplicated sums):
#include <stdio.h>
#include <stdlib.h>
// a node in a linked list of pairs
struct pair_node {
int first;
int second;
struct pair_node *next;
};
// a slot for a hash type containers of pairs indexed by their sum
struct slot {
int number;
struct pair_node *nodes;
struct slot *next;
};
// utility function to find (or create) a slot for a sum
struct slot* find_slot(struct slot **slots, int size, int sum) {
struct slot *slt = slots[sum%size];
while (slt != NULL) {
if (slt->number == sum) {
return slt;
}
slt = slt->next;
}
slt = malloc(sizeof(struct slot));
slt->number = sum;
slt->nodes = NULL;
slt->next = slots[sum%size];
slots[sum%size] = slt;
return slt;
}
int main() {
int A[] = {6,4,12,10,22,54,32,42,21,11}; // the array of numbers
int N = sizeof(A) / sizeof(A[0]);
int arr_size = N * N / 2; // size of the hash table of pairs
struct slot** result = malloc(arr_size * sizeof(struct slot *));
for (int i=0; i<arr_size; i++) {
result[i] = NULL;
}
// process unique pairs
for (int i=0; i<N-1; i++) {
for (int j=i+1; j<N; j++) {
int sum = A[i] + A[j];
// allocate and initialize a node
struct pair_node *node = malloc(sizeof(*node));
node->first = A[i];
node->second = A[j];
// store the node in the hash container
struct slot *slt = find_slot(result, arr_size, sum);
node->next = slt->nodes;
slt->nodes = node;
}
}
// display the result
for (int i=0; i<arr_size; i++) {
for (struct slot* slt=result[i]; slt != NULL;) {
printf("%d :", slt->number);
struct pair_node *node = slt->nodes;
while(node != NULL) {
printf(" (%d,%d)", node->first, node->second);
node = node->next;
free(node); // free what has been allocated
}
printf("\n");
struct slot *old = slt;
slt = slt->next;
free(old);
}
}
free(result);
return EXIT_SUCCESS;
}
C code for calculating all the sums and storing the sums with indexes inside an array of structures. Then we sort the structures and print adjacent structure elements with the same sum.
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
// for debugging
#define debug(...) ((void)0) // printf(__VA_ARGS__)
// two indexes and a sum
struct is_s {
// one index inside the array
size_t i;
// the other index also inside the array
size_t j;
// no idea, must be random
int sum;
};
// used for qsoring the struct is_s
static int is_qsort_compare_sum(const void *a0, const void *b0) {
const struct is_s * const a = a0;
const struct is_s * const b = b0;
return a->sum - b->sum;
}
int unique_pairs(const size_t len, const int arr[len]) {
if (len <= 1) return 0;
// The number of unsorted combinations must be n!/(2!*(n-2)!)
const size_t islen = len * (len - 1) / 2; // #MOehm
debug("%zu\n", islen);
struct is_s * const is = malloc(islen * sizeof(*is));
if (is == NULL) {
return -ENOMEM;
}
size_t isidx = 0;
for (size_t i = 0; i < len; ++i) {
for (size_t j = i + 1; j < len; ++j) {
assert(isidx < islen); // just for safety
struct is_s * const p = &is[isidx++];
p->i = i;
p->j = j;
p->sum = arr[i] + arr[j];
debug("[%zu]=[%zu]=%d [%zu]=%d %d\n", isidx, p->i, arr[p->i], p->j, arr[p->j], p->sum);
}
}
qsort(is, islen, sizeof(*is), is_qsort_compare_sum);
for (size_t i = 0; i < islen - 1; ++i) {
debug("([%zu]=%d,[%zu]=%d)%d = ([%zu]=%d,[%zu]=%d)%d\n",
is[i].i, arr[is[i].i], is[i].j, arr[is[i].j], is[i].sum,
is[i+1].i, arr[is[i+1].i], is[i+1].j, arr[is[i+1].j], is[i+1].sum
);
if (is[i].sum == is[i + 1].sum) {
printf("(%d,%d),(%d,%d) = %d\n",
arr[is[i].i], arr[is[i].j],
arr[is[i+1].i], arr[is[i+1].j], is[i].sum);
}
}
free(is);
return 0;
}
int main(void) {
const int arr[] = {6,4,12,10,22,54,32,42,21,11};
return unique_pairs(sizeof(arr)/sizeof(*arr), arr);
}
The result I get is:
(6,10),(4,12) = 16
(10,22),(21,11) = 32
(12,21),(22,11) = 33
(22,21),(32,11) = 43
(32,21),(42,11) = 53
(12,42),(22,32) = 54
(10,54),(22,42) = 64
As I wonder if this is correct, as #Bathsheba noted, I think the worst case is O(n*n).
It can be done in O(N^2 * log(N^2) * M), where M is the maximum number of pairs(i, j) that have the same sum, so in worst case it would be O(N^3 * log(N)).
Lets iterate for every pair 0 <= i,j < N in order (increasing or decreasing), we have to save the sum of all the previous pairs(i, j) (to know which previous pairs have a certain sum) this can be done with a map with a integer key and a vector of pairs for the mapped value; then for every pair(i, j) you search in the map for it's sum (key = A[i] + A[j]), then al the pairs store in map[sum] are answers to this pair(i, j).
You don't have to worry about for the following pairs to (i, j) that have the sum because the following pairs when they be processed they will count it.
Here is a Java solution:
import java.util.*;
class Duplicate {
public static void main(String[] args) {
int [] a = {5,3,1,4,5,6,3,7,0,10,6,4,9,1};
List<Integer> li = new ArrayList<Integer>();
int p1=0, p2=0;
for(int i=0; i<a.length;i++) {
for(int j=i+1; j<a.length;j++){
if(a[i]+a[j] == 10) {
p1 = a[i];
p2 = a[j];
if(!li.contains(Math.abs(p2-p1))) {
li.add(Math.abs(p2-p1));
System.out.println("Pairs" + ":" + p1 + "," + p2);
}
}
p1=0;
p2=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 have the input as array A = [ 2,3,4,1]
The output is simply all possible permutation from elements in A which can be done by single transposition (single flip of two neighbouring elements) operation. So the output is :
[3,2,4,1],[ 2,4,3,1],[2,3,1,4],[1,3,4,2]
Circular transpositioning is allowed. Hence [2,3,4,1] ==> [1,3,4,2] is allowed and a valid output.
How to do it in C?
EDIT
In python, it would be done as follows:
def Transpose(alist):
leveloutput = []
n = len(alist)
for i in range(n):
x=alist[:]
x[i],x[(i+1)%n] = x[(i+1)%n],x[i]
leveloutput.append(x)
return leveloutput
This solution uses dynamic memory allocation, this way you can do it for an array of size size.
int *swapvalues(const int *const array, size_t size, int left, int right)
{
int *output;
int sotred;
output = malloc(size * sizeof(int));
if (output == NULL) /* check for success */
return NULL;
/* copy the original values into the new array */
memcpy(output, array, size * sizeof(int));
/* swap the requested values */
sotred = output[left];
output[left] = output[right];
output[right] = sotred;
return output;
}
int **transpose(const int *const array, size_t size)
{
int **output;
int i;
int j;
/* generate a swapped copy of the array. */
output = malloc(size * sizeof(int *));
if (output == NULL) /* check success */
return NULL;
j = 0;
for (i = 0 ; i < size - 1 ; ++i)
{
/* allocate space for `size` ints */
output[i] = swapvalues(array, size, j, 1 + j);
if (output[i] == NULL)
goto cleanup;
/* in the next iteration swap the next two values */
j += 1;
}
/* do the same to the first and last element now */
output[i] = swapvalues(array, size, 0, size - 1);
if (output[i] == NULL)
goto cleanup;
return output;
cleanup: /* some malloc call returned NULL, clean up and exit. */
if (output == NULL)
return NULL;
for (j = i ; j >= 0 ; j--)
free(output[j]);
free(output);
return NULL;
}
int main()
{
int array[4] = {2, 3, 4, 1};
int i;
int **permutations = transpose(array, sizeof(array) / sizeof(array[0]));
if (permutations != NULL)
{
for (i = 0 ; i < 4 ; ++i)
{
int j;
fprintf(stderr, "[ ");
for (j = 0 ; j < 4 ; ++j)
{
fprintf(stderr, "%d ", permutations[i][j]);
}
fprintf(stderr, "] ");
free(permutations[i]);
}
fprintf(stderr, "\n");
}
free(permutations);
return 0;
}
Although some people think goto is evil, this is a very nice use for it, don't use it to control the flow of your program (for instance to create a loop), that is confusing. But for the exit point of a function that has to do several things before returning, it think it's actually a nice use, it's my opinion, for me it makes the code easier to understand, I might be wrong.
Have a look at this code I have written with an example :
void transpose() {
int arr[] = {3, 5, 8, 1};
int l = sizeof (arr) / sizeof (arr[0]);
int i, j, k;
for (i = 0; i < l; i++) {
j = (i + 1) % l;
int copy[l];
for (k = 0; k < l; k++)
copy[k] = arr[k];
int t = copy[i];
copy[i] = copy[j];
copy[j] = t;
printf("{%d, %d, %d, %d}\n", copy[0], copy[1], copy[2], copy[3]);
}
}
Sample Output :
{5, 3, 8, 1}
{3, 8, 5, 1}
{3, 5, 1, 8}
{1, 5, 8, 3}
A few notes:
a single memory block is preferred to, say, an array of pointers because of better locality and less heap fragmentation;
the cyclic transposition is only one, it can be done separately, thus avoiding the overhead of the modulo operator in each iteration.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *single_transposition(const int *a, unsigned int n) {
// Output size is known, can use a single allocation
int *out = malloc(n * n * sizeof(int));
// Perform the non-cyclic transpositions
int *dst = out;
for (int i = 0; i < n - 1; ++i) {
memcpy(dst, a, n * sizeof (int));
int t = dst[i];
dst[i] = dst[i + 1];
dst[i + 1] = t;
dst += n;
}
// Perform the cyclic transposition, no need to impose the overhead
// of the modulo operation in each of the above iterations.
memcpy(dst, a, n * sizeof (int));
int t = dst[0];
dst[0] = dst[n-1];
dst[n-1] = t;
return out;
}
int main() {include
int a[] = { 2, 3, 4, 1 };
const unsigned int n = sizeof a / sizeof a[0];
int *b = single_transposition(a, n);
for (int i = 0; i < n * n; ++i)
printf("%d%c", b[i], (i % n) == n - 1 ? '\n' : ' ');
free(b);
}
There are many ways to tackle this problem, and most important questions are: how you're going to consume the output and how variable is the size of the array. You've already said the array is going to be very large, therefore I assume memory, not CPU will be the biggest bottleneck here.
If output is going to be used only few times (especially just once), it'll may be best to use functional approach: generate every transposition on the fly, and never have more than one in memory at a time. For this approach many high level languages would work as well as (maybe sometimes even better than) C.
If size of the array is fixed, or semi-fixed (eg few sizes known at compile-time), you can define structures, using C++ templates at best.
If size is dynamic and you still want to have every transposition in memory then you should allocate one huge memory block and treat it as contiguous array of arrays. This is very simple and straightforward on machine level. Unfortunately it's best tackled using pointer arithmetic, one feature of C/C++ that is renowned for being difficult to understand. (It isn't if you learn C from basics, but people jumping down from high level languages have proven track record of getting it completely wrong first time)
Other approach is to have big array of pointers to smaller arrays, which results in double pointer, the ** which is even more terrifying to newcomers.
Sorry for long post which is not a real answer, but IMHO there are too many questions left open for choosing the best solution and I feel you need bit more C basic knowledge to manage them on your own.
/edit:
As other solutions are already posted, here's a solution with minimum memory footprint. This is the most limiting approach, it uses same one buffer over and over, and you must be sure that your code is finished with first transposition before moving on to the next one. On the bright side, it'll still work just fine when other solutions would require terabyte of memory. It's also so undemanding that it might be as well implemented with a high level language. I insisted on using C++ in case you would like to have more than one matrix at a time (eg comparing them OR running several threads concurrently).
#define NO_TRANSPOSITION -1
class Transposable1dMatrix
{
private:
int * m_pMatrix;
int m_iMatrixSize;
int m_iCurrTransposition;
//transposition N means that elements N and N+1 are swapped
//transpostion -1 means no transposition
//transposition (size-1) means cyclic transpostion
//as usual in C (size-1) is the last valid index
public:
Transposable1dMatrix(int MatrixSize)
{
m_iMatrixSize = MatrixSize;
m_pMatrix = new int[m_iMatrixSize];
m_iCurrTransposition = NO_TRANSPOSITION;
}
int* GetCurrentMatrix()
{
return m_pMatrix;
}
bool IsTransposed()
{
return m_iCurrTransposition != NO_TRANSPOSITION;
}
void ReturnToOriginal()
{
if(!IsTransposed())//already in original state, nothing to do here
return;
//apply same transpostion again to go back to original
TransposeInternal(m_iCurrTransposition);
m_iCurrTransposition = NO_TRANSPOSITION;
}
void TransposeTo(int TranspositionIndex)
{
if(IsTransposed())
ReturnToOriginal();
TransposeInternal(TranspositionIndex);
m_iCurrTransposition = TranspositionIndex;
}
private:
void TransposeInternal(int TranspositionIndex)
{
int Swap1 = TranspositionIndex;
int Swap2 = TranspositionIndex+1;
if(Swap2 == m_iMatrixSize)
Swap2 = 0;//this is the cyclic one
int tmp = m_pMatrix[Swap1];
m_pMatrix[Swap1] = m_pMatrix[Swap2];
m_pMatrix[Swap2] = tmp;
}
};
void main(void)
{
int arr[] = {2, 3, 4, 1};
int size = 4;
//allocate
Transposable1dMatrix* test = new Transposable1dMatrix(size);
//fill data
memcpy(test->GetCurrentMatrix(), arr, size * sizeof (int));
//run test
for(int x = 0; x<size;x++)
{
test->TransposeTo(x);
int* copy = test->GetCurrentMatrix();
printf("{%d, %d, %d, %d}\n", copy[0], copy[1], copy[2], copy[3]);
}
}
This question has been asked here on SO before with below code
find3missing(int* array)
{
int newarray[100] = {0};
For i = 0 to 99
++newarray[array[i]] ;
For i = 0 to 99
If newarray[i] != 1
Cout << “the missing number is ” << i+1 << endl ;
}
But when I checked this code, it doesn't seem to work. Suppose I have an array of {1,2,6}. The output should be 3,4,5 but with the code above I get 1,4,5,6 instead. Below is my implementation of pseudo code with array size 6.
main()
{
int a[6]={1,2,6};
int tmp[6]={0},i;
for(i=0;i<6;i++)
{
++tmp[a[i]];
}
for(i=0;i<6;i++)
{
if(tmp[i]!=1)
{
printf("%d",i+1);
}
}
}
Is this the right code?
This ++newarray[array[i]] should be ++newarray[array[i] - 1]. This because you are interested in a sequence of 1-100 numbers, so no 0, but C arrays are 0 based. If you then look at the cout: the missing number is ” << i+1 here you "unshift" the number by adding 1.
There is another problem: you should pass the number of elements of the array, something like:
find3missing(int* array, int length) {
int newarray[100] = {0};
for (int i = 0; i < length; i++) {
++newarray[array[i] - 1] ;
}
C/C++ arrays are zero based, as A[i] is equivalent to *(A+i). So change ++newarray[array[i]] to ++newarray[array[i]-1]. Also use malloc, free and memset to use an array of dynamic size.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void find3missing(int* pArray, size_t size, int min, int max){
int* newarray;
int i;
unsigned int j;
int range = max - min;
if(range < 0)
return;
newarray = (int*) malloc(range*sizeof(int)); // allocate enough memory
memset(newarray,0,range*sizeof(int)); // set that block to zero
for(j = 0; j < size; ++j){
++newarray[pArray[j]-min];
}
for(i = 0; i < range; ++i){
if(!newarray[i])
printf("%d is missing!\n",min+i);
}
free(newarray);
}
int main(){
int test[] = {1,3,6};
find3missing(test,sizeof(test)/sizeof(int),1,6);
return 0;
}
Please note that this solution is very inefficient if your array is sorted. In this case have a look at Jimmy Gustafsson's answer.
This algoritm will be quite simple, since you're using a sorted array. Simply check if the current value +1 equals the nextvalue like below:
find3missing(){
int array[arraySize]; // the array with integers
for(i=0;i<arraySize;i++)
if(array[i]+1 != array[i+1]) // if value array[i]+1 is not equal the next index
// value, then it's a missing number
printf("A missing number: %i", i+1);
}