새소식

알고리즘 문제풀이/BOJ

[백준 온라인 저지(BOJ)] 3954번 Brainfuck 자바(java) 풀이

  • -

백준 온라인 저지(BOJ) 3954번 Brainfuck 문제

안녕하세요 호호만두에요

이번에는 백준 온라인 저지(BOJ)의 3954번 문제인 Brainfuck을 풀어봤어요

이름이 너무 웃기지 않나요?? 들어가보면 사실 Brainf**k로 표현되어있어요

찾아보니까 이런 단어가 존재하더라구요??? 그게 더 신기...

알고보니까 93년도에 우어반 뮐러라는 사람이 만든 프로그래밍 언어라고 ㅋㅋㅋㅋㅋㅋ

이름 한 번 잘지었네 위키에서 명령어들 같은거 보면 그대로 규칙이 그대로 나왔어요

궁금하신 분은 쭉 훑어보세요
brainfuck 이란??

이 문제는 골드1로 분류되어 있는 난이도가 조금 있는 문제였어요

BOJ 3954번 Brainfuck

이 문제의 유형을 분류하자면 주어진 사항을 잘 읽고 구현하는 시뮬레이션

그리고 규칙 찾기 문제로 분류 할 수 있을 것 같아요

그러면 풀어 봅시다!!


문제의 핵심

이 문제는 문제를 이해하는게 제일 중요하다고 생각합니다.
메모리 배열의 위치를 참조하는 pointer 개념과
읽은 input의 위치를 참조하는 index를 활용하고
짝이 되는 bracket의 위치를 잘 찾는다면 풀 수 있습니다.

문제 풀이

이 문제는 주어진 사항을 그대로 구현하는 문제에요

  1. 먼저 '['와 ']' 쌍을 for문을 돌면서 모두 찾습니다. 찾아서 쌍의 index를 배열에 저장합니다.
  2. 그 다음 program 명령에 맞게 switch문을 이용해 판단하여 수행합니다
  • 2-1. '-'와 '+'는 포인터가 가리키고 있는 메모리의 값을 1 감소, 증가 시켜줍니다(% 256)
    • 2-2. '<' '>'는 포인터의 위치를 감소, 증가 시킵니다. 인덱스를 넘어가는 경우 예외처리를 해줍니다
      • 2-3. '['와 ']'는 메모리 배열의 숫자를 참조하여 jump를 하거나 순차적으로 program 명령을 진행합니다.
        • 2.4 '.'은 그냥 넘어가고 ','는 input string의 한 문자를 읽어서 아스키 코드 값 메모리 배열에 저장합니다. (input을 다 읽은 경우 255 저장)
  1. loop문이 몇번 도는지 검사하며 50000000이 넘으면 무한루프에 빠졌다고 인식하여 Loops 출력
  2. 그렇지 않고 모든 program code를 다 읽은 경우에는 Terminates를 출력합니다

백준 3954번 자바 풀이 코드

  • github주소 아래 링크
    백준3954번 Brainfuck
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.io.OutputStreamWriter;
    import java.util.Stack;
    

class Pair{
int left;
int right;

Pair(int left, int right){
    this.left = left;
    this.right = right;
}

}

class Main {
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
static int mem_size;
static int code_len;
static int input_size;

static int inputIdx;
static int memIdx;
static int[] mem;

static String text;
static String program;

static int loopCount;

static Stack<Integer> stack;
static Pair [] pairs;

public static void main(String[] args) throws IOException{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    init();

    int testNum = Integer.parseInt(br.readLine());

    // test 개수
    for(int i=0; i<testNum; i++){
        String[] temp = br.readLine().split(" ");
        mem_size = Integer.parseInt(temp[0]);
        code_len = Integer.parseInt(temp[1]);
        input_size = Integer.parseInt(temp[2]);

        program = br.readLine();
        text = br.readLine();

        // '[', ']' 검사
        readBracket();

        solve();

        bw.newLine();

        init();
    }
    bw.flush();

    br.close();
    bw.close();
}

public static void readBracket(){
    for(int i=0; i<code_len; i++){
        if(program.charAt(i) == '['){
            stack.push(i);
            pairs[i] = new Pair(i, 0);
        }
        else if(program.charAt(i) == ']'){
            int temp = stack.pop();
            pairs[i] = new Pair(temp, i);
            pairs[temp].right = i;
        }
    }
}

public static void solve() throws IOException{
    // Read program
    int idx = 0;
    int max_index = 0;

    while(true){
        char command = program.charAt(idx);

        switch(command){
            case '-':
                mem[memIdx] = ( mem[memIdx] - 1 ) % 256;
                break;
            case '+':
                mem[memIdx] = ( mem[memIdx] + 1 ) % 256;
                break;
            case '<':
                if(memIdx == 0)
                    memIdx = mem_size - 1;
                else
                    memIdx--;
                break;
            case '>':
                if(mem_size-1 == memIdx)
                    memIdx = 0;
                else
                    memIdx++;
                break;
            case '[':
                if(mem[memIdx] == 0){
                    idx = pairs[idx--].right;
                    loopCount++;
                }
                break;
            case ']':
                if(mem[memIdx] != 0){
                    idx = pairs[idx--].left;
                    loopCount++;
                }
                break;
            case '.':
                break;
            case ',':
                if(inputIdx == input_size)
                    mem[memIdx] = 255;
                else
                    mem[memIdx] = (int)text.charAt(inputIdx++);
        }

        idx++;
        loopCount++;
        // loop문 도는 경우 갇힌 loop문 판단을 위한 index
        if(idx > max_index)
            max_index = idx;

        // 모든 명령 다 읽음
        if(idx == code_len){
            bw.write("Terminates");
            break;
        }
        if(loopCount > 50000000){
            bw.write("Loops" + " " + pairs[max_index].left + " " + pairs[max_index].right);
            break;
        }
    }
}

public static void init(){
    inputIdx = 0;
    memIdx = 0;
    loopCount = 0;

    stack = new Stack<>();
    pairs = new Pair[4096];

    mem = new int[100001];
    Arrays.fill(mem, 0);
}

}

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.