알고리즘/swea

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

흰색텀블러 2025. 1. 21. 20:29

<링크>

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

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com

 

<문제>

  • 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개 암호문을 출력한다.

 

<코드1. - java, linkedList 직접 구현>

import java.util.*;
import java.io.*;

public class Solution {
	// 링크드 리스트 직접 구현

	static int NODE_MAX = 5000;
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

	// Node
	static class Node {
		int data;
		Node next;

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

	static class LinkedList {
		Node head;
		Node tail;
		// new를 최소한으로 쓰기 위한 녀석
		// new 이친구 괴애애애애애장이 느림.
		Node[] nodeArr;
		int nodeCnt;

		public LinkedList() {
			head = null;
			nodeArr = new Node[NODE_MAX];
			nodeCnt = 0;
		}

		// 정적 할당 방식
		// 일단 왕창 메모리에 노드를 만들어 놓고,
		// 새로운 노드를 요청시, 여분의 노드중 안쓴거를 가져오는 것
		// -> 시간이 엄청나게 줄어듬
		Node getNewNode(int data) {
			// data를 값으로 갖는 새로운 node 생성하고, 생성된 node를 return
			nodeArr[nodeCnt] = new Node(data);
			return nodeArr[nodeCnt++];
		}

		// 앞에서 idx개 이후에 nums 들을 추가하기
		void insert(int idx, int[] nums) {
			int st = 0;
			if (idx == 0) {// 맨 앞에 붙이는 경우 (head가 변경되어야하는 경우등)
				// 먼저 한개만 추가하고 head 재조정
				if (head != null) {
					Node newNode = getNewNode(nums[0]);
					newNode.next = head;
					head = newNode;
				} else {
					head = getNewNode(nums[0]);
				}
				// 남은 수들은 head 뒤에 차례로 이어 붙어야 함
				idx = 1;
				st = 1;
			}

			Node cur = head;
			// idx 개 만큼 이동하기
			for (int i = 1; i < idx; i++) {
				cur = cur.next;
			}

			// nums 추가하기
			for (int i = st; i < nums.length; i++) {
				Node newNode = getNewNode(nums[i]);
				// 만약 아래의 코드의 순서를 바꾸면...
				// newNode.next 가 본인 스스로가 되버림. 즉, cur.next가 갈곳이 없어집니다..ㅠ
				newNode.next = cur.next;
				cur.next = newNode;
				cur = newNode;
			}
			if (cur.next == null) {
				tail = cur;
			}
		}

		void delete(int idx, int cnt) { // idx 번 인덱스부터 cnt개 만큼 삭제하기
			Node cur = head;
			// 맨 앞이 삭제되는 경우 (head 가 재조정 되는 경우)
			if (idx == 0) {
				for (int i = 0; i < cnt; i++) {
					cur = cur.next;
				}
				head = cur;
				return;
			}
			// idx개 만큼 이동하기
			for (int i = 0; i < idx; i++) {
				cur = cur.next;
			}

			Node anchor = cur; // 삭제되기 직전 위치 기억하기
			for (int i = 0; i < cnt; i++) {
				cur = cur.next;
			}
			anchor.next = cur.next;

			if (anchor.next == null) {
				tail = anchor;
			}
		}

		void add(int data) { // 제일 뒤에 data 추가하기
			Node cur = tail;
			Node newNode = getNewNode(data);
			cur.next = newNode;
			tail = newNode;
		}

		void print() throws Exception { // 출력하기
			int cnt = 10;
			Node cur = head;
			while (--cnt >= 0) {
				bw.write(cur.data + " ");
				cur = cur.next;
			}
		}

	}

	public static void main(String[] args) throws Exception {
		int T = 10;
		StringTokenizer stk;

		for (int t = 1; t <= T; t++) {
			LinkedList list = new LinkedList();
			bw.write("#");
			bw.write(t + " ");
			int n = Integer.parseInt(in.readLine());
			int[] initArr = new int[n];
			stk = new StringTokenizer(in.readLine());
			for (int i = 0; i < n; i++) {
				initArr[i] = Integer.parseInt(stk.nextToken());
			}
			list.insert(0, initArr);

			int M = Integer.parseInt(in.readLine());
			stk = new StringTokenizer(in.readLine());
			for (int i = 0; i < M; i++) {
				char cmd = stk.nextToken().charAt(0);
				int x, y;
				switch (cmd) {
				case 'I':
					x = Integer.parseInt(stk.nextToken());
					y = Integer.parseInt(stk.nextToken());
					int[] temp = new int[y];
					for (int j = 0; j < y; j++) {
						temp[j] = Integer.parseInt(stk.nextToken());
					}
					list.insert(x, temp);
					break;
				case 'D':
					x = Integer.parseInt(stk.nextToken());
					y = Integer.parseInt(stk.nextToken());
					list.delete(x, y);
					break;
				case 'A':
					y = Integer.parseInt(stk.nextToken());
					for (int j = 0; j < y; j++) {
						list.add(Integer.parseInt(stk.nextToken()));
					}
					break;
				}
			}
			list.print();
			bw.write("\n");
		}
		bw.flush();
		in.close();
		bw.close();
	}
}

 

 

<코드2. java - ArrayList 사용>

import java.util.*;
import java.io.*;

public class Solution2 {

	static StringBuilder sb = new StringBuilder();
	static StringTokenizer st;
	static ArrayList<Integer> list;

	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		int test_case = 10;

		for (int t = 1; t <= test_case; t++) {
			// 원본 암호문 뭉치속 암호문 개수 n (3198)
			int n = Integer.parseInt(in.readLine());

			// 암호문 담을 연결 리스트(801, 482, ....)
			list = new ArrayList<>();
			st = new StringTokenizer(in.readLine());

			for (int i = 0; i < n; i++) {
				list.add(Integer.parseInt(st.nextToken()));
			}
			// 명령어 개수 (425)
			int m = Integer.parseInt(in.readLine());
			
			st = new StringTokenizer(in.readLine());

			for (int i = 0; i < m; i++) {
				char cmd = st.nextToken().charAt(0);
				int x = Integer.parseInt(st.nextToken());
				fun(cmd, x);
			}
			
			sb.append("#" + t);
			// 암호문중 10개만 출력
			for (int i = 0; i < 10; i++) {
				sb.append(" " + list.get(i));
			}
			sb.append("\n");
		}
		System.out.println(sb);

	}

	private static void fun(char cmd, int x) {
		int y;
		switch (cmd) {
		case 'I':
			y = Integer.parseInt(st.nextToken());
			for (int i = 0, insertIdx = x; i < y; i++, insertIdx++) {
				list.add(insertIdx, Integer.parseInt(st.nextToken()));
			}
			break;
		case 'D':
			y = Integer.parseInt(st.nextToken());
			for (int i = 0; i < y; i++) {
				list.remove(x);
			}
			break;
		case 'A':
			for (int i = 0; i < x; i++) {
				list.add(Integer.parseInt(st.nextToken()));
			}
			break;
		}
	}
}

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

(SWEA) 10726. 이진수 표현  (0) 2025.01.20