Value assigned by List, Changes at every iteration - list

This is a function of grouping events by their day. It starts with a List<EventK> which contains all the elements to sort. The result is a Map<DateTime, List<EventK>>.
The problem is with currentDayEvents. Once it is assigned to _events, and the value of currentDayEvents changes in different iterations, the value of _events also changes. How can I get the permanent value of _events outside the function?
void _getEvents()async{
setState(() {
isLoading = true;
});
List<EventK> events = await EventApi.getPersonalEvents();
List<EventK> currentDayEvents = [];
DateTime currentDay;
for(int i = 0; i<events.length-1; i++){
currentDay = events[i].startTime;
currentDayEvents.add(events[i]);
for(int j=i+1; j<events.length; j++){
DateTime analyzedDay = events[j].startTime;
if(currentDay.year == analyzedDay.year &&
currentDay.month == analyzedDay.month &&
currentDay.day == analyzedDay.day
){
currentDayEvents.add(events[j]);
events.removeAt(j);
j -= 1;
}
}
_events.putIfAbsent(currentDay, ()=>currentDayEvents);
currentDayEvents.clear();
}
setState(() {
isLoading = false;
});
}

Move the declaration of currentDayEvents inside the for-loop to reinitialise a new object on each iteration. In doing so, you can remove currentDayEvents.clear().
for(int i = 0; i<events.length-1; i++){
currentDay = events[i].startTime;
var currentDayEvents = [events[i]];
for(int j=i+1; j<events.length; j++){
DateTime analyzedDay = events[j].startTime;
if(currentDay.year == analyzedDay.year &&
currentDay.month == analyzedDay.month &&
currentDay.day == analyzedDay.day
){
currentDayEvents.add(events[j]);
events.removeAt(j);
j -= 1;
}
}
_events.putIfAbsent(currentDay, ()=>currentDayEvents);
}

Related

Detect consecutive objects with a common attribute in 2-D array

I have a 2-D array of gems, all the gems have been given random color. Now i want to detect if three or more consecutive gems in a row or column has the same color. If so i want to do some action with those gems.
Gem gems[10][10];
for(int i=0;i<10;++i){
for(int j=0;j<10;++j){
gems[i][j].setColor(GetRandInRange(0,6));
}
}
bool detectMatch(){
for(int i=0;i<10;++i){
for(int j=0;j<10;++j){
// Code to detect three or more consecutive gems with same color
// Give some special color to the matched gems
}
}
Here is how i tried but it doesn't work
bool GameBoard::findMatch(){
for(int i=0;i<10;++i){
int count=0;
for(int j=0;j<10;++j){
if(j!=0){
if(gems[i][j].getColor()==gems[i][j-1].getColor()){ //Color same with previous one
int a=i, b=j;
while(gems[a][b].getColor()==gems[i][j].getColor() && (a<10 && b<10)){ // Check till the color does not match
count++;
a++;
b++;
}
if(count>=3){ //If 3 or more have matched
for(int a=i, b=j, c=0;c<count;++c){
gems[a][b].setColor(0);
}
return true;
}
}
}
}
}
return false;
}
if you can help me with this code please
Here's how I'd go about it. You need to do two scans. First, you need to scan for runs in one direction, then the other. It's much simpler than trying to loop through once.
I first check for horizontal runs, exiting as soon as one longer than 2 is found. Same with the vertical ones. Your function has a bool signature, so I've assumed you'll use another function to determine the location of the run - you could easily return a struct that held the position, direction and length from the findMatch method.
"use strict";
window.addEventListener('load', onLoaded, false);
var gems;
function onLoaded(evt) {
// create and initialize the array
gems = new Array();
for (var row = 0; row < 10; row++) {
let curRow = new Array();
for (var col = 0; col < 10; col++) {
let curCell = new Gem();
curCell.setColor(GetRandInRange(0, 6));
curRow.push(curCell);
}
gems.push(curRow);
}
// display it for the user
displayGems();
// check if there's 3 or more in a vertical or horizontal line.
console.log(hasMatch());
}
class Gem {
setColor(colIndex) {
this.color = colIndex;
}
getColor() {
return this.color;
}
};
function displayGems() {
var str = '';
for (var row = 0; row < 10; row++) {
if (row != 0)
str += "\n";
var dat = gems[row];
dat.forEach((gem, idx) => {
if (idx != 0)
str += ', ';
str += gem.getColor();
});
}
console.log(str);
}
function GetRandInRange(lower, upper) {
return ((Math.random() * (upper - lower)) + lower + 0.5) >> 0;
}
function hasMatch() {
let matchFound = 0;
// scan #1 - horizontally on each row
for (var row = 0; row < 10; row++) {
let last = undefined;
let runLength = 0;
for (var col = 0; col < 10; col++) {
let cur = gems[row][col].getColor();
if (cur == last) {
runLength++
if (runLength > 2) {
console.log(`horiz - ${row+1}`);
return true;
}
} else {
runLength = 0;
last = cur;
}
}
}
for (var col = 0; col < 10; col++) {
let last = undefined;
let runLength = 1;
for (var row = 0; row < 10; row++) {
let cur = gems[row][col].getColor();
if (cur == last) {
runLength++;
if (runLength > 2) {
console.log(`vert - ${col+1}`);
return true;
}
} else {
runLength = 1;
last = cur;
}
}
}
return false;
}

Huffman coding c++

So I am working on Huffman coding for a project. However, my code just doesn't work. When i ran it on visual studio, it didn't give me an error. What I was trying to do is to read a file and put all of them into a string. And get the frequency for each character in that string. But I think when the file got a little bit large, it seems like my code is running in a infinite loop. Can anyone explain anything to me? By the way, I had a sorted function that I used to sort a vector of node* by their frequency.
ifstream infile;
infile.open(filename);
string q;
string line;
while (getline(infile, line))
{
q += line;
}
char y;
int count = 0;
int check = 0;
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
}
}
if (check == 0)
{
for (int i = 0; i < q.size(); i++)
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}
sort(list1.begin(), list1.end(), sorter); //sort them from small to big
while (list1.size() > 1)
{
node*left = list1[0];
node*right = list1[1];
list1.erase(list1.begin(), list1.begin() + 2);
double sum = left->freq + right->freq;
node* x = new node;
x->freq = sum;
x->left = left;
x->right = right;
list1.push_back(x);
sort(list1.begin(), list1.end(), sorter);
}
list1.clear();
return true;
The following is my sort function
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() != '\0') {
return (int)a->getCharacter() < (int)b->getCharacter();
}
return false;
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
I see two major problems.
You have a for loop inside a for loop both initializing and using int i
Change the variable name of the inner loop.
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
.
.
if (check == 0)
{
for (int i = 0; i < q.size(); i++) //Change this to int j for example
{
.
.
And the Sorter struct. I would rewrite it as this.
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() == '\0') return true;
return (int)a->getCharacter() < (int)b->getCharacter();
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
A few suggestions for your for loop:
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
//You can avoid this entire loop by using a structure like map
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
//break; //if you use a loop, break it once you find the character.
}
}
if (check == 0)
{
for (int j = 0; j < q.size(); j++)//Renamed variable + you can start this loop from j = i as you know there is no occurrence of y before that.
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}

c++ for loop counter failing

Hi I am trying to count the number of zeros after a 1 has occured in a simple 1d array i dont know why the counter is always zero.
int main ()
{
int testarray[9];
testarray[0] = 0;
testarray[1] = 0;
testarray[2] = 1;
testarray[3] = 1;
testarray[4] = 0;
testarray[5] = 0;
testarray[6] = 0;
testarray[7] = 1;
testarray[8] = 1;
int counter = 0;
bool white = false;
bool prevValue =true;
bool black = true;
bool check = false;
int num = 0;
for (int i = 0; i<8; i++) {
num = testarray[i];
if (num == 1)
white = true;
else
white = false;
if((white ==true) && (prevValue == false)) {
if(i == 0) {
check = true;
i++;
}
else
check = false;
}
else {
if (check)
counter++;
}
prevValue = true;
}
cout << "Counter: "<<counter;
return 0;
}
The practical implementation involves using this for loop to detect edges. I have tried messing with the variables but to no avail. the reason that white =1, and black = 0 is because i am using this loop to solve a vision based problem. Any help would be apreciated.
because prevValue is always true : it never come to this block :
if((white ==true) && (prevValue == false)) {
if(i == 0) {
check = true;
i++;
}
else
check = false;
}
so because of this check is never assigned to 'true' so counter is not incremented
If I have understood all what you need is to find at first 1 and then to count the number of zeroes.
It can be done in one statement if to use standard algorithms.
int counter = std::count( std::find( std::begin( testarray ), std::end( testarray ), 1 ),
std::end( testarray ),
0 );
Because, with this values of the array, check is always false and it need to be true in order to allow counter variable to be incremented as you have written:
if (check)
counter++;
Also, your for loop doesn't reach the value testarray[8], you've to write
for (int i = 0; i<9; i++)
in order to include from testarray[0] to testarray[9]

Checking for overlapping characters in a wordsearch game

I am developing a wordsearch generator to learn c++ better and I am stuck on preventing non-overlapping words from overlapping, such as a side-to-side word writing over a letter in a top-down word. Here is the code snippet:
else if (random_choice == 1 && random_word.size() <= 10-j && words_vector.size() != 0) {
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i][j+x] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
j += 1;
}
j -= 1;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
What I have done was create a two dimensional array [10][11] filled with the 0 (zero) character so when I iterate through it all spaces are filled with 0 except for the 11th space in each line with a newline character to make a 10X10 grid. In my else if loop, the first part already has a word chosen and it tests if the word will fit in its proper space by checking if a 0 is present. If it runs into a non-zero character (such as if it runs into a letter from a top-down or diagonal word) the inner loop terminates, sets the boolean flag, and inputs a 1 (or any random letter) instead of the whole word. What happens is that the whole word is inserted anyways and overwrites one letter from the top down word. What am I doing wrong? Here is the rest of the code:
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
srand(time(NULL));
const char* const a_to_z = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
int random_char;
char wordsearch [10][11] = {0};
bool flag;
string words_array[] = {"CAT", "HELLO", "GOODBYE", "DOG", "BAT", "NEW", "SAY", "MAY", "DAY", "HAY"};
vector<string> words_vector (words_array, words_array + sizeof(words_array) / sizeof(string));
string words_found_array[] = {};
vector<string> words_found_vector (words_found_array, words_found_array + sizeof(words_found_array) / sizeof(string));
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 11; j++) {
int random_choice = rand() % 5;
int random_word_number = rand() % words_vector.size();
string random_word = words_vector[random_word_number];
if (j == 10) {
wordsearch[i][j] = '\n';
}
else if (random_choice == 1 && random_word.size() <= 10-j && words_vector.size() != 0) {
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i][j+x] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
j += 1;
}
j -= 1;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
else if (random_choice == 2 && random_word.size() <= 10-i && words_vector.size() != 0) {
int temp_i = i;
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i+x][j] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
i += 1;
}
i = temp_i;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
else {
int random_char = rand() % 26 + 0;
wordsearch[i][j] = a_to_z[random_char];
}
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 11; j++) {
cout<<wordsearch[i][j];
}
}
cout<<"Your words are:"<<endl;
for (int x = 0; x < words_found_vector.size(); x++) {
cout<<words_found_vector[x]<<endl;
}
}
One more thing:
//words_vector.erase(words_vector.begin()+random_word_number);
crashes my program. I think it is a scoping issue with this:
int random_choice = rand() % 5;
int random_word_number = rand() % words_vector.size();
string random_word = words_vector[random_word_number];
What I want to do is eventually have the user give me a list of words they want to search for and this function chooses some of them and presents it to the user when playing the game. This not functioning correctly also causes duplicates to appear in the crossword and words-to-find-list.
Thank you for your help!
You have this error twice in your code:
if (flag = true)
That is not a condition, it's an assignment. It assigns true to flag, and the if-block will always execute. You need to make it a comparison condition by using ==
if (flag == true)
A more common way to write that in C++ would be just
if (flag)

For loop just... not starting?

This is a bizarre problem. I've got a void function that performs a for loop and nothing else, but the for loop doesn't ever start, even though the function is being called. Here is the function:
void Cell::Consolidate()
{
cout << "Consolidating (outside)...\n";
for(int i = 0; i < m_Tiles.size(); ++i)
{
cout << "Consolidating (inside)...\n";
int row = m_Tiles[i]->GetRow();
int col = m_Tiles[i]->GetCol();
//Check below.
if((*m_pTileMap)[row + 1][col].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row + 1][col].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row + 1][col].pParentCell);
}
}
//Check above.
else if((*m_pTileMap)[row - 1][col].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row - 1][col].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row - 1][col].pParentCell);
}
}
//Check the right.
else if((*m_pTileMap)[row][col + 1].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row][col + 1].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row][col + 1].pParentCell);
}
}
//Check the left.
else if((*m_pTileMap)[row][col - 1].pParentCell != this)
{
m_EdgeTiles.push_back(m_Tiles[i]);
m_Tiles[i]->SetColor(sf::Color(100, 100, 100));
bool newNeighbor = true;
for(int j = 0; j < m_Neighbors.size(); ++j)
{
if(m_Neighbors[j] == (*m_pTileMap)[row][col - 1].pParentCell)
{
newNeighbor = false;
break;
}
}
if(newNeighbor)
{
m_Neighbors.push_back((*m_pTileMap)[row][col - 1].pParentCell);
}
}
}
}
When I run the program, "Consolidating (outside)...\n" gets send to cout, but "Consolidating (inside)...\n" does not. Nothing that is supposed to happen in the loop actually happens, either (for example the SetColor() calls don't do anything, nor does anything happen if I send things to cout anywhere else in the loop), so I can only assume the loop is not starting at all. Why not? What could cause this?
i < m_Tiles.size()
This loop condition gets checked on entrance to the loop, not only after each iteration. If your m_Tiles vector is empty, well, no loop for you.
Most likely, m_Tiles.size() returns a negative value or zero value.