How would one see if an array has consecutive numbers in C++? - c++

This is basically the 8 Queens problem, but solving it with brute force in a 1D array. Say I have an array (named b) of size 8, with elements ranging from 0 to 7.
I initialize each index in the array with 8 for-loops, like this:
int b[8]={0};
int count = 0;
for(b[0] = 0; b[0]<8; b[0]++){
for(b[1] = 0; b[1]<8; b[1]++){
for(b[2] = 0; b[2]<8; b[2]++){
for(b[3] = 0; b[3]<8; b[3]++){
for(b[4] = 0; b[4]<8; b[4]++){
for(b[5] = 0; b[5]<8; b[5]++){
for(b[6] = 0; b[6]<8; b[6]++){
for(b[7] = 0; b[7]<8; b[7]++){
if(check(b))
{
count++;
print(b, count);
}
}}
}}
}}
}}
What this program is supposed to do is check every combination of numbers 0 to 7 and returning true for only certain conditions. There are supposed to be 92 solutions, if this sounds familiar, it should be - it is the 8 Queens problem using brute force. From here, this is what I understand are the conditions:
I want to be able to check if an array has a consecutive string of numbers; such as:
[0|5|7|1|2|3|6|4]
Here, the elements b[3], b[4] and b[5] are consecutive. I don't want that, I want to return false, since there is a consecutive string of numbers (basically queens are attacking)
I also do not want an array that has a string of backwards consecutive numbers like this:
[0|5|7|3|2|1|6|4]
And lastly, I do not want two or more numbers in indexes where it would make them look consecutive if we had simply changed then numbers between them:
[0|2|4|6|1|3|5|7]
Above is not acceptable because b[0] and b[7] are numbers in their "consecutive index" (because at least 2 queens are attacking each other).
[6|1|3|0|4|7|5|2]
Above is also not acceptable because b[1] and b[4] are also in consecutive indexes.
Similarly, when the values are swapped, the arrays
[7|2|4|6|1|3|5|0]
[6|4|3|0|1|7|5|2]
are also not acceptable. I also cannot have 2 or more of the same number.
The problem I am having is in creating the check function. I am told I need to use 1 for loop and 1 if-then statement. Can the check function just take the whole array as is? And if it does, how do look at the right-most element in the array, and check to see if it has consecutive indexes (queens are attacking it)? I've tried this:
bool ok(int board[8]){
for(int c = 7; c >= 0; c--){ //row check
for (int j=0; j<c; j++){
if (board[c]==board[j]){
return false;
}
}
for(int i = 1; i <= c; i++){
// diagonal check from top left to bottom right
if ((board[c]-i >= 0) && (board[c-i] == board[c]-i))
{return false;}
if ((board[c]+i <= 7) && (board[c+i] == board[c]+i))
{return false;}
// diagonal check from bottom left to top right
if ((board[c]-i >= 0) && (board[c-i] == board[c]+i))
{return false;}
if ((board[c]+i <= 7) && (board[c+i] == board[c]-i))
{return false;}
}
}
return true;
}
But not only does this not work (I get 300+ solutions), it is not as small as I am told it should be.

I think there is a little problem with your check of collisions in the diagonals: you've got 15 diagonals going each way (including the very short one-square diagonals in the corners), while your code checks only seven of each due to the board[c]+i <= 7 and board[c]-i >= 0 conditions.
Here is how you can simplify the checks and make them faster with the use of three boolean arrays: you've got 8 rows, 15 ascending diagonals, and 15 descending diagonals:
bool row[8];
bool ascending[15];
bool descending[15];
Initially, there are no queens in any of these rows/diagonals. As you go through the elements of board, do this:
for (int i = 0 ; i != 8 ; i++) {
// Check and mark the row
if (row[board[i]]) return false;
row[board[i]] = true;
// Check and mark the ascending diagonal
int ascIdx = board[i]+i;
if (ascending[ascIdx]) return false;
ascending[ascIdx] = true;
int descIdx = 7+board[i]-i;
if (descending[descIdx]) return false;
descending[descIdx] = true;
}
return true;

Related

Given an integer K and a matrix of size t x t. construct a string s consisting of first t lowercase english letters such that the total cost of s is K

I'm solving this problem and stuck halfway through, looking for help and a better method to tackle such a problem:
problem:
Given an integer K and a matrix of size t x t. we have to construct a string s consisting of the first t lowercase English letters such that the total cost of s is exactly K. it is guaranteed that there exists at least one string that satisfies given conditions. Among all possible string s which is lexicographically smallest.
Specifically the cost of having the ith character followed by jth character of the English alphabet is equal to cost[i][j].
For example, the cost of having 'a' followed by 'a' is denoted by cost[0][0] and the cost of having 'b' followed by 'c' is denoted by cost[1][3].
The total cost of a string is the total cost of two consecutive characters in s. for matrix cost is
[1 2]
[3 4],
and the string is "abba", then we have
the cost of having 'a' followed by 'b' is is cost[0][1]=2.
the cost of having 'b' followed by 'b' is is `cost0=4.
the cost of having 'b' followed by 'a' is cost0=3.
In total, the cost of the string "abba" is 2+4+3=9.
Example:
consider, for example, K is 3,t is 2, the cost matrix is
[2 1]
[3 4]
There are two strings that its total cost is 3. Those strings are:
"aab"
"ba"
our answer will be "aab" as it is lexicographically smallest.
my approach
I tried to find and store all those combinations of i, j such that it sums up to desired value k or is individual equals k.
for above example
v={
{2,1},
{3,4}
}
k = 3
and v[0][0] + v[0][1] = 3 & v[1][0] = 3 . I tried to store the pairs in an array like this std::vector<std::vector<std::pair<int, int>>>. and based on it i will create all possible strings and will store in the set and it will give me the strings in lexicographical order.
i stucked by writing this much code:
#include<iostream>
#include<vector>
int main(){
using namespace std;
vector<vector<int>>v={{2,1},{3,4}};
vector<pair<int,int>>k;
int size=v.size();
for(size_t i=0;i<size;i++){
for(size_t j=0;j<size;j++){
if(v[i][j]==3){
k.push_back(make_pair(i,j));
}
}
}
}
please help me how such a problem can be tackled, Thank you. My code can only find the individual [i,j] pairs that can be equal to desired K. I don't have idea to collect multiple [i,j] pairs which sum's to desired value and it also appears my approach is totally naive and based on brute force. Looking for better perception to solve the problems and implement it in the code. Thank you.
This is a backtracking problem. General approach is :
a) Start with the "smallest" letter for e.g. 'a' and then recurse on all the available letters. If you find a string that sums to K then you have the answer because that will be the lexicographically smallest as we are finding it from smallest to largest letter.
b) If not found in 'a' move to the next letter.
Recurse/backtrack can be done as:
Start with a letter and the original value of K
explore for every j = 0 to t and reducing K by cost[i][j]
if K == 0 you found your string.
if K < 0 then that path is not possible, so remove the last letter in the string, try other paths.
Pseudocode :
string find_smallest() {
for (int i = 0; i < t; i++) {
s = (char)(i+97)
bool value = recurse(i,t,K,s)
if ( value ) return s;
s = ""
}
return ""
}
bool recurse(int i, int t, int K, string s) {
if ( K < 0 ) {
return false;
}
if ( K == 0 ) {
return true;
}
for ( int j = 0; j < t; j++ ) {
s += (char)(j+97);
bool v = recurse(j, t, K-cost[i][j], s);
if ( v ) return true;
s -= (char)(j+97);
}
return false;
}
In your implementation, you would probably need another vector of vectors of pairs to explore all your candidates. Also another vector for updating the current cost of each candidate as it builds up. Following this approach, things start to get a bit messy (IMO).
A more clean and understandable option (IMO again) could be to approach the problem with recursivity:
#include <iostream>
#include <vector>
#define K 3
using namespace std;
string exploreCandidate(int currentCost, string currentString, vector<vector<int>> &v)
{
if (currentCost == K)
return currentString;
int size = v.size();
int lastChar = (int)currentString.back() - 97; // get ASCII code
for (size_t j = 0; j < size; j++)
{
int nextTotalCost = currentCost + v[lastChar][j];
if (nextTotalCost > K)
continue;
string nextString = currentString + (char)(97 + j); // get ASCII char
string exploredString = exploreCandidate(nextTotalCost, nextString, v);
if (exploredString != "00") // It is a valid path
return exploredString;
}
return "00";
}
int main()
{
vector<vector<int>> v = {{2, 1}, {3, 4}};
int size = v.size();
string initialString = "00"; // reserve first two positions
for (size_t i = 0; i < size; i++)
{
for (size_t j = 0; j < size; j++)
{
initialString[0] = (char)(97 + i);
initialString[1] = (char)(97 + j);
string exploredString = exploreCandidate(v[i][j], initialString, v);
if (exploredString != "00") { // It is a valid path
cout << exploredString << endl;
return 0;
}
}
}
}
Let us begin from the main function:
We define our matrix and iterate over it. For each position, we define the corresponding sequence. Notice that we can use indices to get the respective character of the English alphabet, knowing that in ASCII code a=97, b=98...
Having this initial sequence, we can explore candidates recursively, which lead us to the exploreCandidate recursive function.
First, we want to make sure that the current cost is not the value we are looking for. If it is, we leave immediately without even evaluating the following iterations for candidates. We want to do this because we are looking for the lexicographically smallest element, and we are not asked to provide information about all the candidates.
If the cost condition is not satisfied (cost < K), we need to continue exploring our candidate, but not for the whole matrix but only for the row corresponding to the last character. Then we can encounter two scenarios:
The cost condition is met (cost = K): if at some point of recursivity the cost is equal to our value K, then the string is a valid one, and since it will be the first one we encounter, we want to return it and finish the execution.
The cost is not valid (cost > K): If the current cost is greater than K, then we need to abort this branch and see if other branches are luckier. Returning a boolean would be nice, but since we want to output a string (or maybe not, depending on the statement), an option could be to return a string and use "00" as our "false" value, allowing us to know whether the cost condition has been met. Other options could be returning a boolean and using an output parameter (passed by reference) to contain the output string.
EDIT:
The provided code assumes positive non-zero costs. If some costs were to be zero you could encounter infinite recursivity, so you would need to add more constraints in your recursive function.

How can I comapre two of the following objects?

I'm trying to solve the 9-tile puzzle with the DFS/BFS (let's focus on the DFS as those two are basically the same) algorithm, and after some debugging I concluded why my code doesn't work.
I'm implementing the algorithm using a stack for the frontier, and a set for the closed set, and at some point I have to check if an object exists in the closed set. So naturally I use (temp is a 9-tile object):
if (closed.find(temp) == closed.end()){
\\do stuff
}
As I was trying to come out with this expression, I have learnt that I had to overload the '<' and '>' operators so that set.find() can work. So reaching my problem, the 9-tile objects are basically a 2d 3x3 array of integers, with
the value 0 where the empty tile is. How can I determine if, for example, one of the following states of my board are "greater" or "smaller" than the other?
6 7 1 3 6 0
0 3 2 2 8 4
4 5 6 5 1 7
I have tried comparing each element with the final state which is:
1 2 3
4 5 6
7 8 0
Adding one point for each tile that is the same as in the final but it doesn't work, obviously because two boards with completely incorrectly placed tiles will have the same score, so I cannot compare them.
I have also tried going through the elements of two boards, and composing scores like this:
bool operator < (const Board &A, const Board &B){
int scoreA=0, scoreB=0;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
scoreA += i * j * A.getTile(i, j);
scoreB += i * j * B.getTile(i, j);
}
}
return scoreA < scoreB;
}
However I'm not positive that this is correct, as I don't get the results I want.
Can you propose a better method of comparing two boards like this?
You could try making an integer from the board such as
1 2 3
4 5 6 = 123456780
7 8 0
or in any pattern you'd like more.
This way, you don't have to compare the boards, only integer representations.
Since your variables which you compare are scores, I assume you want to do the comparison to check which board is closer to the solution of the tile moving problem.
In this case, you have to define some function double calculateScore(const Board& board) and then do a comparison:
double calculateScore(const Board& board)
{
double score = 0.0;
// as you wrote: adding one point for each tile that is the same as in the final
return score;
}
bool operator<(const Board& lhs, const Board& rhs)
{
return calculateScore(lhs) < calculateScore(rhs);
}
Your goal is then to take the board that maximizes that score.
Since you're using BFS/DFS, it doesn't matter which elements are 'greater' or 'less'. You just need the ordering to be consistent (if a < b and b < c, then a < c), and whenever two boards are different you need one to be less than the other.
A lexographic comparison of the tiles suffices. Something like this:
bool operator < (const Board &A, const Board &B){
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
int aTile = A.getTile(i,j);
int bTile = B.getTile(i,j);
if (aTile != bTile) {
return (aTile<bTile);
}
}
}
return false; //equal
}
Note that this will work just fine, but it will be faster to use unordered_set.
Also, since you'll be creating so many boards, it would be nice to use a smaller representation. If you pack them into an int as another poster suggest, then you can compare them with standard <. If you pack them into a byte array, you can use memcmp.

Fastest way to find smallest missing integer from list of integers

I have a list of 100 random integers. Each random integer has a value from 0 to 99. Duplicates are allowed, so the list could be something like
56, 1, 1, 1, 1, 0, 2, 6, 99...
I need to find the smallest integer (>= 0) is that is not contained in the list.
My initial solution is this:
vector<int> integerList(100); //list of random integers
...
vector<bool> listedIntegers(101, false);
for (int theInt : integerList)
{
listedIntegers[theInt] = true;
}
int smallestInt;
for (int j = 0; j < 101; j++)
{
if (!listedIntegers[j])
{
smallestInt = j;
break;
}
}
But that requires a secondary array for book-keeping and a second (potentially full) list iteration. I need to perform this task millions of times (the actual application is in a greedy graph coloring algorithm, where I need to find the smallest unused color value with a vertex adjacency list), so I'm wondering if there's a clever way to get the same result without so much overhead?
It's been a year, but ...
One idea that comes to mind is to keep track of the interval(s) of unused values as you iterate the list. To allow efficient lookup, you could keep intervals as tuples in a binary search tree, for example.
So, using your sample data:
56, 1, 1, 1, 1, 0, 2, 6, 99...
You would initially have the unused interval [0..99], and then, as each input value is processed:
56: [0..55][57..99]
1: [0..0][2..55][57..99]
1: no change
1: no change
1: no change
0: [2..55][57..99]
2: [3..55][57..99]
6: [3..5][7..55][57..99]
99: [3..5][7..55][57..98]
Result (lowest value in lowest remaining interval): 3
I believe there is no faster way to do it. What you can do in your case is to reuse vector<bool>, you need to have just one such vector per thread.
Though the better approach might be to reconsider the whole algorithm to eliminate this step at all. Maybe you can update least unused color on every step of the algorithm?
Since you have to scan the whole list no matter what, the algorithm you have is already pretty good. The only improvement I can suggest without measuring (that will surely speed things up) is to get rid of your vector<bool>, and replace it with a stack-allocated array of 4 32-bit integers or 2 64-bit integers.
Then you won't have to pay the cost of allocating an array on the heap every time, and you can get the first unused number (the position of the first 0 bit) much faster. To find the word that contains the first 0 bit, you only need to find the first one that isn't the maximum value, and there are bit twiddling hacks you can use to get the first 0 bit in that word very quickly.
You program is already very efficient, in O(n). Only marginal gain can be found.
One possibility is to divide the number of possible values in blocks of size block, and to register
not in an array of bool but in an array of int, in this case memorizing the value modulo block.
In practice, we replace a loop of size N by a loop of size N/block plus a loop of size block.
Theoretically, we could select block = sqrt(N) = 12 in order to minimize the quantity N/block + block.
In the program hereafter, block of size 8 are selected, assuming that dividing integers by 8 and calculating values modulo 8 should be fast.
However, it is clear that a gain, if any, can be obtained only for a minimum value rather large!
constexpr int N = 100;
int find_min1 (const std::vector<int> &IntegerList) {
constexpr int Size = 13; //N / block
constexpr int block = 8;
constexpr int Vmax = 255; // 2^block - 1
int listedBlocks[Size] = {0};
for (int theInt : IntegerList) {
listedBlocks[theInt / block] |= 1 << (theInt % block);
}
for (int j = 0; j < Size; j++) {
if (listedBlocks[j] == Vmax) continue;
int &k = listedBlocks[j];
for (int b = 0; b < block; b++) {
if ((k%2) == 0) return block * j + b;
k /= 2;
}
}
return -1;
}
Potentially you can reduce the last step to O(1) by using some bit manipulation, in your case __int128, set the corresponding bits in loop one and call something like __builtin_clz or use the appropriate bit hack
The best solution I could find for finding smallest integer from a set is https://codereview.stackexchange.com/a/179042/31480
Here are c++ version.
int solution(std::vector<int>& A)
{
for (std::vector<int>::size_type i = 0; i != A.size(); i++)
{
while (0 < A[i] && A[i] - 1 < A.size()
&& A[i] != i + 1
&& A[i] != A[A[i] - 1])
{
int j = A[i] - 1;
auto tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
for (std::vector<int>::size_type i = 0; i != A.size(); i++)
{
if (A[i] != i+1)
{
return i + 1;
}
}
return A.size() + 1;
}

Confused as to why my algorithm is running slower than it should be

Purely for fun, I decided to write a simple algorithm that finds all the prime numbers between 2 and x, where x is whatever you want it to be. I am using a clock_t to time how long it takes the algorithm to finish for varying x values. (I go x=0, then 25000, then 50000, then 75000, ..., up to 1,000,000). For example, when x = 25000, I go into a for loop with i going from 2 to 25000, and for each value of i, I check to see if it's prime by dividing it with every number between two and itself, looking for a remainder of 0.
Here is the algorithm:
vector<int> calcPrimesWithoutPrechecking(int upperLimit)
{
vector<int> res;
for(int i = 2; i <= upperLimit; i++)
{
int currentNum = i;
bool foundDivisible = false;
for(int j = 2; j < currentNum; j++)
{
if(currentNum % j == 0)
{
foundDivisible = true;
break;
}
}
if(!foundDivisible)
{
res.push_back(i);
}
}
return res;
}
I figured I could make this faster by checking the last digit of the number we're currently testing. If that digit is a 0, 2, 4, 5, 6, or 8, then I don't have to even check if it's prime because I know it's not (of course 2, 3, and 5 are, so those are handled in the beginning). I'm calling this prechecking. Here is the algorithm with prechecking:
vector<int> calcPrimesWithPrechecking(int upperLimit)
{
vector<int> res;
res.push_back(2);res.push_back(3);res.push_back(5);
for(int i = 6; i <= upperLimit; i++)
{
bool foundDivisible = false;
int lastDig = i%10;
if(lastDig == 0
|| lastDig == 2
|| lastDig == 4
|| lastDig == 6
|| lastDig == 8
|| lastDig == 5)
{
foundDivisible = true;
}
int currentNum = i;
for(int j = 2; j < currentNum && !foundDivisible; j++)
{
if(currentNum % j == 0)
{
foundDivisible = true;
break;
}
}
if(!foundDivisible)
{
res.push_back(i);
}
}
return res;
}
I output the results to the console, as well as write them to a text file. I then copy the times over to excel, and plot them. However, for some reason the algorithm with prechecking is slower. I was almost sure it would be faster. When I run the program, I purposefully close every program on my computer and I run it in release mode. I have tested each algorithm in debug and they are indeed both working as intended.
Here is my data.
The x axis is the the number of primes we're checking (eg 25000 means we're looking for all primes between 2 and 25000), and the y axis is the time in seconds to get all the primes.
Can someone explain why the second algorithm, which should theoretically take out many of the computations, is in fact slower?
The reason the implementation with pre-checking is a little slower is that it needs to do more work to eliminate many of the numbers that would be eliminated after the first step of the inner loop anyway.
Consider number 8 as an example: pre-checking needs to find a division remainder and perform five comparisons before eliminating it, while the program with no pre-checking eliminates 8 too, but with a single division by two and a comparison to zero.
The only number for which you may see a little win is 5, but these are not nearly as common as even numbers, on which your program loses CPU cycles.
A better way to speed this one up is to avoid even numbers altogether: recall that all prime numbers after 3 are either of the form 6*k+1 or 6*k-1. Now you can iterate nearly three times as fast!
Another thing is that you do not need to check divisors past the square root of the candidate prime (can you prove why this is so?) This change alone will give you a huge improvement.
Finally, a very useful trick is to store all the primes that you have discovered so far, and use them for your trial divisors. This will greatly improve the speed of your inner loop.
Because it doesn't take out many of the computations. If a number is even, that will be discovered immediately upon checking whether it is divisible by 2 (which is the first number you check in your loop). That's a lot faster than what you're doing here:
int lastDig = i%10;
if(lastDig == 0
|| lastDig == 2
|| lastDig == 4
|| lastDig == 6
|| lastDig == 8
|| lastDig == 5)

Generating all subsets from a single set

I was trying to understand the code to generate all the subsets from one set. Here is the code
#include <stdio.h>
/* Applies the mask to a set like {1, 2, ..., n} and prints it */
void printv(int mask[], int n) {
int i;
printf("{ ");
for (i = 0; i < n; ++i)
if (mask[i])
printf("%d ", i + 1); /*i+1 is part of the subset*/
printf("\\b }\\n");
}
/* Generates the next mask*/
int next(int mask[], int n) {
int i;
for (i = 0; (i < n) && mask[i]; ++i)
mask[i] = 0;
if (i < n) {
mask[i] = 1;
return 1;
}
return 0;
}
int main(int argc, char *argv[]) {
int n = 3;
int mask[16]; /* Guess what this is */
int i;
for (i = 0; i < n; ++i)
mask[i] = 0;
/* Print the first set */
printv(mask, n);
/* Print all the others */
while (next(mask, n))
printv(mask, n);
return 0;
}
I am not understand the logic behind this line for (i = 0; (i < n) && mask[i]; ++i) inside the next function. How is the next mask being generated here?
Code and algorithm looked here:
http://compprog.wordpress.com/2007/10/10/generating-subsets/
That is simply an implementation of counting in binary. The basic idea is to change the least-significant (last) zero to a one, and change all the ones after it to zeroes. The "next" mask will be "one more" than the previous if interpreted as a binary number.
Because the array is arranged with the one's place first, it looks backwards from traditional numeric notation.
Instead of using an array of Boolean values, it could just as well use the bits in the binary representation of one number and the ++ operator.
int next(int &mask, int n) { // using C++ reference
if ( mask == ( 1u << n ) - 1 ) return 0;
++ mask;
return 1;
}
void printv(int mask, int n) {
int i;
printf("{ ");
for (i = 0; i < n; ++i)
if (mask & ( 1 << i ) )
printf("%d ", i + 1); /*i+1 is part of the subset*/
printf("\\b }\\n");
}
I've used a little C++ since you tagged the question as such, but the posted code is plain C.
Last year I participated in the C language contest of the 6th ITAT competition where I solved the second problem by generating all comabinations with the help of a mask (though, it might not be an optimal solution to that problem.)
When you try to derive all the subsets of {a,b,c}, you do it this way:
You may or may not take the first element a.
May or may not take the 2nd element b.
Same for c.
So you wind up with a set of 3 take-or-not-take choices. This can be represented in binaries or boolean values: represent taking by 1, and not taking by 0.
You get the following eight masks: (by the order of a,b,c)
000 100 010 110 001 101 011 111
To generate the next mask of 110:
element 0 is 1. Switch it to 0.
element 1 is 1. Switch it to 0.
element 2 is 0. Switch it to 1.
now you have 001 which is the next mask, which generates subset {c}.
for (i = 0; (i < n) && mask[i]; ++i) does exactly that.
start at element 0.
while (i doesn't exceed your mask length AND element i is 1)
do the body code which flips i to 0, and ++i (go to next element). goto 2 (check).
If the current mask is 111 (the last mask), the next() function simply returns 1 to indicate END.
(P.S. a non-zero integer always represents true.)
The loop in questions starts at the beginning of the array and sets all 1s to 0s until a 0 in encountered. The next statement sets this 0 to a 1 (if possible). So what happens is: 0,0,0 -> 1,0,0 -> 0,1,0 -> 1,1,0 -> 0,0,1... I am not a hardcore C programmer but I think this could have been done easier by using a bit field and incrementing by 1 iteratively.
for (i = 0; (i < n) && mask[i]; ++i)
for:
start at 0 and increment i by 1 each time
don't stop while i is less than n and the bit in the mask array at position i is set
it's straightforward really: 3 parts to a for statement: initial state; end condition; operation.
So if you can understand for (i=0; i < 5; i++) means start at 0 and increment i by 1 each time until it fails to be less than 5, you can understand the more complex for loop you asked about.
in this case, it's going through the loop looking for the first element of the mask that is not set, clearing each element as it goes, then it performs some other operation - namely if there was no mask bits set, and it reached the end of the array. Seems to me like a simple way of setting only one element of an array to 1, in sequence to get the result: 100, 010, 001