본문 바로가기
Language/Java

[Programmers | Java | 연습문제 풀이] 동영상 재생기- Solution with Stream.reduce() & 조건문

by ㅇ달빛천사ㅇ 2024. 12. 1.
728x90

코딩테스트 연습 / 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
  }
}

위에서는 설정한 초기값은 다음과 같은 경우에 적용됩니다.

  1. 스트림에서 연산 시작 값으로 사용
  2. 스트림에 요소가 하나도 없는 경우, reduce는 초기값을 그대로 결과로 반환합니다.
    • 초기값이 없다면 비어 있는 스트림을 처리할 때, NoSuchElementException 발생
  3. 병렬 스트림(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'
  }
}

 


📗 참고 자료

728x90