JAVA/코딩테스트
프로그래머스 레벨 1 - 동영상 재생기[자바]
진짠
2024. 9. 7. 11:07
728x90
문제
답
시간의 흐름 순으로 이동하며 풀었습니다.
1 - 초기 pos가 오프닝 구간일 경우 건너뛰기 실행
2 - command 배열만큼 10초 뒤, 앞으로 이동
3 - 10초 뒤 이동했는데 동영상 시작시간보다 짧아질 경우 0분 0초로 변환
4 - 10초 앞으로 이동했는데 동영상 종료시간보다 길어질 경우 동영상 종료시간으로 변환
5 - 구간이동 후 오프닝 구간일 경우 건너뛰기 실행
그래서 저는 이렇게 풀었습니다.
import java.util.*;
class Solution {
public String solution(String video_len, String pos, String op_start, String op_end, String[] commands) {
int count = 0;
pos = opening(op_start, op_end, pos); //초기 pos 오프닝 건너뛰기 실행
while(count < commands.length) {
String command = commands[count];
pos = beforeSec(command, pos, op_start, op_end); //prev 로직 실행
pos = afterSec(command, video_len, pos, op_start, op_end); //next 로직 실행
pos = opening(op_start, op_end, pos); //구간 이동 후 오프닝 건너뛰기실행
count++;
}
return pos;
}
private String opening(String op_start, String op_end, String pos) {
String[] posSplit = pos.split(":");
int posLength = Integer.parseInt(posSplit[0])*60 + Integer.parseInt(posSplit[1]);
String[] osSplit = op_start.split(":");
int osLength = Integer.parseInt(osSplit[0])*60 + Integer.parseInt(osSplit[1]);
String[] oeSplit = op_end.split(":");
int oeLength = Integer.parseInt(oeSplit[0])*60 + Integer.parseInt(oeSplit[1]);
// pos가 오프닝 구간에 있다면 건너뛴다.
if(posLength >= osLength && posLength < oeLength) {
pos = op_end;
}
return pos;
}
private String beforeSec(String command, String pos, String op_start, String op_end) {
if("prev".equals(command)) { //command가 prev면 재생 시간 10초 전으로 이동
String[] timeSplit = pos.split(":");
int m = Integer.parseInt(timeSplit[0]);
int s = Integer.parseInt(timeSplit[1])-10;
if(s<0) {
m-=1;
s+=60;
}
if(m<0) { //10초 뒤로 갔는데 시작시간보다 작다면 0분0초
m=0;
s=0;
}
String mm = m<10 ? "0"+m : ""+m;
String ss = s<10 ? "0"+s : ""+s;
pos = mm+":"+ss;
}
return pos;
}
private String afterSec(String command, String video_len, String pos, String op_start, String op_end) {
if("next".equals(command)) { //command가 next 재생 시간 10초 뒤로 이동
String[] timeSplit = pos.split(":");
int m = Integer.parseInt(timeSplit[0]);
int s = Integer.parseInt(timeSplit[1])+10;
if(s>=60) {
m+=1;
s-=60;
}
String[] videoSplit = video_len.split(":");
int vm = Integer.parseInt(videoSplit[0]);
int vs = Integer.parseInt(videoSplit[1]);
if((vm == m && vs < s) || vm < m) { //10초 앞으로 갔는데 비디오길이보다 크다면 비디오 길이만큼
m=vm;
s=vs;
}
String mm = m<10 ? "0"+m : ""+m;
String ss = s<10 ? "0"+s : ""+s;
pos = mm+":"+ss;
}
return pos;
}
}
리팩토링
시간을 변환 부분에서 풀면서도 더 좋은 방법이 있을 것 같은데, 고민했습니다.
어느 부분에서는 mm:ss를 잘라서 하고, 어느 부분에서는 mm*60 + ss 로 해서 통일해서 풀면 좀 더 깔끔한 코드가 되지 않을까 생각했습니다.
import java.util.*;
class Solution {
public String solution(String video_len, String pos, String op_start, String op_end, String[] commands) {
int count = 0;
int convertPos = timeConvertInt(pos);
//초기 pos 오프닝 건너뛰기 실행
convertPos = opening(op_start, op_end, convertPos);
while(count < commands.length) {
String command = commands[count];
//prev 로직 실행
convertPos = beforeSec(command, convertPos, op_start, op_end);
//next 로직 실행
convertPos = afterSec(command, video_len, convertPos, op_start, op_end);
//구간 이동 후 오프닝 건너뛰기실행
convertPos = opening(op_start, op_end, convertPos);
count++;
}
return intConvertTime(convertPos);
}
private int opening(String op_start, String op_end, int convertPos) {
int osLength = timeConvertInt(op_start);
int oeLength = timeConvertInt(op_end);
// pos가 오프닝 구간에 있다면 건너뛴다.
if(convertPos >= osLength && convertPos < oeLength) {
convertPos = oeLength;
}
return convertPos;
}
private int beforeSec(String command, int convertPos, String op_start, String op_end) {
//command가 prev면 재생 시간 10초 전으로 이동
if("prev".equals(command)) {
convertPos-= 10;
//10초 뒤로 갔는데 시작시간보다 작다면 0분0초
if(convertPos<0) {
convertPos = 0;
}
return convertPos;
}
return convertPos;
}
private int afterSec(String command, String video_len, int convertPos, String op_start, String op_end) {
//command가 next 재생 시간 10초 뒤로 이동
if("next".equals(command)) {
convertPos += 10;
int videoLength = timeConvertInt(video_len);
//10초 앞으로 갔는데 비디오길이보다 크다면 비디오 길이만큼
if(convertPos > videoLength) {
convertPos = videoLength;
}
return convertPos;
}
return convertPos;
}
private int timeConvertInt(String time) {
String[] timeSplit = time.split(":");
int mm = Integer.parseInt(timeSplit[0]);
int ss = Integer.parseInt(timeSplit[01]);
return mm * 60 + ss;
}
private String intConvertTime(int time) {
int mm = time / 60;
int ss = time % 60;
return String.format("%02d:%02d", mm, ss);
}
}
결과
time convert용 메소드를 만들어서 시간 계산을 int값으로 통일했습니다. 나중에 값 출력할때만 다시 포맷을 변경하여 출력하도록 수정했습니다.
코드 개수도 줄었고 가독성도 좋아졌으며 테스트 돌린 결과 성능도 10배가량 향상되었습니다.
아마 불필요한 분기처리문(초가 60초이상이면 분을 올린다던가)을 빼고 숫자계산으로 통일하니 그런 것 같습니다.
728x90