I've done quite some java coding already, but I'm totally new to c++ and have no idea what's going on with my code right now. This code gives me a compile error in the map standard library. It says: Cannot increment value of type ' std::_1::pari<int, int>', and is happening in map, insert(_InputIterator __f, _InputIterator __l) if that's of any relevance.
I know the stackoverflow community generally doesn't like solving other peoples homework, but I think I made a genuine attempt at implementing this and besides that I'm very curious as to what's going on.
typedef std::pair<int, int> location;
std::set<location> neighbours(location loc, std::set<std::pair<location, location>> labyrinth, int& size) {
std::set<location> neighbours;
location locFmin = location(loc.first - 1, loc.second);
location locSmin = location(loc.first, loc.second - 1);
location locFplus = location(loc.first + 1, loc.second);
location locSplus = location(loc.first, loc.second + 1);
if (loc.first - 1 >= 0 && labyrinth.find(std::pair<location, location>(loc, locFmin)) == labyrinth.end()) {
neighbours.insert(locFmin);
}
if (loc.second - 1 >= 0 && labyrinth.find(std::pair<location, location>(loc, locSmin)) == labyrinth.end()) {
neighbours.insert(locSmin);
}
if (loc.first + 1 < size && labyrinth.find(std::pair<location, location>(loc, locFplus)) == labyrinth.end()) {
neighbours.insert(locFplus);
}
if (loc.second + 1 < size && labyrinth.find(std::pair<location, location>(loc, locSplus)) == labyrinth.end()) {
neighbours.insert(locSplus);
}
return neighbours;
}
int Labyrinth(std::set<std::pair<location, location>> labyrinth, int size) {
std::map<location, location> forest;
std::set<location> level;
std::set<location> known;
known.insert(location(0,0));
level.insert(location(0,0));
while (!level.empty()) {
std::set<location> nextLevel;
for (location loc: level) {
for (location neighbour: neighbours(loc, labyrinth, size)) {
if (known.find(neighbour) != known.end()) {
known.insert(neighbour);
forest.insert(neighbour, loc);
nextLevel.insert(neighbour);
}
}
}
level = nextLevel;
}
std::list<location> path;
location walk = location(size - 1, size - 1);
path.push_front(walk);
while (walk != location(0, 0)) {
walk = forest[walk];
path.push_front(walk);
}
int answ = path.size();
return answ;
}
It's an algorithm that should perform a breadth-first search trough a square maze of size size with of course size * size location(x, y) objects.
the incoming list labyrinth defines the walls of the maze one can't go trough. Eventually the function should return the number of nodes contained in the shortest path from (0, 0) to (size - 1, size - 1).
this is a simple test for the algorithm
std::set<std::pair<location, location> > labyrinth;
labyrinth.insert(std::pair<location, location>(location(0, 0), location(1, 0)));
labyrinth.insert(std::pair<location, location>(location(0, 1), location(1, 1)));
labyrinth.insert(std::pair<location, location>(location(0, 2), location(0, 3)));
labyrinth.insert(std::pair<location, location>(location(1, 1), location(1, 2)));
labyrinth.insert(std::pair<location, location>(location(1, 2), location(2, 2)));
labyrinth.insert(std::pair<location, location>(location(2, 3), location(3, 3)));
labyrinth.insert(std::pair<location, location>(location(2, 2), location(3, 2)));
labyrinth.insert(std::pair<location, location>(location(2, 1), location(3, 1)));
int labAnswer = Labyrinth(labyrinth, 4);
std::cout << labAnswer << std::endl;
if (labAnswer == 13)
{
std::cout << "Correct" << std::endl;
}
else
{
std::cout << "Incorrect" << std::endl;
}
Before anyone starts to come up with better ideas to solve this problem. I got the idea for the bfs code from a graph bfs java implementation from a book on algorithms. I'm not interested in solving this puzzle more efficiently, there'll always be better ways to do something. I'd like to know what is going on with my code and possibly what c++ aspect I'm missing here.
You aren't using std::map correctly with insert,
the line
forest.insert(neighbour, loc);
should be
forest[neighbor] = loc;
Check your #include headers, you will need to
#include <map>
Also, if you add using namespace std; then you can skip adding std:: to every declaration.
Related
I am creating a game with a 3D grid for flying entities, So I have a lot of points and connections in the air where there aren't any obstructions. I didn't want to decrease the resolution of my grid so I thought I could just skip over chunks (or empties as I call them) of the Astar map while they're not containing any obstructions, and I modified Godot's Astar algorithm to do this.
Unfortunately this ended up being slower than looping through points one at a time due to the way I implemented this modification, which needs to loop through all the edge points of an empty.
2D representation of how one edge point of an empty connects to all other edge points:
This ends up looping through a larger number of points than letting the A* algorithm work it's way through the empty.
So I'm sorta stumped on how to make this more efficient while still preserving the most optimal path.
I could potentially narrow down what faces of the empty should be scanned over by first comparing the center points of all 8 faces of the empty (as my grid consists of hexagonal prisms). Or maybe I should somehow use the face center points of the empty's faces exclusively instead of all edge points.
I mainly want to know if anyone has worked on an issue like this before, and if so what would be the recommended solution?
Here is the astar loop for reference:
bool AStar::_solve(Point *begin_point, Point *end_point, int relevant_layers) {
pass++;
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
bool supported = relevant_layers == 0 || (relevant_layers & end_point->parallel_support_layers) > 0;
if (!end_point->enabled || !supported) {
return false;
}
bool found_route = false;
Vector<Point *> open_list;
SortArray<Point *, SortPoints> sorter;
begin_point->g_score = 0;
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
open_list.push_back(begin_point);
while (!open_list.empty()) {
Point *p = open_list[0]; // The currently processed point
if (p == end_point) {
found_route = true;
break;
}
sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list
open_list.remove(open_list.size() - 1);
p->closed_pass = pass; // Mark the point as closed
//if the point is part of an empty, look through all of the edge points of said empty (as to skip over any points within the empty).
OAHashMap<int, Point*> connections;
PoolVector<Empty*> enabled_empties;
int size = p->empties.size();
PoolVector<Empty*>::Read r = p->empties.read();
for (int i = 0; i < size; i++) {
Empty* e = r[i];
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
//if the empty is enabled and the end point is not within the empty
if (e->enabled && supported && !end_point->empties.has(e)) {
enabled_empties.append(e);
//can travel to any edge point
for (OAHashMap<int, Point*>::Iterator it = e->edge_points.iter(); it.valid; it = e->edge_points.next_iter(it)) {
int id = *it.key;
Point* ep = *(it.value);
ep->is_neighbour = false;
//don't connect to the same point
if (id != p->id && (i == 0 || !connections.has(id))) {
connections.set(id, ep);
}
}
}
}
//add neighbours to connections
for (OAHashMap<int, Point*>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) {
int id = *it.key;
Point* np = *(it.value);// The neighbour point
np->is_neighbour = true;
//don't need to check for duplicate point connections if no empties
if (size == 0 || !connections.has(id)) {
//don't add points within enabled empties since they're meant to be skipped over
if (np->empties.size() > 0 && !np->on_empty_edge) {
bool in_enabled_empty = false;
PoolVector<Empty*>::Read r1 = np->empties.read();
for (int i = 0; i < np->empties.size(); i++) {
if (enabled_empties.has(r1[i])) {
in_enabled_empty = true;
break;
}
}
if (!in_enabled_empty) {
connections.set(id, np);
}
}
else {
connections.set(id, np);
}
}
}
for (OAHashMap<int, Point *>::Iterator it = connections.iter(); it.valid; it = connections.next_iter(it)) {
Point *e = *(it.value); // The neighbour point
//make sure parallel layers are supported
// or if *relevant_layers is 0 then use all points
supported = relevant_layers == 0 || (relevant_layers & e->parallel_support_layers) > 0;
if (!e->enabled || e->closed_pass == pass || !supported) {
continue;
}
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
bool new_point = false;
if (e->open_pass != pass) { // The point wasn't inside the open list.
e->open_pass = pass;
open_list.push_back(e);
new_point = true;
} else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous.
continue;
}
e->prev_point = p;
e->prev_point_connected = e->is_neighbour;
e->g_score = tentative_g_score;
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
if (new_point) { // The position of the new points is already known.
sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw());
} else {
sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw());
}
}
}
return found_route;
}
Note: I'm still not exactly sure what the sorter does.
the entire code can be seen here in a_star.cpp and a_star.h
Edit:
if anyone wants to reference or use this, I've modified the Astar code to add user-defined octants and to use a user-defined straight line function (they are user-defined so they can work with any type of grid) to be used between octants when possible to further decrease runtime, and it works very well in terms of speed. Though the pathing is not optimal, especially when adding a lot of obstacles/restricting the available positions.
In a simple vehicle routing problem solved by Google OR-tools library, two nodes (2, 3) are marked as optional with visiting penalty set to 0. The shortest path of distance 2 from the depot to the landfill is 0 -> 1 -> 4, however, the solver ends-up with path 0 -> 2 -> 3 -> 1 -> 4 of distance 4.
Where is the problem? Why the solver insists on the longer path through optional nodes and does not skip them?
#include "ortools/constraint_solver/routing.h"
using namespace operations_research;
struct DataModel {
static constexpr int I = 2;
const std::vector<std::vector<int>> dist {
{ 0, 1, 1, I, I},
{ I, 0, I, 1, 1},
{ I, I, 0, 1, 1},
{ I, 1, 1, 0, I},
{ I, I, I, 1, 0},
};
const RoutingIndexManager::NodeIndex depot{0};
const RoutingIndexManager::NodeIndex landfill{4};
};
void printSolution(const RoutingIndexManager& manager,
const RoutingModel& routing,
const Assignment& solution)
{
if (routing.status() != RoutingModel::Status::ROUTING_SUCCESS)
return;
int index = routing.Start(0);
std::ostringstream route;
while (routing.IsEnd(index) == false) {
route << manager.IndexToNode(index).value() << " -> ";
index = solution.Value(routing.NextVar(index));
}
LOG(INFO) << route.str() << manager.IndexToNode(index).value();
LOG(INFO) << "Problem solved in " << routing.solver()->wall_time() << "ms";
}
int main(int /*argc*/, char** /*argv*/)
{
DataModel data;
RoutingIndexManager manager(data.dist.size(), 1, {data.depot}, {data.landfill});
RoutingModel routing(manager);
const int callback = routing.RegisterTransitCallback(
[&data, &manager](int from_index, int to_index) -> int {
auto from_node = manager.IndexToNode(from_index).value();
auto to_node = manager.IndexToNode(to_index).value();
return data.dist[from_node][to_node];
});
routing.SetArcCostEvaluatorOfAllVehicles(callback);
// make nodes 2, 3 optional
routing.AddDisjunction({manager.NodeToIndex(RoutingIndexManager::NodeIndex(2))}, 0, 1);
routing.AddDisjunction({manager.NodeToIndex(RoutingIndexManager::NodeIndex(3))}, 0, 1);
const Assignment* solution = routing.Solve();
printSolution(manager, routing, *solution);
return 0;
}
Interestingly, for I = 1, the correct solution 0 -> 1 -> 4 is found. However, such dist matrix is trivial.
This was answered on the or-tools-discuss mailing list.
You encountered a corner case for the default parameter setup. Thanks for forwarding this, we will work on a proper fix.
To work around the problem, you can modify the default parameters as follows:
Option 1 - activate make_chain_inactive - faster option
RoutingSearchParameters search_parameters = DefaultRoutingSearchParameters();
search_parameters.mutable_local_search_operators()->set_use_make_chain_inactive(OptionalBoolean::BOOL_TRUE);
const Assignment* solution = routing.SolveWithParameters(search_parameters);
Option 2 - activate inactive_lns - slower option but slightly more generic
RoutingSearchParameters search_parameters = DefaultRoutingSearchParameters();
search_parameters.mutable_local_search_operators()->set_use_inactive_lns(OptionalBoolean::BOOL_TRUE);
const Assignment* solution = routing.SolveWithParameters(search_parameters);
need your help. I have the following problem , for example i have a formula how i can check if a station is on each line. I found it , but then i need to check everytime and it can be that one line has 10 stations. Then i take a line ( multimap) create a name of a line and also stations which are on that line. The following code i have so far implemented.
multimap<int, int>numberofStation;
for (int newSt = 0; newSt <dimentionOfNewStation; newSt++)
{
int station = 0;
for (int Edges = 0; Edges < dimenstionOfEdges; Edges++)
{
float firstsol = 0;
float secondsol = 0;
float thirdsol = 0;
firstsol = (busEdges[Edges].y2 - busEdges[Edges].y1) / (busEdges[Edges].x2 - busEdges[Edges].x1);//check if a station on that line
secondsol = (apointCollection4[newSt].y- busEdges[Edges].y1) / (apointCollection4[newSt].x - busEdges[Edges].x1);//check if a station on that line
thirdsol = (busEdges[Edges].y2 - apointCollection4[newSt].y) / (busEdges[Edges].x2 - apointCollection4[newSt].x);//check if a station on that line
if (firstsol == secondsol && firstsol == thirdsol)//values should be the same
{
station = Edges;//i take that edge/line(id)
}
}
if (numberofStation.find(station) == numberofStation.end())
{
numberofStation.insert(pair<int, int>(station, newSt));//i add that station to that line
}
else
{
here i need to have a line of station for each line( 0 line has 2,5,3 station)
}
}
for (auto it = numberofStation.begin(); it != numberofStation.end(); it++)
{
and how i can print it out in the order i want above.
}
Tell me please if it is possible to imlement such idea or maybe it is quite crazy and tell me please the way how i can do that.
So the idea , i need to find the number of stations on each line.
Thanks in advance
Like selyunin I'm not quite sure what you're asking for.
Maybe it's std::equal_range() or (since it's a multimap anyway) std::multimap::equal_range like in
std::multimap<int,int> m;
m.insert(pair<int, int>(0, 1));
m.insert(pair<int, int>(2, 2));
m.insert(pair<int, int>(1, 3));
m.insert(pair<int, int>(1, 4));
m.insert(pair<int, int>(0, 5));
m.insert(pair<int, int>(1, 6));
int station = 1;
// get the range of entries having (station) as "key"/first
auto r = m.equal_range(station);
while(r.first!=r.second) {
cout << (*(r.first)).second << ' ';
r.first++;
}
which prints 3 4 6
I am encountering issues with both std::thread and std::mutex, unable to get both to play nicely with each other. I've been pulling my hair out over this for the past few hours and just cannot make any progress whatsoever. I believe it is out of my skill area. The code is just below:
void GekkoFyre::TuiHangouts::gui_userRosterListNav(std::shared_ptr<WINDOW> display,
std::vector<const char *> userList,
const short &menuItem)
{
while (rosterEnabled) {
for (short i = 0; i < totalMenuItems; ++i) {
short diff = (menuItem - i);
if (i < numMenuItems) {
if (i == menuItem) {
size_t msgLen = strlen(userList.at(i));
size_t l = 0;
if (msgLen > subMaxX) {
for (l = subMaxX; l < msgLen; ++l) {
// Scroll the message from left to right, then vice versa, so that it fits within
// the designated window.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
rosterListMutex.lock();
wattron(usrSubWin.get(), A_REVERSE); // Highlight selection
const char *msg = userList.at(i);
mvwaddstr(usrSubWin.get(), i, 0, &msg[(msgLen - l)]);
wrefresh(usrSubWin.get());
touchwin(usrSubWin.get());
rosterListMutex.unlock();
}
} else {
rosterListMutex.lock();
wattron(usrSubWin.get(), A_REVERSE); // Highlight selection
mvwaddstr(usrSubWin.get(), i, 0, userList.at(i));
wrefresh(usrSubWin.get());
touchwin(usrSubWin.get());
rosterListMutex.unlock();
}
}
wattroff(usrSubWin.get(), A_REVERSE); // Remove highlight
if ((i + 1) < numMenuItems) {
mvwaddstr(usrSubWin.get(), (i + 1), 0, userList.at((i + 1)));
}
} else if (diff < (totalMenuItems - numMenuItems) && diff > 0) {
// Allow the scrolling of a username list, from downwards and then back upwards, so that
// the user may see the list in its entirety.
wclear(usrSubWin.get());
int pos = 0;
for (short c = diff; c < (numMenuItems + diff); ++c) {
++pos;
mvwaddstr(usrSubWin.get(), pos, 0, userList.at(c));
}
pos = 0;
break;
}
}
rosterListMutex.lock();
wattroff(usrSubWin.get(), A_REVERSE); // Remove highlight
touchwin(usrSubWin.get());
wrefresh(usrSubWin.get());
wrefresh(display.get());
rosterListMutex.unlock();
}
}
I am trying to display a list of users to the left of a chat window in NCurses, as can be seen in [ 1 ] below, albeit without any users present in said screenshot. I want to keep my privacy :) What happens is that as you scroll down the list, flickering begins to occur back and forth between two usernames after scrolling past just a few. They keep repeatedly selecting each other, just over and over. I believe this is reason of the threads not syncing up properly. The function is implemented as so:
[ 1 ] - http://imgur.com/ZZlFHg2
#define WIDGET_USERS_LIST 1
short menuItem = 0;
int ch = 0;
int curr_widget = 0;
std::thread rosterListNav1(&GekkoFyre::TuiHangouts::gui_userRosterListNav, this, userListWin, rosterFormatted, menuItem);
rosterListNav1.detach();
while ((ch = wgetch(display.get())) != KEY_F(12)) {
switch (ch) {
case KEY_DOWN:
if (curr_widget == WIDGET_USERS_LIST && rosterEnabled) {
++menuItem;
if (menuItem > totalMenuItems - 1) {
menuItem = 0;
}
}
break;
case KEY_UP:
if (curr_widget == WIDGET_USERS_LIST && rosterEnabled) {
--menuItem;
if (menuItem < 0) {
menuItem = totalMenuItems - 1;
}
}
}
std::thread rosterListNav2(&GekkoFyre::TuiHangouts::gui_userRosterListNav, this, userListWin, rosterFormatted, menuItem);
rosterListNav2.detach();
}
Any help on this issue would be dearly appreciated, and I believe I have placed the std::mutex's in the right areas. I am really stumped with this problem. Also beware that while I know a few tricks of the trade, I am entirely self-taught. Some of the nomenclature that is normal to programmers who have gone through university is completely unintelligible to me.
I am trying to implement a simple Gif-Reader in c++.
I currently stuck with decompressing the Imagedata.
If an image includes a Clear Code my decompression algorithm fails.
After the Clear Code I rebuild the CodeTable reset the CodeSize to MinimumLzwCodeSize + 1.
Then I read the next code and add it to the indexstream. The problem is that after clearing, the next codes include values greater than the size of the current codetable.
For example the sample file from wikipedia: rotating-earth.gif has a code value of 262 but the GlobalColorTable is only 256. How do I handle this?
I implemented the lzw decompression according to gif spec..
here is the main code part of decompressing:
int prevCode = GetCode(ptr, offset, codeSize);
codeStream.push_back(prevCode);
while (true)
{
auto code = GetCode(ptr, offset, codeSize);
//
//Clear code
//
if (code == IndexClearCode)
{
//reset codesize
codeSize = blockA.LZWMinimumCodeSize + 1;
currentNodeValue = pow(2, codeSize) - 1;
//reset codeTable
codeTable.resize(colorTable.size() + 2);
//read next code
prevCode = GetCode(ptr, offset, codeSize);
codeStream.push_back(prevCode);
continue;
}
else if (code == IndexEndOfInformationCode)
break;
//exists in dictionary
if (codeTable.size() > code)
{
if (prevCode >= codeTable.size())
{
prevCode = code;
continue;
}
for (auto c : codeTable[code])
codeStream.push_back(c);
newEntry = codeTable[prevCode];
newEntry.push_back(codeTable[code][0]);
codeTable.push_back(newEntry);
prevCode = code;
if (codeTable.size() - 1 == currentNodeValue)
{
codeSize++;
currentNodeValue = pow(2, codeSize) - 1;
}
}
else
{
if (prevCode >= codeTable.size())
{
prevCode = code;
continue;
}
newEntry = codeTable[prevCode];
newEntry.push_back(codeTable[prevCode][0]);
for (auto c : newEntry)
codeStream.push_back(c);
codeTable.push_back(newEntry);
prevCode = codeTable.size() - 1;
if (codeTable.size() - 1 == currentNodeValue)
{
codeSize++;
currentNodeValue = pow(2, codeSize) - 1;
}
}
}
Found the solution.
It is called Deferred clear code. So when I check if the codeSize needs to be incremented I also need to check if the codeSize is already max(12), as it is possible to to get codes that are of the maximum Code Size. See spec-gif89a.txt.
if (codeTable.size() - 1 == currentNodeValue && codeSize < 12)
{
codeSize++;
currentNodeValue = (1 << codeSize) - 1;
}