I have a code that looks something like this:
bool var = some condition...
if( var )
{
for( int i=0; i<10; ++i )
{
//execute some code ...
}
}
else
{
for( int i=9; i>=0; --i )
{
//execute some other code...
}
}
However, the code that needs to be executed inside the for loop is almost entirely identical, and so I don't want to write it twice. I know I can do something like this:
bool var = some condition...
for( int i = (var ? 0 : 9 ); (var ? i<10 : i>=0 ); (var ? ++i : --i ) )
{
//Execute my code
}
But this is a really un-elegant solution.
Is there a short, more elegant way of doing this? I checked std::iterator but I don't think it's what I need.
You're focusing on the wrong problem here. If you have a direction flag, don't get all hung up on the iteration variable being literally correct. Just interpret it as required:
for (int i = 0; i < n; ++i)
{
int j = var ? i : n - 1 - i;
// j goes from 0..n-1 or n-1..0
}
Unless you're doing billions of these calls, the overhead of the secondary variable will be insignificant.
You can just break the body of the loop out into a function/method and pass in sufficient context for the operation to occur. If the loop body uses mostly fields on this, making it a method should be fairly easy. Otherwise, you shouldn't need more parameters than the loop currently has.
If you're using C++11, you could implement this as a lambda capturing any necessary info, and call the lambda from within each of the loops (so as not to have a loose function). Using a function or method you can test independently is a good idea, though.
Does the code inside the loop depend on the value of the iterator, and if so, how? You might be able to use some basic math in a clever fashion, like transforming the start/end to always be 1..n, or using abs and negatives. This would leave you with one loop, and moving the body out into a function wouldn't be strictly necessary.
It's smart to want to minimize duplicate code, but that doesn't mean that your solution needs to fit in one line. Just write out the logic in a way that makes sense and is legible. Include comments to explain what you're doring and why.
bool var = some condition...
int start = 0;
int end = 9;
int increment = 1;
if (!var)
{
// Reverse direction
start = 9;
end = 0;
increment = -1;
}
// Loop (forwards if var; reversed if !var)
for (int i = start; i != end; i += increment)
{
}
You may use something like that.
for(int j = 0; j < 10; ++j) { // always increases
int i = var ? j : 10 - 1 - j;
//go
}
This looks suspiciously like iteration to me, so let's try to write a function that will help us out:
void incr(int& i) { ++i; }
void decr(int& i) { --i; }
template <typename Iter, typename Incr>
void do_work(Iter start, Iter finish, Incr incr)
{
for(Iter i = start, i != finish; incr(i))
{
// Do your code.
}
}
bool var = some condition...
if( var )
{
do_work(0, 10, &incr);
}
else
{
do_work(9, -1, &decr);
}
Related
I'm currently trying to create a sudoku solver in C++, but I have run into a slight problem. Instead of starting out with a 9x9 sudoku, I've started with a 4x4 one. For every square that can contain a number I am trying to get the possible numbers that square can hold into an array, e.g. if the possibilities in square 3 are 1 and 4,
for ( int i; i < 4; i++ ) {
cout << candidates[3][i];
}
would give me 1004. It is easily accessible when I need to code hard solving methods or a brute force solving method.
Here is the problem: I need to check whether a number occurs in any row, column or (2x2 or 3x3) box, and if it does not, add it to the candidates array. Here's what I thought of:
for ( int i = 0; i < 16; i++ ) {
for ( int j = 1; j < 5; j++ ) {
if ( for ( int k = 0; k < 4; k++ ) { allRows[getRow(i)][k] != j || allCols[getCol(i)] [k] != j || allBoxs[getBox(i)][k] != j}) {
candidates[i][j-1] = j;
}
}
}
The arrays allRows, allCols, allBoxs all contain the sudoku, only in such an order that they are easily accessible when they are needed. The functions getRow(), getCol() and getBox() return the number of the row, column or box (respectively, of course) the input number is in.
I tried to make it loop though everything in the same row, column or box as the number, to get all twelve checked by the if, and if they all passed, then I would add the number to the candidates array.
It came to me as no surprise that it returned an error when I tried to compile this. But I really don't want to write out twelve AND conditions in the if statement, or 27 when I upgrade to 9x9 sudoku, because:
I don't learn anything and
Where's the fun in that?
Can anyone help me / suggest another idea to do this without typing everything out?
I apologize if my inability to be concise hinders an answer to this question, I was only trying to provide all the details I thought maybe were necessary...
Condition of if should be an expression convertible to bool. it is not the case of for-statement.
You might do instead (assuming I correctly understood your condition):
for ( int i = 0; i < 16; i++ ) {
for ( int j = 1; j < 5; j++ ) {
bool b = false;
for ( int k = 0; k < 4; k++ ) {
if (allRows[getRow(i)][k] != j || allCols[getCol(i)][k] != j || allBoxs[getBox(i)][k] != j) {
b = true;
break;
}
}
if (b) {
candidates[i][j-1] = j;
}
}
}
or with helper function
template <typename Range, typename T>
bool contains(const Range& range, constT& value)
{
using std::begin;
using std::end;
return std::find(begin(range), end(range), value) != end(range);
}
// ...
for ( int i = 0; i < 16; i++ ) {
for ( int j = 1; j < 5; j++ ) {
if (!contains(allRows[getRow(i)], j)
|| !contains(allCols[getCol(i)], j)
|| !contains(allBoxs[getBox(i)], j)) {
candidates[i][j-1] = j;
}
}
}
Like you already noticed, adding an for-statement inside of the condition of the if doesn't work. There are several reasons for it, however, let me point out a few that cause confusion:
What if the for-loop wouldn't iterate? Would this result in true or false?
What if you have multiple iterations? Would we && or || the boolean values into it? And how about short cutting of those operators?
Long story short: Even if this would be considered to ever add to the standard, I expect it to be blocked thanks to the many edge cases.
So what does this mean? Is this impossible? Off course not, it's C++. Like already mentioned in the answer of #Jarod42 you can calculate a boolean and than do the if-statement. Or like both of us mentioned (me in the comments), you could move this into a function.
Personally, I've stepped away from remembering state about my for-loop like with this boolean. The main reason: This is hard to read. Every single time you read that code, you need to check what's actually happening.
Hence, I suggest to move this to a function. A function has a clear name and could even be tested separately to ensure it's behavior is correct.
So in this case, I would write something like:
template<typename T1, typename T2, typename T3>
auto checkForExistanceOf(int shouldExist, int locator, T1 &&allRows, T2 &&allCols, T3 &&allBoxs)
{
for ( int k = 0; k < 4; k++ )
{
if (allRows[getRow(locator)][k] != shouldExist)
return true;
if (allCols[getCol(locator)] [k] != shouldExist)
return true;
if (allBoxs[getBox(locator)][k] != shouldExist)
return true;
}
return false;
}
The code on caller side than becomes:
for ( int i = 0; i < 16; i++ )
{
for ( int j = 1; j < 5; j++ )
{
if (checkForExistanceOf(j, i, allRows, allCols, allBoxs))
{
candidates[i][j-1] = j;
}
}
}
For sure, my names ain't that good, as I don't know the exact purpose, nor would I suggest using a template as you know the actual types, though, this is the idea behind it.
I am trying to solve this problem:
Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.
https://leetcode.com/problems/maximum-product-of-word-lengths/
You can create a bitmap of char for each word to check if they share chars in common and then calc the max product.
I have two method almost equal but the first pass checks, while the second is too slow, can you understand why?
class Solution {
public:
int maxProduct2(vector<string>& words) {
int len = words.size();
int *num = new int[len];
// compute the bit O(n)
for (int i = 0; i < len; i ++) {
int k = 0;
for (int j = 0; j < words[i].length(); j ++) {
k = k | (1 <<(char)(words[i].at(j)));
}
num[i] = k;
}
int c = 0;
// O(n^2)
for (int i = 0; i < len - 1; i ++) {
for (int j = i + 1; j < len; j ++) {
if ((num[i] & num[j]) == 0) { // if no common letters
int x = words[i].length() * words[j].length();
if (x > c) {
c = x;
}
}
}
}
delete []num;
return c;
}
int maxProduct(vector<string>& words) {
vector<int> bitmap(words.size());
for(int i=0;i<words.size();++i) {
int k = 0;
for(int j=0;j<words[i].length();++j) {
k |= 1 << (char)(words[i][j]);
}
bitmap[i] = k;
}
int maxProd = 0;
for(int i=0;i<words.size()-1;++i) {
for(int j=i+1;j<words.size();++j) {
if ( !(bitmap[i] & bitmap[j])) {
int x = words[i].length() * words[j].length();
if ( x > maxProd )
maxProd = x;
}
}
}
return maxProd;
}
};
Why the second function (maxProduct) is too slow for leetcode?
Solution
The second method does repetitive call to words.size(). If you save that in a var than it working fine
Since my comment turned out to be correct I'll turn my comment into an answer and try to explain what I think is happening.
I wrote some simple code to benchmark on my own machine with two solutions of two loops each. The only difference is the call to words.size() is inside the loop versus outside the loop. The first solution is approximately 13.87 seconds versus 16.65 seconds for the second solution. This isn't huge, but it's about 20% slower.
Even though vector.size() is a constant time operation that doesn't mean it's as fast as just checking against a variable that's already in a register. Constant time can still have large variances. When inside nested loops that adds up.
The other thing that could be happening (someone much smarter than me will probably chime in and let us know) is that you're hurting your CPU optimizations like branching and pipelining. Every time it gets to the end of the the loop it has to stop, wait for the call to size() to return, and then check the loop variable against that return value. If the cpu can look ahead and guess that j is still going to be less than len because it hasn't seen len change (len isn't even inside the loop!) it can make a good branch prediction each time and not have to wait.
Assuming a loop that invariably iterates one at a time through some sequence, I want to know if there is some clever loop structure or trick that avoids doing a check upon each iteration for the end of the array.
for (int i=0; i<length; i++) {
//something
}
or
int i=0;
while (i<length) {
//something
i++;
}
For clarification, I'm referring to comparisons like those in the above examples (i<length).
If relevant, I generally code in C++, but am open to hearing about other languages that provide ways around this.
Yes, you can unroll the loop like this:
int i;
for (i = 0; i < length - 3; i += 4) { // 4x unrolled loop
//something(i)
//something(i+1)
//something(i+2)
//something(i+3)
}
for ( ; i < length; i++) { // clean up loop for residual 0..3 iterations
//something(i)
}
You can unroll the loop:
int length = 20 ;
int i=0;
while (i+3<length) {
//something
i++;
//something
i++;
//something
i++;
//something
i++;
}
//handle any remaining cases
while (i<length) {
//something
i++ ;
}
I want to know if there is some clever loop structure or trick that avoids doing a check upon each iteration for the end of the array.
Set i to the length, then decrement i on each iteration of the loop.
int i = length;
while ( i-- >= 0) {
// do something
}
In a function, I have several consecutive for loops with the same code but different initial values for the control variable. The initial values are obtained from inputs to the function. Ie,
void thisFunction( class A a){
//some other code
for (int i = a.x; i != 0; --i){
code
}
for (int i = a.y; i != 0; --i){
code
}
for (int i = a.z; i != 0; --i){
code
}
//some other code
}
Is there any way to condense all the for loops into one loop so that when I make changes to the code within the loop, I won't have to change it for all three loops? An alternative is to write anotherFunction() with the initial values as input, but I need access to local variables in thisFunction().
void anotherFunction(int in){
for (int i = in; i != 0; --i){
code
}
}
So is there another way to condense the loops?
Thank you.
Your hunch is right - you'll have to refactor your code into a separate function. Local variables of thisFunction will become arguments to anotherFunction; often these will be passed by reference .
EDIT: In most cases you should avoid doing this, and rather follow MSalter's answer. Just because you can, doesn't mean you should.
I am not sure how good an idea this is, but without any more context, a simple solution could be:
int starts[3] = { a.x, a.y, a.z };
for ( int var = 0; var < 3; ++var ) {
for ( int i = starts[var]; i != 0; --i ) {
// code
}
}
Note that the values of the conditions are obtained once at the beginning of the function, that means that if the object a changes throughout the first loop, that change will not be visible in the later control loops. If you need that, the solution can be modified to store pointers.
EDIT: There is a comment suggesting the use of the size of the array. I did not add that here not to modify, but anyway, a better way of getting the array size is:
template<typename T, unsigned int N>
inline unsigned int array_size( T (&)[N] ) {
return N;
}
//...
for ( int var = 0; var < array_size(starts); ++i ) {
Using lambda expressions, you could do this:
void thisFunction( class A a)
{
//some other code
auto code = [&] (int i)
{
// your code here
};
for (int i = a.x; i != 0; --i)
code(i);
for (int i = a.y; i != 0; --i)
code(i);
for (int i = a.z; i != 0; --i)
code(i);
}
You can use macro
#define ITERATE(_IN) \
{\
for (int _I = (_IN); _I != 0; --_I){\
code \
}\
}\
Then you have access to local variables, and you only have to manage one copy of the code.
So, your code becomes
void thisFunction( class A a){
//some other code
ITERATE(a.x)
ITERATE(a.y)
ITERATE(a.z)
//some other code
}
This may become difficult to debug, so you have to make sure first that it works well, before you make a macro of your code
Not really. The loops will all be running for different numbers of iterations, surely?
The best you can do is factor out as much of the internals as possible, for instance, into a function like you suggested. Alternatively, have the loop outside the function.
To avoid passing in a load of variables independently, you could consider wrapping them in a class or struct.
Update On second thoughts, David Rodriguez's answer suggestion is a pretty good solution!
I have been looking through some code and I have seen several examples where the first element of a for cycle is omitted.
An example:
for ( ; hole*2 <= currentSize; hole = child)
What does this mean?
Thanks.
It just means that the user chose not to set a variable to their own starting value.
for(int i = 0; i < x; i++)
is equivalent to...
int i = 0;
for( ; i < x; i++)
EDIT (in response to comments): These aren't exactly equivalent. the scope of the variable i is different.
Sometimes the latter is used to break up the code. You can also drop out the third statement if your indexing variable is modified within the for loop itself...
int i = 0;
for(; i < x;)
{
...
i++
...
}
And if you drop out the second statement then you have an infinite loop.
for(;;)
{
runs indefinitely
}
The for construct is basically ( pre-loop initialisation; loop termination test; end of loop iteration), so this just means there is no initialisation of anything in this for loop.
You could refactor any for loop thusly:
pre-loop initialisation
while (loop termination test) {
...
end of loop iteration
}
Some people have been getting it wrong so I just wanted to clear it up.
int i = 0;
for (; i < 10; i++)
is not the same as
for (int i = 0; i < 10; i++)
Variables declared inside the for keyword are only valid in that scope.
To put it simply.
Valid ("i" was declared outside of the loops scope)
int i = 0;
for (; i < 10; i++)
{
//Code
}
std::cout << i;
InValid ("i" does not exist outside the loop scope)
for (int i = 0; i < 10; i++)
{
//Code
}
std::cout << i;
It means that the initial value of hole was set before we got to the loop
That means loop control variable is initialized before the for loop .
For C code,
int i=0;
for( ; i <10 ; i++) { } //since it does not allow variable declaration in loop
For C++ code,
for(int i=0 ; i <10 ; i++) { }
You could omit any of the parameters of a for loop.
ie: for(;;) {} is about the same as while(true) {}
It means that the initial value of hole was set before we got to the loop.
Looks like a list traversal of some kind.
Suppose you wanted to
for (hole=1 ; hole*2 <= currentSize; hole = child)
But the value of hole just before the for loop was already 1, then you can slip this initilization part of the loop:
/* value of hole now is 1.*/
for ( ; hole*2 <= currentSize; hole = child)