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