코딩테스트 연습 / PCCP 기출문제 / [PCCP 기출문제] 1번
📺 동영상 재생기
🏷️ 관련 주제 : Stream
reduce
String
format
💡 Solution With Stream.reduce() & 조건문
import java.util.Arrays;
class Solution {
public String solution(String video_len, String pos, String op_start, String op_end, String[] commands) {
String answer = "";
int video_time = Arrays.stream(video_len.split(":"))
.mapToInt(Integer::parseInt)
.reduce((x, y) -> x * 60 + y)
.orElse(0);
int pos_time = Arrays.stream(pos.split(":"))
.mapToInt(Integer::parseInt)
.reduce((x, y) -> x * 60 + y)
.orElse(0);
int op_start_time = Arrays.stream(op_start.split(":"))
.mapToInt(Integer::parseInt)
.reduce((x, y) -> x * 60 + y)
.orElse(0);
int op_end_time = Arrays.stream(op_end.split(":"))
.mapToInt(Integer::parseInt)
.reduce((x, y) -> x * 60 + y)
.orElse(0);
for (String command : commands) {
if (pos_time >= op_start_time && pos_time < op_end_time) {
pos_time = op_end_time;
}
if (command.equals("next")) {
if (pos_time == video_time) {
continue;
}
if (pos_time + 10 > video_time) {
pos_time = video_time;
continue;
}
pos_time += 10;
} else if (command.equals("prev")) {
if (pos_time == 0) {
continue;
}
if (pos_time - 10 < 0) {
pos_time = 0;
continue;
}
pos_time -= 10;
}
}
if (pos_time >= op_start_time && pos_time < op_end_time) {
pos_time = op_end_time;
}
answer = String.format("%02d:%02d", pos_time / 60, pos_time % 60);
return answer;
}
}
실행 결과
문자열로 주어진 시간을 숫자로 변경하기 위해 Stream.reduce()
를 사용하였습니다.
초깃값을 0
으로 주고
"mm
:ss
" 형식으로 주어진 시간을 :
로 분리한 후, 정수형으로 변환,
reduce()를 사용하여 초 단위 시간으로 각 시간을 초기화 해 주었습니다.
for-each문으으로 commands
의 명령어를 하나씩 돌면서 시간을 계산하였습니다.(현재 위치)
가 op
구간 안이면 op
를 건너 뛰어야하므로 if문 로직을 추가하였습니다.
명령어가 next
일 경우,(현재 위치) + 10 > (비디오 길이)
일 경우, (현재 위치) = (비디오 길이)
로 값을 할당하고 반복문 처음으로 돌아가도록 하고
그렇지 않으면 (현재 위치) += 10
로 값을 할당하도록 하였습니다.
명령어가 prev
일 경우,(현재 위치) - 10 < 0
일 경우, (현재 위치) = 0
로 값을 할당하고 반복문 처음으로 돌아가도록 하고
그렇지 않으면 (현재 위치) -= 10
로 값을 할당하도록 하였습니다.
마지막 명령어에는 현재 위치가 op
구간 안이면 op
구간을 건너뛰는 로직을 실행하지 않았으므로
for-each문 밖에서 해당 로직을 추가하였습니다.
그리고 마지막으로 String.format()을 사용하여
result에 mm:ss
형식의 문자열로 시간을 변환하여 반환하였습니다.
Stream.reduce() 사용법
일단은 제가 사용한 방법만 정리해 보았습니다.
1. 초기값이 있는 Stream.reduce() 사용법
Stream.reduce(init, accumulator)
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String pos = "04:05";
String[] posList = pos.split(":");
int pos_time = Arrays.stream(posList)
.mapToInt(Integer::parseInt)
.reduce(0, (mm, ss) -> mm * 60 + ss); // 4 * 60 + 5 = 245
System.out.printf("pos_time: %d", pos_time); // 출력 >> pose_time: 245
}
}
만약 Stream의 요소가 여러개인 경우, 다음과 같이 계산됩니다.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] intList = {5, 6, 10, 3, 2};
int result = Arrays.stream(intList)
.reduce(0, (x, y) -> x * 60 + y); // (((5 * 60)+ 6) * 60 + 10) * 60 + 3) * 60 + 2
System.out.printf("result: %d", result); // result: 66132182
}
}
위에서는 설정한 초기값은 다음과 같은 경우에 적용됩니다.
- 스트림에서 연산 시작 값으로 사용
- 스트림에 요소가 하나도 없는 경우, reduce는 초기값을 그대로 결과로 반환합니다.
- 초기값이 없다면 비어 있는 스트림을 처리할 때,
NoSuchElementException
발생
- 초기값이 없다면 비어 있는 스트림을 처리할 때,
- 병렬 스트림(parallelStream)을 사용할 경우, 스트림의 각 부분 결과가 초기값으로 시작하여 처리됩니다. 이후에 병합 결과를 계산하는 데도 초기값이 영향을 미칩니다.
2. 초기값 없이 첫 번째 스트림 요소를 기본값처럼 사용하는 방법
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String pos = "04:05";
String[] posList = pos.split(":");
int pos_time = Arrays.stream(posList)
.mapToInt(Integer::parseInt)
.reduce((mm, ss) -> mm * 60 + ss)
.orElse(0); // 4 * 60 + 5 = 245
System.out.printf("pos_time: %d", pos_time); // 출력 >> pose_time: 245
}
}
📗 참고 자료
String.format() 사용법
일단은 제가 사용한 방법만 정리해 보았습니다.
1. 문자열(숫자) 왼쪽 정렬
%[최소길이]s : 최소길이만큼 “문자열”을 출력하며, “왼쪽”에서 부터 “공백”으로 채웁니다.
%[최소길이]d
2. 문자열(숫자) 오른쪽 정렬
%-[최소길이]s : 최소길이만큼 “문자열”을 출력하며, “오른쪽”에서 부터 “공백”으로 채웁니다.
%-[최소길이]d
3. 문자열(숫자) 오른쪽에 기호 채우기
%0[최소길이]s : 최소길이만큼 “문자열”을 출력하며, “왼쪽”에서 부터 “공백”으로 채웁니다.
%0[최소길이]d
4. 문자열(숫자) 왼쪽에 기호 채우기
위와 동일한 방법이 존재하지 않습니다.
위의 2번 방법으로 문자열을 오른쪽 정렬 후, replace()를 사용하여 원하는 기호로 채웁니다.
- % : 시작
- 채울 기호
- (없음) : 공백으로 채움
- 0 : 해당 기호로 남은 문자열 길이를 채움
- 기호를 채우는 방향
- (없음) : 왼쪽에서부터 기호를 채움
- - : 오른쪽에서부터 기호를 채움
- 숫자 : 반환될 문자열 길이(이미 정의된 문자열 포함 길이)
- s : 문자열
- d : 정수
public class Main {
public static void main(String[] args) {
// 문자열에 사용하기
String right_align = String.format("%10s", "abc");
System.out.println("right_align: '" + right_align + "'"); // 출력 >> right_align: ' abc'
String left_align = String.format("%-10s", "abc");
System.out.println("left_align: '" + left_align + "'"); // 출력 >> left_align: 'abc '
// System.out.printf()에 적용하기
System.out.printf("right_align: '%10s'\n", "abc"); // 출력 >> right_align: ' abc'
System.out.printf("left_align: '%-10s'\n", "abc"); // 출력 >> left_align: 'abc '
// 정수에 사사용하기
String right_align2 = String.format("%10d", 123);
System.out.println("right_align: '" + right_align2 + "'"); // 출력 >> right_align2: ' 123'
String left_align2 = String.format("%-10d", 123);
System.out.println("left_align2: '" + left_align2 + "'"); // 출력 >> left_align2: '123 '
// System.out.printf()에 적용하기
System.out.printf("right_align2: '%10d'\n", 123); // 출력 >> right_align2: ' 123'
System.out.printf("left_align2: '%-10d'\n", 123); // 출력 >> left_align2: '123 '
// 0으로 남은 문자열 채우기
String right_align3 = String.format("%010d", 123);
System.out.println("right_align3: '" + right_align3 + "'"); // 출력 >> right_align3: '0000000123'
String left_align3 = String.format("%-9d", 123).replace(" ", "0");
System.out.println("left_align3: '" + left_align3 + "'"); // 출력 >> left_align3: '123000000'
}
}