Generate random coordinates in a rectangle qt - c++

I have a rectangle with length 27.5 and width 3.5 and I am supposed to generate coordinates within this rectangle which are unique i.e., without any duplicates. The number of coordinates that need to be generated are based on the size of a list. Here is what I have done so far using Qt:
struct coordinates_t{
int x;
int y;
};
QVector<coordinates_t> coordinatesList;
QList<QString> listOfDevices;
//populate listOfDevices
for( int i = 0; i < listOfDevices.count(); i++)
{
coordinatesList.pushback({rand() % 51 + (-25), rand() % 11 + (-5)});
}
The problem now is that even though the rand function generates random numbers within the rectangle, it does not however avoid duplicates. Is there someway in which I can avoid the duplicates and produce unique coordinates within the given rectangle.

The normal way of solving this would be to shuffle a predefined set of coordinates. But this isn't practical in this instance. Furthermore, duplicates on one axis are allowed too.
Consider solving this by
Defining bool operator<(const coordinates_t& other) const and bool operator==(const coordinates_t& other) const
Use a std::set<coordinates_t>. This is possible once you've done (1).
Insert random coordinates into the set until the desired size of the set is reached.
Copy that set into the QVector if you still need them to be stored that way. If you want to preserve the insertion order (set will sort the values according to how you define the operators in (1)), then retain the QVector, and only push a point to it if insertion into the set was successful.
Insertion of a duplicate into a set is an O(Log N) no-op. Also note that rand() as a linear congruential generator might throw out undesirable autocorrelation effects that manifest themselves particularly in an x, y plot. Consider using Mersenne Twister instead.

Here is an example that demonstrates the check for duplicates using QVector and QPoint. If you want to use QVector::contains with your own struct, you must implement the operator==().
#include <QCoreApplication>
#include <QVector>
#include <QPoint>
#include <QDateTime>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVector<QPoint> point_vector;
qsrand(QDateTime::currentMSecsSinceEpoch());
const int max_points = 20;
while(point_vector.size() < max_points)
{
QPoint point(qrand() % 27, qrand() % 4);
if(!point_vector.contains(point))
point_vector.append(point);
}
qDebug() << point_vector;
return a.exec();
}

Just for completeness sake. :)
In my comment I suggested using a QMap but I had a std::set in mind, which in Qt does not have an equivalent. :(
Anyway, I wanted to see if a QMap could do the trick as well and came up with an ... a little bit strange approach.
Putting a QPoint into the QMap does not work since the inserted key needs to have the < operator implemented, which is not the case for QPoint but it for QPair. Thus my choice.
The idea is to (a bit like in thuga's answer) compare the size() of the resulting list to the list of devices and insert until they are equally long. However, since I bound myself to using QMap, here's my version. :)
#include <ctime>
#include <QMap>
#include <QDebug>
#include <QPair>
int main()
{
qsrand(std::time(nullptr));
QMap<QPair<int, int>, QString> coords;
QList<QString> listOfDevices;
//populate listOfDevices
for (int i = 10; i < 30; ++i) {
listOfDevices.append("dev" + QString::number(i));
}
qDebug() << "Number of devices:" << listOfDevices.size();
int demo_counter = 0;
while (coords.size() < listOfDevices.size()) {
coords.insert(
qMakePair(qrand() % 51 + (-25), qrand() % 11 + (-5)),
listOfDevices.at(coords.size())
);
++demo_counter;
}
for (auto it = coords.cbegin(); it != coords.cend(); ++it) {
qDebug() << it.key() << ':' << it.value();
}
qDebug() << "Entries inserted:" << coords.size();
qDebug() << "Tries needed:" << demo_counter;
return 0;
}
This outputs (see how it tried 23 times for adding 20 entries):
Number of devices: 20
QPair(-25,-2) : "dev14"
QPair(-23,3) : "dev28"
QPair(-22,5) : "dev20"
QPair(-20,5) : "dev11"
QPair(-19,-1) : "dev22"
QPair(-19,0) : "dev27"
QPair(0,-2) : "dev29"
QPair(5,-3) : "dev23"
QPair(9,0) : "dev28"
QPair(10,1) : "dev17"
QPair(11,-5) : "dev18"
QPair(11,4) : "dev25"
QPair(16,-2) : "dev12"
QPair(16,4) : "dev26"
QPair(21,-2) : "dev26"
QPair(21,2) : "dev16"
QPair(21,4) : "dev15"
QPair(23,-2) : "dev24"
QPair(25,2) : "dev21"
QPair(25,4) : "dev23"
Entries inserted: 20
Tries needed: 23
Since your requirement is not exactly clear and you might be able to fill in the devices within the while loop as well, there is no way to tell, which solution is better suited but if you really want two different lists, one with devices and one with coords, the solution with the contains() check is to be preferred.

Related

Is it possible to do math inside of a variable name? For example: S[BP1P - 8]O == false

I am trying to create a program that outputs all possible moves(chess). I started by creating variables to check if the spaces are occupied or not so S0O, S1O, etc. Now I want to take a piece marked by a variable in this case BP1(Black pawn 1) with an int value marking square. So if BP1 = 48 how would I check if S40O is empty. This goes for any value of BP1.
Edit: I have been getting suggestions to use a std::unordered_map. So now that I have looked into these I do not quite see how this would let me check a certain entry based on an input.
Using the example from the link above, I put together some code that demonstrates how to use the unordered_map and manipulate the strings within, or you can change the keys before they're assigned (the keys are the colors "RED", "BLUE", and "GREEN" in this example).
#include <iostream>
#include <string>
#include <unordered_map>
int main()
{
// Create an unordered_map of three strings (that map to strings)
std::unordered_map<std::string, std::string> u = {
{"RED","#FF0000"},
{"GREEN","#00FF00"},
{"BLUE","#0000FF"}
};
u["RED"][3] = '2';
// Just a random string manipulation
for(unsigned long long i = 0; i < u["BLUE"].length(); i++)
u["BLUE"][i] = i + 'a';
std::cout << u["RED"] << std::endl;
std::cout << u["BLUE"] << std::endl;
return 0;
}

How to properly iterate over QT's STL style vector

I am trying to iterate over a vector.
The vector memory is initialized to hold 10 elements max.
Now I assigned first 3 elements and try to print them using STL style iterator in QT.
#include <QDebug>
int main() {
QVector<int> vv(10);
vv[0] = 1;
vv[1] = 2;
vv[2] = 3;
QVector<int>::iterator itt;
for (itt = vv.begin(); itt != vv.end(); ++itt) {
qDebug() << vv.at(*itt);
}
}
the output is weird:
It's not 1 2 3
instead its 2 3 0 1 1 1 1 1 1 1
Why is this happening ? Can you someone explain this please.
As #NathanOliver pointed out you have two problems:
*itt already is the element of the vector, so it should just be qDebug() << *itt;.
If you create a vector of a certain size for each vector index a default element of the type the vector holds is created. That is also the reason why you can't use container classes like QVector for types without a default constructor. In your case the vector is filled with 1s on creation because 1 is the default value of an int. You then just override the first 3 values.
I have some further concerns regarding your code:
If you expect your vector to only hold as much values as you add, why even provide a length of the vector? QVector is perfectly capable of managing its storage itself. You just use QVector::append or QVector::operator<< to add values and your vector has exactly as many values as you added.
Why use STL style iterators in this case anyway? QVectorIterator provides such convenient methods to iterate over a vector. They also make the code much more readable.
If I were you I would have written the code as follows:
#include <QVector>
#include <QDebug>
int main() {
QVector<int> numbers = QVector<int>() << 1 << 2 << 3;
QVectorIterator<int> itNumbers(numbers);
while (itNumbers.hasNext()) {
qDebug() << itNumbers.next();
}
}

Replacing N-level for loops with recursion in C++

I have been trying for some time now to come up with a way to compute all the various combinations of strings of words for some time now. Unlike most methods for combining on the web though, the algorithm must produce every combination, including those in which all the combined elements aren't in a single combination. ie, if I am combining 'Hello', 'New' and 'World', the combinations I am looking for are:
HelloNewWorld
HelloNew
HelloWorld
Hello
NewWorld
New
World
A professor from my college did come up with a quick and dirty solution for doing just that, but it is using nested for loops.
#include <iostream>
#include <vector>
#include <array>
#include <string>
int main()
{
std::vector<std::array<std::string, 2>> vec(3);
vec[0] = {"Hello", ""};
vec[1] = {"New", ""};
vec[2] = {"World", ""};
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
std::cout << vec[0][i] + vec[1][j] + vec[2][k] << std::endl;
}
As you might imagine, I desired a way to make this actually somewhat usable and portable. I know that this is possible with recursion, I just don't know how to implement it. Optimally, I would like to make this tail-recursive if at all possible, as the plan is to compute very large combinations. What would be the best way to do this recursively, and would it be easy to make tail-recursive?
At each level it recurses both with and without the current word printing the result when it gets to the end of all the words:
#include <iostream>
#include <string>
#include <vector>
void recurse(std::vector<std::string> &values,size_t level,std::string str) {
if (level<values.size()) {
recurse(values,level+1,str+values[level]);
recurse(values,level+1,str);
} else {
std::cout<<str<<"\n";
}
}
int main(int argc, char*argv[]) {
if (argc<2)
std::cout<<argv[0]<<" <word> [<word> [...]]\n";
else {
std::vector<std::string> values;
for(int i=1;i<argc;++i) {
values.push_back(argv[i]);
}
recurse(values,0,"");
}
return 0;
}
Which, when run with ./a.out Hello New World produces:
HelloNewWorld
HelloNew
HelloWorld
Hello
NewWorld
New
World
You can do this pretty efficiently by using all combinations from k=1 to k=N for a vector of N elements. Using Howard Hinnant's library available here, you can use it fairly effectively. In my case, I've named the library sampling.h, which is the only external dependency and can be viewed in it's entirety here.
#include "sampling.h"
#include <iostream>
#include <vector>
/**
* This function can take any container that has a bidirectional
* iterator (std::list, std::deque, std::vector) that contains elements
* of type std::string or similar, that must implement an `operator+`
* and `operator<<` for printing.
*/
template <typename BiDirStringContainer>
void print_combinations(BiDirStringContainer& container)
{
auto first = container.begin();
auto last = container.end();
for (size_t i = 1; i <= container.size(); ++i) {
auto mid = first + i;
for_each_combination(first, mid, last, [](auto f, auto l) {
std::string w;
for (; f != l; ++f) {
w += *f;
}
std::cout << w << std::endl;
return false;
});
}
}
int main(void)
{
std::vector<std::string> words = {
"Hello",
"New",
"World",
};
print_combinations(words);
return 0;
}
Compiling this with the C++14 standard and running it outputs:
Hello
New
World
HelloNew
HelloWorld
NewWorld
HelloNewWorld
This is exactly what your post described. Since the lambda is a custom functor, and can store state, you can do whatever you would like with the combinations: store a copy, print them, etc.
This is dramatically faster than anything you can get in the standard library without major work, or from suggestions made for the standard library. For example, std::next_combination and std::next_permutation (the former was not included, but was suggested here). I highly suggest reading Howard Hinnant's entirely blog post: it is enlightening. The time complexity on his implementations, and brute speed beats most other suggestions. If you need high performance combinations or permutations, he's already done the work for you.
If i understand this correctly you want to generate all combinations of a string. in that case you can use a BFS along with a set and a queue to generate the combinations, I will try to explain.
Say your string is ABCD. You have a queue to which you add ABCD and a set to which you add ABCD now
while the queue is not empty
1) you pop the top element
2) you generate substrings of that popped element
a) if that substring is not in the set add it to the queue
to generate substrings in step 2 you do the following
for(int i =0;i<string.length();i++)
{
string substr1 = string.substr(0,i);
string substr2 = string.substr(i,string.length()-1);
string substring = substr1+substr2;
}
doing this on ABCD(the input string) will generate BCD,ACD and ABD and ABC. now add those 3 to the set and the queue
now, you add BCD,ACD and ABD to the set. Lets say BCD is queue.front(). You pop that and generate CD,BD and BC and add them to the set and queue. when you pop ACD next, you generate CD,AD and AC but now you wont add CD to the queue because it is in the set.
EDIT:
I see your issue, my answer works for a string but you can use the same principle on a vector<string> to generate all combinations ABCD would just beHello(A)World(B)...
If the only possibilities is for a word to appear or not appear, that makes two possibilities. So for n words you have 2^n combinations. So you just count through the 2^n numbers from 0 (including) to 2^n-1 (including) and map each bit to one word.
No recursion needed, just one counting for loop.

Is there a pattern to track currently selected item in a container? Does state fits here?

My original project is complex but I wrote a small demo which illustrates the problem and my question.
My model contains a list of objects. When I call its method increment(), it is applied to the current selected item. My question is how should I track the currently selected item?
My code below uses a pointer currentItem to track the current selected item.
But my real project has do/undo functionality via command pattern so it needs to track. Additionally I have more states there to keep track of including current selected item and previous selected item.
Besides the code below, I have tried state design pattern but than I have to implement alot of the functions in the strategy that applies to the object and seems to complicate things. Is there a specific pattern for this? Does strategy suits here or is an overkill or perhaps simple plain pointer approach is fine? Please keep in mind my application needs to support do/undo functionality.
#include <QCoreApplication>
#include <iostream>
#include <QList>
#define ITEM_COUNT 5
using namespace std;
class ObjectA {
public:
ObjectA(string n, int p) {
name = n;
price = p;
}
string name;
int price;
void increment() {
price++;
}
};
class ContainerObject
{
public:
QList<ObjectA*> items;
ContainerObject() {
for (int i = 0; i < ITEM_COUNT; i++)
{
string name = ("name " + std::to_string((_ULonglong)i));
ObjectA * item = new ObjectA(name, 0);
items.append( item );
}
// assume at index 3 is current item
setCurrentItem( items.at(2) );
}
ObjectA* currentItem;
void setCurrentItem(ObjectA * obj) {
currentItem = obj;
}
void increment(){
currentItem->increment();
if( currentItem->price >= 2)
setCurrentItem( items.at( 4) );
}
void print()
{
for (int i = 0; i < ITEM_COUNT; i++)
{
ObjectA * item = items.at( i );
cout << item->name << " " << item->price << " added" << endl;
}
cout << endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ContainerObject container;
// initial values
container.print();
container.increment();
container.print();
container.increment();
container.print();
container.increment();
container.print();
return a.exec();
}
First it seems that you have multiple opened questions :
1) How should you track the selected item?
There is no good answer it depends on your container's type. Here it seems that you have a list, then a pointer approach better fits compared to an index approach since the number of elements can vary (you could insert/append new items at different locations)
2) About the type of pattern to achieve this?
I haven't understood well why you tried to implement State design pattern, I assume because you read the assumption "it allows to adapt the behavior of an object when its internal state changes". I think that changing the selected item is not representative to an "internal state change" then it won't fit. It's usually used in state machine implementation.
For the specific purpose of undo/do there is anoter pattern which is called memento design pattern, it can recalls something important such as the previous selected item or so and allows you to restore the situation. I guess it could simplify your design when receiving a command :
Recall the situation via memento (selected items...or more)
Process the command (update selected items...)
if needed on undo command :
Restore the situation

How can I convert from a class with a 2D vector of chars to a 2D vector of another obj with a char variable?

I'm still new to this so my apologies in advance if I provide too much or not enough information for my problem.
The Run Down
This question isn't a rogue like game related question, but for a little background of what my program does.. is to be similar to a rogue like game.
Ok, so I had a class that had a member 2D char vector (the chars were manipulated to represent a "dungeon"). Everything worked seamlessly. I wanted to expand what my program could do so I decided to create a new class to replace the 2D vector of chars so that the char is just the visual representation of the new class and other variables can be stored along with that char.
For simplistic sake, I tried to remove what isn't necessary for this question. This new class is called Tile - which represents a space being used for the dungeon level. Tile has:
a char variable called displayChar.. defaults to ' ' changes to represent what it contains
(other variables..)
The Problems / My Poor guesses
I'm not the best at completely understanding some concepts of programming syntax/implementation, so please don't judge.
The way I filled the vector of chars, I resized it to the width of the game board, and set everything to ' ' since all the values were chars
I think I need to fill it with new, Tile objects and push them to the
2D Tile vector?
My other methods that manipulated the char values are giving errors.
I think I should change the methods to take a pointer to the Tile
object and use the setDisplayChar(' ') method to change its
value?
My at(int, int) method used to return the char at that location
I thought I could change it to "return m_vvTiles[y][x].getDisplayChar()" but I get an error
I'm bad at changing how something works and I usually end up making a mess out of my code. I'll post the code that is relevant for this. I'd greatly appreciate any help you can offer. And please let me know if I need to add more. (I'll try to keep the code minimized to only related methods). Thanks!
DungeonLevel.h
#include "Tile.h"
#include <vector>
#include <random>
class DungeonLevel {
public:
DungeonLevel(int iWidth, int iHeight, std::mt19937 & mt);
~DungeonLevel(void);
void dump();
char at(int x, int y);
int getWidth();
int getHeight();
private:
std::vector<std::vector<Tile>> m_vvTiles; //Tile was char
};
DungeonLevel.cpp
#include <iostream>
#include <random>
#include "DungeonLevel.h"
using namespace std;
DungeonLevel::DungeonLevel(int iWidth, int iHeight, std::mt19937 & mt){
// Initialize the blank vector
m_vvTiles.resize(iHeight);
for(auto it = m_vvTiles.begin(); it != m_vvTiles.end(); it++ ){
// Tile tempTile = new;?
(*it).resize(iWidth,' ');
}
// divide the level into 4x2 chunks
int iChunkWidth = iWidth / 4;
int iChunkHeight = iHeight / 2;
// Taking the easy way out, and generating
// a loop of tunnels first to drop rooms on to
for( int x = (iChunkWidth/2); x <= ((3 * iChunkWidth) + (iChunkWidth/2)$
m_vvTiles[iChunkHeight/2][x] = '#';
m_vvTiles[iChunkHeight + (iChunkHeight/2)][x] = '#';
}
for( int y = (iChunkHeight/2); y <= (iChunkHeight + (iChunkHeight/2)); $
m_vvTiles[y][iChunkWidth/2] = '#';
m_vvTiles[y][(3 * iChunkWidth) + (iChunkWidth/2)] = '#';
}
void DungeonLevel::dump(){
for( auto itOuter = m_vvTiles.begin(); itOuter != m_vvTiles.end(); itOu$
for( auto itInner = (*itOuter).begin(); itInner != (*itOuter).e$
cout << *itInner.getDisplayChar(); ///Updated:: CAUSING ERROR//
}
cout << endl;
}
}
//SEVERAL IRRELEVANT LINES FOR THIS PROBLEM..
}
char DungeonLevel::at(int x, int y){
return m_vvTiles[y][x].getDisplayChar();
//return m_vvTiles[y][x]; WORKED BEFORE
}
Tile.h
#include "Entity.h"
#include <vector>
class Tile : public Entity {
public:
Tile(void);
virtual ~Tile(void);
//void setEntity(Entity * entityToSet); BOTH IRRELEVANT
//Entity * getEntity();
void setDisplayChar(char displayCharToSet);
char getDisplayChar();
//virtual void dumpObjectData(); IRRELEVANT AT THIS TIME
private:
char displayChar;
//Entity * theEntity; IRRELEVANT AT THIS TIME
};
Tile.cpp
#include "Tile.h"
#include "Entity.h"
using namespace std;
Tile::Tile(void){
displayChar = '.';
//theEntity = NULL;
}
Tile::~Tile(void){
}
void Tile::setDisplayChar(char displayCharToSet){
displayChar = displayCharToSet;
}
char Tile::getDisplayChar(){
return displayChar;
}
*Heres my existing error: *
For the method dump() in DungeonLevel.cpp,
Some of your questions with my answers
I think I need to fill it with new, Tile objects and push them to the 2D Tile vector?
No you need to resize it and fill it with Tile objects. Pretty much like you did when it was a char array. new doesn't come into it.
I think I should change the methods to take a pointer to the Tile object and use the setDisplayChar(' ') method to change its value?
I would use a reference.
I thought I could change it to return m_vvTiles[y][x].getDisplayChar() but I get an error.
That sounds right to me, what error did you get?
Everything about your redesign sounds well motivated to me. Good idea to make a back up before going on a major reorganization however.