본문 바로가기
알고리즘

2025 프로그래머스 코드챌린지 1차 예선 파이썬

by HanYaung 2025. 3. 26.

https://school.programmers.co.kr/learn/challenges?order=recent&page=1&partIds=81177

유연 근무제 lv1 30분 [구현]

def solution(schedules, timelogs, startday):
    answer = len(schedules)

    for i, time in enumerate(timelogs):
        limit=schedules[i]+10
        if limit%100>59: 
            limit+=100
            limit-=60

        day=startday
        print(limit)
        for j in time:
            print(day)

            if (day!=6 and day!=7) and j>limit:     #괄호에 or가 아니라 and
                answer-=1
                break

            day%=7     #나머지 연산
            day+=1

    return answer
# 단, 토요일, 일요일의 출근 시각은 이벤트에 영향을 끼치지 않습니다. 
#1. 각 사람마다 마지노 선 알아야 함
#2. 토, 일인 인덱스 알아야 함.

내 코드와의 차이점

  • 평일 인덱스를 따로 만들어 슬라이싱 후 비교해서 속도가 느림
  • 그냥 for문에서 처리하는게 좋아보임
  • enumerate를 사용하지 않음 자꾸 까먹음 기억하자

비밀코드해독 lv2 30분 [완전탐색]

from itertools import combinations
def solution(n, q, ans):
    
    li = [i for i in range(1,n+1)]
    tmp = list(combinations(li,5))
    
    for i,a in enumerate(ans):
        tmp_li = []
        
        for t in tmp:
            if comparison(q[i],t,a):
                tmp_li.append(t)
        tmp = tmp_li 
        
    answer = len(tmp)
    return answer

def comparison(a,b,num):
    count = 0
    for i in range(5):
        if a[i] in b:
            count +=1 
    
    if num == count:
        return 1 
    return 0 
    

import itertools 

def solution(n, q, ans):
    f = list(itertools.combinations(range(1, n + 1), 5))

    for g, cnt in zip(q, ans):
         f = [code for code in f if len(set(code) & set(g)) == cnt]

    return len(f)
  • 완전 탐색 itertools 기억하기
  • zip 쓰기

지게차와 크레인 1시간 반 실패 [dfs]

def isOutside(storage, x, y):
    dx, dy = [0, 0, 1, -1], [1, -1, 0, 0]
    outside = False

    for i in range(4):
        nx, ny = x + dx[i], y + dy[i]
        if storage[nx][ny] == "0":
            storage[x][y] = "0"
            outside = True
            break

    if outside:
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if storage[nx][ny] == "1":
                storage[nx][ny] = "0"
                isOutside(storage, nx, ny)

def fork(storage, box):  # 지게차
    dx, dy = [0, 0, 1, -1], [1, -1, 0, 0]
    index = []
    for i in range(1, len(storage)-1):
        for j in range(1, len(storage[0])-1):
            if storage[i][j] == box:
                for k in range(4):
                    nx, ny = i + dx[k], j + dy[k]
                    if storage[nx][ny] == "0":
                        index.append((i, j))
                        break
    for i, j in index:
        storage[i][j] = "0"
        isOutside(storage, i, j)

def crane(storage, box):  # 크레인
    for i in range(1, len(storage)-1):
        for j in range(1, len(storage[0])-1):
            if storage[i][j] == box:
                storage[i][j] = "1"
                isOutside(storage, i, j)

def solution(storage, requests):
    n, m = len(storage), len(storage[0])
    # 테두리에 '0' 추가 (외부 공간 표시)
    storage = [list("0" + row + "0") for row in storage]
    storage.insert(0, list("0" * (m + 2)))
    storage.append(list("0" * (m + 2)))

    for req in requests:
        if len(req) == 1:
            fork(storage, req[0])
        else:
            crane(storage, req[0])

    # 남은 컨테이너 세기
    answer = 0
    for i in range(1, len(storage) - 1):
        for j in range(1, len(storage[0]) - 1):
            if storage[i][j] not in ["0", "1"]:
                answer += 1
    return answer
  • 복잡할 수록 함수를 나눠서 처리하자
  • 외부로 연결하는걸 0 으로 표현해야함
  • 아직 외부랑 연결되지 않은 빈 공간이라면 1로하고 그 칸도 재귀적으로 연결을 확장

홀짝트리 - 실패 [dfs+트리탐색]

import sys
sys.setrecursionlimit(2_000_000)  # 재귀 깊이 제한을 매우 크게 설정 (트리 크기가 최대 40만이므로)

def solution(nodes, edges_):
    visited = [-1 for _ in range(1_000_001)]  # 노드 번호가 최대 100만이므로 미리 배열 생성, -1이면 방문 안함
    edges = [[] for _ in range(1_000_001)]   # 인접 리스트 방식의 그래프 (무방향)

    for a,b in edges_ :
        edges[a].append(b)  # 양방향 연결
        edges[b].append(a)

    def dfs(cur, prev, arr) :
        cnt = 0  # 자식 수를 셈
        for nxt in edges[cur] :
            if nxt == prev : continue  # 부모 노드는 다시 안 감 (무한 루프 방지) 트리구조 이기 떄문에 이전이전 노드는 갈 수없음  
            dfs(nxt, cur, arr)  # 자식 노드 DFS 호출
            cnt += 1  # 자식 수 증가

        # 노드 유형 판별 (0: 홀짝노드/짝수노드, 1: 역홀수노드/역짝수노드)
        # visited[cur] = (노드번호%2 + 자식수%2) % 2
        visited[cur] = (cur % 2 + cnt % 2) % 2
        arr[visited[cur]] += 1  # 유형별 노드 수 집계 (arr[0], arr[1])

    ans = [0,0]  # [홀짝 트리 개수, 역홀짝 트리 개수]
    for node in nodes :
        if visited[node] != -1 : continue  # 이미 방문한 트리는 스킵

        arr = [0,0]  # 현재 트리의 노드 타입 개수 저장: [0]은 홀짝 노드들, [1]은 역홀짝 노드들
        dfs(node, -1, arr)  # 해당 트리 루트 잡고 DFS 실행

        # 아래는 조건에 따라 트리 타입 판별 (케이스별 예외처리 포함)

        # 만약 트리에 딱 2개의 노드만 있고 (둘 중 하나만 타입 존재),
        # 그것이 모두 하나의 타입이면 두 트리 모두로 가능 (ex: 2개의 홀짝 노드 or 2개의 역홀짝 노드)
        if (arr[0] == 0 and arr[1] == 2) or (arr[0] == 2 and arr[1] == 0) :
            ans[0] += 1
            ans[1] += 1

        # 역홀짝 노드만 있음 → 역홀짝 트리
        elif arr[0] == 0 :
            ans[1] += 1

        # 홀짝 노드만 있음 → 홀짝 트리
        elif arr[1] == 0 :
            ans[0] += 1

        # 특별 케이스: 두 개의 홀짝 노드인데 루트 노드가 홀짝 타입이면 역홀짝 트리도 가능
        elif arr[0] == 2 and visited[node] == 0 :
            ans[1] += 1

        # 두 개의 역홀짝 노드인데 루트 노드가 역홀짝이면 홀짝 트리도 가능
        elif arr[1] == 2 and visited[node] == 1 :
            ans[0] += 1

    return ans  # [홀짝 트리 수, 역홀짝 트리 수]
  • 재귀에 대한 공부가 필요할꺼같다
  • 양방향 노드 연결 기억하자
  • for a,b in edges_ : edges[a].append(b) # 양방향 연결 edges[b].append(a)
  • visited 배열 적극 사용