연습문제풀이-2
Practice1
문제 설명
로마 숫자 표기를 정수형으로 변환하는 프로그램을 작성하세요.
로마 숫자 표기법은 I, V, X, L, C, D, M 으로 이루어져있다.
로마 숫자 | 정수형 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
로마 숫자 표기 방식
- 큰 기호에서 작은 기호 방향으로 작성 (XI, VI, II, …)
- 다음의 경우 작은 기호가 큰 기호 앞에 올 수 있다.
- I 는 V 와 X 의 앞에 올 수 있다. (IV: 4, IX: 9)
- X 는 L 과 C 의 앞에 올 수 있다. (XL: 40, XC: 90)
- C 는 D 와 M 의 앞에 올 수 있다. (CD: 400, CM: 900)
입력 | 출력 |
---|---|
“III” | 3 |
“IV” | 4 |
“VI” | 6 |
“XIII” | 13 |
“XXVI” | 26 |
“MCMXCIV” | 1994 |
import java.util.HashMap;
public class Practice1 {
public static void solution(String s) {
// 해시 맵으로 로마 숫자 표기 우선 초기화
HashMap<Character, Integer> map = new HashMap<>();
map.put('I', 1);
map.put('V', 5);
map.put('X', 10);
map.put('L', 50);
map.put('C', 100);
map.put('D', 500);
map.put('M', 1000);
int sum = 0;
char[] arr = s.toCharArray();
for (int i = 0; i < arr.length - 1; i++) {
// 작은 표기가 앞에 온 경우 뺌
if (map.get(arr[i]) < map.get(arr[i + 1])) {
sum -= map.get(arr[i]);
} else { // 일반 표기 순서의 경우 더함
sum += map.get(arr[i]);
}
}
sum += map.get(arr[arr.length - 1]);
System.out.println(sum);
}
public static void main(String[] args) {
// Test code
solution("III");
solution("IV");
solution("VI");
solution("XIII");
solution("XXVI");
solution("MCMXCIV");
}
}
3
4
6
13
26
1994
Practice2
문제 설명
정수형 숫자를 로마 숫자 표기로 변환하는 프로그램을 작성하세요.
로마 숫자 표기법은 I, V, X, L, C, D, M 으로 이루어져있다.
로마 숫자 | 정수형 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
로마 숫자 표기 방식
- 큰 기호에서 작은 기호 방향으로 작성 (XI, VI, II, …)
- 다음의 경우 작은 기호가 큰 기호 앞에 올 수 있다.
- I 는 V 와 X 의 앞에 올 수 있다. (IV: 4, IX: 9)
- X 는 L 과 C 의 앞에 올 수 있다. (XL: 40, XC: 90)
- C 는 D 와 M 의 앞에 올 수 있다. (CD: 400, CM: 900)
입출력 예시
입력 | 출력 |
---|---|
3 | “III” |
4 | “IV” |
6 | “VI” |
13 | “XIII” |
26 | “XXVI” |
1994 | “MCMXCIV” |
public class Practice2 {
public static String solution(int num){
String result = "";
// 로마 숫자 표기 방법 규칙 적용 역순 나열
String[] roman = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 };
int i = 0;
// 입력 num 이 0보다 큰 동안
while (num > 0) {
// 로마 숫자 표기 법 중 큰 수부터 현재 num 에서 뺄 수 있는지 체크
while (num >= values[i]) {
num -= values[i];
result += roman[i];
}
i++;
}
return result;
}
public static void main(String[] args) {
// Test code
System.out.println(solution(3));
System.out.println(solution(4));
System.out.println(solution(6));
System.out.println(solution(13));
System.out.println(solution(26));
System.out.println(solution(1994));
}
}
III
IV
VI
XIII
XXVI
MCMXCIV
Practice3
문제 설명
간단한 편집기를 구현하려고 한다.
편집기에는 문자열과 편집 명령어가 주어지는데, 명령어의 동작은 다음과 같다.
- L : 커서를 왼쪽으로 한 칸 옮김 (커서가 문장의 맨 앞이면 무시)
- D : 커서를 오른쪽으로 한 칸 옮김 (커서가 문장의 맨 뒤이면 무시)
- B : 커서 왼쪽에 있는 문자를 삭제 (커서가 문장의 맨 앞이면 무시)
- P x : x라는 문자를 커서 왼쪽에 추가
여기서 커서는 문자열에서 편집이 시작되는 기준 위치로,
문장의 맨 앞, 맨 뒤, 중간에 위치할 수 있다.
편집기에 문자열과 명령어들이 주어졌을 때,
편집을 완료한 후의 문자열을 출력하는 프로그램을 작성하시오.
(초기 커서의 위치는 문장의 맨 뒤에서 시작한다.)
(문자열은 소문자만 입력 가능하다.)
초기 문자열 | 명령어 | 결과 출력 |
---|---|---|
“aba” | “L B” | “aa” |
“abcd” | “P x L P y” | “abcdyx” |
“abc” | “L L L P x L B P y” | “yxabc” |
“a” | “B B L L D D P a P b P c” | “abc” |
import java.util.ArrayList;
public class Practice3 {
public static String solution(String input, String cmd) {
// 문자열의 편집이 빈번할 때 유리한 StringBuffer 로 변환하여 사용
StringBuffer sb = new StringBuffer(input);
ArrayList<String> cmdArr = new ArrayList<>();
// 명령어들 분할하여 배열에 추가
for (String s: cmd.split(" ")) {
cmdArr.add(s);
}
// 초기 커서 위치
int curSor = sb.length();
// 명령어 배열의 인덱스로 사용할 변수
int cmdIdx = 0;
while (cmdIdx != cmdArr.size()) {
String cur = cmdArr.get(cmdIdx);
if (cur.equals("L")) {
// 0일 때는 -1로 가지 않도록
curSor = Math.max(0, curSor - 1);
} else if (cur.equals("D")) {
// 가장 맨 끝일 때는 그 이상 넘어가지 않도록
curSor = Math.min(sb.length(), curSor + 1);
} else if (cur.equals("B")) {
// 커서가 맨 앞일 때는 지울게 없으므로 continue
if (curSor == 0) {
cmdIdx++;
continue;
}
// 해당 위치의 문자 삭제 후 커서 재조정
sb.delete(curSor - 1, curSor);
curSor = Math.max(0, curSor - 1);
} else if (cur.equals("P")) {
String s = cmdArr.get(++cmdIdx);
sb.insert(curSor, s);
curSor += 1;
}
cmdIdx++;
}
return sb.toString();
}
public static void main(String[] args) {
// test code
System.out.println(solution("aba", "L B"));
System.out.println(solution("abcd", "P x L P y"));
System.out.println(solution("abc", "L L L P x L B P y"));
System.out.println(solution("a", "B B L L D D P a P b P c"));
}
}
aa
abcdyx
yxabc
abc
Practice4
문제 설명
특수 작전을 위해 상대방의 PC에 키보드 입력 내용을 얻을 수 있는 키로깅 프로그램을 설치했다.
해당 키로깅 프로그램으로부터는 아래와 같이 특정 값으로 내용이 수신된다.
- 8 : Backspace
- 16 : Shift
- 20 : Caps Lock
- 32 : Space bar
- 37 : 키보드 왼쪽 화살표
- 39 : 키보드 오른쪽 화살표
- 155: Insert
- 127: Delete
- 97~122: 알파벳 소문자 (기본 입력은 소문자 기준, Shift 나 Caps Lock 에 의해 변경)
- 48~57: 숫자 0~9
(이 외의 값은 들어오지 않는다고 가정)
키로깅 프로그램으로부터 수신된 데이터를 원래 내용으로 복구하는 프로그램을 작성하세요.
수신 내용 | 결과 |
---|---|
16, 106, 101, 108, 108, 111, 37, 37, 37, 37, 37, 155, 16, 104 | “Hello” |
20, 104, 16, 105, 32, 20, 16, 106, 97, 118, 97 | “Hi Java” |
49 51 8 50 51 53 55 37 37 127 127 52 53 | “12345” |
20 65 66 16 67 16 68 49 50 51 | “ABcd!@#” |
public class Practice4 {
public static String solution(int[] keyLog) {
final int BACK_SPACE = 8;
final int SHIFT = 16;
final int CAPS_LOCK = 20;
final int SPACE_BAR = 32;
final int KEY_LEFT = 37;
final int KEY_RIGHT = 39;
final int INSERT = 155;
final int DELETE = 127;
StringBuffer sb = new StringBuffer();
int step = (int)('a' - 'A');
int curSor = 0;
int cmdIdx = 0;
boolean isShift = false;
boolean isCapsLock = false;
boolean isInsert = false;
while (cmdIdx != keyLog.length) {
int cur = keyLog[cmdIdx];
// backspace 는 이전과 동일
if (cur == BACK_SPACE) {
if (curSor == 0) {
cmdIdx++;
continue;
}
sb.delete(curSor - 1, curSor);
curSor = Math.max(0, curSor - 1);
} else if (cur == SHIFT) { // shift 입력은 해당 변수 true 로 변경
isShift = true;
} else if (cur == CAPS_LOCK) { // CapsLock 은 한 번 누르면 지속 (토글)
isCapsLock = !isCapsLock;
} else if (cur == SPACE_BAR) {
inputData(sb, ' ', curSor, isInsert); // 공백 문자 입력 후 커서 증가
curSor += 1;
} else if (cur == KEY_LEFT) {
curSor = Math.max(0, curSor - 1);
} else if (cur == KEY_RIGHT) {
curSor = Math.min(sb.length(), curSor + 1);
} else if (cur == INSERT) { // Insert 는 한 번 누르면 지속 (토글)
isInsert = !isInsert;
} else if (cur == DELETE) { // Delete 는 backspace 와 커서 부분 살짝 다름
if (curSor == sb.length()) {
cmdIdx++;
continue;
}
sb.delete(curSor, curSor + 1);
} else if (cur >= 97 && cur <= 122) { // 알파벳 입력 부분
int data = cur;
// CapLock 켜진 상태에서 Shift 누르면 다시 소문자
if (isCapsLock && isShift) {
data = cur;
} else if (isCapsLock || isShift) { // 둘 중 하나가 true 면 대문자로 변경
data -= step;
}
inputData(sb, (char)data, curSor, isInsert);
isShift = false;
curSor += 1;
} else if (cur >= 48 && cur <= 57) {
if (isShift) {
// 각 숫자에 대응하는 특수문자 배열 (인덱스 0 부터 시작 -> ')')
char[] specialKey = {')', '!', '@', '#', '$', '%', '^', '&', '*', '('};
inputData(sb, specialKey[cur - '0'], curSor, isInsert);
} else {
inputData(sb, (char)cur, curSor, isInsert);
}
isShift = false;
curSor += 1;
}
cmdIdx++;
}
return sb.toString();
}
public static void inputData(StringBuffer sb, char data, int curSor, boolean isInsert) {
// Insert 가 false 면 해당 위치에 삽입 true 면 해당 위치 변경
if (isInsert == false) {
sb.insert(curSor, data);
} else {
sb.setCharAt(curSor, data);
}
}
public static void main(String[] args) {
// Test code
int[] keyLog = {16, 106, 101, 108, 108, 111, 37, 37, 37, 37, 37, 155, 16, 104};
System.out.println(solution(keyLog));
keyLog = new int[]{20, 104, 16, 105, 32, 20, 16, 106, 97, 118, 97};
System.out.println(solution(keyLog));
keyLog = new int[]{49, 51, 8, 50, 51, 53, 55, 37, 37, 127, 127, 52, 53};
System.out.println(solution(keyLog));
keyLog = new int[]{20, 97, 98, 16, 99, 16, 100, 16, 49, 16, 50, 16, 51};
System.out.println(solution(keyLog));
}
}
Hello
Hi Java
12345
ABcd!@#
Practice5
문제 설명
N 명의 아이들이 한 줄로 서있다.
각각의 아이들은 점수 표를 가지고 있는데 점수 표에 따라 다음과 같은 규칙으로 사탕을 나누어 줘야 한다.
- 적어도 1개 이상의 사탕을 나누어줘야 한다.
- 점수가 높은 아이에게는 바로 옆의 아이 보다는 사탕을 많이 줘야 한다.
N 명의 아이들에 대한 점수 표가 ratings 배열에 주어질 때,
나누어 줘야하는 최소한의 사탕 개수를 출력하세요.
입력 | 출력 |
---|---|
1 2 3 | 6 |
3 2 1 | 6 |
1 0 2 | 5 |
1 2 2 | 4 |
1, 3, 5, 3, 1, 3, 5, 7, 5, 3, 1, 0 | 29 |
public class Practice5 {
public static int solution(int[] ratings) {
if (ratings == null || ratings.length == 0) {
return 0;
}
int result = 1;
int upCnt = 1;
int downCnt = 0;
int peak = 0;
for (int i = 1; i < ratings.length; i++) {
// 다음 순번의 rating 이 더 높은 경우, upCnt 증가, peak 갱신, downCnt 쪽은 0으로 초기화
if (ratings[i] > ratings[i - 1]) {
upCnt++;
peak = upCnt;
downCnt = 0;
result += upCnt;
} else if (ratings[i] == ratings[i - 1]) {
// 다음 순번과 rating 이 같은 경우는 1 개 주면 됨
// upCnt 는 1로, downCnt 와 peak 는 0으로 초기화
upCnt = 1;
downCnt = 0;
peak = 0;
result += 1;
} else {
// 다음 순번의 rating 이 낮은 경우, downCnt 증가, upCnt 쪽은 1로 초기화
downCnt++;
upCnt = 1;
result += downCnt;
// rating 이 낮은 쪽으로 진행되다가 앞의 peak 를 넘어선 경우 1 씩 더해줌
if (peak <= downCnt) {
result += 1;
}
}
}
return result;
}
public static void main(String[] args) {
// Test code
int[] ratings = {1, 2, 3};
System.out.println(solution(ratings));
ratings = new int[]{3, 2, 1};
System.out.println(solution(ratings));
ratings = new int[]{1, 0, 2};
System.out.println(solution(ratings));
ratings = new int[]{1, 2, 2};
System.out.println(solution(ratings));
ratings = new int[]{1, 3, 5, 3, 1, 3, 5, 7, 5, 3, 1, 0};
System.out.println(solution(ratings));
}
}
6
6
5
4
29
Leave a comment