I am following this tutorial on Lower_bound() in C++. I have made a simple code to find a number in a vector lesser than or equal to a number from the vector + any number that I want. My code goes like this
cout << *lower_bound(A.begin(), A.end(), A[x] + 3);
where the vector A[] is sorted. But the code points it to a number greater than the sum of both the numbers.
For example if my vector has values as 0, 3, 5, 8, 12 and I want it to print the nearest number lesser than or equal to A[3] + 3 = 11 it should give output as 8 but it gives the output of 12. Any reasons?
Here is my code:
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> A = {0, 5, 3, 12, 8};
sort(A.begin(), A.end());
cout << "A[3] = " << A[3] << endl;
cout << *lower_bound(A.begin(), A.end(), A[3] + 3) << endl;
return 0;
}
lower_bound
Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.
In your case it is not returning the last value less than 11. It returns the first value not less than 11, which in your example is 12.
If you want the largest number not greater than your target, you can use std::greater<> and reverse iterators (or sort by std::greater<>)
#include <vector>
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> A = {0, 5, 3, 12, 8};
std::sort(A.begin(), A.end());
std::cout << "A[3] = " << A[3] << std::endl;
std::cout << *std::lower_bound(A.rbegin(), A.rend(), A[3] + 3, std::greater<int>{}) << std::endl;
return 0;
}
Related
I am new in C++ world.
There is a upper_bound function in a set that returns number greater than passed value. I would like to know if there is any way to get a number lower than the passed value? Let's say if we have {3,6,8,9,11} in set and by passing to my function: func(8), I will receive 6, since 6 is the number that stays before 8.
Any idea?
Your approach is reasonable, but instead of std::upper_bound, you should use std::lower_bound, like this for example:
#include <iostream>
#include <set>
using namespace std;
int main(void)
{
set<int> myset{3, 6, 8, 9, 11};
set<int>::iterator it = myset.lower_bound(8);
if (it != myset.begin()) {
it--;
cout << *it << endl;
} else {
cout << "No smaller element found!" << endl;
}
return 0;
}
Ouptut:
6
I'm creating text based TicTacToe in C++ and need to create a function that checks for a win.
Right now, I have a vector of all the moves player X has made:
std::vector<int> x_vector = {1, 2, 3, 5, 7};
I also have a 2d vector of win conditions:
std::vector<std::vector> > wins = {{1, 2, 3}, {4, 5, 6}, {7, 8, 8}};
In this case, each element of the wins vector represents a win condition. If player X ever has a combination of inputs in their vector that includes one of the win conditions, I'm trying to get a bool function to return true.
I'm new to C++ and coding in general, so all patience is appreciated, and the simpler the solution you can help me find the better.
You can iterate through your list of known wins, checking each to see if it is a subset of the list of user's moves. The std::includes function will do this test – but note that the two 'lists' need to be sorted.
To avoid having to manually sort the list of user's moves after each input, you can use the std::set container (which is inherently sorted), instead of std::vector.
The following snippet shows a relatively simple implementation of an isWin() function using this approach, along with some rudimentary test cases:
#include <iostream>
#include <vector>
#include <set>
#include <algorithm> // For std::includes
bool isWin(const std::set<int>& test)
{
static std::vector<std::set<int>> winlist = {
{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, // Horizontal lines
{1, 4, 7}, {2, 5, 8}, {3, 6, 9}, // Vertical lines
{1, 5, 9}, {3, 5, 7}, // Diagonal lines
};
for (auto win : winlist) {
if (std::includes(test.begin(), test.end(), win.begin(), win.end())) {
return true; // Match - Win!
}
}
return false; // Didn't get a match - no win
}
int main()
{
std::set<int> s1{ 1, 2 }; // Trivial "No win" (only 2 moves)
std::cout << "s1: " << isWin(s1) << "\n";
std::set<int> s2{ 1, 2, 3 }; // Trivial "Win" (top row)
std::cout << "s2: " << isWin(s2) << "\n";
std::set<int> s3{ 2, 4, 1, 5 }; // " No Win"
std::cout << "s3: " << isWin(s3) << "\n";
std::set<int> s4{ 5, 2, 4, 6 }; // "Win" (middle row)
std::cout << "s4: " << isWin(s4) << "\n";
std::set<int> s5{ 5, 1, 3, 6, 9 }; // "Win" (diagonal)
std::cout << "s5: " << isWin(s5) << "\n";
return 0;
}
Note that this approach may not be the best for checking wins in a Tic-Tac-Toe game; however, if your purpose is to learn about vectors, sets and looking for matching sub-sequences, it may provide a useful starting-point.
For your actual user input, you would declare and initialize an empty set and then add moves using the insert member function of the std::set container class; something like this:
int main()
{
std::set<int> user{}; // Empty Set
user.insert(5);
user.insert(2);
user.insert(4);
user.insert(6);
std::cout << "user (1): " << isWin(user) << "\n";
user.clear();
user.insert(2);
user.insert(4);
user.insert(1);
user.insert(5);
std::cout << "user (2): " << isWin(user) << "\n";
return 0;
}
I am trying to find a rightmost subsequence in a range with std::search and std::make_reverse_iterator.
However the iterator returned always point to the start of a range. What am I doing wrong?
TEST(basic_test, find_from_right)
{
std::vector<uint8_t> array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::array<uint8_t, 2> subSeq{3, 4};
auto found = std::search(std::make_reverse_iterator(array.cend()),
std::make_reverse_iterator(array.cbegin()),
subSeq.cbegin(),
subSeq.cend());
// makes no difference
// std::make_reverse_iterator(subSeq.cend()),
// std::make_reverse_iterator(subSeq.cbegin()));
auto distance = std::distance(found.base(), array.cbegin());
EXPECT_EQ(distance, 3);
}
Output:
Failure
Expected equality of these values:
distance
Which is: 0
3
I have a function that is provided with 2 template RandomIterators, so I have to call std::make_reverse_iterator. These containers are just for the sake of reproducing the problem and compiling the example.
I think this could solve your problem (if you are okay with C++17):
From https://en.cppreference.com/w/cpp/algorithm/find_end:
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4};
std::vector<int>::iterator result;
std::vector<int> t1{1, 2, 3};
result = std::find_end(v.begin(), v.end(), t1.begin(), t1.end());
if (result == v.end()) {
std::cout << "sequence not found\n";
} else {
std::cout << "last occurrence is at: "
<< std::distance(v.begin(), result) << "\n";
}
std::vector<int> t2{4, 5, 6};
result = std::find_end(v.begin(), v.end(), t2.begin(), t2.end());
if (result == v.end()) {
std::cout << "sequence not found\n";
} else {
std::cout << "last occurrence is at: "
<< std::distance(v.begin(), result) << "\n";
}
}
So in your case:
auto result = std::find_end(array.begin(), array.end(), subSeq.begin(), subSeq.end());
if (result == array.end()) {
std::cout << "sequence not found\n";
} else {
std::cout << "last occurrence is at: "
<< std::distance(array.begin(), result) << "\n";
}
In C++ prime 5 Ed chapter 11. Associative containers. "Table 11.7. Operations to Find Elements in an Associative Container":
It is said: "c.equal_range(k) returns a pair of iterators denoting the elements with key k. if k is not present, both members are c.end()."
set<int> si{ 5, 7, 23, 16, 81, 24, 10};
auto it = si.equal_range(13);
cout << *it.first << " " << *it.second << endl; // 16 16
But as you can see above 13 was not found but it returns a pair of iterators for elements16, 16?!
Running this program, it works as intended: It returns the end iterators.
int main (int argc, char** argv) {
std::set<int> si{ 5, 7, 23, 16, 81, 24, 10};
auto it = si.equal_range(99);
if(it.first == std::end(si)) {
std::cout << "Element not found." << std::endl;
}
else {
std::cout << *it.first << ", " << *it.second << std::endl;
}
return 0;
}
But, if I were to check for 13, I'd get back 16, 16.
According to cppreference.com
Returns a range containing all elements with the given key in the container. The range is defined by two iterators, one pointing to the first element that is not less than key and another pointing to the first element greater than key. Alternatively, the first iterator may be obtained with lower_bound(), and the second with upper_bound().
16 just happens to be the first element that is not less than and also greater than 13 in your example.
I want to implement an insert function in c++ to build a d-max heap. The d is referring to the number of children in the heap and a max heap is a heap which has its' elements structured in a priority (3,2,1...). The heap is supposed to be represented as an array and the function I'm looking for is adding items from the top one by one and then continuing downward. This may seem like an easy task but I'm confused about how this is going to work.
Here is a rough example of the template function:
template <typename Comparable>
void buildHeapTopDown(Comparable arr[], int size, int d)
{
for (int i = 0; i < 5; ++i)
{
arr[0] = 2;
arr[1] = 3;
arr[2] = 4;
arr[3] = 6;
arr[4] = 9;
}
}
Now as this is some really basic code the function is not really informative about the way a d-heap works. What I mean is I have not implemented the theory behind the d-heap, which basically is pretty much the same as the theory behind a binary heap (we only replace 2 with d in the formulas). The formulas for finding a parent and a child for a heap then becomes:
(x-1) / d, x*d + 1 (left child) and x*d + 2 (right child).
I also know there is a way to create a heap using the <algorithm> class, but as these functions are already prepared and they are using vectors, it's not really what I'm looking for.
Example using the algorithm class:
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int myInts[] = { 1, 2, 3, 5, 4, 7, 10, 13, 15, 6, 8, 17, 9, 11, 9 };
vector <int> v(myInts, myInts + 15);
make_heap(v.begin(), v.end());
cout << "Initial max heap: " << v.front() << endl;
pop_heap(v.begin(), v.end());
v.pop_back();
cout << "Max heap after pop: " << v.front() << endl;
v.push_back(77); // insert example
push_heap(v.begin(), v.end());
cout << "Max heap after push: " << v.front() << endl;
sort_heap(v.begin(), v.end());
cout << "Final sorted range:";
for (unsigned i = 0; i < v.size(); i++)
{
cout << " " << v[i];
}
cout << endl;
getchar();
getchar();
}
Anyone who can give any hints how to do it as the way I described in the top?