Assigning through random generated indexes - c

I'm trying to write a function that assign N elements to M players. Here's what I wrote:
void assignElements(Player *p, Tab *t, int n) {
int i = 0, nRand, flagElements = 0;
do {
do {
nRand = MINRANDT + rand() % (MAXRANDT - MINRANDT + 1);
} while(t[nRand].type != Terrain && t[nRand].idProp != -1);
if (i == n) {
i = 0; //this makes "i" reset when it reaches the number of players
}
t[nRand].idProp = i;
p[i].numTerrains++;
i++;
flagElements++;
} while (flagElements != NELEMENTS);
}
So, if I try to run this function, it's not respecting the condition of the second while (maybe the problem is the condition.): in fact, it also assign to t elements that are not of type Terrain (this is an enum). The condition to do the actions under the nRand do / while, is that nRand have to be an index of a t element that is of type Terrain, and that its idProp is -1 (this mean it has not been assigned yet). Hope anyone can help. :)

t[nRand].type != Terrain | t[nRand].idProp != -1 | &&
-------------------------+-----------------------+---
0 | 0 | 0
0 | 1 | 0
1 | 0 | 0
1 | 1 | 1
Meaning that the loop will exit for 3 conditions and repeat only when both sub-conditions are met
Try ||
t[nRand].type != Terrain | t[nRand].idProp != -1 | ||
-------------------------+-----------------------+---
0 | 0 | 0
0 | 1 | 1
1 | 0 | 1
1 | 1 | 1

Related

efficient way to count adjacent empty points of a connected group on a grid

A connected group means a set of vertices of equal values on a grid being adjacent horizontally or vertically.
For example, on this grid where . is an empty point, there are 4 connected groups.
X O O . X O O
. X O X -> X O X
X X O X X X O X
You can also see that each group has 1 connected empty point.
I'm trying to count the number of these connected empty points given a grid and the coordinates that point to a vertex of a group.
If the input is,
. . X X X O O .
X X . X . X O X
. X X X X X O X
X X . O O X . X
(0, 2)
The output should be 7 because the big group including the vertex at (0, 2) (row, column) has 7 connected empty points.
If you are familiar of the game of Go (baduk), connected empty point is in other words liberty. This operation is the core of a routine analyzing a position in Go, and it has to be done fast.
Below is my try. It's terribly inefficient in many ways involving a lot of branches and recursion. I'm tracking the 4 possible directions and incrementing the count whenever there's an empty space, and put a mark on the vertex at which the counting has been done to not count twice.
Could you shed some light on how to efficiently solve this problem?
General algorithmic improvement and x86-AVX2-specific optimizations are both welcome.
typedef __attribute__((vector_size(32))) char vec8_c;
enum {H = 4, W = 8};
static int count_();
static int count__();
static int count(vec8_c x, int i, int j) {
vec8_c m = {0};
return count_((char *)&x, (char *)&m, i, j, i * W + j);
}
static int count_(char *x, char *m, int i, int j, int idx) {
m[idx] = 1;
int r = 0;
if (j - 1 >= 0) {
r += count__(x, m, i, j - 1, idx - 1, idx);
}
if (j + 1 < W) {
r += count__(x, m, i, j + 1, idx + 1, idx);
}
if (i - 1 >= 0) {
r += count__(x, m, i - 1, j, idx - W, idx);
}
if (i + 1 < H) {
r += count__(x, m, i + 1, j, idx + W, idx);
}
return r;
}
static int count__(char *x, char *m, int i, int j, int idx, int idx_) {
if (!m[idx]) {
if (!x[idx]) {
m[idx] = 1;
return 1;
} else if (x[idx] == x[idx_]) {
return count_(x, m, i, j, idx);
}
}
return 0;
}
Run online.
From the description I would convert the problem into intersection/union;
Make a mask C from the connected component
Make a mask E from the empty pixels
Make a larger mask M by concatenating the shifted version of C
M = C<<1 | C^^1 | C >> 1 | C^^-1
return PopCount(M & E)
This approach should easily vectorize and even autovectorize.
When C is large enough, use SIMD registers to work in blocks of 16x8, where each bit represents a boolean in the mask. One can then shift a whole block up/down by alignr / left/right with _mm_slli_epi16/_mm_srli_epi16 or their equivalents in AVX2/-512, where unfortunately the cross bank shifting is a bit costly.
For the specific inputs:
. . X X X O O . -> C = 0 0 1 1 1 0 0 0 E = 1 1 0 0 0 0 0 1
X X . X . X O X 1 1 0 1 0 1 0 0 0 0 1 0 1 0 0 0
. X X X X X O X 0 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0
X X . O O X . X 1 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0
Then the mask M would be the union of C shifted to left,right,up,down
M = 0 0 0 1 1 1 0 0 0 0
0 |1 1 1 1 1 1 0 0| 0 <-- you only need the
1 |1 1 1 1 1 1 1 0| 0 inner / 'valid' area
0 |1 1 1 1 1 1 1 0| 0
1 |1 1 1 1 1 1 1 0| 0
0 1 1 0 0 0 1 0 0 0
M.*E = 1 1 0 0 0 0 0 0
0 0 1 0 1 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 1 0, sum == 7

Creating a diagonal matrix

This is the code I currently have:
forv i = 1/10 {
set obs 10
gen x`i' = (_n-1)*10+`i'
}
How can I make it into a diagonal matrix so that entries are 0 whenever row ad column indexes are not equal?
This is the code I tried but did not work:
forv i=1/10 {
set obs 10
gen x`i' = (_n-1)*10+`i'
foreach j of varlist x1-x10 {
if _n ~= "`i'"
replace `j' = 0
}
}
Your first code block is legal (assuming no more than 10 observations in memory) but doesn't produce any thing close to a diagonal matrix. The command set obs 10 should be executed once before the loop, not every time around the loop.
There are several errors in your inner loop in your second code block, but I won't spell them out. You're guessing wildly, not the way to write code!
You can get a diagonal matrix directly in Stata like this:
. matrix whatever = 7 * I(5)
. matrix list whatever
symmetric whatever[5,5]
c1 c2 c3 c4 c5
r1 7
r2 0 7
r3 0 0 7
r4 0 0 0 7
r5 0 0 0 0 7
If you have reason to hold that as variables, then use svmat. You could create such a matrix as values of several variables in a loop, but it would be somewhat perverse:
clear
set obs 5
forvalues j = 1/5 {
generate x`j' = 7 * (_n == `j')
}
list
+------------------------+
| x1 x2 x3 x4 x5 |
|------------------------|
1. | 7 0 0 0 0 |
2. | 0 7 0 0 0 |
3. | 0 0 7 0 0 |
4. | 0 0 0 7 0 |
5. | 0 0 0 0 7 |
+------------------------+
The solution by #NickCox is also applicable in mata - Stata's matrix programming language:
. mata: A = 7 * I(5)
. mata: A
[symmetric]
1 2 3 4 5
+---------------------+
1 | 7 |
2 | 0 7 |
3 | 0 0 7 |
4 | 0 0 0 7 |
5 | 0 0 0 0 7 |
+---------------------+
One can then get the matrix as variables with the getmata command:
. getmata (A*) = A
. list A*
+------------------------+
| A1 A2 A3 A4 A5 |
|------------------------|
1. | 7 0 0 0 0 |
2. | 0 7 0 0 0 |
3. | 0 0 7 0 0 |
4. | 0 0 0 7 0 |
5. | 0 0 0 0 7 |
+------------------------+

An Iteration for particular combinations on SAS

The table below lists each possibility for each variable 'A', 'B' and 'C', and the probability of that combination occurring. I already know all the probabilities.
Row # | A | B | C | Probability
============================================================
0 | ... | ... | ... | P0
------------------------------------------------------------
1 | ... | ... | ... | P1
------------------------------------------------------------
. | ... | . | . | .
------------------------------------------------------------
. | ... | . | . | .
------------------------------------------------------------
10 | ... | ... | ... | P10
------------------------------------------------------------
I would like to write an iteration within a combination of variables 'A', 'B' and 'C':
start from Row = 0, keep increasing
for Row = i.
If P(Row >= i) * 300 - P(Row < i) * 600 > 0
do
i = i+1;
until P(Row >= i) * 300 - P(Row < i) * 600 <= 0 or i =10.
It will stop and output i for a combination of 'A', 'B' and 'C'. And i is what I need for a combination of (A / B / C). Which is regarded as 'Threshold' in my problem.
How could I write this kind of code since there are many combinations of variables 'A', 'B' and 'C'.
Example:
When i = 0, P(Row >= 0) * 300 - P(Row < 0) * 600 = 1* 300 - 0* 600 = 300 > 0 Hence, i = 0+1 = 1
When i = 1, P(Row >= 1) * 300 - P(Row < 1) * 600 = 0.95* 300 - 0.05* 600 = 255 > 0 i = 1+1 = 2
When i = 2, P(Count >= 2) * 300 - P(Row < 2) * 600 = 0.85* 300 - 0.15* 600 = 165 > 0 i = 2+1 = 3
When i = 3, P(Row >= 3) * 300 - P(Row < 3) * 600 = 0.70* 300 - 0.30* 600 = 30 > 0 i = 3+1 = 4
When i = 4, P(Row >= 4) * 300 - P(Row < 4) * 600 = 0.50* 300 - 0.50* 600 = -150 < 0
we stop and output i =4 for this combination of 'A', 'B' and 'C'.
Thank you!
Observing that P(Row >= i) * 300 - P(Row < i) * 600 > 0 is the same as P(Row >= i) > 2 * P(Row < i), we simply sum P(Row<i) until it's greater than half of the current element.
double sum = 0;
auto it = data.begin();
while(it != data.end() && *it > 2*sum) {
sum += *it;
++it;
}

generate all possible combinations of array values in C

I have an array of N values from 0 to k (0 <= k <= N), I need to generate all possible combinations of N values
void generate(int n, int k) {
int q = -1;
char res = '|';
int r;
int j;
for (j = 1; j <= n; j++) {
q = j / (k + 1);
r = j % (k + 1);
printf("%d %c", r, res);
}
}
int main() {
int n = 2;
int k = 2;
int i, nbr_comb;
nbr_comb = pow((k + 1), n); number of combinations
for (i = 0; i < nbr_comb; i++) {
generate(n, i);
printf("\n");
}
return (EXIT_SUCCESS);
}
for this test (N=2 K=2) I had those combinations
0 |0 |
1 |0 |
1 |2 |
1 |2 |
1 |2 |
1 |2 |
1 |2 |
1 |2 |
1 |2 |
you see that it begins to generate but it fixed at a point, I can't find why ! ?
Expected Examples:
for n=2 k=2 n=3 k=2
0 0 0 0 0
0 1 0 0 1
0 2 0 0 2
1 0 1 0 0
1 1 1 0 1
1 2 1 0 2
2 0 1 1 0
2 1 1 1 1
2 2 1 1 2
1 2 0
1 2 1
1 2 2
2 0 0
.....
This is how your loops unfurl at n=2, k=2:
for (i=0; i<nbr_comb; i++)
i=0: generate(2,0) --> j=1: 1 mod 1 = 0
j=2: 2 mod 1 = 0
i=1: generate(2,1) --> j=1: 1 mod 2 = 1
j=2: 2 mod 2 = 0
i=2: generate(2,2) --> j=1: 1 mod 3 = 1
j=2: 2 mod 3 = 2
i=3: generate(2,3) --> j=1: 1 mod 4 = 1
j=2: 2 mod 4 = 2
i=4: generate(2,4) --> j=1: 1 mod 5 = 1
j=2: 2 mod 5 = 2
i=5: generate(2,5) --> j=1: 1 mod 6 = 1
j=2: 2 mod 6 = 2
i=6: generate(2,6) --> j=1: 1 mod 7 = 1
j=2: 2 mod 7 = 2
i=7: generate(2,7) --> j=1: 1 mod 8 = 1
j=2: 2 mod 8 = 2
i=8: generate(2,8) --> j=1: 1 mod 9 = 1
j=2: 2 mod 9 = 2
As you can see, your j for-loop in generate() just keeps calling modulo on j, the result of which will always be j once argument k is greater than j.
What you need is a nested for-loop that will take the current combination (range [0..(k+1)^n]) and the current array index (range [0..n-1]) into consideration when it decides which value to print from the set of [0..k].
If you think of the output as rows and columns, then in the right-most column, the value should change on each row, iterating from 0..k. In next column, the value should change every (k+1)th row. In next column, the value should change every (k+1)^2 row.
For example, when n = 3 and k = 2, then for the first 9 rows, the right-most column should look like 0,1,2,0,1,2,0,1,2. The middle column should look like 0,0,0,1,1,1,2,2,2. The left-most column should look like 0,0,0,0,0,0,0,0,0.
Thus, you end up with something like this:
int n = 2;
int k = 2;
int row, col;
int cell;
int rdiv;
int nbr_comb = pow(k+1, n);
for (row=0; row < nbr_comb; row++)
{
for (col=n-1; col>=0; col--)
{
rdiv = pow(k+1, col);
cell = (row/rdiv) % (k+1);
printf("%d |", cell);
}
printf("\n");
}

please explain the output

#include<stdio.h>
#include<conio.h>
int t=8;
int dok(int);
int doky(int);
int main()
{
int clrscr();
int x,y;
int s=2;
s*=3;
x=dok(s);
y=doky(s);
printf("%d%d%d",s,y,x);
getch();
return 0;
}
int dok(int a)
{
a+=-5;
t-=4;
return(a+t);
}
int doky(int a)
{
a=1;
t+=a;
return(a+t);
}
Answer to above code: 665
I understand why s=6, x=1+4=5 (a=6-5=1,t=8-4=4)... Please tell me how y comes as 6, I thought y would be 1+4=5 (a=1, t=4)
Thanks, please help me.
tell me how y comes as 6 ...
Call to dok function modifies t to 4.
int doky(int a)
{
a=1;
t+=a; // Previously t is 4 because of t-=4 in earlier function call
// t = 4+1 = 5
return(a+t); // 1+5 = 6 retured
}
first t increases by a and then sum of a and t is returned
so, t was 4. then operator t += a is executed and t becomes 5.
and a+t == 1+5 == 6 is returned
The value of t is changed to 4 with the dok function, and the doky function increments that value by 1 (the value in a). Sum that (5 so far) to the value of a again (set to 1), and that's 4+1+1 = 6.
//t is 4, the value of a is irrelevant since it changes on the next instruction.
a=1;
t+=a; // t is now 5
return(a+t); // 1+5 = 6
y = a + t = a + t + a = 1 + 4 + 1 = 6 :)
Just do it with pencil and paper ...
| t | x | y | s | a |
-----------------+---+---+---+---+---+
before main | 8 |#NA|#NA|#NA|#NA|
before x=dok(s) | 8 | ? | ? | 6 |#NA|
inside dok | 4 |#NA|#NA|#NA| 1 |
after dok | 4 | 5 | ? | 6 |#NA|
before y=doky(s) | 4 | 5 | ? | 6 |#NA|
inside doky | 5 |#NA|#NA|#NA| 1 |
after doky | 5 | 5 | 6 | 6 |#NA|

Resources