본문 바로가기
알고리즘/Codewars

Codewars - [5 kyu] Simple assembler interpreter

by 개발자J의일상 2022. 4. 29.
반응형

Assembler로 들어온 문자열을 해석하여 실행하여 unordered_map<string, int>로 구성된 저장된 값들을 반환하는 문제이다!

 

MAIN

#include <string>
#include <unordered_map>

Describe(SolutionTest)
{
  It(Simple1)
  {
    std::vector<std::string> program{ "mov a 5", "inc a", "dec a", "dec a",
      "jnz a -1", "inc a" };
    std::unordered_map<std::string, int> out{ { "a", 1 } };
    Assert::That(assembler(program), Equals(out));
  }
};

ANSWER

#include <string>
#include <unordered_map>
#include <cctype>

std::vector<std::string> split(const std::string line)
{
  std::vector<std::string> splitedLine;
  std::string temp;
  for(int i=0; i< (int)line.size(); i++)
  {
    if(line[i] == ' ')
    {
      splitedLine.push_back(temp);
      temp.clear();
    } else {
      temp += line[i];  
    }
  }
  splitedLine.push_back(temp);
  return splitedLine;
}
bool isDigit(std::string c)
{
  if(c[0] == '-') return true;
  int digit = c[0] - '0';
  if(digit == 0 || digit == 1 || digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || digit ==7 || digit == 8 || digit == 9)
  {
    return true;
  }
  return false;
}
std::unordered_map<std::string, int> assembler(const std::vector<std::string>& program)
{
  std::unordered_map<std::string, int> maps;
  for (int i=0; i<(int)program.size(); i++)
  {
      std::cout << program[i] << std::endl;
  }
  for(int i=0; i<(int)program.size(); i++)
  {
    std::string line = program[i];
    std::vector<std::string> splitedLine = split(line);
    if (splitedLine[0] == "mov") {
      if(isDigit(splitedLine[2]))
      {
        maps[splitedLine[1]] = std::stoi(splitedLine[2]);
      }
      else {
        maps[splitedLine[1]] = maps[splitedLine[2]];
      }
    } 
    else if (splitedLine[0] == "inc")
    {
        maps[splitedLine[1]]++;  
    }
    else if (splitedLine[0] == "dec")
    {
        maps[splitedLine[1]]--;  
    }
    else if (splitedLine[0] == "jnz")
    {
      //jump to splitedLine[2]
      if (isDigit(splitedLine[1]))
      {
        if(std::stoi(splitedLine[1]) != 0)
        {
          //check y is digit
          if (isDigit(splitedLine[2]))
            i = i + std::stoi(splitedLine[2]) - 1;
          else 
            i = i + maps[splitedLine[2]] - 1;
        }
      } 
      else
      {
        if (maps[splitedLine[1]] != 0) {
          //check y is digit
          if (isDigit(splitedLine[2]))
            i = i + std::stoi(splitedLine[2]) - 1;
          else 
            i = i + maps[splitedLine[2]] - 1;
        }
      }
    }
  }
  return maps;
}

 

코드가 지저분한데 string을 line 단위로 잘 뽑아서 공백이 나오는 부분을 가지고 splitedLine을 구하고

그 첫번 째 값이 명령어가 될 것이기 때문에 그 명령어에 해당하는 연산을 수행하면된다.

 

여기서 까다로웠던 부분은 jnz 부분인데 우리는 line의 size를 알고 있기 때문에 그 size만큼 for문을 돌면서 i를 수정하여 그 line으로 가서 그 명령어를 다시 수행하는 방식으로 구현을 하면 된다. 

 

이게 숫자가 올수도 있고 변수가 올 수도 있어서 이 것을 다루는 부분이 좀 까다롭다. 

 

코드를 정리를 따로 안하고 올려서 지저분한데 막히는 분들에게 도움이 되었으면 한다.

 

질문이 있으면 댓글을 달아주시면 답변 드립니다!

300x250

'알고리즘 > Codewars' 카테고리의 다른 글

Codewars - [7 kyu] Reverse words  (0) 2022.05.03
Codewars - [6 kyu] Sum consecutives  (0) 2022.01.17

댓글