Absurd condition in Longest Increasing Subquence - c

/* A Naive recursive implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>
/* To make use of recursive calls, this function must return two things:
1) Length of LIS ending with element arr[n-1]. We use max_ending_here
for this purpose
2) Overall maximum as the LIS may end with an element before arr[n-1]
max_ref is used this purpose.
The value of LIS of full array of size n is stored in *max_ref which is our final result
*/
int _lis( int arr[], int n, int *max_ref)
{
/* Base case */
if(n == 1)
return 1;
int res, max_ending_here = 1; // length of LIS ending with arr[n-1]
/* Recursively get all LIS ending with arr[0], arr[1] ... ar[n-2]. If
arr[i-1] is smaller than arr[n-1], and max ending with arr[n-1] needs
to be updated, then update it */
for(int i = 1; i < n; i++)
{
res = _lis(arr, i, max_ref);
if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
max_ending_here = res + 1;
}
// Compare max_ending_here with the overall max. And update the
// overall max if needed
if (*max_ref < max_ending_here)
*max_ref = max_ending_here;
// Return length of LIS ending with arr[n-1]
return max_ending_here;
}
// The wrapper function for _lis()
int lis(int arr[], int n)
{
// The max variable holds the result
int max = 1;
// The function _lis() stores its result in max
_lis( arr, n, &max );
// returns max
return max;
}
/* Driver program to test above function */
int main()
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of LIS is %d\n", lis( arr, n ));
getchar();
return 0;
Let arr[0..n-1] be the input array and L(i) be the length of the LIS till index i such that arr[i] is part of LIS and arr[i] is the last element in LIS, then L(i) can be recursively written as.
L(i) = { 1 + Max ( L(j) ) } where j < i and arr[j] < arr[i] and if there is no such j then L(i) = 1.
In the above implementation , i am not able to understand the use/importance of the condition if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here). It's doesn't even looks like the recursive formula , then why is it needed.When L(i)/*is just*/ = { 1 + Max ( L(j) ) } where j < i and arr[j] < arr[i] and if there is no such j then L(i) = 1 thenwhy do we need to compare arr[i-1] < arr[n-1]. Is it possible to come with a recursive solution which is similar to the recursive formula?

LIS: Here's a simple solution following the definition of LIS.
Assuming A is the input array of numbers, N is the size of A.
int L[51];
int res=-1;
for(int i=0;i<N;i++)
{
L[i]=1;
for(int j=0;j<i;j++)
if(A[j]<A[i])
{
L[i]=max(L[i],L[j]+1);
}
res=max(res,L[i]);
}
return res;
Time Complexity: O(N2).

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 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

Minimum sum of two elements from two arrays such that indices are not same

Given two arrays ar1 and ar2, how can we find sum of two elements from two arrays such that indices are not same and their sum is minimum?
However, I have written the following, but I am not sure regarding storing the sum in a temporary variable and comparing the sum with the sum in the immediately next pass:
int twinArrays(int ar1_size, int* ar1, int ar2_size, int* ar2)
{
int temp;
for(int i = 0; i < ar1_size;i++)
{
for(int j=0; j < ar2_size; j++) {
int sum=0;
if( i != j)
sum = ar1[i] + ar2[j];
}
}
return temp;
}
}
Suggestions in C would be helpful.
The minimal sum of 2 elements from 2 arrays is the sum of its minimum elements.
But, what happens when any of the arrays is 0 size...? The formulation of the question is undefined in this regard.
The following worst-case time complexity is O(N) and worst-case space complexity is O(1):
#include <limits.h>
int twinArrays(int ar1_size, int* ar1, int ar2_size, int* ar2)
{
int min1 = INT_MAX, min2 = INT_MAX;
for(int i = 0; i < ar1_size; i++)
min1 = ar1[i] < min1? ar[1]: min1;
for(int i = 0; i < ar2_size; i++)
min2 = ar2[i] < min2? ar2[1]: min2;
if (min1 > 0 && min2 > INT_MAX - min1) {
/* handle overflow */
return INT_MAX;
} else if (min1 < 0 && min2 < INT_MIN - min1) {
/* handle underflow */
return INT_MIN;
}
return min1 + min2;
}
Your code was not so far of one solution, but:
temp should have been initialized to value big enough to be under the wanted result,
when i != j, you should have compared sum to temp to store the result if sum was under temp,
return was miss placed.
So your corrected code could looks like:
#include <limits.h>
int twinArrays(int ar1_size, int* ar1, int ar2_size, int* ar2)
{
int sum_min = INT_MAX;
/* for each element in ar1 */
for (int i = 0; i < ar1_size; i++)
{
/* for each element in ar2 */
for (int j = 0; j < ar2_size; t++)
{
/* go to next j if indices are the same */
if (i != j)
{
/* compute sum */
int sum = ar1[i] + ar2[j];
/* compare to best */
if (sum < sum_min)
{
/* remember the best */
sum_min = sum;
}
}
}
}
return sum_min;
}

I need help creating a k-combinations algorithm non-recursively

I've looked around online for an non-recursive k-combinations algorithm, but have had trouble understanding all of the reindexing involved; The code I've found online is not commented well, or crashes.
For example, if I have the collection, {'a', 'b', 'c', 'd', 'e'} and I want to find a 3 combinations; ie,
abc
abd
abe
acd
ace
ade
bcd
bce
bde
cde
How can I implement an algorithm to do this? When I write down the general procedure, this it is clear. That is; I increment the last element in a pointer until it points to 'e', increment the second to last element and set the last element to the second to last element + 1, then increment the last element again until it reaches 'e' again, and so on and so forth, as illustrated by how I printed the combinations. I looked at Algorithm to return all combinations of k elements from n for inspiration, but my code only prints 'abc'. Here is a copy of it:
#include <stdio.h>
#include <stdlib.h>
static void
comb(char *buf, int n, int m)
{
// Initialize a pointer representing the combinations
char *ptr = malloc(sizeof(char) * m);
int i, j, k;
for (i = 0; i < m; i++) ptr[i] = buf[i];
while (1) {
printf("%s\n", ptr);
j = m - 1;
i = 1;
// flag used to denote that the end substring is at it's max and
// the j-th indice must be incremented and all indices above it must
// be reset.
int iter_down = 0;
while((j >= 0) && !iter_down) {
//
if (ptr[j] < (n - i) ) {
iter_down = 1;
ptr[j]++;
for (k = j + 1; k < m; k++) {
ptr[k] = ptr[j] + (k - j);
}
}
else {
j--;
i++;
}
}
if (!iter_down) break;
}
}
int
main(void)
{
char *buf = "abcde";
comb(buf, 5, 3);
return 1;
}
The very big problem with your code is mixing up indices and values. You have an array of chars, but then you try to increment the chars as if they were indices into the buffer. What you really need is an array of indices. The array of chars can be discarded, since the indices provide all you need, or you can keep the array of chars separately.
I found a psuedocode description here, http://www4.uwsp.edu/math/nwodarz/Math209Files/209-0809F-L10-Section06_03-AlgorithmsForGeneratingPermutationsAndCombinations-Notes.pdf
and implemented it in C by
#include <stdlib.h>
#include <stdio.h>
// Prints an array of integers
static void
print_comb(int *val, int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d ", val[i]);
}
printf("\n");
}
// Calculates n choose k
static int
choose(int n, int k)
{
double i, l = 1.0;
double val = 1.0;
for (i = 1.0; i <= k; i++) {
l = ((double)n + 1 - i) / i;
val *= l;
}
return (int) val;
}
static void
comb(int n, int r)
{
int i, j, m, max_val;
int s[r];
// Initialize combinations
for (i = 0; i < r; i++) {
s[i] = i;
}
print_comb(s, r);
// Iterate over the remaining space
for (i = 1; i < choose(n, r); i++) {
// use for indexing the rightmost element which is not at maximum value
m = r - 1;
// use as the maximum value at an index, specified by m
max_val = n - 1; // use for
while(s[m] == max_val) {
m--;
max_val--;
}
// increment the index which is not at it's maximum value
s[m]++;
// iterate over the elements after m increasing their value recursively
// ie if the m-th element is incremented, all elements afterwards are
// incremented by one plus it's offset from m
// For example, this is responsible for switching 0 3 4 to 1 2 3 in
// comb(5, 3) since 3 and 4 in the first combination are at their maximum
// value
for (j = m; j < r - 1; j++) {
s[j + 1] = s[j] + 1;
}
print_comb(s, r);
}
}
int
main(void)
{
comb(5, 3);
return 1;
}

Strange C function - What is this function doing?

I encountred this function without any comment. I wonder what is this function doing? Any help?
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
What a fun problem!
Other posters are correct that it returns the index of a minimum, but it's actually more interesting than that.
If you treat the array as being circular (i.e. when you get past the end, go back to the beginning), the function returns the starting index of the minimum lexicographic subsequence.
If only one element is minimal, that element is returned. If multiple elements are minimal, we compare the next element along from each minimal element.
E.g. with an input of 10 and {0, 1, 2, 1, 1, 1, 0, 0, 1, 0}:
There are four minimal elements of 0, at indices 0, 6, 7 and 9
Of these two are followed by a 1 (the 0 and 7 elements), and two are followed by a 0 (the 6 and 9 elements). Remember that the array is circular.
0 is smaller than 1, so we only consider the 0s at 6 and 9.
Of these the sequence of 3 elements starting at 6 is '001' and the sequence from 9 is also '001', so they're still both equally minimal
Looking at the sequence of 4 elements, we have '0010' from element 6 onwards and '0012' from element 9 onwards. The sequence from 6 onwards is therefore smaller and 6 is returned. (I've checked that this is the case).
Refactored and commented code follows:
int findStartOfMinimumSubsequence(int length, char circular_array[])
{
#define AccessWithOffset(index) circular_array[(index + offset) % length]
int indicesStillConsidered[length], count_left = length, indicator[length], minIndex = 0;
for (int index = 0; index < length; index++)
{
indicesStillConsidered[index] = index;
indicator[index] = 1;
}
// Keep increasing the offset between pairs of minima, until we have eliminated all of
// them or only have one left.
for (int offset = 0; count_left >= 2; offset++)
{
// Find the index of the minimal value for the next term in the sequence,
// starting at each of the starting indicesStillConsidered
minIndex = indicesStillConsidered[0];
for (int i=0; i<count_left; i++)
minIndex = AccessWithOffset(indicesStillConsidered[i])<AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
minIndex;
// Ensure that indicator is 0 for indices that have a non-minimal next in sequence
// For minimal indicesStillConsidered[i], we make indicator 0 1+offset away from the index.
// This prevents a subsequence of the current sequence being considered, which is just an efficiency saving.
for (int i=0; i<count_left; i++){
offsetIndexToSet = AccessWithOffset(indicesStillConsidered[i])!=AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
(indicesStillConsidered[i]+offset+1)%length;
indicator[offsetIndexToSet] = 0;
}
// Copy the indices where indicator is true down to the start of the l array.
// Indicator being true means the index is a minimum and hasn't yet been eliminated.
for (int count_before=count_left, i=count_left=0; i<count_before; i++)
if (indicator[indicesStillConsidered[i]])
indicesStillConsidered[count_left++] = indicesStillConsidered[i];
}
return count_left == 1 ? indicesStillConsidered[0] : minIndex;
}
Sample uses
Hard to say, really. Contrived example: from a circular list of letters, this would return the index of the shortest subsequence that appears earlier in a dictionary than any other subsequence of the same length (assuming all the letters are lower case).
It returns the position of the smallest element within the substring of a ranging from element 0..n-1.
Test code
#include <stdio.h>
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
int main() {
printf(" test 1: %d\n", flr(4, "abcd"));
printf(" test 3: %d\n", flr(6, "10e-10"));
printf(" test 3: %d\n", flr(3, "zxyghab");
printf(" test 4: %d\n", flr(5, "bcaaa"));
printf(" test 5: %d\n", flr(7, "abcd"));
return 0;
}
This code gives following output:
[root#s1 sf]# ./a.out
test 1: 0
test 2: 3
test 3: 1
test 4: 2
test 5: 4
1. 0 is the position of `a` in the first case
2. 3 is the position of `-` in second case.
3. 1 is the position of `x` in third case.
4. 2 is the position of the second `a`.
5. 4 is the position of the `\0`
So the function returns the position of smallest element of a character pointer pointed by a and it will consider n elements. (Thats why it returned the position of x in the third case).
But when multiple smallest element available, it does not seems to be work in a predictable way, as it does not return the first occurrence, nor the last.
It should do a error checking for out of bound cases. Which may lead to problem in future.
so i'm running tests on this.
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
int main()
{
int in = 10;
char array[] = {0, 1, 1, 1, 1, 1, 0, 1, 1, 0};
int res = flr(in, array);
printf("expecting res to be 6;\tres = %d\n", res);
system("pause");
return 0;
}
output was res=9;

Resources