Map - finding nearest value? - c++

I am trying find nearest RGB value in QMap (I know it probably should be HSV, but that is not the problem). Here is what I got so far:
it = images_map.find(current_rgb);
if(it != images_map.begin()){
mi = images_map.lowerBound(current_rgb).value();
}
else{
mi = images_map.upperBound(current_rgb).value();
}
My map looks like this has that indexes:
images_map[ 4283914078 ]
images_map[ 4284046165 ]
images_map[ 4284902241 ]
images_map[ 4289239953 ]
images_map[ 4282200377 ]
images_map[ 4289440688 ]
When my current_rgb is for example 4285046165 it is OK, but if there is some value greater than greatest index, program crashes. What am I doing wrong?

Possibly because .value() tries to de-reference a non-existing item?
This looks like your own custom map implementation (or wrapper), but your logic appears to be incorrect
You call lowerBound every time - except if the item you are looking for is the first in the map
If it is the first in the map, you do a search again???
If it's not you search again (which if already found is repeating the operation again), else if not found, looks for nearest (which is okay), however do you handle the case where there is none (i.e. in lowerBound)?
The logic should be something like:
it = images_map.find(current_rgb);
if(it == images_map.end())
{
it = images_map.lowerBound(current_rgb);
if (it == images_map.begin())
{
it = images_map.upperBound(current_rgb);
if (it == images_map.end())
// throw error
}
// now you know you have a valid iterator - de-reference
mi = *it.value();
}

Call
images_map.upperBound(current_rgb)
May return
images_map.end()
In that case you should not call value().

You can solve the iterator out of range problem by adding sentinel values 0x000000 and 0xFFFFFF (once). That way, you always have a valid lower- and upperbound. Of course, this may affect the outcome of your algorithm. E.g. if your "smallest" real color was pure blue (0x0000FF), then dark blue (0x00007F) will now find black, not pure blue. This is easily fixed by two comparisons, of course.
With the sentinels in place, call QMap::lower_bound. You need to check whether you've actually found a precise match: if *lower_bound is the value you want, return it. Else, lower_bound points to the first element that's bigger than your input. Therefore, --lowerbound points to the last element that's smaller than your input. Check which of the two is closer.
Note that the only way lower_bound can point to begin is when your input is precisely 0x000000 (the sentinel), in which case you won't get to --lower_bound. No range error there. By the same logic, the end sentinel 0xFFFFFF means you'll always find an lower_bound.

Related

-nan Error when trying to return the index of a class object

So in my intro to CS class, we're learning about classes and I'm having a lot of trouble right now.
This is project 2 part 2:
https://github.com/CSCI1300-StartingComputing/CSCI1300-Spring2022/blob/main/project/project2/project2pt2.md#question0
project 2 part 1 (part 2 builds on a lot of this stuff:https://github.com/CSCI1300-StartingComputing/CSCI1300-Spring2022/blob/main/project/project2/project2pt1.md#question4
I am specifically on number 6 for part 2.
I believe the problem lies in the below snippet of code:
while (k < numbMovies){temp = movies[k].getTitle(); //store movie title into temp arr
//convert temp to lowercase for case insensitivity
while (b < temp.length()){temp[b] = tolower(temp[b]);
b++;
}
//if the title we're searching is found in the movies array
if (temp == title)
{
movieIdx = k; //the kth movie will be our match, so save k as our index
numMatches++; //increment number of matches. if the title is found, this should be one at most
}
k++;
}
There is an issue somewhere with the line temp = movies[k].getTitle();, I think.
What this line is supposed to do is reference an array from the Movie class developed in part 1, store a title found at 'k' from the movies array into a string so that I can compare it to the string being passed into the function (this comparison is done in the line containing if(temp == title).
I then wish to save the value of k when temp == title as movieIdx, so that this can be used further in this function.
I think that the problem is with my referencing of the movies[] array, but I'm not sure what it might be.
Since there are a lot of things going on in this project, I'd be happy to send my files over to anyone who'd be willing to take a look.
Thanks in advance.
FURTHER CONTEXT:
I was attempting to test edge cases by returning 'movieIdx' immediately after setting movieIdx = k, just to see what was going wrong. Example of what I mean:
{
movieIdx = k; //the kth movie will be our match, so save k as our index
numMatches++; //increment number of matches. if the title is found, this should be one at most
return movieIdx;
}
-nan was returned consistently, although if I returned k outside of the first while loop (that contains the other while loops), I'd get the value that was expected (50, in this case, which equals numbMovies). If I returned movieIdx outside of the loop, I got 0.
This told me that there was some issue with the condition if(temp == title). I then did a test where I replaced 'temp' with a hardcoded value that I knew would be passed, "the prestige".
Doing this returned the expected value. I then knew that there must be some issue with 'temp' itself, and I have assumed that the issue therein would probably have to do with how I'm referencing the movies[] array.

How can I check if two cells are equal in brainf*ck?

How can I check if the value in cell #0 is equal to the value in cell #1? I am trying to write code equivalent to:
if(a == b)
{
//do stuff
}
else
{
//do something else
}
I have read Brainfuck compare 2 numbers as greater than or less than, and the second answer gave me a general idea of what I'd need to do, but I cannot figure it out. (That solution gives if a < b, else.)
I am thinking I need to do something along the lines of decrementing both values, and if they reach 0 at the same time, then they are true. But I keep getting stuck at the same exit point every time I think about it.
How can I check if two cells are equal in brainfuck?
I think I have it, I'm not a brainfuck expert but this question looked interesting. There might be a simpler way to do it, but I went with your method of decrementing values one by one.
In this case, if the two values in cell 0 and 1 are equal jump a ton forward, if they are not equal jump a little forward (second brackets is the not equal case, third brackets is the equal case)
Note that I'm using brainfucks while statements as a ghetto if (cell != 0)
+++++++++++++++++
>
+++++++++++++++++
>+<
[ - < - >] <[>>>>>] >> [>>>>>>>>>>>>>>>>>>>>>]
Try it online: http://fatiherikli.github.io/brainfuck-visualizer/#KysrKysrKysrKysrKysrKysKPgorKysrKysrKysrKysrKysrKwo+KzwKWyAtIDwgLSA+XSA8Wz4+Pj4+XSA+PiBbPj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+XQoKCg==
An example implementation, print T (true) if the two values are equal, F (false) if they are not equal
http://fatiherikli.github.io/brainfuck-visualizer/#KysrCj4KKysrKwo+KzwKWyAtIDwgLSA+XSA8Wz4+PgorKysrKysrKysrKysrKysrKysrKworKysrKysrKysrKysrKysrKysrKworKysrKysrKysrKysrKysrKysrKworKysrKysrKysrCi4KPgoKXSA+PiBbCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKysrKysrKysrKysrKysrKysrCisrKwouCj4KXQ==
+>>(a+++++)>(b+++++)>>+<<<
[[->]<<]
<
[>>>>>-<<<<<
a>b
]
>>
[->>-<
a<b
]
>>
[-
a=b
]
Pointer ends on the same pointer in the same state but the code within the appropriate brackets has been executed.
I came up with this for my bf compiler thing
basically it subtracts and then checks if the result is 0.
Can be easily changed to execute stuff in if/else-ish way
Layout:
[A] B
>[-<->]+<[>-<[-]]>
Output
0 [result]
Result is 1 if equal

getline() Adding Character to Front of String? -- Actually substr syntax error

I'm writing a program that will balance Chemistry Equations; I thought it'd be a good challenge and help reinforce the information I've recently learned.
My program is set up to use getline(cin, std::string) to receive the equation. From there it separates the equation into two halves: a left side and right side by making a substring when it encounters a =.
I'm having issues which only concerns the left side of my string, which is called std::string leftSide. My program then goes into a for loop that iterates over the length of leftSide. The first condition checks to see if the character is uppercase, because chemical formulas are written with the element symbols and a symbol consists of either one upper case letter, or an upper case and one lower case letter. After it checks to see if the current character is uppercase, it checks to see if the next character is lower case; if it's lower case then I create a temporary string, combine leftSide[index] with leftSide[index+1] in the temp string then push the string to my vector.
My problem lies on the first iteration; I've been using CuFe3 = 8 (right side doesn't matter right now) to test it out. The only thing stored in std::string temp is C. I'm not sure why this happening; also, I'm still getting numbers in my final answer and I don't understand why. Some help fixing these two issues, along with an explanation, would be greatly appreciated.
[CODE]
int index = 0;
for (it = leftSide.begin(); it!=leftSide.end(); ++it, index++)
{
bool UPPER_LETTER = isupper(leftSide[index]);
bool NEXT_LOWER_LETTER = islower(leftSide[index+1]);
if (UPPER_LETTER)// if the character is an uppercase letter
{
if (NEXT_LOWER_LETTER)
{
string temp = leftSide.substr(index, (index+1));//add THIS capital and next lowercase
elementSymbol.push_back(temp); // add temp to vector
temp.clear(); //used to try and fix problem initially
}
else if (UPPER_LETTER && !NEXT_LOWER_LETTER) //used to try and prevent number from getting in
{
string temp = leftSide.substr(index, index);
elementSymbol.push_back(temp);
}
}
else if (isdigit(leftSide[index])) // if it's a number
num++;
}
[EDIT] When I entered in only ASDF, *** ***S ***DF ***F was the output.
string temp = leftSide.substr(index, (index+1));
substr takes the first index and then a length, rather than first and last indices. You want substr(index, 2). Since in your example index is 0 you're doing: substr(index, 1) which creates a string of length 1, which is "C".
string temp = leftSide.substr(index, index);
Since index is 0 this is substr(index, 0), which creates a string of length 0, that is, an empty string.
When you're processing parts of the string with a higher index, such as Fe in "CuFe3" the value you pass in as the length parameter is higher and so you're creating strings that are longer. F is at index 2 and you call substr(index, 3), which creates the string "Fe3".
Also the standard library usually uses half open ranges, so even if substr took two indices (which, again, it doesn't) you would do substr(index, index+2) to get a two character string.
bool NEXT_LOWER_LETTER = islower(leftSide[index+1]);
You might want to check that index+1 is a valid index. If you don't want to do that manually you might at least switch to using the bounds checked function at() instead of operator[].

Repeat random placing of ships in battleship, depending on restrictions

I'm creating a battleship field and I have created a method that creates spots based off of random parameters. The spots would be like the "1a", "2a" setup.
Here's what it looks like when you call it
ships.append(place_ship(ships, randint(2,3), letter, str(randint(1,4)), random.choice([True,False])))
randint(2,3) refers to the length of the ship, the random choice parameter is whether the boat is vertical or not, the letter refers to the random letter from this:
letter = ''
while letter != "a" and letter != "b" and letter != "c":
letter = random.choice(string.ascii_lowercase)
The method that creates it is place_ships:
def place_ship(ships, length, x, y, vert):
idk = {}
for i in range(length):
square = y+x
if vert:
x = chr(ord(x) + 1)
else:
y = str(int(y) + 1)
idk[i] = square
return idk
My question is how to place the ships without having any of the spots cross ships.
Here is an example of what the locations in a list look like:
['2c', '2d', '3c', '4c', '2c', '2d']
So 2c,2d is a ship 3c,4c, then 2c,2d
I've tried to do the following, but it only checks the first ship
for i in all_ship_loc:
occurence = all_ship_loc.count(i)
while occurence > 1:
place_ship(ships, randint(2,3), letter, str(randint(1,4)),random.choice([True,False]))
Thanks!
You may want to cretate a dictionary for every possible place, so you check if the generated position is already occuped.
dict = { "a1" : True } # True is occuped
Or you could use a list but with only the occuped places.
You might store a matrix of occupied places (values 0,1). Placing a ship occupies some elements (spots where the ship is located, adjacent etc.). For a given ship size, and a given row/column you easely can find out amount of positions available. So your alogorithm may be as follows:
starting from biggest ship
randomly choose a direction (horisontal/vertical)
enumerate positions available in that direction
if none available, reposition some last ships
choose a random position within available set, mark corresponding spots occupied

C++ - solve a sudoku game

I'm new to C++ and have to do a home assignment (sudoku). I'm stuck on a problem.
Problem is that to implement a search function which to solve a sudoku.
Instruction:
In order to find a solution recursive search is used as follows. Suppose that there is a
not yet assigned field with digits (d1....dn) (n > 1). Then we first try to
assign the field to d1, perform propagation, and then continue with search
recursively.
What can happen is that propagation results in failure (a field becomes
empty). In that case search fails and needs to try different digits for one of
the fields. As search is recursive, a next digit for the field considered last
is tried. If none of the digits lead to a solution, search fails again. This in
turn will lead to trying a different digit from the previous field, and so on.
Before a digit d is tried by assigning a field to
it, you have to create a new board being a copy of the current board (use
the copy constructor and allocate the board from the heap with new). Only
then perform the assignment on the copy. If the recursive call to search
returns unsuccessfully, a new board can be created for the next digit to be
tried.
I've tried:
// Search for a solution, returns NULL if no solution found
Board* Board::search(void) {
// create a copy of the cur. board
Board *copyBoard = new Board(*this);
Board b = *copyBoard;
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
// if the field has not been assigned, assign it with a digit
if(!b.fs[i][j].assigned()){
digit d = 1;
// try another digit if failed to assign (1 to 9)
while (d <=9 && b.assign(i, j, d) == false){
d++;
// if no digit matches, here is the problem, how to
// get back to the previous field and try another digit?
// and return null if there's no pervious field
if(d == 10){
...
return NULL;
}
}
}
}
return copyBoard;
}
Another problem is where to use the recursive call? Any tips? thx!
Complete instruction can been found here: http://www.kth.se/polopoly_fs/1.136980!/Menu/general/column-content/attachment/2-2.pdf
Code: http://www.kth.se/polopoly_fs/1.136981!/Menu/general/column-content/attachment/2-2.zip
There is no recursion in your code. You can't just visit each field once and try to assign a value to it. The problem is that you may be able to assign, say, 5 to field (3,4) and it may only be when you get to field (6,4) that it turns out there can't be a 5 at (3, 4). Eventually you need to back out of recursion until you come back to (3,4) and try another value there.
With recursion you might not use nested for loops to visit fields, but visit the next field with a recursive call. Either you manage to reach the last field, or you try all possibilities and then leave the function to get back to the previous field you visited.
Sidenote: definitely don't allocate dynamic memory for this task:
//Board *copyBoard = new Board(*this);
Board copyBoard(*this); //if you need a copy in the first place
Basically what you can try is something like this (pseudocode'ish)
bool searchSolution(Board board)
{
Square sq = getEmptySquare(board)
if(sq == null)
return true; // no more empty squares means we solved the puzzle
// otherwise brute force by trying all valid numbers
foreach (valid nr for sq)
{
board.doMove(nr)
// recurse
if(searchSolution(board))
return true
board.undoMove(nr) // backtrack if no solution found
}
// if we reach this point, no valid solution was found and the puzzle is unsolvable
return false;
}
The getEmptySquare(...) function could return a random empty square or the square with the least number of options left.
Using the latter will make the algorithm converge much faster.