Adding two polynomials - c

I am trying to add two polynomial functions and store the answer into first one. So far I have this:
// co = coefficient, ex = exponent
void add_polynom(int co1[], int ex1[], int co2[], int ex2[])
{
int i, j;
for (i = 0; i < dataSize; i++)
{
for (j = 0; j < dataSize; j++)
{
if (ex1[i] == ex2[j])
{
co1[i] = co1[i] + co2[i];
co2[i] = 0;
}
}
}
}
Am I on the right track?

Your representation of polynomials is impractical:
you iterate in 2 nested loops (quadratic complexity) to try and match the corresponding terms of both polynomials, but if the second has a power that the first does not have, it will be missing in the sum.
you pass the degree as a global variable dataSize that may have an inappropriate value.
You should instead use an array of coefficients for all exponents from 0 to the degree of the polynomial and pass the destination polynomial and its degree this way:
/* add 2 polynomials into a destination array.
* count variables are the sizes of the arrays,
* ie 1 more than the degree of the polynomials.
* return the size of the resulting polynomial,
* potentially larger than the size of the destination array.
*/
int add_polynomials(int dest[], int dest_count,
const int co1[], int count1,
const int co2[], int count2) {
/* compute the result coefficients */
int i, count;
for (i = count = 0; i < dest_count; i++) {
int coef = 0;
if (i < count1)
coef += co1[i];
if (i < count2)
coef += co2[i];
dest[i] = coef;
if (coef != 0)
count = i + 1;
}
/* determine the result count */
for (; i < count1 && i < count2; i++) {
if (co1[i] + co2[i] != 0)
count = i + 1;
}
for (; i < count1; i++) {
if (co1[i] != 0)
count = i + 1;
}
for (; i < count2; i++) {
if (co2[i] != 0)
count = i + 1;
}
return count;
}
If you must use the given prototype and global definition for dataSize, you could use 2 nested loops indeed, but depending on how the exponents are used in both polynomials, it might be impossible to fit the result in the destination array:
the source polynomials can each have up to dataSize terms with any range of exponents. The resulting polynomial might have a total number of terms that exceeds dataSize and thus not representable in an array of size dataSize.
your code fails because you wrote co1[i] = co1[i] + co2[i]; instead of co1[i] = co1[i] + co2[j];, but you also modify co2[i], which is inappropriate and you miss the terms that are only present in co2/ex2.
If we can assume that the maximum exponent is less than dataSize, here is an efficient approach (linear time) that will generate a result in normalized form:
#define dataSize 50
// co = coefficients, ex = exponents
void add_polynom(int co1[], int ex1[], int co2[], int ex2[]) {
int res[dataSize] = { 0 };
int i, j;
for (i = 0; i < dataSize; i++) {
res[ex1[i]] += co1[i];
res[ex2[i]] += co2[i];
}
j = 0;
for (i = dataSize; i-- > 0;) {
if (res[i] != 0) {
co1[j] = res[i];
ex1[j] = i;
j++;
}
}
while (j < dataSize) {
co1[j] = ex1[j] = 0;
}
}

Take for example say 7x^3 + 2x + 1 as first and 5x^4 + 9x^2 as second polynomial. Now dataSize becomes 5(since higher degree of both is 4).
Now co1 would be {1, 2, 0, 7, 0} and co2 would be {0, 0, 9, 0, 5}.
for (i = 0; i < dataSize; i++)
{
co1[i] += co2[i];
}

Your interface is "suboptimal". It forces guarantees to to be made for it to work at all.
Use option 1 if you can guarantee that all values of exs1 and exs2 are in [0..(DATASIZE-1)].
Use option 2 if you can merely guarantee that there are fewer than DATASIZE different values in exs1 and exs2 combined.
Option 1
This solution's performance is bound by O(N).
#define DATASIZE 50
void panic(const char* msg) {
fprintf(stderr, msg);
exit(EXIT_FAILURE);
}
find_ex(ex,
// Assumes all values in exs1 are in [0..49].
// Assumes all values in exs2 are in [0..49].
void add_polynom(int cos1[], int exs1[], int cos2[], int exs2[]) {
int cos_sum[DATASIZE];
size_t i;
int exs1i, exs2i;
for (i=DATASIZE; i--; )
cos_sum[i] = 0;
for (i=DATASIZE; i--; ) {
if (exs1[i] < 0 || exs1[i] >= DATASIZE || exs2[i] < 0 || exs2[i] >= DATASIZE)
panic("add_polynom: Exponent out of range\n");
cos_sum[exs1[i]] += cos1[i];
cos_sum[exs2[i]] += cos2[i];
}
for (i=DATASIZE; i--; ) {
cos1[i] = cos_sum[i];
exs1[i] = i;
cos2[i] = 0;
/* exs2[i] = i; */
}
}
Option 2
This solution's performance is bound by O(N2). The bound can be reduced to O(N) by using an associative array instead of find_index_of_ex, but that's too much work for this answer.
#define DATASIZE 50
void panic(const char* msg) {
fprintf(stderr, msg);
exit(EXIT_FAILURE);
}
ssize_t find_index_of_ex(int ex, int cos[], int exs[], size_t size) {
ssize_t i;
for (i=0; i<size; ++i) {
if (exs[i] == ex) {
return i;
}
}
return -1;
}
// Assumes there are fewer than DATASIZE different values in exs1 and exs2 combined.
void add_polynom(int cos1[], int exs1[], int cos2[], int exs2[]) {
int cos_sum[];
int exs_sum[];
ssize_t lookup_is_by_ex[datasize];
size_t i, sum_count;
ssize_t i_sum;
for (i=DATASIZE; i--; ) {
cos_sum[i] = 0;
exs_sum[i] = 0;
}
sum_count = 0;
for (i=DATASIZE; i--; ) {
if (cos1[i] == 0)
continue;
i_sum = find_index_of_ex(exs1[i], exs_sum, sum_count);
if (i_sum >= 0)
cos_sum[i_sum] += cos1[i];
continue;
}
if (sum_count == DATASIZE)
panic("add_polynom: Too many different exponents\n");
cos_sum[sum_count] = cos1[i];
exs_sum[sum_count] = exs1[i];
++sum_count;
}
for (i=DATASIZE; i--; ) {
if (cos2[i] == 0)
continue;
i_sum = find_index_of_ex(exs2[i], exs_sum, sum_count);
if (i_sum >= 0)
cos_sum[i_sum] += cos2[i];
continue;
}
if (sum_count == DATASIZE)
panic("add_polynom: Too many different exponents\n");
cos_sum[sum_count] = cos2[i];
exs_sum[sum_count] = exs2[i];
++sum_count;
}
for (i=DATASIZE; i--; ) {
cos1[i] = cos_sum[i];
exs1[i] = exs_sum[i];
cos2[i] = 0;
/* exs2[i] = i; */
}
}

Related

dealing with dups in end of the array

This is the task I have got:
I need to write a function (not recursive) which has two parameters.
An array of integers.
An integer representing the size of the array.
The function will move the duplicates to an end of the array.
And will give the size of the different digits.
Example:
5 , 2 , 4 , 5 , 6 , 7 , 2, n = 7
we will get back 5 , 2 , 4 , 6 , 7 , 5 , 2 and 5
We must keep the original sort as it is (which means like in example 5 must)
It does not matter how we sort the duplicates ones but just keep the sort for the original array as it is)
The function has to print the number of different digits (like in example 5)
The the input range of numbers in array [-n,n]
I can only use 1 additional array for help.
It has to be O(n)
I tried it so many times and feel like am missing something. Would appreciate any advice/suggestions.
int moveDup(int* arr, int n)
{
int* C = (int*)calloc(n * 2 + 1, sizeof(int));
assert(C);
/*int* count = C + n;*/
int *D = arr[0];
int value = 0, count = 0;
for (int i = 0; i < n; i++)
{
value = arr[i];
if (C[value + n] == 0)
{
*D = arr[i];
D++;
count++;
}
C[value + n] = C[value + n] + 1;
}
while (1 < C[value + n])
{
*D = i;
D++;
C[value + n]--;
}
free(C);
return count;
}
This algorithm will produce the required results in O(n) arithmetic complexity:
Input is an array A with n elements indexed from A0 to An−1 inclusive. For each Ai, −n ≤ Ai ≤ n.
Create an array C that can be indexed from C−n to C+n, inclusive. Initialize C to all zeros.
Define a pointer D. Initialize D to point to A0.
For 0 ≤ i < n:
If CAi=0, copy Ai to where D points and advance D one element.
Increment CAi.
Set r to the number of elements D has been advanced from A0.
For −n ≤ i ≤ +n:
While 1 < CAi:
Copy i to where D points and advance D one element.
Decrement CAi.
Release C.
Return r. A contains the required values.
A sample implementation is:
#include <stdio.h>
#include <stdlib.h>
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int moveDuplicates(int Array[], int n)
{
int *memory = calloc(2*n+1, sizeof *Array);
if (!memory)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
int *count = memory + n;
int *destination = Array;
for (int i = 0; i < n; ++i)
// Count each element. If it is unique, move it to the front.
if (!count[Array[i]]++)
*destination++ = Array[i];
// Record how many unique elements were found.
int result = destination - Array;
// Append duplicates to back.
for (int i = -n; i <= n; ++i)
while (0 < --count[i])
*destination++ = i;
free(memory);
return result;
}
int main(void)
{
int Array[] = { 5, 2, 4, 5, 6, 7, 2 };
printf("There are %d different numbers.\n",
moveDuplicates(Array, NumberOf(Array)));
for (int i = 0; i < NumberOf(Array); ++i)
printf(" %d", Array[i]);
printf("\n");
}
here is the right answer, figured it out by myself.
int moveDup(int* arr, int n)
{
int* seen_before = (int*)calloc(n * 2 + 1, sizeof(int));
assert(seen_before);
int val = 0, count = 0, flag = 1;
int j = 0;
for (int i = 0; i < n; i++)
{
val = arr[i];
if (seen_before[arr[i] + n] == 0)
{
seen_before[arr[i] + n]++;
count++;
continue;
}
else if (flag)
{
j = i + 1;
flag = 0;
}
while (j < n)
{
if (seen_before[arr[j] + n] == 0)
{
count++;
seen_before[arr[j] + n]++;
swap(&arr[i], &arr[j]);
j++;
if (j == n)
{
free(seen_before);
return count;
}
break;
}
/*break;*/
j++;
if (j == n)
{
free(seen_before);
return count;
}
}
}
}
second right answer
int* mem = (int*)calloc(2 * n + 1, sizeof * arr);
assert(mem);
int* count = mem + n;
int* dest = arr;
for (i = 0; i < n; ++i)
{
if (count[arr[i]]++ == 0)
{
*dest = arr[i];
*dest++;
}
}
res = dest - arr;
for (i = -n; i <= n; ++i)
{
while (0 < --count[i])
{
*dest++ = i;
}
}
free(mem);
return res;

How to get all permutations in CBMC?

I am trying to get all permutations of an array in CBMC.
For small cases, e.g., [1,2,3], I suppose I can write
i1 = nondet()
i2 = nondet()
i3 = nondet()
assume (i > 0 && i < 4); ...
assume (i1 != i2 && i2 != i3 && i1 != i3);
// do stuffs with i1,i2,i3
But with larger elements, the code will be very messy.
So my question is that is there a better/general way to express this?
Building on Craig's suggestion of using an array, you could loop over the values you want to permute, and nodeterministically select a location that has not been taken. For example, a loop like this (where sequence is pre-initalized with -1 for all values).
for(int i = 1; i <= count; ++i) {
int nondet;
assume(nondet >= 0 && nondet < count);
// ensure we don't pick a spot already picked
assume(sequence[nondet] == -1);
sequence[nondet] = i;
}
So a full program would look something like this:
#include <assert.h>
#include <memory.h>
int sum(int *array, int count) {
int total = 0;
for(int i = 0; i < count; ++i) {
total += array[i];
}
return total;
}
int main(){
int count = 5; // 1, ..., 6
int *sequence = malloc(sizeof(int) * count);
// this isn't working - not sure why, but constant propagator should
// unroll the loop anyway
// memset(sequence, -1, count);
for(int i = 0; i < count; ++i) {
sequence[i] = -1;
}
assert(sum(sequence, count) == -1 * count);
for(int i = 1; i <= count; ++i) {
int nondet;
__CPROVER_assume(nondet >= 0);
__CPROVER_assume(nondet < count);
__CPROVER_assume(sequence[nondet] == -1); // ensure we don't pick a spot already picked
sequence[nondet] = i;
}
int total = (count * (count + 1)) / 2;
// verify this is a permuation
assert(sum(sequence, count) == total);
}
However, this is pretty slow for values >6 (though I haven't compared it against your approach - it doesn't get stuck unwinding, it gets stuck solving).

How do I fill an array with random numbers such that they are different?

I have a task where I have to fill an array with 16 random numbers, in random indexes.
4 of those elements have to be -1, and all the other left indexes have to be 0-15, but different from another, meaning it is impossible for two different indexes have the same number (0-15).
Filling 4 random indexes is easy, and so is filling the other indexes with random numbers between 0-15, but how do I feel them in such way that they are necessarily different from each other?
There are also two more conditions which complicate this task much more, the first one is that the number of the index cannot have the same number within it, meaning arr[3] == 3 is impossible, and another condition is that
(m[p] == j && m[j] == mp && m != j)
is something that we must take care of so it won't happen. For example, if arr[2] == 0 and arr[0] == 2, we have to change it so it won't happen.
I'm so confused, I had literally sat 8 hours yesterday in front of this, trying all sort of things, and I have no idea, honestly..
void FillArray(int *sites, int length)
{
int checkarr[N] = { 0 };
int i,
cnt = 0,
j = 0,
t = 0,
k,
times = 0;
int *p = sites;
while (cnt < C)
{
i = rand() % length;
if (p[i] - 1)
cnt = cnt;
p[i] = -1;
cnt++;
}
while (j < length)
{
if (p[j] == -1) j++;
else
{
p[j] = rand() % length;
checkarr[p[j]]++;
j++;
}
}
j =0;
while (j<length)
{
for (k=0; k<length;k++)
{
while (checkarr[k] > 1)
{
while (t < length)
{
if (p[j] == p[t] && p[j] != -1 && j != t)
{
checkarr[p[t]]--;
p[t] = rand() % length;
checkarr[p[t]]++;
times++;
}
else t++;
}
if (times < 11)
{
j++;
t = 0;
times = 0;
}
}
}
}
}
I tried using the Fisher-Yates shuffle method, but for somereason it doesn't even fill the array. I don't know why
while (j
if (p[j] == -1)
j++;
else {
while (m < length) {
m = rand() % length;
if (helpingArray[m] != -2)
{
p[j] = helpingArray[m];
helpingArray[m] = -2;
j++;
}
else if (helpingArray[m] == -2)
{
j = j;
}
for (w = 0; w < length; w++)
{
if (helpingArray[w] == -2)
count++;
}
if (count == 12) {
m = length;
}
}
}
}
}
I hope this will help, I tried to stay in the line with your first draft and what you were going for, just to note that this should work for an N length array. I changed the conditions on your second while to check the conditions before placing the value- and now you don't need to go over the set array and check and update the values.
you can also go another way as was commented here and just fill the array with values with help of one aux array to check each value is used only once and then randomly swap the indexes under the conditions.
I wrote this down but I didn't run tests- so make sure you understand whats going on and upgrade it to your needs. I do recommend using only one aux array, easy on memory and less whiles and checks.
GOOD LUCK
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 16
#define C 4
void FillArray(int *sites, int length) {
/*these aux arrays will keep track if an index was fill of if a value was used*/
int checkarrIndex[N] = { 0 };
int checkarrVal[N] = { 0 };
int i, cnt = 0, full=0; /*full is when all index are filled */
int *p = sites;
while (cnt < C) {
i = rand() % length;
if (checkarrIndex[i] == 0) /* checkarrIndex will let you know if an index has been gvin a value*/
{
++checkarrIndex[i]; /*now checkarrIndex[i] will be one so this index is now not valid for placement next time*/
p[i] = -1;
++full;/*at the end of this while full will equal 4*/
cnt++;
}
}
while (full < length) /*here you need to draw a random index and a random value for it,
not just a random value for a fixed index like you did, if I got this wrong just
go over the free indexes and place a rand value one at a time in the same manner*/
{
int index; /*will store new random index */
int value; /*will store new random value */
index = rand() % N;
value = rand() % N;/*max value is 15*/
while(checkarrIndex[index]!= 0) /*check if this index was already placed */
{
index = rand() % N; /*try a another one */
}
/*I made this while loop to check all the con before filling the array */
while(checkarrVal[value]!= 0 || p[value]== index || index == value) /*check if this value was already used or if p[i]=j&&p[j]=i cond happens and make sure p[a] != a*/
{
value = rand() % N; /*try a another one */
}
++checkarrIndex[index];/*set index as used */
++checkarrVal[value];/*set value as used */
p[index] = value;
++full; /*another place was filled */
}
}
static void PrintArray(int* arr, size_t size)
{
int i = 0 ;
for (i = 0 ; i< size; ++i)
{
printf("%d| ", arr[i]);
}
printf("\n");
}
int main(void)
{
int array[N] = {0};
FillArray(array, N);
PrintArray(array, N);
return 0;
}
I'm not completely sure, but I think the following meets all your special constraints [hopefully].
The random list function is a variation on Fisher Yates. You could recode it to use Durstenfeld if you wish.
I'm not sure that the constraints can be done cleanly in a single pass. That is, apply them while generating the random list.
What I've done is to generate a simple random list. Then, try to detect/fix (by swapping) some of the constraint violations.
Then, fill with negative values, trying to fix the self constraint violations if possible.
If that can't be done, repeat the whole process.
Anyway, here is my version. I split up the large function into several smaller ones. I also added a check function and a diagnostic loop. It is quite a bit different from yours, but other answers did this as well:
#include <stdio.h>
#include <stdlib.h>
#define NEG 4
int opt_N;
int opt_v;
int opt_T;
#ifdef DEBUG
#define dbg(_fmt...) \
do { \
if (opt_v) \
printf(_fmt); \
} while (0)
#else
#define dbg(_fmt...) /**/
#endif
// prtarray -- print array
void
prtarray(int *arr,int len)
{
int idx;
int val;
int hangflg = 0;
int cnt = 0;
for (idx = 0; idx < len; ++idx) {
val = arr[idx];
if (val < 0)
printf(" [%2.2d]=%d",idx,val);
else
printf(" [%2.2d]=%2.2d",idx,val);
hangflg = 1;
if (++cnt >= 8) {
printf("\n");
cnt = 0;
hangflg = 0;
continue;
}
}
if (hangflg)
printf("\n");
}
// fillrand -- generate randomized list (fisher yates?)
void
fillrand(int *arr,int len)
{
char idxused[len];
char valused[len];
int fillcnt = 0;
int idx;
int val;
for (idx = 0; idx < len; ++idx) {
idxused[idx] = 0;
valused[idx] = 0;
}
for (fillcnt = 0; fillcnt < len; ++fillcnt) {
// get random index
while (1) {
idx = rand() % len;
if (! idxused[idx]) {
idxused[idx] = 1;
break;
}
}
// get random value
while (1) {
val = rand() % len;
if (! valused[val]) {
valused[val] = 1;
break;
}
}
arr[idx] = val;
}
}
// swap2 -- swap elements that are (e.g.) arr[i] == arr[arr[i]])
int
swap2(int *arr,int len)
{
int idx;
int lhs;
int rhs;
int swapflg = 0;
dbg("swap2: ENTER\n");
for (idx = 0; idx < len; ++idx) {
lhs = arr[idx];
rhs = arr[lhs];
// don't swap self -- we handle that later (in negfill)
if (lhs == idx)
continue;
if (rhs == idx) {
dbg("swap2: SWAP idx=%d lhs=%d rhs=%d\n",idx,lhs,rhs);
arr[idx] = rhs;
arr[lhs] = lhs;
swapflg = 1;
}
}
dbg("swap2: EXIT swapflg=%d\n",swapflg);
return swapflg;
}
// negfill -- scan for values that match index and do -1 replacement
int
negfill(int *arr,int len)
{
int idx;
int val;
int negcnt = NEG;
dbg("negfill: ENTER\n");
// look for cells where value matches index (e.g. arr[2] == 2)
for (idx = 0; idx < len; ++idx) {
val = arr[idx];
if (val != idx)
continue;
if (--negcnt < 0)
continue;
// fill the bad cell with -1
dbg("negfill: NEGFIX idx=%d val=%d\n",idx,val);
arr[idx] = -1;
}
// fill remaining values with -1
for (; negcnt > 0; --negcnt) {
while (1) {
idx = rand() % len;
val = arr[idx];
if (val >= 0)
break;
}
dbg("negfill: NEGFILL idx=%d\n",idx);
arr[idx] = -1;
}
dbg("negfill: EXIT negcnt=%d\n",negcnt);
return (negcnt >= 0);
}
// fillarray -- fill array satisfying all contraints
void
fillarray(int *arr,int len)
{
while (1) {
// get randomized list
fillrand(arr,len);
if (opt_v)
prtarray(arr,len);
// swap elements that are (e.g. arr[i] == arr[arr[i]])
while (1) {
if (! swap2(arr,len))
break;
}
// look for self referential values and do -1 fill -- stop on success
if (negfill(arr,len))
break;
}
}
// checkarray -- check for contraint violations
// RETURNS: 0=okay
int
checkarray(int *arr,int len)
{
int idx;
int lhs;
int rhs;
int negcnt = 0;
int swapflg = 0;
dbg("checkarray: ENTER\n");
if (opt_v)
prtarray(arr,len);
for (idx = 0; idx < len; ++idx) {
lhs = arr[idx];
if (lhs < 0) {
++negcnt;
continue;
}
rhs = arr[lhs];
if (rhs == idx) {
printf("checkarray: PAIR idx=%d lhs=%d rhs=%d\n",idx,lhs,rhs);
swapflg = 2;
}
if (lhs == idx) {
printf("checkarray: SELF idx=%d lhs=%d\n",idx,lhs);
swapflg = 1;
}
}
if (negcnt != NEG) {
printf("checkarray: NEGCNT negcnt=%d\n",negcnt);
swapflg = 3;
}
dbg("checkarray: EXIT swapflg=%d\n",swapflg);
return swapflg;
}
int
main(int argc,char **argv)
{
char *cp;
int *arr;
--argc;
++argv;
opt_T = 100;
opt_N = 16;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'N':
opt_N = (cp[2] != 0) ? atoi(cp + 2) : 32;
break;
case 'T':
opt_T = (cp[2] != 0) ? atoi(cp + 2) : 10000;
break;
case 'v':
opt_v = ! opt_v;
break;
}
}
arr = malloc(sizeof(int) * opt_N);
for (int tstno = 1; tstno <= opt_T; ++tstno) {
printf("\n");
printf("tstno: %d\n",tstno);
fillarray(arr,opt_N);
if (checkarray(arr,opt_N))
break;
prtarray(arr,opt_N);
}
free(arr);
return 0;
}
My C is rusty, and I don't want to implement a Fisher-Yates shuffle or deal with the bad behavior of C PRNGs, so I'm expressing the algorithm in pseudo-code. Okay, I lie. It's Ruby, but it reads like pseudo-code and is heavily commented to show the logic of the solution. Consider the comments to be the solution, and the stuff in between a concrete illustration that the algorithm being described actually works.
N = 16
# Create + populate an array containing 0,...,N-1
ary = Array.new(N) { |i| i }
# Shuffle it
ary.shuffle!
# Iterate through the array. If any value equals its index, swap it with
# the value at the next index, unless it's the last array element
ary.each_index { |i| ary[i], ary[i + 1] = ary[i + 1], ary[i] if ary.length - i > 1 && ary[i] == i }
# If the last element equals its index, swap it with any other element
# selected at random. The rand function generates a random integer
# between 0, inclusive, and its argument, exclusive.
last = ary.length - 1
if ary[last] == last
random_index = rand(last)
ary[last], ary[random_index] = ary[random_index], ary[last]
end
# Replace 4 randomly selected entries with -1
4.times { ary[rand(ary.length)] = -1 }
# The array now contains unique elements (except for the -1's),
# none of which are equal to their index value
p ary
# Produces, e.g.: [4, 10, -1, 5, 9, -1, 15, 14, 7, 8, 12, 1, -1, 0, -1, 2]
All of this takes O(N) work. If your last constraint is violated, reject the solution and retry.
I believe the following generates a solution to the constraints with uniform distribution over all the solutions that satisfy the constraints:
Put the numbers 0 to 15 in pool A.
Put the numbers 0 to 15 in pool B.
12 times, draw a number a from pool A and a number b from pool B (in each case drawing randomly with uniform distribution and removing the drawn number from its pool, so it will not be chosen again later). Assign m[a] = b.
For each of the four numbers a remaining in pool A, assign m[a] = -1.
For all i from 0 to 15 (inclusive) and all j from i to 15 (inclusive), test whether m[i] == j && m[j] == i (note that this tests for both swaps and for m[i] == i, as it includes i == j). If such a case is found, reject the assignments and repeat the algorithm from the beginning.
I expect algorithmic improvements are possible to reduce or eliminate the frequency of rejection, but this establishes a baseline correct algorithm.
It is also possible to use a single pool instead of two and instead do some rearranging when the −1 elements are assigned, but the algorithm above is more easily expressed.
I am confused with your description. For placing N elements into N positions, I have a solution.
Question:
Place N elements into N positions with constraints:
(1) arr[i] != i;
(2) if arr[i] = j, then arr[j] != i
Solution:
For current element i (0 <= i < N)
(1) Find candidate position count
(a) count = N - i
(b) if arr[i] is empty => count -= 1
else if arr[arr[i]] is empty => count -= 1
(2) Select a random position from candidates
(a) relative_index = random() % count
(Note: relative_index means the position index in candidates)
(b) Find absolute_index by searching candidates
a candidate index j satisfies following constrains
<1> arr[j] is empy
<2> j != i
<3> j != arr[i] when arr[i] is not empty

Access Violation in C program involving pointer variable?

I was trying to solve Project Euler question 16 using c. I did not use bignnum libraries. The question asks 2^1000. I decided to store every digit of that number in an array.
For Example: 45 means arr[0]=4, arr[1]=5;
The problem is definitely i the function int multi.
#include<stdio.h>
#include<conio.h>
int multi(int *base, int k);// does the multiplication of array term by 2
void switcher();//switches every term when the fore mostvalue is >10
int finder();// finds the array address of last value
int arr[1000];
int summer();//sums all values of the array
int main()
{
arr[1000] = { 0 };
arr[0] = 1;
int i, j, sum, k, p;
for (i = 0; i < 1000; i++)
{
j = 0;
k = finder();
p = multi(arr + k, j);
}
sum = summer();
printf("sum of digits of 2^1000 is %d", sum);
_getch();
}
int multi(int *base, int k)
{
int p;
if (base == arr)
{
*base = *base - 1;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
switcher();
}
return 0;
}
*base = *base * 2;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
p = multi(base - 1, 1);
}
else
{
p = multi(base - 1, 0);
}
}
void switcher()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
j--;
for (; j > 0; j--)
{
arr[j + 1] = arr[j];
}
arr[0] = 1;
}
int finder()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
return --j;
}
int summer()
{
int summ, i;
summ = 0;
for (i = 0; i<1000; i++)
{
summ = summ + arr[i];
if (arr[i] == 0)
break;
}
return summ;
}
It compiles but during runtime it shows Access Write Violation, base was ......
Please explain this error and how to resolve it ?
Array is of 100 Bytes but you are looping for 1000. Also in function Finder() , you do not have a limit on variable j so your array size is going beyond 100 bytes.
Also use memset to assign array variables to 0.
As said in the comments, 2^1000 has 302 decimal digits.
You're going far outside your array.
But your code is very complicated because you store the digits with the most significant one first.
Since you're only interested in the digits and not the order in which they would be written, you can store the number "in reverse", with the least significant digit first.
This makes the code much simpler, as you can loop "forwards" and no longer need to shuffle array elements around.
Using -1 as "end of number" marker, it might look like this:
void twice(int* digits)
{
int i = 0;
int carry = 0;
while (digits[i] >= 0)
{
digits[i] *= 2;
digits[i] += carry;
if (digits[i] >= 10)
{
carry = 1;
digits[i] -= 10;
}
else
{
carry = 0;
}
i++;
}
if (carry)
{
digits[i] = 1;
digits[i+1] = -1;
}
}
int main()
{
int digits[302] = {1, -1}; /* Start with 1 */
twice(digits); /* digits is now { 2, -1 } */
return 0;
}

Enumerating Permutations of a set of subsets

I have sets S1 = {s11,s12,s13), S2 = {s21,s22,s23) and so on till SN.I need to generate all the permutations consisting elements of S1,S2..SN.. such that there is only 1 element from each of the sets.
For eg:
S1 = {a,b,c}
S2 = {d,e,f}
S3 = {g,h,i}
My permuations would be:
{a,d,g}, {a,d,h}, {a,d,i}, {a,e,g}, {a,e,h}....
How would I go about doing it? (I could randomly go about picking up 1 from each and merging them, but that is even in my knowledge a bad idea).
For the sake of generality assume that there are 'n' elements in each set. I am looking at implementing it in C. Please note that 'N' and 'n' is not fixed.
It's just a matter of recursion. Let's assume these definitions.
const int MAXE = 1000, MAXN = 1000;
int N; // number of sets.
int num[MAXN]; // number of elements of each set.
int set[MAXN][MAXE]; // elements of each set. i-th set has elements from
// set[i][0] until set[i][num[i]-1].
int result[MAXN]; // temporary array to hold each permutation.
The function is
void permute(int i)
{
if (i == N)
{
for (int j = 0; j < N; j++)
printf("%d%c", result[j], j==N-1 ? '\n' : ' ');
}
else
{
for (int j = 0; j < num[i]; j++)
{
result[i] = set[i][j];
permute(i+1);
}
}
}
To generate the permutations, simply call permute(0);
If you know exactly how many sets there are and it's a small number one might normally do this with nested loops. If the number of sets is greater than 2 or 3, or it is variable, then a recursive algorithm starts to make sense.
And if this is homework, it's likely that implementing a recursive algorithm is the object of the entire assignment. Think about it, for each set, you can call the enumeration function recursively and have it start enumerating the next set...
If they are in a container, just iterate through each:
#include <stdio.h>
int main(void)
{
int set1[] = {1, 2, 3};
int set2[] = {4, 5, 6};
int set3[] = {7, 8, 9};
for (unsigned i = 0; i < 3; ++i)
{
for (unsigned j = 0; j < 3; ++j)
{
for (unsigned k = 0; k < 3; ++k)
{
printf("(%d, %d, %d)", set1[i], set2[j], set3[k]);
}
}
}
return 0;
}
Generic solution:
typedef struct sett
{
int* nums;
int size;
} t_set;
inline void swap(t_set *set, int a, int b)
{
int tmp = set->nums[a];
set->nums[a] = set->nums[b];
set->nums[b] = tmp;
}
void permute_set(t_set *set, int from, void func(t_set *))
{
int i;
if (from == set->size - 1) {
func(set);
return;
}
for (i = from; i < set->size; i++) {
swap(set, from, i);
permute_set(set, from + 1, func);
swap(set, i, from);
}
}
t_set* create_set(int size)
{
t_set *set = (t_set*) calloc(1, sizeof(t_set));
int i;
set->size = size;
set->nums = (int*) calloc(set->size, sizeof(int));
for(i = 0; i < set->size; i++)
set->nums[i] = i + 1;
return set;
}
void print_set(t_set *set) {
int i;
if (set) {
for (i = 0; i < set->size; i++)
printf("%d ", set->nums[i]);
printf("\n");
}
}
int main(int argc, char **argv)
{
t_set *set = create_set(4);
permute_set(set, 0, print_set);
}
This is a fairly simple iterative implementation which you should be able to adapt as necessary:
#define SETSIZE 3
#define NSETS 4
void permute(void)
{
char setofsets[NSETS][SETSIZE] = {
{ 'a', 'b', 'c'},
{ 'd', 'e', 'f'},
{ 'g', 'h', 'i'},
{ 'j', 'k', 'l'}};
char result[NSETS + 1];
int i[NSETS]; /* loop indexes, one for each set */
int j;
/* intialise loop indexes */
for (j = 0; j < NSETS; j++)
i[j] = 0;
do {
/* Construct permutation as string */
for (j = 0; j < NSETS; j++)
result[j] = setofsets[j][i[j]];
result[NSETS] = '\0';
printf("%s\n", result);
/* Increment indexes, starting from last set */
j = NSETS;
do {
j--;
i[j] = (i[j] + 1) % SETSIZE;
} while (i[j] == 0 && j > 0);
} while (j > 0 || i[j] != 0);
}
You may think about the elements of a set as values of a cycle counter. 3 sets means 3 for cycles (as in GMan answare), N sets means N (emulated) cycles:
#include <stdlib.h>
#include <stdio.h>
int set[3][2] = { {1,2}, {3,4}, {5,6} };
void print_set( int *ndx, int num_rows ){
for( int i=0; i<num_rows; i++ ) printf("%i ", set[i][ndx[i]] );
puts("");
}
int main(){
int num_cols = sizeof(set[0])/sizeof(set[0][0]);
int num_rows = sizeof(set)/sizeof(set[0]);
int *ndx = malloc( num_rows * sizeof(*ndx) );
int i=0; ndx[i] = -1;
do{
ndx[i]++; while( ++i<num_rows ) ndx[i]=0;
print_set( ndx, num_rows );
while( --i>=0 && ndx[i]>=num_cols-1 );
}while( i>=0 );
}
The most efficient method I could come up with (in C#):
string[] sets = new string[] { "abc", "def", "gh" };
int count = 1;
foreach (string set in sets)
{
count *= set.Length;
}
for (int i = 0; i < count; ++i)
{
var prev = count;
foreach (string set in sets)
{
prev = prev / set.Length;
Console.Write(set[(i / prev) % set.Length]);
Console.Write(" ");
}
Console.WriteLine();
}

Resources