C++ trying multiple conditions in if statement with loop - c++

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.

Related

C++ Part of brute-force knapsack

reader,
Well, I think I just got brainfucked a bit.
I'm implementing knapsack, and I thought about I implemented brute-force algorithm like 1 or 2 times ever. So I decided to make another one.
And here's what I chocked in.
Let us decide W is maximum weight, and w(min) is minimal-weighted element we can put in knapsack like k=W/w(min) times. I'm explaining this because you, reader, are better know why I need to ask my question.
Now. If we imagine that we have like 3 types of things we can put in knapsack, and our knapsack can store like 15 units of mass, let's count each unit weight as its number respectively. so we can put like 15 things of 1st type, or 7 things of 2nd type and 1 thing of 1st type. but, combinations like 22222221[7ed] and 12222222[7ed] will mean the same for us. and counting them is a waste of any type of resources we pay for decision. (it's a joke, 'cause bf is a waste if we have a cheaper algorithm, but I'm very interested)
As I guess the type of selections we need to go through all possible combinations is called "Combinations with repetitions". The number of C'(n,k) counts as (n+k-1)!/(n-1)!k!.
(while I typing my message I just spotted a hole in my theory. we will probably need to add an empty, zero-weighted-zero-priced item to hold free space it's probably just increases n by 1)
so, what's the matter.
https://rosettacode.org/wiki/Combinations_with_repetitions
as this problem is well-described up here^ I don't really want to use stack this way, I want to generate variations in single cycle, which is going from i=0 to i<C'(n,k).
so, If I can make it, how it works?
we have
int prices[n]; //appear mystically
int weights[n]; // same as previous and I guess we place (0,0) in both of them.
int W, k; // W initialized by our lord and savior
k = W/min(weights);
int road[k], finalroad[k]; //all 0
int curP = curW = maxP = maxW = 0;
for (int i = 0; i < rCombNumber(n, k); i ++) {
/*guys please help me to know how to generate this mask which is consists of indices from 0 to n (meaning of each element) and k is size of mask.*/
curW = 0;
for (int j = 0; j < k; j ++)
curW += weights[road[j]];
if (curW < W) {
curP = 0;
for (int l = 0; l < k; l ++)
curP += prices[road[l]];
if (curP > maxP) {
maxP = curP;
maxW = curW;
finalroad = road;
}
}
}
mask, road -- is an array of indices, each can be equal from 0 to n; and have to be generated as C'(n,k) (link about it above) from { 0, 1, 2, ... , n } by k elements in each selection (combination with repetitions where order is unimportant)
that's it. prove me wrong or help me. Much thanks in advance _
and yes, of course algorithm will take the hell much time, but it looks like it should work. and I'm very interesting in it.
UPDATE:
what do I miss?
http://pastexen.com/code.php?file=EMcn3F9ceC.txt
The answer was provided by Minoru here https://gist.github.com/Minoru/745a7c19c7fa77702332cf4bd3f80f9e ,
it's enough to increment only the first element, then we count all of the carries, set where we did a carry and count reset value as the maximum of elements to reset and reset with it.
here's my code:
#include <iostream>
using namespace std;
static long FactNaive(int n)
{
long r = 1;
for (int i = 2; i <= n; ++i)
r *= i;
return r;
}
static long long CrNK (long n, long k)
{
long long u, l;
u = FactNaive(n+k-1);
l = FactNaive(k)*FactNaive(n-1);
return u/l;
}
int main()
{
int numberOFchoices=7,kountOfElementsInCombination=4;
int arrayOfSingleCombination[kountOfElementsInCombination] = {0,0,0,0};
int leftmostResetPos = kountOfElementsInCombination;
int resetValue=1;
for (long long iterationCounter = 0; iterationCounter<CrNK(numberOFchoices,kountOfElementsInCombination); iterationCounter++)
{
leftmostResetPos = kountOfElementsInCombination;
if (iterationCounter!=0)
{
arrayOfSingleCombination[kountOfElementsInCombination-1]++;
for (int anotherIterationCounter=kountOfElementsInCombination-1; anotherIterationCounter>0; anotherIterationCounter--)
{
if(arrayOfSingleCombination[anotherIterationCounter]==numberOFchoices)
{
leftmostResetPos = anotherIterationCounter;
arrayOfSingleCombination[anotherIterationCounter-1]++;
}
}
}
if (leftmostResetPos != kountOfElementsInCombination)
{
resetValue = 1;
for (int j = 0; j < leftmostResetPos; j++)
{
if (arrayOfSingleCombination[j] > resetValue)
{
resetValue = arrayOfSingleCombination[j];
}
}
for (int j = leftmostResetPos; j != kountOfElementsInCombination; j++)
{
arrayOfSingleCombination[j] = resetValue;
}
}
for (int j = 0; j<kountOfElementsInCombination; j++)
{
cout<<arrayOfSingleCombination[j]<<" ";
}
cout<<"\n";
}
return 0;
}
thanks a lot, Minoru

Almost same code running much slower

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.

Iterating from 1..n or n..1 conditionally in C++

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);
}

Pointer Array Sorting Algorithm in C++

hoping I can get a little advice on a sorting method I made.
This is just a test for another program i am making and this test has a bug I can't figure out. The purpose of this code is to create a int pointer array and sort the pointers in that array by the contents of regular int array.
The bug is for my second for loop which doesn't allow me to use a j!=-1 therefore not allowing me to sort the first element of the array. Please help. Thanks!!
//create array
int c[8] = {3,1,5,7,8,2,6,4};
//create pointer array
int *newptr[8];
for(int k = 0; k<8; k++)
{
newptr[k] = &c[k];
}
//sort pointer array
for(int j = 0; j<8; j++)
{
cout << "test1\n\n";
cout << *newptr[j] << "and" << *newptr[j+1];
for(;*newptr[j] < *newptr[j+1] && j!=0; j--)
//using j!=-1 doesn't work which causes me to not be able to sort the first element
//in the array properly
{
cout<< "test2";
int *temp;
temp = newptr[j+1];
newptr[j+1] = newptr[j];
newptr[j] = temp;
}
}**
Order matters.
Change
for(;*newptr[j] < *newptr[j+1] && j!=0; j--)
to:
for(; j != -1 && *newptr[j] < *newptr[j+1]; j--)
Presumably the bug is something that causes the code to crash. This happens because the expression in the for loop is evaluated left-to-right. So *newptr[j] is evaluated before checking if j != -1. So it's conceivable that, at some point, j is equal to -1 when *newptr[j] is evaluated, which is illegal.
Changing the order does make a difference for a second reason: short-circuit evaluation.
When evaluating two an expression made of two conditions A and B, C++ does not always need to evaluate both conditions.
For example in the statement
if (A && B) {
//do something
}
if A is evaluated to be false, then obviously A && B cannot evaluate to true regardless of what B evaluates to. So B's value is never even checked. So in your case, in the expression
j != -1 && *newptr[j] < *newptr[j+1]
if j != -1 is false, C++ will not need to evaluate the rest of the expression in order to know that the whole expression is false. So *newptr[j] never happens and you don't get the bug.
As pointed out by maditya the problem is that the expression tries to access an invalid index before checking the index itself but I see the question is tagged C++. Do you have any explicit reason to not use STL?
struct sorter {
bool operator() (const int* i, const int* j) { return (*i<*j);}
};
int c[8] = {3,1,5,7,8,2,6,4};
int *newptr[8];
for(int k = 0; k<8; k++)
newptr[k] = &c[k];
std::sort(newptr, newptr+8, sorter());
or even shorter in C++11:
int c[8] = {3,1,5,7,8,2,6,4};
int *newptr[8];
for(int k = 0; k<8; k++)
newptr[k] = &c[k];
std::sort(newptr, newptr+8, [](const int *i, const int *j){return *i < *j;});

Positive rows in a matrix

I have to do an exercise for University that asks me to check ( for k times ) if a matrix has positive rows ( i mean a row with all positive elements ) , i think there's something wrong with the indices of for loops but i cannot find the mistakes.
i tried to debug with a cout statement apply to the counter an it gives me "101" , so it seems like compiler assign "1" to the positive rows and "0" to the negative
This is the code i wrote:
#include <iostream>
using namespace std;
const int N = 3;
bool positive(int a[N][N], int row[N], int x) {
bool condition = false;
for(int i = 0; i < N; i++) {
row[i] = a[x][i];
}
int j = 0;
while(j < N) {
if(row[j] >= 0) {
condition = true;
} else {
condition = false;
}
j++;
}
return condition;
}
bool function (int a[N][N], int z, int j, int k) {
int b[N];
int c[N];
int count = 0;
if(positive(a, b, z) && positive(a, c, j)) {
count++;
}
if(count == k) {
return true;
} else {
return false;
}
}
int main() {
int a[N][N] = {
{
2, 8, 6
}, {
-1, - 3, - 5
}, {
6, 10, 9
}
};
int k = 2;
for(int i = 0; i < N; i++) {
for(int j = 0; j < N; j++) {
if(function (a, i, j, k)) {
cout << "OK";
} else {
cout << "NO";
}
}
}
return 0;
}
You should probably take another look at this problem and restart with a different solution. The objective is pretty easy but your code is surprisingly complex and some of it doesn't really make sense.
For example, if you had a matrix like this:
1 2 4 --> matrix A
-1 8 -6
3 9 2
You have N=3 rows and columns. The only thing you have to to based on what you said is take the matrix, cycle through the N rows, and for each row, check it's N columns to see if anything is < 0.
Doing this K times, as you put it, makes no sense. The matrix will be the same every time you compare it since you're not changing it, why would you do it more than once? I think you should reread the assignment brief there.
As for the logic of finding which rows are positive or negative, just do something simple like this.
//Create array so we have one marker for each row to hold results.
bool rowPositiveFlags[N] = { true, true, true };
//Cycle through each row.
for (int row = 0; row < N; ++row)
//Cycle through every column in the current row.
for (int col = 0; col < N; ++col)
//If the column is negative, set the result for this row to false and break
//the column for loop as we don't need to check any more columns for this row.
if (A[row][col] < 0) {
rowPositiveFlags[row] = false;
break;
}
You should always name things so that you can read your code like a book. Your i's, j's, and k's just make something simple confusing. As for the problem, just plan out your solution.
Solve the problem by hand on paper, write the steps in comments in your code, and then write code below the comments so what you do definitely makes sense and isn't overkill.
And this is a great site, but next time, post a smaller piece of code that shows your problem. People shouldn't ever give you a full solution here for homework so don't look for one. Just find the spot where your indices are broken and paste that set of 5 lines or whatever else is wrong. People appreciate that and you'll get faster, better answers for showing the effort :)