I am confused as to what what the difference is between for loop and for each loop in C++.
I read tutorials and some books but I am yet to see how for each loop is different.
With arrays, examples I have seen seem to suggest for each loop loops through the whole elements at a go. Could that be the special advantage range based loop has?
The main difference is that the ordinary for-loop uses an additional variable used as an index inside the array and has the scope of the loop and you can yourself write the condition of the for loop.
For example let's assume that you need to output either all even elements of an array or until an element with a zero value is encountered. You can write
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N && a[i] != 0; i++ )
{
if ( a[i] % 2 == 0 ) std::cout << i << ": " << a[i] << '\n';
}
return 0;
}
The program output is
1: 2
3: 4
5: 6
7: 8
How to do this with the range-based for loop? For starters before the loop you need to declare a variable that will play the role of the index. One drawback of this is the variable is not declared in the scope where it is used.
Also to stop the iterations of the loop you need to use a break statement within the loop. That also makes the code more complicated.
Compare the above program with this
#include <iostream>
int main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11, 12 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t i = 0;
for ( const auto &item : a )
{
if ( item == 0 )
{
break;
}
else if ( item % 2 == 0 )
{
std::cout << i << ": " << item << '\n';
}
++i;
}
return 0;
}
In general to use the range based for loop the used container either shall have member functions begin and end or the general functions begin and end shall support the container. For arrays begin and end mean expressions a and a + N.
The difference between a for loop and a range based for loop is roughly analogous to the difference between goto and a for loop. Former is a more generic control flow, while the latter is more structured. Every range based loop can be written as a for loop and every for loop can be written as a goto. But the reverse is not true.
Goto encapsulates the idea of jumping elsewhere. Loop encapsulates the idea of repetition (which involves jumping back). Range based loop encapsulates the idea of iterating over a range from begin until end (which involves repetition).
If your intention is to iterate over an entire range, then the range based loop is typically syntactically simpler, and easier to understand than a for loop. Likewise, a for loop is easier to understand than a goto loop. This is what makes structured approach superior. Compare for example the following, and consider which one is easier to understand:
for (auto it = list.begin(), end = list.end(); it != end; ++it) {
auto& element = *it;
// do stuff with element
}
for (auto& element : list) {
// do stuff with element
}
loops through the whole elements at a go. Could that be the special advantage range based loop has?
Looping through an entire range is what range based loop can do. A for loop can do that too. But a for loop can do much more: it can iterate indices, it can iterate indefinitely, it can iterate until a terminator etc.
Let's say I have a set of elements S = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
I would like to create combinations of 3 and group them in a way such that no number appears in more than one combination.
Here is an example:
{ {3, 7, 9}, {1, 2, 4}, {5, 6, 8} }
The order of the numbers in the groups does not matter, nor does the order of the groups in the entire example.
In short, I want every possible group combination from every possible combination in the original set, excluding the ones that have a number appearing in multiple groups.
My question: is this actually feasible in terms of run time and memory? My sample sizes could be somewhere around 30-50 numbers.
If so, what is the best way to create this algorithm? Would it be best to create all possible combinations, and choose the groups only if the number hasn't already appeared?
I'm writing this in Qt 5.6, which is a C++ based framework.
You can do this recursively, and avoid duplicates, if you keep the first element fixed in each recursion, and only make groups of 3 with the values in order, eg:
{1,2,3,4,5,6,7,8,9}
Put the lowest element in the first spot (a), and keep it there:
{a,b,c} = {1, *, *}
For the second spot (b), iterate over every value from the second-lowest to the second-highest:
{a,b,c} = {1, 2~8, *}
For the third spot (c), iterate over every value higher than the second value:
{1, 2~8, b+1~9}
Then recurse with the rest of the values.
{1,2,3} {4,5,6} {7,8,9}
{1,2,3} {4,5,7} {6,8,9}
{1,2,3} {4,5,8} {6,7,9}
{1,2,3} {4,5,9} {6,7,8}
{1,2,3} {4,6,7} {5,8,9}
{1,2,3} {4,6,8} {5,7,9}
{1,2,3} {4,6,9} {5,7,8}
{1,2,3} {4,7,8} {5,6,9}
{1,2,3} {4,7,9} {5,6,8}
{1,2,3} {4,8,9} {5,6,7}
{1,2,4} {3,5,6} {7,8,9}
...
{1,8,9} {2,6,7} {3,4,5}
Wen I say "in order", that doesn't have to be any specific order (numerical, alphabetical...), it can just be the original order of the input. You can avoid having to re-sort the input of each recursion if you make sure to pass the rest of the values on to the next recursion in the order you received them.
A run-through of the recursion:
Let's say you get the input {1,2,3,4,5,6,7,8,9}. As the first element in the group, you take the first element from the input, and for the other two elements, you iterate over the other values:
{1,2,3}
{1,2,4}
{1,2,5}
{1,2,6}
{1,2,7}
{1,2,8}
{1,2,9}
{1,3,4}
{1,3,5}
{1,3,6}
...
{1,8,9}
making sure the third element always comes after the second element, to avoid duplicates like:
{1,3,5} ⇆ {1,5,3}
Now, let's say that at a certain point, you've selected this as the first group:
{1,3,7}
You then pass the rest of the values onto the next recursion:
{2,4,5,6,8,9}
In this recursion, you apply the same rules as for the first group: take the first element as the first element in the group and keep it there, and iterate over the other values for the second and third element:
{2,4,5}
{2,4,6}
{2,4,8}
{2,4,9}
{2,5,6}
{2,5,8}
{2,5,9}
{2,6,7}
...
{2,8,9}
Now, let's say that at a certain point, you've selected this as the second group:
{2,5,6}
You then pass the rest of the values onto the next recursion:
{4,8,9}
And since this is the last group, there is only one possibility, and so this particular recursion would end in the combination:
{1,3,7} {2,5,6} {4,8,9}
As you see, you don't have to sort the values at any point, as long as you pass them onto the next recursion in the order you recevied them. So if you receive e.g.:
{q,w,e,r,t,y,u,i,o}
and you select from this the group:
{q,r,u}
then you should pass on:
{w,e,t,y,i,o}
Here's a JavaScript snippet which demonstrates the method; it returns a 3D array with combinations of groups of elements.
(The filter function creates a copy of the input array, with elements 0, i and j removed.)
function clone2D(array) {
var clone = [];
for (var i = 0; i < array.length; i++) clone.push(array[i].slice());
return clone;
}
function groupThree(input) {
var result = [], combination = [];
group(input, 0);
return result;
function group(input, step) {
combination[step] = [input[0]];
for (var i = 1; i < input.length - 1; i++) {
combination[step][1] = input[i];
for (var j = i + 1; j < input.length; j++) {
combination[step][2] = input[j];
if (input.length > 3) {
var rest = input.filter(function(elem, index) {
return index && index != i && index != j;
});
group(rest, step + 1);
}
else result.push(clone2D(combination));
}
}
}
}
var result = groupThree([1,2,3,4,5,6,7,8,9]);
for (var r in result) document.write(JSON.stringify(result[r]) + "<br>");
For n things taken 3 at a time, you could use 3 nested loops:
for(k = 0; k < n-2; k++){
for(j = k+1; j < n-1; j++){
for(i = j+1; i < n ; i++){
... S[k] ... S[j] ... S[i]
}
}
}
For a generic solution of n things taken k at a time, you could use an array of k counters.
I think You can solve it by using coin change problem with dynamic programming, just assume You are looking for change of 3 and every index in array is a coin value 1, then just output coins(values in Your array) that has been found.
Link: https://www.youtube.com/watch?v=18NVyOI_690
In this project, there are multiple sets in which they hold values from 1 - 9. Within this, I need to efficiently determine if there are values that is unique in one set but not others.
For Example:
std::set<int> s_1 = { 1, 2, 3, 4, 5 };
std::set<int> s_2 = { 2, 3, 4 };
std::set<int> s_3 = { 2, 3, 4, 6 };
Note: The number of sets is unknown until runtime.
As you can see, s_1 contains the unique value of 1 and 5 and s_3 contains the unique value of 6.
After determining the unique values, the aforementioned sets should then just contain the unique values like:
// s_1 { 1, 5 }
// s_2 { 2, 3, 4 }
// s_3 { 6 }
What I've tried so far is to loop through all the sets and record the count of the numbers that have appeared. However I wanted to know if there is a more efficient solution out there.
There are std algorithm in the std C++ library for intersection, difference and union operations on 2 sets.
If I understood well your problem you could do this :
do an intersection on all sets (in a loop) to determine a base, and then apply a difference between each set and the base ?
You could benchmark this against your current implementation. Should be faster.
Check out this answer.
Getting Union, Intersection, or Difference of Sets in C++
EDIT: cf Tony D. comment : You can basically do the same operation using a std::bitset<> and binary operators (& | etc..), which should be faster.
Depending on the actual size of your input, might be well worth a try.
I would suggest something in c# like this
Dictionary<int, int> result = new Dictionary<int, int>();
foreach(int i in sets){
if(!result.containskey(i))
result.add(i,1);
else
result[i].value = result[i].value+1;
}
now the Numbers with count value only 1 means its unique, then find the sets with these numbers...
I would suggest :
start inserting all the elements in all the sets into a multimap.
Here each element is a key and and the set name with be the value.
One your multimap is filled with all the elements in all the sets,
then loop throgth the multimap and take count of each element in the
multimap.
If the count is 1 for any key, this means its unique and value of
that will be the set name.