<commit_before>#include "Grid.hpp"

#include <cassert>
#include <stdexcept>
#include <algorithm>
#include <array>

#include "Util.hpp"
#include "TileLogic.hpp"
#include "Types.hpp"


using namespace jakway_antf;

namespace
{
#ifdef DEBUG
    void assertGridIsRectangular(std::deque<std::deque<bool>*>& tiles)
    {
        //sanity check
        assert(!tiles.empty());

        //check the grid is rectangular and not jagged
        //i.e. all sublists are the same size
        //note that the number of sublists does not have to be equal to the number of columns
        for(std::deque<bool>* thisSubList : tiles)
        {
            for(std::deque<bool>* otherSubList : tiles)
            {
                assert(!otherSubList->empty());
                assert(thisSubList->size() == otherSubList->size());
            }
        }
    }
#endif
}

POS_TYPE Grid::getWidth()
{
    return tiles.front()->size();
}

POS_TYPE Grid::getHeight()
{
    return tiles.size();
}

POS_TYPE Grid::getSize()
{
    return getWidth() * getHeight();
}

void Grid::expandGrid()
{
    //check the grid is the right shape before and after we modify it
#ifdef DEBUG
    assertGridIsRectangular(tiles);
#endif
    const POS_TYPE newWidth = getWidth() + 2;

    //add 1 tile to the beginning of each sublist (prepending a column)
    //add 1 tile to the end of each sublist (appending a column)
    for(std::deque<bool>* thisSubList : tiles)
    {
        thisSubList->push_front(TILE_DEAD);
        thisSubList->push_back(TILE_DEAD);
    }

    //add 1 row to the beginning of the tiles list (prepending a row)
    //add 1 row to the end of the tiles list (appending a column)
    std::deque<bool> *firstList = new std::deque<bool>(newWidth, TILE_DEAD),
        *lastList = new std::deque<bool>(newWidth, TILE_DEAD);
    tiles.push_front(firstList);
    tiles.push_back(lastList);
    
    
#ifdef DEBUG
    //check the size is correct
    assertGridIsRectangular(tiles);
#endif
}



/**
 * should this be renamed to liveEdges()?
 */
bool Grid::touchingEdges()
{
    //check top edge for live tiles
    std::deque<bool>* topSubList = tiles.front();
    for(bool thisBool : *topSubList)
    {
        if(thisBool == TILE_ALIVE)
            return true;
    }

    //check bottom edge for live tiles
    std::deque<bool>* bottomSubList = tiles.back();
    for(bool thisBool : *bottomSubList)
    {
        if(thisBool == TILE_ALIVE)
            return true;
    }

    //check the left and right edges
    for(std::deque<bool>* thisSubList : tiles)
    {
        if(thisSubList->front() == TILE_ALIVE || thisSubList->back() == TILE_ALIVE)
            return true;
    }

    //if we haven't found any live tiles yet, there arent any in the edges
    return false;
}

Grid::Grid(const Grid& other)
{
    //TODO: IMPLEMENT
}

Grid::Grid(const POS_TYPE width, const POS_TYPE height)
{
    //making i the same type is easier
    for(POS_TYPE i = 0; i < height; i++)
    {
        //don't have to loop to add items to the list
        //this list CTOR will insert <width> number of bools all at once
        std::deque<bool>* subList = new std::deque<bool>(width, TILE_DEAD);
        //insert the sublist
        tiles.push_back(subList);
    }
}

Grid::~Grid()
{
    for(std::deque<bool>* thisSubList : tiles)
    {
        delete thisSubList;
    }
}

namespace
{
    /**
     * a barebones immutable Tile class
     */
    class Tile
    {
    private:
        const POS_TYPE x, y;
        const bool alive;
    public:
        Tile(const POS_TYPE pX, const POS_TYPE pY, const bool pAlive)
            : x(pX), y(pY), alive(pAlive) {}

        POS_TYPE getX()
        { return x; }
        POS_TYPE getY()
        { return y; }
        bool isAlive()
        { return alive; }
    };
}


void Grid::runGeneration()
{
    if(touchingEdges())
        expandGrid();

    assert(!touchingEdges());

    //XXX -- TODO: implement runGeneration
    //XXX -- TODO: instead of making changes in-place, change the method signature to return a unique_ptr<Grid> -- a new pointer to a grid
    //make all changes to the new grid so that the generation only calculates which tiles live based on ALREADY ALIVE tiles, otherwise you're modifying a tiles' neighbor right before you check if it will live.  THIS IS A BUG!
    assert(false); //XXX
    for(auto gridIt = begin(); gridIt != end(); gridIt++)
    {
        const bool isAlive = *gridIt;
        unsigned int numLiveNeighbors = gridIt.getNumLiveNeighbors();

        //change the tile based on if it will live
        *gridIt = TileLogic::WillBeAlive(isAlive, numLiveNeighbors);


    }
}

/**<commit_msg>implemented runGeneration by getting a list of changes and then applying them<commit_after>#include "Grid.hpp"

#include <cassert>
#include <stdexcept>
#include <algorithm>
#include <array>
#include <vector>

#include "Util.hpp"
#include "TileLogic.hpp"
#include "Types.hpp"


using namespace jakway_antf;

namespace
{
#ifdef DEBUG
    void assertGridIsRectangular(std::deque<std::deque<bool>*>& tiles)
    {
        //sanity check
        assert(!tiles.empty());

        //check the grid is rectangular and not jagged
        //i.e. all sublists are the same size
        //note that the number of sublists does not have to be equal to the number of columns
        for(std::deque<bool>* thisSubList : tiles)
        {
            for(std::deque<bool>* otherSubList : tiles)
            {
                assert(!otherSubList->empty());
                assert(thisSubList->size() == otherSubList->size());
            }
        }
    }
#endif
}

POS_TYPE Grid::getWidth()
{
    return tiles.front()->size();
}

POS_TYPE Grid::getHeight()
{
    return tiles.size();
}

POS_TYPE Grid::getSize()
{
    return getWidth() * getHeight();
}

void Grid::expandGrid()
{
    //check the grid is the right shape before and after we modify it
#ifdef DEBUG
    assertGridIsRectangular(tiles);
#endif
    const POS_TYPE newWidth = getWidth() + 2;

    //add 1 tile to the beginning of each sublist (prepending a column)
    //add 1 tile to the end of each sublist (appending a column)
    for(std::deque<bool>* thisSubList : tiles)
    {
        thisSubList->push_front(TILE_DEAD);
        thisSubList->push_back(TILE_DEAD);
    }

    //add 1 row to the beginning of the tiles list (prepending a row)
    //add 1 row to the end of the tiles list (appending a column)
    std::deque<bool> *firstList = new std::deque<bool>(newWidth, TILE_DEAD),
        *lastList = new std::deque<bool>(newWidth, TILE_DEAD);
    tiles.push_front(firstList);
    tiles.push_back(lastList);
    
    
#ifdef DEBUG
    //check the size is correct
    assertGridIsRectangular(tiles);
#endif
}



/**
 * should this be renamed to liveEdges()?
 */
bool Grid::touchingEdges()
{
    //check top edge for live tiles
    std::deque<bool>* topSubList = tiles.front();
    for(bool thisBool : *topSubList)
    {
        if(thisBool == TILE_ALIVE)
            return true;
    }

    //check bottom edge for live tiles
    std::deque<bool>* bottomSubList = tiles.back();
    for(bool thisBool : *bottomSubList)
    {
        if(thisBool == TILE_ALIVE)
            return true;
    }

    //check the left and right edges
    for(std::deque<bool>* thisSubList : tiles)
    {
        if(thisSubList->front() == TILE_ALIVE || thisSubList->back() == TILE_ALIVE)
            return true;
    }

    //if we haven't found any live tiles yet, there arent any in the edges
    return false;
}

Grid::Grid(const Grid& other)
{
    //TODO: IMPLEMENT
}

Grid::Grid(const POS_TYPE width, const POS_TYPE height)
{
    //making i the same type is easier
    for(POS_TYPE i = 0; i < height; i++)
    {
        //don't have to loop to add items to the list
        //this list CTOR will insert <width> number of bools all at once
        std::deque<bool>* subList = new std::deque<bool>(width, TILE_DEAD);
        //insert the sublist
        tiles.push_back(subList);
    }
}

Grid::~Grid()
{
    for(std::deque<bool>* thisSubList : tiles)
    {
        delete thisSubList;
    }
}

namespace
{
    /**
     * a barebones immutable Tile class
     */
    class Tile
    {
    private:
        const POS_TYPE x, y;
        const bool alive;
    public:
        Tile(const POS_TYPE pX, const POS_TYPE pY, const bool pAlive)
            : x(pX), y(pY), alive(pAlive) {}

        POS_TYPE getX()
        { return x; }
        POS_TYPE getY()
        { return y; }
        bool isAlive()
        { return alive; }
    };
}


void Grid::runGeneration()
{
    if(touchingEdges())
        expandGrid();

    assert(!touchingEdges());

    std::vector<Tile> differenceList;

    //XXX -- TODO: implement runGeneration
    //XXX -- TODO: instead of making changes in-place, change the method signature to return a unique_ptr<Grid> -- a new pointer to a grid
    //make all changes to the new grid so that the generation only calculates which tiles live based on ALREADY ALIVE tiles, otherwise you're modifying a tiles' neighbor right before you check if it will live.  THIS IS A BUG!
    for(auto gridIt = begin(); gridIt != end(); gridIt++)
    {
        const bool isAlive = *gridIt;
        unsigned int numLiveNeighbors = gridIt.getNumLiveNeighbors();

        //change the tile based on if it will live
        const bool willBeAlive = TileLogic::WillBeAlive(isAlive, numLiveNeighbors);
        
        //check if the tile has changed
        //if so, add it to the difference list
        if(willBeAlive != isAlive)
        {
            differenceList.emplace_back(gridIt.getX(), gridIt.getY(), willBeAlive);
        }
    }

    //apply the changes to the grid
    for(Tile& diff : differenceList)
    {
        setTile(diff.getX(), diff.getY(), diff.isAlive());
    }
}

/**
{'fraction_non_alphanumeric': 0.11462288353001539, 'fraction_numerical': 0.0012314007183170856, 'mean_word_length': 2.5286024619840695, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2700864', 'n_tokens_mistral': 3159, 'n_tokens_neox': 3081, 'n_words': 950}