알고리즘

[프로그래머스] 2025 프로그래머스 코드챌린지 1차 예선 - 유연근무제

swanzzz 2025. 4. 30. 22:49
반응형

[오늘의 문제]

https://school.programmers.co.kr/learn/courses/30/lessons/388351?language=python3

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr


[오늘의 학습 키워드]

  • 구현

1. 문제설명

 

직원 N 명이 지각하지 않고 출근한 경우 그 사람수에 맞춰 선물을 주려는 문제입니다.

 

이벤트 시작 날짜가 주어질 때, 직원이 출근을 목표로 하는 시간을 기준으로 + 10분 까지는 지각이 인정되지 않습니다.

 

주말을 제외하고 직원이 지각하지 않고 출근한 경우 그 사람수를 구하는 문제입니다.


[제한사항]

  • 1 ≤ schedules의 길이 = n ≤ 1,000
    • schedules[i]는 i + 1번째 직원이 설정한 출근 희망 시각을 의미합니다.
    • 700 ≤ schedules[i] ≤ 1100
  •  1 ≤ timelogs의 길이 = n ≤ 1,000
    • timelogs[i]의 길이 = 7
    • timelogs[i][j]는 i + 1번째 직원이 이벤트 j + 1일차에 출근한 시각을 의미합니다.
    • 600 ≤ timelogs[i][j] ≤ 2359
  •  1 ≤ startday ≤ 7
    • 1은 월요일, 2는 화요일, 3은 수요일, 4는 목요일, 5는 금요일, 6은 토요일, 7은 일요일에 이벤트를 시작했음을 의미합니다.
  •  출근 희망 시각과 실제로 출근한 시각을 100으로 나눈 나머지는 59 이하입니다.

2. 접근방식

전체 요일을 기준으로 평일에 지각하지 않은 사원을 구하는 문제입니다.

 

사원별로 출근시간이 timelogs 에 담겨있고 해당 사원의 출근 목표 시간은 schedules에 주어집니다.

 

즉, schedules[0] 은 timelogs[0] 사원의 출근 목표 시간이고

주어진 배열에 담긴 순서는 startday를 기준으로 주어져 있습니다.

 

예제 1번을 토대로 문제를 살펴보면

 

timelogs 가 아래와 같이 주어집니다.

[

[710, 2359, 1050, 700, 650, 631, 659],

[800, 801, 805, 800, 759, 810, 809],

[1105, 1001, 1002, 600, 1059, 1001, 1100]

]

 

여기서 startday 가 5로 시작하니 주어진 timelogs[0][0] 은 금요일 이라는 소리입니다.

 

주말은 지각해도 상관없으니 제외해 주어야 합니다.

 

그러면 startday를 기준으로 하나씩 timelogs를 뽑아 시간을 확인할 때, startday를 늘려주며 일주일을 확인해 주고 startday가 8 즉 6 토요일, 7 일요일을 지난 경우 다시 1로 바꿔 월요일로 처리해주면 될 것 같습니다.

 

그렇게 startday를 맞춰주고 뽑아온 평일 시간이 목표 출근 시간 + 10 분 안쪽으로 출근한 경우 해당 사원은 지각을 하지 않은 사원이므로 answer를 1 늘려주고

 

만약 1번이라도 지각을 했다면 해당 사원은 더이상 확인할 필요가 없으니 다음 사원을 탐색해주면 될 것 같습니다.


3. 코드

# 입력받은 시간을 계산하기 편하게 분으로 모두 변경
def change_time(n):
    h = n // 100
    m = n % 100
    
    return h * 60 + m

def solution(schedules, timelogs, startday):
    answer = 0
    
    # 직원 수 만큼 탐색
    for i in range(len(schedules)):
        
        # 시작요일
        s = startday
        
        # 직원의 출근 목표 시간
        schedule = change_time(schedules[i])
        
        # 직원이 출근한 시간
        for time in timelogs[i]:
            # 주말은 제외해주기
            if s in [6, 7]:
                s += 1
                # 일주일 지나면 월요일로 초기화
                if s == 8:
                    s = 1
                continue
            
            # 직원이 도착한 시간
            arrived_time = change_time(time)
            
            # 목표 시간 + 10분 보다 늦게 출근한 경우 지각처리
            if schedule + 10 < arrived_time:
                break
            
            # 그게 아니라면 계속 탐색하며 평일 출근 시간 확인하기
            else:
                s += 1
        # for-else 조건으로 해당 직원이 지각하지 않았다면 anwer + 1
        else:
            answer += 1
    return answer

[코드설명]

# 입력받은 시간을 계산하기 편하게 분으로 모두 변경
def change_time(n):
    h = n // 100
    m = n % 100
    
    return h * 60 + m

 

우선 직원이 출근한 시간을 계산해 주어야 하는데 지각 여부를 확인하는 가장 편한 방법은 모든 시간을 분으로 바꿔 계산하는 방법입니다.

 

분으로 시간을 바꾸면 굳이 60분 지나면 1시간 처리 하는 귀찮은 경우를 해주지 않아도 되니 입력받은 시간을 모두 분으로 변경해 주는 코드를 작성해 주었습니다.


def solution(schedules, timelogs, startday):
    answer = 0
    
    # 직원 수 만큼 탐색
    for i in range(len(schedules)):
        
        # 시작요일
        s = startday
        
        # 직원의 출근 목표 시간
        schedule = change_time(schedules[i])
        
        # 직원이 출근한 시간
        for time in timelogs[i]:
            # 주말은 제외해주기
            if s in [6, 7]:
                s += 1
                # 일주일 지나면 월요일로 초기화
                if s == 8:
                    s = 1
                continue

 

입력받은 schedules를 통해 직원의 수를 파악할 수 있다.

따라서 직원의 수 만큼 탐색을 시작하는데

 

직원이 출근을 목표로 하는 시간을 구해주기 위해 schedule를 계산해 주었고

이를 바탕으로 직원이 출근한 시간을 찾아준다.

 

시작요일을 최초 입력받은 startday를 기준으로 s로 설정해 s를 변경하는 방식으로 startday를 건드리지 않고 계속 사용가능한 방법을 이용

 

주말 예외를 처리하기 위해 주말인 6과 7을 묶어서 s가 6또는 7이 되는 경우 s를 늘려주고 시간 비교는 해주지 않는다.

만약 s가 8이 되면 월요일로 변경해주기 위해 s를 1로 바꿔준다.


            
            # 직원이 도착한 시간
            arrived_time = change_time(time)
            
            # 목표 시간 + 10분 보다 늦게 출근한 경우 지각처리
            if schedule + 10 < arrived_time:
                break
            
            # 그게 아니라면 계속 탐색하며 평일 출근 시간 확인하기
            else:
                s += 1
        # for-else 조건으로 해당 직원이 지각하지 않았다면 anwer + 1
        else:
            answer += 1
    return answer

 

이후 직원이 도착한 시간을 계산해주고 조건을 비교해 줍니다.

출근 목표 시간 + 10분 보다 더 늦게 도착했다면 지각이니 break를 써서 탐색을 종료합니다.

 

이 경우 break에 걸리면 for-else 조건에 걸리지 않기 때문에 for문이 정상적으로 종료되는 경우 else 조건을 통해 answer 를 1씩 늘려줍니다.

 

지각이 아닌 경우 s를 1씩 늘려가며 모든 평일을 검사해 주었습니다.


4. 결과


[회고]

원래 백준 문제를 해결하려 했는데 렉이 걸리면서 사이트에 잘 들어가지지 않아 오랜만에 프로그래머스 문제를 풀어보았습니다.

 

간단한 구현문제 였는데 시간 계산 방법에 따라 복잡해질것 같습니다.

 

처음에는 입력받은 시간에 10을 더해 문자열로 형변환을 실시하여 문자열 슬라이싱을 통해 출근 목표 시간을 계산하고, 도착 시간과 비교하려 하였는데 그렇게 하면 코드가 좀 복잡해 졌습니다.

 

좀더 간단한 방법을 찾다가 모든 시간을 분시간을 바꿔 버리면 복잡한 계산이 필요 없겠다 생각하여 시간을 모두 분으로 바꿔주었고, 이를 바탕으로 목표시간, 도착시간을 계산하여 쉽게 비교가 가능하였습니다.

 

이후에는 문제에 주어진 조건을 잘 이해하고 그대로 적용만 해주면 되었어서 크게 어렵지 않았습니다.

반응형