Skip to content

Commit

Permalink
Add bitsream hash table
Browse files Browse the repository at this point in the history
  • Loading branch information
Sedictious committed May 1, 2019
1 parent 4422010 commit 244a248
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 30 deletions.
8 changes: 4 additions & 4 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"type": "model",
"uid": "gameOfLife",
"title": "Conway's Game of Life",
"uid": "lifeLike",
"title": "Life-like automata",
"version": 1,
"author": "Ethan Padden, Marcos Cardinot and Eleftheria Chatziargyriou",
"author": "Eleftheria Chatziargyriou",
"description": "This implements life-like cellular automata.",
"supportedGraphs": ["squareGrid"],
"pluginAttributesScope": [ {"rules": "string"} ],
"nodeAttributesScope": [ {"live": "bool"} ]
}
}
53 changes: 33 additions & 20 deletions plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@

namespace evoplex {

QStringList GameOfLife::parseCmd(const QString &cmd)
QBitArray LifeLike::parseCmd(const QString &cmd)
{
if (cmd.isEmpty())
{
qWarning() << "The command cannot be empty";
return QStringList();
return QBitArray();
}

QBitArray rules(18);
QStringList _cmds;
QString _cmd1, _cmd2;

Expand All @@ -27,41 +28,53 @@ QStringList GameOfLife::parseCmd(const QString &cmd)
if (cmd.indexOf("/") == -1)
{
qWarning() << "Commands must be of the form B{number of neighbors for cell birth} / S{number of neighbors for cell survival";
return QStringList();
return QBitArray();
}

_cmds = cmd.split("/");

if (!_cmds.at(0).startsWith("B") || !_cmds.at(1).startsWith("S"))
{
qWarning() << "Commands must be of the form B{number of neighbors for cell birth} / S{number of neighbors for cell survival";
return QStringList();
return QBitArray();
}

_cmd1 = _cmds.at(0);
_cmd1.remove(0, 1);
_cmd2 = _cmds.at(1);
_cmd2.remove(0, 1);

int intRule1 = _cmd2.toInt(&isInt1);
int intRule2 = _cmd1.toInt(&isInt2);
int intRule1 = _cmd1.toInt(&isInt1);
int intRule2 = _cmd2.toInt(&isInt2);

// check if rules are integers
if (!isInt1 || !isInt2)
// check if rules are integers or empty
if (!(isInt1 || _cmd1.isEmpty()) || !(isInt2 || _cmd2.isEmpty()))
{
qWarning() << "Unable to parse command. Make sure you give a valid integer.";
return QStringList();
return QBitArray();
}
// check if the rulestring has unique integers
if (QSet<QString>::fromList(_cmd1.split("")).count() != _cmd1.size() + 1 || QSet<QString>::fromList(_cmd2.split("")).count() != _cmd2.size() + 1)

// convert rule to a bitstream
for (const auto& c : _cmd1)
{
qWarning() << "Integers can't appear more than once on each rule.";
return QStringList();
if (rules[c.digitValue() + 0x0A]){
qWarning() << "Rulestring should contain only unique integers.";
return QBitArray();
}
rules.setBit(c.digitValue() + 0x0A);
}
for (const auto& c: _cmd2)
{
if (rules[c.digitValue()]){
qWarning() << "Rulestring should contain only unique integers.";
return QBitArray();
}
rules.setBit(c.digitValue());
}
return QStringList() << _cmd1 << _cmd2;
return rules;
}

bool GameOfLife::init()
bool LifeLike::init()
{
// gets the id of the `live` node's attribute, which is the same for all nodes
m_liveAttrId = node(0).attrs().indexOf("live");
Expand All @@ -77,15 +90,15 @@ bool GameOfLife::init()

m_rulesetLst = parseCmd(m_ruleset);

if (m_rulesetLst.isEmpty())
if (m_rulesetLst.isNull())
{
return false;
}

return m_liveAttrId >= 0;
}

bool GameOfLife::algorithmStep()
bool LifeLike::algorithmStep()
{
std::vector<Value> nextStates;
nextStates.reserve(nodes().size());
Expand All @@ -101,11 +114,11 @@ bool GameOfLife::algorithmStep()
if (node.attr(m_liveAttrId).toBool()) {
// If the node is alive, then it only survives if its number of neighbors is specified in the rulestring.
// Otherwise, it dies from under/overpopulation
nextStates.emplace_back(m_rulesetLst.at(1).contains(QString::number(liveNeighbourCount)));
nextStates.emplace_back(m_rulesetLst[liveNeighbourCount]);
} else {
// Any dead cell can become alive if its number of neighbors matches the one specified in the rulestring.
// Otherwise, it remains dead.
nextStates.emplace_back(m_rulesetLst.at(0).contains(QString::number(liveNeighbourCount)));
nextStates.emplace_back(m_rulesetLst[liveNeighbourCount + 0x0A]);
}
}
// For each node, load the next state into the current state
Expand All @@ -118,5 +131,5 @@ bool GameOfLife::algorithmStep()
}

} // evoplex
REGISTER_PLUGIN(GameOfLife)
REGISTER_PLUGIN(LifeLike)
#include "plugin.moc"
14 changes: 8 additions & 6 deletions plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@
* the LICENSE file in the root directory of this source tree.
*/

#ifndef GAME_OF_LIFE_H
#define GAME_OF_LIFE_H
#ifndef LIFELIKE_H
#define LIFELIKE_H

#include <QBitArray>

#include <plugininterface.h>

namespace evoplex {
class GameOfLife: public AbstractModel
class LifeLike: public AbstractModel
{
public:
bool init() override;
bool algorithmStep() override;
QStringList parseCmd(const QString &cmd);
QBitArray parseCmd(const QString &cmd);

private:
int m_liveAttrId; // the id of the 'live' node's attribute
QString m_ruleset; // the model's ruleset (B/S format)
QStringList m_rulesetLst;
QBitArray m_rulesetLst; // the bitstream representing the input ruleset
};
} // evoplex
#endif // GAME_OF_LIFEL_H
#endif // LIFELIKE_H

0 comments on commit 244a248

Please sign in to comment.