[알고리즘문제]

[SWEA] 1230. [S/W 문제해결 기본] 8일차 - 암호문3

whatezlife 2025. 2. 18. 17:05

 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV14zIwqAHwCFAYD

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV14zIwqAHwCFAYD

 

0 ~ 999999 사이의 수로 표현되는 암호문이 있고, 이 암호문을 N개 모아 놓은 암호문 뭉치가 있다.
암호문 뭉치를 급히 수정해야 할 일이 발생했는데, 암호문은 특수 제작된 처리기로만 수정이 가능하다.
처리기는 다음과 같이 3개의 명령어로 제어한다.
 
1. I(삽입) x, y, s : 앞에서부터 x번째 암호문 바로 다음에 y개의 암호문을 삽입한다. s는 덧붙일 암호문들이다.[ ex) I 3 2 123152 487651 ]
2. D(삭제) x, y : 앞에서부터 x번째 암호문 바로 다음부터 y개의 암호문을 삭제한다.[ ex) D 4 4 ]
3. A(추가) y, s : 암호문 뭉치 맨 뒤에 y개의 암호문을 덧붙인다. s는 덧붙일 암호문들이다. [ ex) A 2 421257 796813 ]

위의 규칙에 맞게 작성된 명령어를 나열하여 만든 문자열이 주어졌을 때, 암호문 뭉치를 수정하고, 수정된 결과의 처음 10개 암호문을 출력하는 프로그램을 작성하여라.


[입력]
첫 번째 줄 : 원본 암호문 뭉치 속 암호문의 개수 N ( 2000 ≤ N ≤ 4000 의 정수)
두 번째 줄 : 원본 암호문 뭉치
세 번째 줄 : 명령어의 개수 ( 250 ≤ M ≤ 500 의 정수)
네 번째 줄 : 명령어
위와 같은 네 줄이 한 개의 테스트 케이스이며, 총 10개의 테스트 케이스가 주어진다.

[출력]
#기호와 함께 테스트 케이스의 번호를 출력하고, 공백 문자 후 수정된 암호문 뭉치의 앞 10개 암호문을 출력한다.

[제약 사항]
실행 시간 60ms 이하

 

 

알고리즘 : 그냥 구현하는 문제
자료구조 : LinkedList

 

 

package SW문제해결기본8일차_암호문3;

import java.io.FileInputStream;
import java.util.Scanner;

// Node
class Node {
    int data;
    Node link;

    public Node(int data) {
        this.data = data;
        this.link = null;
    }
}

// LinkedList 클래스
class CustomLinkedList {
    Node head;
    int size;

    public CustomLinkedList() {
        this.head = null;
        this.size = 0;
    }

    // 맨 끝에 추가 (addLast)
    public void addLast(int data) {
        Node node = new Node(data);
        if (head == null) {
            head = node;
        } else {
            Node curr = head;
            while (curr.link != null) {
                curr = curr.link;
            }
            curr.link = node;
        }
        size++;
    }

    // 특정 위치에 삽입 (insert)
    public void insert(int index, int data) {
        if (index < 0 || index > size) return; // 범위 초과 방지
        Node node = new Node(data);
        if (index == 0) {
            node.link = head;
            head = node;
        } else {
            Node prev = get(index - 1);
            node.link = prev.link;
            prev.link = node;
        }
        size++;
    }

    // 특정 위치의 노드 가져오기
    public Node get(int index) {
        if (index < 0 || index >= size) return null;
        Node curr = head;
        for (int i = 0; i < index; i++) {
            curr = curr.link;
        }
        return curr;
    }

    // 특정 위치에서 삭제 (delete)
    public void delete(int index) {
        if (index < 0 || index >= size) return;
        if (index == 0) {
            head = head.link;
        } else {
            Node prev = get(index - 1);
            prev.link = prev.link.link;
        }
        size--;
    }

    // 처음 10개 출력
    public void printFirstTen() {
        Node curr = head;
        int count = 0;
        while (curr != null && count < 10) {
            System.out.print(curr.data + " ");
            curr = curr.link;
            count++;
        }
        System.out.println();
    }
}

class Solution {
    public static void main(String args[]) throws Exception {
        System.setIn(new FileInputStream("res/문제1230암호문3.txt"));
        Scanner sc = new Scanner(System.in);
        int T = 10;  // 테스트 케이스 개수

        for (int test_case = 1; test_case <= T; test_case++) {
            int N = sc.nextInt();  // 2000<=N<=4000
            sc.nextLine();  // 개행 처리
            String s = sc.nextLine();  // 원본 암호문
            String[] sArray = s.split(" ");

            // 원본 암호문을 CustomLinkedList로 변환
            CustomLinkedList secrets = new CustomLinkedList();
            for (String str : sArray) {
                secrets.addLast(Integer.parseInt(str));
            }

            int M = sc.nextInt();  // 250<=M<=500
            sc.nextLine();
            String order = sc.nextLine();  // 명령어 한 줄 읽기
            String[] parts = order.split(" ");

            int i = 0; // parts 배열의 인덱스
            while (i < parts.length) {
                // 명령어 처리
                switch (parts[i]) {
                    case "I":  // Insert
                        int index = Integer.parseInt(parts[i + 1]);
                        int count = Integer.parseInt(parts[i + 2]);
                        for (int j = 0; j < count; j++) {
                            secrets.insert(index + j, Integer.parseInt(parts[i + 3 + j]));  // index 위치에 삽입
                        }
                        i = i + 3 + count;  // 명령어 처리 후 i 업데이트 (i + index + count + ~~~) 이렇게 해서 3개
                        break;
                    case "D":  // Delete
                        int delIndex = Integer.parseInt(parts[i + 1]);
                        int delCount = Integer.parseInt(parts[i + 2]);
                        for (int j = 0; j < delCount; j++) {
                            secrets.delete(delIndex);  // delIndex 위치에서 삭제
                        }
                        i = i + 3;  // 명령어 처리 후 i 업데이트
                        break;
                    case "A":  // Append
                        int appendCount = Integer.parseInt(parts[i + 1]);
                        for (int j = 0; j < appendCount; j++) {
                            secrets.addLast(Integer.parseInt(parts[i + 2 + j]));  // 끝에 추가
                        }
                        i = i + 2 + appendCount;  // 명령어 처리 후 i 업데이트
                        break;
                }
            }

            // 결과 출력 (첫 10개 값만 출력)
            System.out.print("#" + test_case + " ");
            secrets.printFirstTen();
        }
        sc.close();
    }
}