문제

 

2304번: 창고 다각형

첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의

www.acmicpc.net

코드

N = int(input())

coordinate=[]

for i in range(N):
    coordinate.append(tuple(map(int,input().split())))

max_x = max(coord[0] for coord in coordinate)
max_y = max(coord[1] for coord in coordinate)

grid = [[0 for _ in range(max_x)] for _ in range(max_y)]

for x, y in coordinate:
    for i in range(y):
        grid[i][x - 1] = 1 

grid.reverse()

res=0

for i in range(len(grid)):
    if(grid[i].count(1)==0):
        continue
    if(grid[i].count(1)==1):
        res+=1
        continue
    front_index = grid[i].index(1) + 1
    back_index = len(grid[i]) - grid[i][::-1].index(1) 
    res+=back_index-front_index+1
print(res)

풀이

  • 모든 기둥이 들어가는 최소 다각형 면적을 구해라
  1. 좌표를 입력받아 기둥은 1, 빈공간은 0으로 이차원 배열을 만든다.
  2. 배열을 y좌표 기준 한줄씩 돌면서 면적을 측정한다.
    1. 우선 한 줄에 기둥이 없으면 바로 다음줄로 넘어간다.
    2. 한 줄에 기둥이 한개 있으면 무조건 면적은 1이 추가된다.
    3. 한 줄에 기둥이 여러개 있으면 가장 바깥의 기둥 두개의 면적을 추가한다.

문제

 

22233번: 가희와 키워드

1번째 글을 쓰고 난 후에, 메모장에 있는 키워드는 set, floyd, os가 됩니다. 2번째 글을 쓰고 난 후에, 메모장에 있는 키워드는 set, os가 됩니다. map은 1번째 글과 2번째 글에 중복으로 등장하였음을

www.acmicpc.net

코드

import sys

input = sys.stdin.readline

m, n =map(int,input().rstrip().split())
keyword = {}

unUse=m

for i in range(m):
    keyword[input().rstrip()]=False

for i in range(n):
    memo = input().rstrip().split(',')
    for j in memo:
        if(j in keyword):
            if(not keyword[j]):
                keyword[j]+=True
                unUse-=1
    print(unUse)

풀이

  • 사용되지 않은 키워드의 개수를 구해라
  1. 키워드를 입력받아 딕셔너리 키워드:0 형태로 만들어준다.
  2. unUse , 사용되지 않은 키워드의 개수를 세는 변수는 만들어준다
  3. 블로그에 사용한 키워드를 memo에 입력받고, 언급된 키워드들을 제거해준다.
    1. keyword에 없는 단어들은 체크하지 않는다.
    2. keyword에 있는데 value가 False이 아닌 단어는 이미 한번 이상 사용된 단어이므로 넘어간다.
    3. keyword에 있는 단어인데 value가 False인경우 사용하지 않은 단어이므로 True로 바꿔준 후 unUse-=1을 해준다

문제

 

20006번: 랭킹전 대기열

모든 생성된 방에 대해서 게임의 시작 유무와 방에 들어있는 플레이어들의 레벨과 아이디를 출력한다. 시작 유무와 플레이어의 정보들은 줄 바꿈으로 구분되며 레벨과 아이디는 한 줄에서 공백

www.acmicpc.net

코드

p,m = map(int, input().split())

res=[]
for i in range(p):
    l,n =input().split()
    l = int(l)
    if(len(res)==0):
        res.append([(l,n)])
        continue
    flag=True
    for j in range(len(res)):
        if len(res[j])==m:
            continue
        if abs(res[j][0][0]-l)<=10:
            res[j].append((l,n))
            flag = False
            break
    if flag:
        res.append([(l,n)])

for i in res:
    i.sort(key=lambda x: x[1])
    if(len(i)==m):
        print('Started!')
    else:
        print('Waiting!')

    for l,n in i:
        print(l,n)

풀이

  • 단순한 구현 문제
  1. 플레이어 수 p와 방의 인원 제한 m을 입력 받는다
  2. 각 플레이어를 받으면서 방에 넣는다.
    1. 현재 방이 하나도 없으면 새로 생성한다.
    2. 존재하는 방이 인원제한에 차면 넘어간다.
    3. 만약 인원제한을 안넘긴다면 방을 생성한 사람의 레벨과 비교해서 +-10이면은 넣는다.
    4. 위에 해당하지 않으면 방을 새로 생성한다.
  3. 출력하기 전 닉네임을 기준으로 sort한 후 출력한다

문제

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드

def solution(dirs):
    answer = 0
    num = {'U':(0,1),'D':(0,-1),'R':(1,0),'L':(-1,0)}
    res={}
    visited = set()
    x, y = 0, 0

    for i in dirs:
        nx, ny = x + num[i][0], y + num[i][1]
        if -5 <= nx <= 5 and -5 <= ny <= 5:
            if ((x, y), (nx, ny)) not in visited:
                answer += 1
                visited.add(((x, y), (nx, ny)))
                visited.add(((nx, ny), (x, y)))
            x, y = nx, ny

    return answer

풀이

  • 중복을 제외하고 방문한 선분을 체크하기
  1. 입력받는 문자열에 따라 이동하는 좌표값 딕셔너리를 구현.
  2. 입력에 따라서 x,y를 움직인다. -5 ~ 5의 범위는 넘어가면 continue 해준다,
  3. set()에 이동좌표를 넣어서 만약 그 좌표가 존재하지 않으면 answer+=1해주고, 존재하면 중복한 값이라고 판단하고 넘어간다.

문제

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

코드

def changeStrToInt(time):
        return int(time[0:2]) * 60 + int(time[3:])

def solution(book_time):
        sort_time = sorted([[changeStrToInt(i[0]), changeStrToInt(i[1]) + 10] for i in book_time])

    res = []

    for i in sort_time:
        if len(res)==0:
            res.append(i)
            continue
        for j in range(len(res)):
            if(i[0] >= res[j][1]):
                res[j] = res[j]+i
                break
        else:
            res.append(i)

    return len(res)

풀이

  • 빈틈없이 예약해서 최소의 방 개수를 구하자
  1. 문자열로 입력받은 시간을 분으로 그리고 int형으로 만들어주는 함수를 작성한다.
  2. 그 다음 변환한 시간을 바탕으로 정렬해준다
  3. 정렬한 시간을 바탕으로 res배열에 넣어준
    1. res배열이 비어 있으면 바로 넣어준다.
    2. res배열을 돌면서 각각의 res배열의 제일 마지막 시간이 현재 첫번째 시간보다 작으면 거기 넣어준다.
    3. 넣을 곳이 없으면 배열에 새롭게 추가한다.
  4. 방의 개수를 리턴해준다.

문제설명 (링크 참조)

문자열 압축

문자열의 반복되는 부분을 겹쳐서 제일 짧은 문자열을 만들어 리턴하라!

풀이

입력받은 문자열을 1~제일 크게 나눌 수 있을 때까지 나눠서 겹치는지 확인하는 문제

결국 최대 두개가 겹치는 건 길이의 1/2일때니깐 1~len(s//2) 까지 확인하면 된다.

1~len(s//2)까지 매 시행횟수에 초기값 설정.


초기값

  • arr=””
  • count=1
  • cur=s[0:i]

  • cur은 매 시행의 크기만큼 첫번째 문자열.
  • count는 현재 몇번 반복되었는지 확인

반복문을 돌면서 다음 조건을 통해 arr에 차례차례 담는다.

  1. cur과 같은 크기만큼 다음 문자열을 비교
  2. 같으면 count+=1 해주고 넘어감
  3. 다르면 count가 1이면 겹치는게 하나도 없는것이므로로 그냥 cur만 arr에 더해줌
    다르고 count가 1이 아니면 여러번 겹친것이므로 count+cur로 문자열에 더해줌

코드

def solution(s):
    answer=len(s)
    for i in range(1,len(s)//2+1):
        arr = ''
        count=1
        cur=s[0:i]
        for j in range(i,len(s),i):
            if(cur==s[j:j+i]):
                count+=1
            else:
                if(count==1):
                    arr+=cur
                else:
                    arr+=str(count)+cur
                    count=1
                cur=s[j:j+i]
        if(count==1):
            arr+=cur
        else:
            arr+=str(count)+cur

        if(answer>len(arr)):
            answer=len(arr)
    return answer

특이사항

  • 처음에 무조건 같은 크기로 나누는지 몰라서 엄청 어렵게 생각함.
    (1 + 3 + 3)이런식으로 나눠도 되는줄 알고 원래 난이도보다 훨씬 올려서 생각했다.
  • 문제를 잘 읽자...

문제설명 (링크 참조)

프로그래머스 튜플

입력받은 문자열을 확인하여 제대로 된 순서의 리스트로 변환 후 리턴

풀이

문제에서 입력받은 문자열 s에서 값들을 추출하는게 관건이었던 문제.

처음에는 리스트 형식으로 요소를 주는 줄 알았지만 하다보니 문자열로 준다는 것을 깨닫고 어떻게 문자열에서 각 요소들을 정리해서 추출할 수 있을까 고민을 많이 함.

  1. 우선 입력받은 s의 튜플 하나하나를 리스트로 바꿔준다.
  1. 리스트의 요소들을 str에서 int로 바꿔준다.
  • s[2:-2:].split('},{')를 해주면 { }전부 제외하고 각 튜플을 하나의 요소로 만들어 줄 수있다.
  • 그리고 for문을 돌며 각 요소를 다시 split(',')해주고 값들을 str에서 int로 바꿔주면 각각의 요소들을 얻을 수 있다.
  1. res 딕셔너리에 길이를 key로 저장해준다.

{{2},{2,1},{2,1,3},{2,1,3,4}} 이 문자열을
{1: [2], 2: [2, 1], 3: [2, 1, 3], 4: [2, 1, 3, 4]} 이런식으로 길이를 key값으로 얻을 수 있음.

  1. res를 반복문으로 돌면서 모든 배열의 요소를 확인하며 answer에 값을 넣어준다.

 

{{a1}, {a1, a2}, {a1, a2, a3}, {a1, a2, a3, a4}, ... {a1, a2, a3, a4, ..., an}} 의 형식이므로
res에서 길이가 1인(key값이 1인) value 부터 확인하면서 answer에 없을경우 요소 추가.

코드

def solution(s):
    res={}
    answer = []
    #입력받은 문자열은 인덱싱해서 리스트로 만들어줌
    arr=s[2:-2:].split('},{')
    for i in arr:
        a=i.split(',')
        #str을 int로 바꿔줌
        for j in range(len(a)):
            a[j]=int(a[j])
        res[len(a)]=a
    #크기가 1인 것 부터 확인하면서 answer배열에 안들어가 있으면 넣고 다음으로 넘어감.
    for i in range(1,len(res)+1):
        for j in range(len(res[i])):
            if(res[i][j] not in answer):
                answer.append(res[i][j])
                break
    return answer

특이사항

  • 다른사람풀이 보니까 여러 방법이 있는 것 같다. 정규표현식으로 한줄로 푼 괴수분을 보았다...
  • 또 정규표현식이 아니더라도 나처럼 굳이 딕셔너리를 쓰지않고 리스트를 sort해서 작성하신 분들도 보았다.

문제설명 (링크 참조)

프로그래머스 양궁 대회 문제

라이언이 어피치를 이기는 경우 중 낮은 점수를 더 많이 맞힌 경우를 리턴, 리턴 값은 10점 화살의 개수 부터 0점까지 리스트 형식으로 반환 한다.
ex [1,2,3,0,0,0,0,0,0,0,1]
단 어떠한 경우에도 못이기면 -1 리턴.

풀이

결국은 라이언이 어피치를 이기는 경우를 체크해주면 된다.

코드는 이런방법으로 작성했다.

  1. 우선 0~10의 화살을 쏠 수 있는 경우의 수를 조합을 이용해 뽑았다. (여기서 같은 점수를 여러번 맞힐 수 있으므로 중복이 가능하게 뽑아야 했다. 그래서 그냥 combinations가 아닌 combinations_with_replacement 사용.)
  2. 나온 경우의 수와 어피치의 과녁을 비교해서 라이언이 더 많이 맞힌 수는 라이언의 점수로, 어피치가 더많이 맞혔거나 같으면 어피치 점수로, 둘다 0이면 점수를 세지 않았다.

-> 여기서 여러발을 맞혀도 누적 점수가 아닌 과녁의 점수만 +해줘야한다.

  1. 점수를 체크한 뒤 라이언이 어피치보다 더 많은 점수를 획득했을 때, 가장 큰 차이로 이기는 경우를 찾아야 한다. 그래서 count 변수로 점수의 차이를 저장해놓고 현재 결과 점수가 count보다 클경우 c배열과 count 업데이트.
  2. 그렇게 찾은 조합을 점수로 변환한 후 answer에 넣어서 return

코드

from itertools import combinations_with_replacement
def solution(n, info):
    arr=[0,1,2,3,4,5,6,7,8,9,10]
    b=list(combinations_with_replacement(arr,n))
    # 가능한 모든 경우의 수를 중복 조합으로 구함.
    c=[] #결과 저장할 배열 선언
    count=0
    for i in range(len(b)):
        l=0
        a=0
        for j in range(11):
            if(info[j]<b[i].count(10-j)):
                l+=10-j
            elif(info[j]>=b[i].count(10-j) and info[j]!=0):
                a+=10-j
                #둘다 0이면 그냥 넘어간다.
        if(l<a):
            continue
        elif(l>a):
            #라이언이 이기는 경우 중에서도 최대 점수차이가 나올때만 업데이트.
            if(count<l-a):
                count=l-a
                c=b[i]

        else:
            continue
    answer=[0,0,0,0,0,0,0,0,0,0,0]
    #결과 배열이 비어있으면 -1 리턴.
    if(len(c)==0):
        return [-1]
    #결과 배열의 값을 answer배열의 인덱스로 사용해서 답 작성.
    for i in range(len(c)):
        answer[10-c[i]]+=1
    return answer

특이사항

  • 둘다 0이면 점수를 세지 않는 조건을 생각하지 않아서 몇번 틀림
  • 그리고 조건중에 “같은 점수일경우 적은 수의 과녁을 더 많이 맞힌 경우를 우선한다”라는 조건이 있었는데 딱히 신경안써도 통과해서 왜 그럴지 고민함
    → 고민한 결과 조합을 함수로 구했을 경우 배열의 앞쪽부분을 순서대로 먼저 조합으로 구함. 즉 arr이 0,1,2..순서대로 시작했기 때문에 0,1,2..순서대로 많은 조합부터 구한 것!
    그렇기 때문에 코드에서는 점수가 똑같을 경우를 생각 안하고 클때만 바꿨지만, 결국 점수가 같을 경우를 체크해도 앞에 나온게 무조건 우선일 수 밖에 없다. (상대적으로 낮은 번호의 수가 더 많기 때문에)

+ Recent posts