Skip to content
Snippets Groups Projects
Strategy.cpp 4.23 KiB
Newer Older
Franck Dary's avatar
Franck Dary committed
#include "Strategy.hpp"
Franck Dary's avatar
Franck Dary committed

Strategy::Strategy(const std::vector<std::string_view> & lines)
{
  if (!util::doIfNameMatch(std::regex("Strategy : ((incremental)|(sequential))"), lines[0], [this](auto sm)
  {type = sm[1] == "sequential" ? Type::Sequential : Type::Incremental;}))
  util::myThrow(fmt::format("Invalid strategy identifier '{}'", lines[0]));

  for (unsigned int i = 1; i < lines.size(); i++)
  {
    auto splited = util::split(lines[i], ' ');
Franck Dary's avatar
Franck Dary committed
    std::pair<std::string, std::string> key;
    std::string value;
Franck Dary's avatar
Franck Dary committed
    int movement;
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
    if (splited.size() == 3)
Franck Dary's avatar
Franck Dary committed
    {
      key = std::pair<std::string,std::string>(splited[0], "");
      value = splited[1];
Franck Dary's avatar
Franck Dary committed
      movement = std::stoi(std::string(splited[2]));
      if (defaultCycle.empty())
        initialState = splited[0];
Franck Dary's avatar
Franck Dary committed
      defaultCycle.emplace_back(value);
    }
Franck Dary's avatar
Franck Dary committed
    else if (splited.size() == 4)
Franck Dary's avatar
Franck Dary committed
    {
Franck Dary's avatar
Franck Dary committed
      key = std::pair<std::string,std::string>(splited[0], splited[2]);
Franck Dary's avatar
Franck Dary committed
      value = splited[1];
Franck Dary's avatar
Franck Dary committed
      movement = std::stoi(std::string(splited[3]));
Franck Dary's avatar
Franck Dary committed
    }
Franck Dary's avatar
Franck Dary committed
    else
      util::myThrow(fmt::format("Invalid strategy line '{}'", lines[i]));
Franck Dary's avatar
Franck Dary committed

    if (edges.count(key))
      util::myThrow(fmt::format("Edge {} {} defined twice", key.first, key.second));
Franck Dary's avatar
Franck Dary committed
    edges[key] = std::make_pair(value, movement);
Franck Dary's avatar
Franck Dary committed
    isDone[key.first] = false;
Franck Dary's avatar
Franck Dary committed

  if (edges.empty())
    util::myThrow("Strategy is empty");
Franck Dary's avatar
Franck Dary committed
  if (type == Type::Sequential)
    defaultCycle.pop_back();
Franck Dary's avatar
Franck Dary committed
  std::reverse(defaultCycle.begin(), defaultCycle.end());
  originalDefaultCycle = defaultCycle;
Franck Dary's avatar
Franck Dary committed
}

std::pair<std::string, int> Strategy::getMovement(const Config & c, const std::string & transition)
Franck Dary's avatar
Franck Dary committed
{
Franck Dary's avatar
Franck Dary committed
  std::string transitionPrefix(util::split(transition, ' ')[0]);

Franck Dary's avatar
Franck Dary committed
  if (c.stateIsDone())
    isDone[c.getState()] = true;

Franck Dary's avatar
Franck Dary committed
  if (type == Type::Sequential)
Franck Dary's avatar
Franck Dary committed
  {
Franck Dary's avatar
Franck Dary committed
    while (defaultCycle.size() && isDone[defaultCycle.back()])
      defaultCycle.pop_back();

    return getMovementSequential(c, transitionPrefix);
  }

  for (unsigned int i = 0; i < defaultCycle.size(); i++)
Franck Dary's avatar
Franck Dary committed
    if (isDone[defaultCycle[i]])
    {
      while (defaultCycle.size() != i)
        defaultCycle.pop_back();
      break;
    }
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
  return getMovementIncremental(c, transitionPrefix);
Franck Dary's avatar
Franck Dary committed
}

std::pair<std::string, int> Strategy::getMovementSequential(const Config & c, const std::string & transition)
{
  auto foundSpecific = edges.find(std::make_pair(c.getState(), transition));
  auto foundGeneric = edges.find(std::make_pair(c.getState(), ""));

  std::string target;
Franck Dary's avatar
Franck Dary committed
  int movement = -1;
Franck Dary's avatar
Franck Dary committed

  if (foundSpecific != edges.end())
Franck Dary's avatar
Franck Dary committed
  {
    target = foundSpecific->second.first;
    movement = foundSpecific->second.second;
  }
Franck Dary's avatar
Franck Dary committed
  else if (foundGeneric != edges.end())
Franck Dary's avatar
Franck Dary committed
  {
    target = foundGeneric->second.first;
    movement = foundGeneric->second.second;
  }
Franck Dary's avatar
Franck Dary committed

  if (target.empty())
    util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));

  if (!c.stateIsDone())
    return {c.getState(), c.canMoveWordIndex(movement) ? movement : 0};
Franck Dary's avatar
Franck Dary committed

  if (!isDone[target])
    return {target, -c.getWordIndex()};

  return endMovement;
}

std::pair<std::string, int> Strategy::getMovementIncremental(const Config & c, const std::string & transition)
Franck Dary's avatar
Franck Dary committed
{
  auto foundSpecific = edges.find(std::make_pair(c.getState(), transition));
  auto foundGeneric = edges.find(std::make_pair(c.getState(), ""));

Franck Dary's avatar
Franck Dary committed
  std::string target;
  int movement = -1;
Franck Dary's avatar
Franck Dary committed

Franck Dary's avatar
Franck Dary committed
  if (foundSpecific != edges.end())
Franck Dary's avatar
Franck Dary committed
  {
    target = foundSpecific->second.first;
    movement = foundSpecific->second.second;
  }
Franck Dary's avatar
Franck Dary committed
  else if (foundGeneric != edges.end())
Franck Dary's avatar
Franck Dary committed
  {
    target = foundGeneric->second.first;
    movement = foundGeneric->second.second;
  }
Franck Dary's avatar
Franck Dary committed

  if (target.empty())
    util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition));
Franck Dary's avatar
Franck Dary committed
  if (c.hasStack(0) and c.getStack(0) == c.getWordIndex() and not c.canMoveWordIndex(movement))
    target = c.getState();

Franck Dary's avatar
Franck Dary committed
  if (!isDone[target])
    return {target, c.canMoveWordIndex(movement) ? movement : 0};
Franck Dary's avatar
Franck Dary committed
  if (defaultCycle.empty())
    return endMovement;
Franck Dary's avatar
Franck Dary committed
  return {defaultCycle.back(), movement};
const std::string Strategy::getInitialState() const
{
  return initialState;
}

void Strategy::reset()
{
  for (auto & it : isDone)
    it.second = false;
  defaultCycle = originalDefaultCycle;
}