In the following for loop, I test if a letter in a query is in an unordered_map<string, int>. If it is not, I print out some things.
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]
for (vector<string>& q : queries) {
int start = index[q[0]], end = index[q[1]];
if (index.find("z") == index.end()) {cout << "z" << '\n';
}
index only contains a, b, c. Correspondingly, the output is this:
z
z
z
z
z
Which it should be, because one of the queries has an z in it. Printing the size of index gives 3.
However, if I run this:
for (vector<string>& q : queries) {
int start = index[q[0]], end = index[q[1]];
if (index.find(q[0]) == index.end()) {cout << "z" << '\n';
}
I don't get any output, but I expect output for x because that isn't in index.
Why is this?
By the description of the operator [] of map in cppreferance:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
index[q[0]] created the entry of the key "x".
The operator[] for a std::(unordered_)map creates a new entry in the map if the requested key is not found.
index only contains a, b, c.
In your first example, index.find("z") will return index.end() if q[0] and q[1] are never "z", which is true in your example.
However, by the time your loop finishes, index will not contain just a, b, c like you think. It will actually contain a, b, c, e, x. When you initialize start and end with the values of index[q[0]] and index[q[1]], the operator[] will insert the values of q[0] and q[1] into index if they do not already exist.
I don't get any output, but I expect output for x because that isn't in index.
In your second example, index.find(q[0]) will never return index.end(), because of initializing start and end with the values of index[q[0]] and index[q[1]]. Every value in q[0] and q[1] gets added into index. So, adding the value of q[0] and then searching for the value of q[0] will always succeed, and never return index.end().
So yes, there actually IS an entry for "x" in index, when the loop reaches the last vector in queries containing "x" strings and the operator[] adds them into index.
Related
I am inserting number from a vector in map with key as the number and value as it's (index + 1).
But when I print the contents of the map, value being shown is 0 though I pass interger i.
// taking input of n integers in vector s;
vector<int> s;
for(int i=0;i<n;i++){
int tmp;cin>>tmp;
s.push_back(tmp);
}
//creating map int to int
map<int,int> m;
bool done = false;
for(int i=1;i<=s.size();i++){
//check if number already in map
if (m[s[i-1]]!=0){
if (i-m[s[i-1]]>1){
done = true;
break;
}
}
// if number was not in map then insert the number and it's index + 1
else{
m.insert({s[i-1],i});
}
}
for(auto it=m.begin();it!=m.end();it++){
cout<<endl<<it->first<<": "<<it->second<<endl;
}
For input
n = 3
and numbers as
1 2 1 in vector s, I expect the output to be
1: 1
2: 2
but output is
1: 0
2: 0
Why 0? What's wrong?
Your code block following the comment:
// check if number already in map
is logically faulty, because operator[] will actually insert an element, using value initialisation(a), if it does not currently exist.
If you were to instead use:
if (m.find(s[i-1]) != m.end())
that would get rid of this problem.
(a) I believe(b) that value initialisation for classes involve one of the constructors; for arrays, value initialisation for each item in the array; and, for other types (this scenario), zero initialisation. That would mean using your method creates an entry for your key, with a zero value, and returns that zero value
It would then move to the else block (because the value is zero) and try to do the insert. However, this snippet from the standard (C++20, [map.modifiers] discussing insert) means that nothing happens:
If the map already contains an element whose key is equivalent to k, there is no effect.
(b) Though, as my kids will point out frequently, and without much prompting, I've been wrong before :-)
std::map::operator[] will create a default element if it doesn't exist. Because you do m[s[i-1]] in the if condition, m.insert({s[i-1],i}); in else branch will always fail.
To check if key is already present in map use either find(), count() or contains() (if your compiler supports C++20)
//either will work instead of `if (m[s[i-1]]!=0)`
if (m.find(s[i-1]) != m.end())
if (m.count(s[i-1]) == 1)
if (m.contains(s[i-1])) //C++20
I'm trying to make a program that gives the last element that is less than or equal to our given value.
According to the definition of lower_bound, it gives the first element that is greater than or equal to the given key value passed. I created a comparator function
bool compare(int a, int b) {
return a <= b;
}
This was passed in my lower bound function:
int largest_idx = lower_bound(ic, ic + n, m, compare)
On execution, it was giving me the last element which was less than equal to my m (key value). Isn't this opposite to how lower_bound works ? Lower bound is supposed to give me the first value for my comparison or does the comparator actually change that?
If you want to turn "first" into "last", you have two options. First, you can use std::upper_bound and then take the previous element (see below). Second, you can use reverse iterators:
const auto pos = std::lower_bound(
std::make_reverse_iterator(ic + n),
std::make_reverse_iterator(ic), m, compare);
where compare is
bool compare(int a, int b) {
return b < a;
}
With this comparator, std::lower_bound() returns the iterator pointing to the first element that is not greater (= less than or equal) than m. On the reversed range this is equivalent to returning the iterator pointing to the last element satisfying this criterion in the original range.
Simple example:
int ic[] = {1, 3, 3, 5};
// pos
// m = 1 ^
// m = 2 ^
// m = 3 ^
How do I modify that search criteria (change <= to something else)?
std::lower_bound finds the first element in the range (partitioned by the comparator into true, ..., true, false, ... false), for which the comparator returns false. If your criterion can be rephrased in this language, you can use std::lower_bound.
Suppose we have a range 1 3 3 5 and we replace < with <= (your version of compare). Then we have:
1 3 3 5
m = 2 T F F F
m = 3 T T T F
m = 4 T T T F
For m = 3 and m = 4, std::lower_bound will return the iterator to 5, i.e. past the last 3. In other words, std::lower_bound with default < being replaced with <= is exactly what std::upper_bound with default < is. You can advance the resulting iterator by -1 to get the last element (but be careful about corner cases like m = 0 in this example).
How do I change whether I want the first or last element
It always returns the first element for which the comparator returns false. You can either reverse the range or find the first element that follows the one you want to find.
The comparator must not check for equality, use less than.
Also the data shall already be sorted or must at least be partitioned according to the comparator.
cf. https://www.cplusplus.com/reference/algorithm/lower_bound/
In the following code, I have tried using a field variable (of class or record) or an array element directly as a loop counter, but this was illegal ("error: invalid index expression"). Is this simply because the loop counter must be a scalar variable?
class Cls {
var n: int;
}
proc main()
{
var x = new Cls( 100 );
var k: [1..10] int;
for x.n in 1..3 do // error: invalid index expression
writeln( x.n );
for k[1] in 1..3 do // error: invalid index expression
writeln( k[1] );
}
On the other hand, if I create a reference to x.n, it compiled successfully but x in the outer scope was not modified. Is this because a new loop variable named n is created in the for-loop? (which I'm afraid is almost the same as my another question...)
proc main()
{
var x = new Cls( 100 );
ref n = x.n;
for n in 1..3 do
writeln( n );
writeln( "x = ", x ); // x = {n = 100}
}
If a loop variable is created independently, I guess something like "var x.n = ..." might happen (internally) if I write for x.n in 1..3, which seems really invalid (because it means that I'm trying to declare a loop variable with a name x.n).
You're correct that this relates to your other question. As described there, Chapel's for-loops create new index variables to store the values yielded by the iterator expression(s), so a loop like for i in ... results in a new variable i being declared rather than using an existing variable or expression. If you think the error message should be improved to make this clearer, please consider suggesting a new wording in a GitHub issue.
Note that in addition to single variable names, a loop can also use tuples of index variables to capture the results of a zippered iteration or an iterand that yields tuple values. For instance, the values of the following zippered iteration can either be captured as scalar values i and j:
for (i,j) in zip(1..3, 2..6 by 2) do // store values in 'i' and 'j' respectively
writeln((i,j));
or as a single variable of tuple type:
for ij in zip(1..3, 2..6 by 2) do // store values in 2-tuple 'ij'
writeln(ij);
Similarly, when iterating over something that yields tuple values, such as a multidimensional index set, the results can be captured either as scalar values or tuples:
const D = {1..3, 0..2}; // declare a 2D rectangular domain
for (i,j) in D do // store indices in new scalars 'i' and 'j'
writeln((i,j));
for ij in D do // store indices in new 2-tuple 'ij'
writeln(ij);
More complex iterators that return larger, or nested tuples, can similarly be de-tupled or not in the declaration of the index variable(s).
So, I just started out with Kotlin and tried to solve "min steps for a knight to reach a destination on a chessboard" problem.
Here is my code:
fun knightSteps(i:Int,j:Int,a:Int,b:Int,board:Int,c :Int,d:Int,visited : MutableList<Pair<Int,Int>>,steps:Int):Int{
// (i,j) start (a,b)knight moves (c,d) destination visited - visited positions board - size of board
if(i==c && j==d) return steps
if(isValid(Pair(i,j),board)){
val v = visited
v.add(Pair(i,j))
var possible = mutableListOf<Int>()
if(Pair(i+a,j+b) !in v ) {
possible.add(knightSteps(i + a, j + b, a, b, board,c,d, v, 1 + steps))
}
if(Pair(i+a,j-b) !in v ) {
if(i==1&&j==3) println("YES!!")
possible.add(knightSteps(i + a, j - b, a, b, board,c,d, v, 1 + steps))
}
.
. // rest of other 8 possible moves
.
possible.removeAll{it==-1}
if(possible.size==0){
return -1
}
//println(possible)
return possible.min()!!
}
return -1
}
But once it passes the first 'if' condition the 'visited' and 'v' mutable lists are changing their values as a result the println("YES!!") in second 'if' is never executed.
So the function is changing them.. again if i change val v = visited.toMutableList() it enters into infinite loop! Can someone help.
Yes, in java and kotlin almost everything is being passed as reference. But in kotlin you have compile-time verified ability to make any MutableList immutable - just change method argument type from MutableList to List
When you add values to visited they will be added to the argument of your function (i.e. are also visible outside the function). Also, v and visited are pointing to the same object. It doesn't matter which variable you use to add elements to, the list will contain a new element afterwards. The statement val v = visited does not create any copy.
For copying a list you can do visited.toList() which under the hood basically maps to a call of ArrayList(visited).
Currently, i have a loop iterating through a vector, and i'm trying to find the index of an object, while i'm in the loop, to delete it. How can i go about this?
Here's my code :
for (Object &a : objectDict)
{
a.setTime(theTime);
double tempMoveX = 0, tempMoveZ = 0, tempUX = 0,tempUZ = 0;
for (Object &b : objectDict)
{
if (a != b)
{
...
debug << fixed << setprecision(20) << "Collision" << endl;
a.appendMass(b.getMass());
objectDict.erase(find(objectDict.begin(), objectDict.end(), b));
...
Thats the important part. How can i erase object b from the vector?
One easy way is to simply build a separate vector containing the indexes of elements to erase later. Once you've finished going through the regular vector, loop in reverse order through the "to be removed" vector (in reverse because you don't want to invalidate the indexes as you go), and erase them.
Alternatively, as you iterate over the original vector, select the elements you want to keep, and copy them to another vector. At the very end, swap the two vectors (which is cheap). This will work better if you have relatively many elements to delete, on average.
Well, in case you need an index while iterating vector's elements, instead of:
for (Object &a : objectDict) { ...
do traditional:
for (size_t i = 0; i < objectDict.size(); ++i) { ...
and within the loop's body: instead of using reference a, you'll use objectDict[i], then when you will need to erase element, you can do:
objectDict.erase(vec.begin() + i);
i--;
i-- is used to move the index backwards by 1 so that when the next iteration increments it again, the element that follows right after the element that has been erased is not skipped.