Reduce or make a function of the code below - c

I want to see if all surrounds of a cell in a 2d array are something , or do something with them.
if (mapmines[rndr][rndc] != 9) {
mapmines[rndr][rndc] = 9;
if (mapmines[rndr - 1][rndc - 1] != 9)
mapmines[rndr - 1][rndc - 1]++;
if (mapmines[rndr - 1][rndc] != 9)
mapmines[rndr - 1][rndc]++;
if (mapmines[rndr - 1][rndc + 1] != 9)
mapmines[rndr - 1][rndc + 1]++;
if (mapmines[rndr][rndc - 1] != 9)
mapmines[rndr][rndc - 1]++;
if (mapmines[rndr][rndc + 1] != 9)
mapmines[rndr][rndc + 1]++;
if (mapmines[rndr + 1][rndc - 1] != 9)
mapmines[rndr + 1][rndc - 1]++;
if (mapmines[rndr + 1][rndc] != 9)
mapmines[rndr + 1][rndc]++;
if (mapmines[rndr + 1][rndc + 1] != 9)
mapmines[rndr + 1][rndc + 1]++;
I have this similir code exept with diferent code between if
can i make a function or reduce? i feel like its posible .

if (mapmines[rndr][rndc] != 9)
{
// Do all elements in a 3x3 grid:
for (i = -1; i <= 1; ++i)
for (j = -1; j <= 1; ++j)
if (mapmines[rndr+i][rndc+j] != 9)
++mapmines[rndr+i][rndc+j];
/* Set the center element afterward so we do not care about the
loop above modifying it (gives brevity, not efficiency):
*/
mapmines[rndr][rndc] = 9;
}
That said, preferable code for this may be significantly affected by the context, including how frequently the condition occurs, interactions between the rows and columns, and more. There may be other data structures that are more useful. You would have to give more context.

Well, you could make it a bit smaller with a function like this:
void incrementIfNotNine(int *cell) {
if(*cell != 9) (*cell)++;
}
and then call it like this:
incrementIfNotNine(&mapmines[rndr - 1][rndc - 1]);
incrementIfNotNine(&mapmines[rndr - 1][rndc]);
incrementIfNotNine(&mapmines[rndr - 1][rndc + 1]);
...
You could also use loops, but for a 3x3 grid, it's hardly worth it.

Related

Rayon - how to apply values in parallel to all rows of a particular column and vice-versa

I have a simple for loop that I want to parallelize using Rayon in Rust. However I am stuck at applying the boundary conditions.
The loop in Rust is:
let mut u: Vec<Vec<f64>> = vec![vec!(10.0; x.len()); y.len()]; // Set initial condition = u(x,0) = 10
let mut u_new: Vec<Vec<f64>> = vec![vec!(0.0; x.len()); y.len()]; // Set initial condition = u_new(x,0) = 0
for t in 1..N_t - 1 {
for i in 1..N_x - 1 {
for j in 1..N_y - 1 {
u_new[i][j] = u[i][j]
+ (dt / (dx * dx)) * (u[i - 1][j] + u[i + 1][j] - 2.0 * u[i][j])
+ (dt / (dy * dy)) * (u[i][j - 1] + u[i][j + 1] - 2.0 * u[i][j]);
u_new[0][j] = 0.0;
u_new[N_x - 1][j] = 0.0;
u_new[i][0] = 0.0;
u[i][N_y - 1] = 0.0;
}
}
u = u_new.clone();
}
I managed to parallelize the loop in Rayon but not able to add the boundary conditions:
for t in 1..N_t - 1 {
u_new.par_iter_mut().enumerate().for_each(|(i, r)| {
if (i != 0) && (i != N_x - 1) {
for (j, c) in r.iter_mut().enumerate() {
if (j != 0) && (j != N_x - 1) {
*c = u[i][j]
+ (dt / (dx * dx)) * (u[i - 1][j] + u[i + 1][j] - 2.0 * u[i][j])
+ (dt / (dy * dy)) * (u[i][j - 1] + u[i][j + 1] - 2.0 * u[i][j]);
}
}
}
});
// TODO: add boundary conditions
u = u_new.clone();
}
I want to add the boundary conditions in parallel using Rayon parallel iteration. Any ideas please?

Negative numbers with modulo operator in 'De-Vigenere' program

I am making a program that decrypts the vigenere cipher. User can only give alphabetical key.
for (int i = 0, counter = strlen(text); i < counter; i++)
{
// prints non-alphabetical characters straight away
if (!isalpha(text[i]))
{
printf("%c", text[i]);
}
else
{
// for index of key
index = meta % strlen(key);
if (islower(text[i]))
{
// separate cases depending upon case of key
if (islower(key[index]))
{
printf("%c", (((text[i] - 97) - (key[index] - 97)) % 26) + 97);
}
else
{
printf("%c", (((text[i] - 97) - (key[index] - 65)) % 26) + 97);
}
}
else
{
if (islower(key[index]))
{
printf("%d", (((text[i] - 65) - (key[index] - 97)) % 26) + 65);
}
else
{
printf("%c", (((text[i] - 65) - (key[index] - 65)) % 26) + 65);
}
}
// incrementing for next key alphabet
meta++;
}
Vigenere:
Input: MyName
key: qwerty
output: CuRrfc
De Vigenere:
Input: CuRrfc
key:qwerty
expected output: MyName
given output: 3_NaSK
How can I fix it?
The problem is the way the modulus operator deals with negative numbers.
For some characters you get negative values and the modulus operation then returns a negative value. You want a value in the range [0, 25].
You can fix it by adding 26 before taking the modulus.
printf("%c", (((text[i] - 97) - (key[index] - 97)) % 26) + 97);
would become
printf("%c", (((text[i] - 97) - (key[index] - 97) + 26) % 26) + 97);
Change all four rows the same way.

Vigenere Cypher Program in C

This program is supposed to crypt a certain message with the vigenere cypher. The program is supposed to be 'case sensitive' both the message and the keyword. If the program encounters any special characters or numbers, is also supposed to print them untouched.
The last part seems to be working, and the rest, even though the math seems to be right, it doesn't print as it's supposed to. I'm also converting the ASCII values to A-Z/0-26, doing the cypher formula, and them converting them back to ASCII.
// key validation
string kw = argv[1];
int kwl = strlen(kw);
for (int i = 0; i < kwl; i++)
{
if (!isalpha(kw[i]))
{
printf("Usage: ./vigenere keyword\n");
return 1;
}
}
// get message and length
string mssg;
mssg = GetString();
int lngth = strlen(mssg);
// cryptography
int k = 0;
for (int j = 0; j < lngth; j++)
{
if (isalpha(mssg[j]))
{
if (islower(mssg[j]))
{
if (islower(kw[k % kwl]))
printf("%c", (((mssg[j] - 97) + (kw[k % kwl] - 97)) & 26) + 97);
else
printf("%c", (((mssg[j] - 97) + (kw[k % kwl] - 65)) & 26) + 97);
k++;
}
else if (isupper(mssg[j]))
{
if (isupper(kw[k % kwl]))
printf("%c", (((mssg[j] - 65) + (kw[k % kwl] - 65)) & 26) + 65);
else
printf("%c", (((mssg[j] - 65) + (kw[k % kwl] - 97)) & 26) + 65);
k++;
}
}
else
printf("%c", mssg[j]);
}
printf("\n");
return 0;
}
I'm still getting an error somewhere on the math
The error is that you have & 26 instead of % 26.

Numerical Instability of C Loop

I am writing a piece of code to solve the LaPlacian at a boundary with charge density, in C. It uses the following loop:
chargeold[i] = charge[i];
charge[i] = -0.05*sgn(mat[i][j])*mat[i][j]*mat[i][j];
charge[i] = (1.0 - alpha)*charge[i] + alpha*chargeold[i];
mat[i][j] = (( mat[i][j-1] + di2*mat[i][j+1] ) / ( di2 + 1.0)) + 80.0*charge[i];
where the constant alpha is an under-relaxation parameter 0 < alpha < 1. This hasn't seemed to work and I think it may be to do with the numerical instability of the code - so far I have tried changing the constants, here -0.05, alpha and 80.0, and the sign in various the lines for calculating charge and mat[i][j] and get wildly different results depending on what I put: for example changing the coefficient of charge[i] on the last line by just 10.0 can cause the programme to get trapped inside a loop, diverge to infinity or -infinity, or quickly converge to 0 (which is not to be expected). This suggests to me a problem with the code I have created.
I have also tried condensing the calculation down into one line, or doing the same steps in different lines, and these also change the result wildy.
Any help on this would be appreciated. Thanks.
n.b. all data types are double
EDIT - full loop looks like:
do
{
sum_matdiff = 0;
for (i = 1; i < meshno; i++)
{
for (j = 1; j < meshno; j++)
{
if (bound[i][j] == 1) // holds boundary conditions
continue;
else
matold[i][j] = mat[i][j];
if ((i + j + count) % 2 == 1)
{
continue;
}
else if (j == (int)(0.3 * meshno))
{ // if statement to calculate at boundary
chargeold[i] = charge[i];
charge[i] = -0.05 * sgn(mat[i][j]) * mat[i][j] * mat[i][j];
charge[i] = (1.0 - alpha) * charge[i] + alpha * chargeold[i];
mat[i][j] =
((mat[i][j - 1] + di2 * mat[i][j + 1]) / (di2 + 1.0)) +
80.0 * charge[i];
if (i == 50)
{
printf("%f\n", charge[50]);
}
}
else
{ // calculates outside boundary
omega = 1.0 / (1.0 - 0.25 * omega * rho_sq);
mat[i][j] =
0.25 * (mat[i + 1][j] + mat[i - 1][j] + mat[i][j + 1] +
mat[i][j - 1] + (mat[i + 1][j] - mat[i - 1][j]) / (2 * i));
}
mat[i][j] = (1.0 - omega) * matold[i][j] + omega * mat[i][j];
sum_matdiff += fabs(1.0 - matold[i][j] / mat[i][j]);
}
}
count += 1;
av_diff = sum_matdiff / N;
}
while (av_diff > 0.01 || count < meshno * 2);

Parallelize Fibonacci sequence generator

I'm learning about parallelization and in one exercise I'm given a couple of algorithms that I should improve in performance. One of them is a Fibonacci sequence generator:
array[0] = 0;
array[1] = 1;
for (q = 2; q < MAX; q++) {
array[q] = array[q−1] + array[q−2];
}
My suspicion is, that this cannot be optimized (by parallelization), since every number depends on the two preceding numbers (and therefore indirectly on all preceding numbers). How could this be parallelized?
The Fibonacci sequence is determined just by its first two elements; in fact, you could somehow parallelize it, although ugly:
F(n + 2) = F(n + 1) + F(n)
F(n + 3) = F(n + 1) + F(n + 2) = F(n + 1) * 2 + F(n)
F(n + 4) = F(n + 2) + F(n + 3) = F(n + 1) * 3 + F(n) * 2
F(n + 5) = F(n + 3) + F(n + 4) = F(n + 1) * 5 + F(n) * 3
F(n + 6) = F(n + 4) + F(n + 5) = F(n + 1) * 8 + F(n) * 5
Hopefully by now, you can see that:
F(n + k) = F(n + 1) * F(K) + F(n) * F(k - 1)
So after computing the first k numbers, you could use this relation to compute the next k items in the sequence, at the same time, parallelized.
You could also use the direct formula for Fibonacci numbers to compute them in parallel, but that is kind of too uncool (also might be too simple for learning purposes that it might serve).
The best way to approach it to use 2-dimensional matrix form of Fibonacci
Now you can easily expand it. Simple matrix multiplication concepts will do it.
or you can go with other mathematical way, such as
A number 'n' is a Fibanocci number if either (5n^2 - 4) or (5n^2 + 4) is a perfect square.
http://en.wikipedia.org/wiki/Fibonacci_number
So given a large number, you can find the next two Fib nums using this algorithm and continue with your addition then onwards.
In that way, you could partition the problem as between (0 to N/2) and then (N/2 + 1 to N) and run it in parallel threads.

Resources