본문 바로가기
스터디/Python

[CodingTest][2023-02-14~]프로그래머스 코딩테스트 Lv.1 문제들

by SeO.V 2023. 4. 10.

프로그래머스 코딩테스트 Lv.1 문제들

2023-02-14 ~ 03-20

푼 문제 : 푸드 파이트 대회, 가장 가까운 같은 글자, 소수 만들기, 실패율, [1차] 다트 게임, 과일장수, 명예의 전당 (1), 로또의 최고 순위와 최저 순위, 체육복, 완주하지 못한 선수, 숫자 짝꿍, 기사단원의 무기, 옹알이 (2), 카드 뭉치, 키패드 누르기, 바탕화면 정리

 

 


푸드 파이트 대회

link : https://school.programmers.co.kr/learn/courses/30/lessons/134240

 

문제 설명

수웅이는 매달 주어진 음식을 빨리 먹는 푸드 파이트 대회를 개최합니다. 이 대회에서 선수들은 1대 1로 대결하며, 매 대결마다 음식의 종류와 양이 바뀝니다. 대결은 준비된 음식들을 일렬로 배치한 뒤, 한 선수는 제일 왼쪽에 있는 음식부터 오른쪽으로, 다른 선수는 제일 오른쪽에 있는 음식부터 왼쪽으로 순서대로 먹는 방식으로 진행됩니다. 중앙에는 물을 배치하고, 물을 먼저 먹는 선수가 승리하게 됩니다.

이때, 대회의 공정성을 위해 두 선수가 먹는 음식의 종류와 양이 같아야 하며, 음식을 먹는 순서도 같아야 합니다. 또한, 이번 대회부터는 칼로리가 낮은 음식을 먼저 먹을 수 있게 배치하여 선수들이 음식을 더 잘 먹을 수 있게 하려고 합니다. 이번 대회를 위해 수웅이는 음식을 주문했는데, 대회의 조건을 고려하지 않고 음식을 주문하여 몇 개의 음식은 대회에 사용하지 못하게 되었습니다.

예를 들어, 3가지의 음식이 준비되어 있으며, 칼로리가 적은 순서대로 1번 음식을 3개, 2번 음식을 4개, 3번 음식을 6개 준비했으며, 물을 편의상 0번 음식이라고 칭한다면, 두 선수는 1번 음식 1개, 2번 음식 2개, 3번 음식 3개씩을 먹게 되므로 음식의 배치는 "1223330333221"이 됩니다. 따라서 1번 음식 1개는 대회에 사용하지 못합니다.

수웅이가 준비한 음식의 양을 칼로리가 적은 순서대로 나타내는 정수 배열 food가 주어졌을 때, 대회를 위한 음식의 배치를 나타내는 문자열을 return 하는 solution 함수를 완성해주세요.\

 

제한사항

  • 2 ≤ food의 길이 ≤ 9
  • 1 ≤ food의 각 원소 ≤ 1,000
  • food에는 칼로리가 적은 순서대로 음식의 양이 담겨 있습니다.
  • food[i]는 i번 음식의 수입니다.
  • food[0]은 수웅이가 준비한 물의 양이며, 항상 1입니다.
  • 정답의 길이가 3 이상인 경우만 입력으로 주어집니다.

입출력 예

food  result
[1, 3, 4, 6] "1223330333221"
[1, 7, 1, 2] "111303111"

 

코드 제출 :

# 제출
def solution(food):
    answer = ''
    for a in range(1,len(food)):
        answer += str(a)*(food[a]//2)
    return answer+'0'+answer[::-1]

 

해설

더보기

처음에는 food를 0부터 시작하게 하고 index를 썼더니 동일한 수에 대해서 먼저번 index가 나오면서 6,14,20에서 틀리고 뭐가 문제지 하다가 food=[1, 5, 3, 5] 를 해보고 나서 index의 문제를 확인하고 수정해서 해결.

 

점수 : 1389(+1)

 


 

가장 가까운 같은 글자

link : https://school.programmers.co.kr/learn/courses/30/lessons/142086

 

문제 설명

문자열 s가 주어졌을 때, s의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알고 싶습니다.예를 들어, s="banana"라고 할 때,  각 글자들을 왼쪽부터 오른쪽으로 읽어 나가면서 다음과 같이 진행할 수 있습니다.

  • b는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
  • a는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
  • n은 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.
  • a는 자신보다 두 칸 앞에 a가 있습니다. 이는 2로 표현합니다.
  • n도 자신보다 두 칸 앞에 n이 있습니다. 이는 2로 표현합니다.
  • a는 자신보다 두 칸, 네 칸 앞에 a가 있습니다. 이 중 가까운 것은 두 칸 앞이고, 이는 2로 표현합니다.

따라서 최종 결과물은 [-1, -1, -1, 2, 2, 2]가 됩니다.

문자열 s이 주어질 때, 위와 같이 정의된 연산을 수행하는 함수 solution을 완성해주세요.

 

제한사항

  • 1 ≤ s의 길이 ≤ 10,000
    • s은 영어 소문자로만 이루어져 있습니다.

입출력 예

result
"banana" [-1, -1, -1, 2, 2, 2]
"foobar" [-1, -1, 1, -1, -1, -1]

 

 

코드 제출 :

# 제출
def solution(s):
    answer = [-1]*len(s)
    tmp = {}
    for i, char in enumerate(s):
        if char in tmp:
            answer[i] = i - tmp[char]
        tmp[char] = i
    return answer

 

해설

더보기

처음에는 answer를 -1로 해놓고 나서 동일한 게 나오면 answer에서 i번째에서 tmp에 있는 index로 계산해서 처리하다가

def solution(s): 
	answer = [-1]*len(s) 
    tmp = [] 
    for i in range(len(s)): 
        if tmp.count(s[i]): 
        	answer[i] = i - tmp.index(s[i]) 
        else: 
        	tmp.append(s[i]) 
	return answer


이렇게 풀었더니 결과가 `[-1, -1, -1, 2, 2, 4]` 이렇게 나오는 거 보고 마지막 a 때문에 index의 위치를 갱신해서 저장해야한다는 걸 알고 dict으로 바꿔서 처리해서 해결함. 

 

점수 : 1390(+1)

 


 

소수 만들기

link : https://school.programmers.co.kr/learn/courses/30/lessons/12977

 
 

문제 설명

주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하려고 합니다. 숫자들이 들어있는 배열 nums가 매개변수로 주어질 때, nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.
  • nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.

입출력 예

nums  result
[1,2,3,4] 1
[1,2,7,6,4] 4

 

 

코드 제출 :

# 제출
from itertools import combinations
def is_prime(x):
    for d in range(2,int(x**.5)+1):
        if x%d==0:
            return False
    return True
def solution(nums):
    return sum([is_prime(sum(i)) for i in combinations(nums,3)])

 

해설

더보기

이번에는 경우의 수를 다 구해서 sum한 게 소수인지 판별하면 되는 거라 이전의 is_prime으로 소수 구하는 함수로 한 번 돌려서 sum으로 갯수 구함.

 

점수 : 1392(+2)

 


 

실패율

link : https://school.programmers.co.kr/learn/courses/30/lessons/42889

 

문제 설명

실패율

슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.

이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.

  • 실패율은 다음과 같이 정의한다.
    • 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수

전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.

 

제한사항

  • 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
  • stages의 길이는 1 이상 200,000 이하이다.
  • stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
    • 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
    • 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
  • 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
  • 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.

입출력 예

stages  result
5 [2, 1, 2, 6, 2, 4, 3, 3] [3,4,2,1,5]
4 [4,4,4,4,4] [4,1,2,3]

 

 

코드 제출 :

# 제출
def solution(N, stages):
    ppl = len(stages)
    stage_dict = {}
    for i in range(1, N+1):
        stage_dict[i] = stages.count(i)/ppl if (ppl != 0 and stages.count(i) != 0) else 0
        ppl -= stages.count(i)

    return [stage for stage, perc in sorted(stage_dict.items(), key=lambda item: (-item[1],item[0]))]

 

해설

더보기

처음에 stages.count(i)/ppl 이걸 round(stages.count(i)/ppl,2) 로 해놓은 채로 하다가 사람 수가 0일 때를 고려 안 한 걸 뒤늦게 에러로 알아서 고쳤는데 자꾸 틀리길래 다른 사람들거 봐도 다른 게 없는데 싶다가 혹시나 하고 round 푸니까 바로 되었는데… 바보였다..

 

점수 : 1396(+4)

 


 

[1차] 다트 게임

link : https://school.programmers.co.kr/learn/courses/30/lessons/17682

 

문제 설명

카카오톡에 뜬 네 번째 별! 심심할 땐? 카카오톡 게임별~

카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.

  1. 다트 게임은 총 3번의 기회로 구성된다.
  2. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
  3. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수 , 점수 , 점수 )으로 계산된다.2
  4. 3
  5. 1
  6. 옵션으로 스타상() , 아차상(`#`)이 존재하며 스타상() 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
  7. 스타상()은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상()의 점수만 2배가 된다. (예제 4번 참고)
  8. 스타상()의 효과는 다른 스타상()의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(``) 점수는 4배가 된다. (예제 4번 참고)
  9. 스타상(``)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
  10. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
  11. 스타상(``), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.

0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.

 

입력 형식

"점수|보너스|[옵션]"으로 이루어진 문자열 3세트.예) 1S2D*3T

  • 점수는 0에서 10 사이의 정수이다.
  • 보너스는 S, D, T 중 하나이다.
  • 옵선은 *이나 # 중 하나이며, 없을 수도 있다.

 

출력 형식

3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다.예) 37

 

입출력 예제

예제 dartResult  answer  설명
1 1S2D*3T 37 11 * 2 + 22 * 2 + 33
2 1D2S#10S 9 12 + 21 * (-1) + 101
3 1D2S0T 3 12 + 21 + 03
4 1S2T3S 23 11 * 2 * 2 + 23 * 2 + 31
5 1D#2S*3S 5 12 * (-1) * 2 + 21 * 2 + 31
6 1T2D3D# -4 13 + 22 + 32 * (-1)
7 1D2S3T* 59 12 + 21 * 2 + 33 * 2

 

 

코드 제출 :

# 제출
import re
def solution(dartResult):
    prize = {'S':1,'D':2,'T':3}
    option = {'': 1, '*': 2, '#': -1}
    p = re.compile('(\d+)([SDT])([*#]?)')
    dartResult = p.findall(dartResult)
    for i in range(len(dartResult)):
        n, p, o = dartResult[i]
        if o == '*' and i != 0:
            dartResult[i-1] = dartResult[i-1]*2
        dartResult[i] = (int(n)**prize[p]) * option[o]

    return sum(dartResult)

 

해설

더보기

하다가 자꾸 애매해져서 그냥 re를 써서 (\d+) : 숫자 1자리 이상, (SDT) : S나D나T를 한 그룹, ([*#]?) : *나 #이 있을 수도 있고 없어도 됨으로 해서 3개의 그룹으로 쪼개지도록 re.compile처리해서 findall로 list의 요소로 쪼갠 다음에 for로 돌려서 tuple로 되어있는 걸 각 변수로 받고, SDT와 옵션인 *,#를 dict으로 처리해서 숫자로서 덮어씌운 다음에 sum처리.

그리고 0일 경우 i-1 하니까 가장 마지막 걸 불러와서 조건에 0이 아닐 경우로 한정하여 처리.

 

점수 : 1398(+2)

 


 

과일 장수

link : https://school.programmers.co.kr/learn/courses/30/lessons/135808

 

문제 설명

과일 장수가 사과 상자를 포장하고 있습니다. 사과는 상태에 따라 1점부터 k점까지의 점수로 분류하며, k점이 최상품의 사과이고 1점이 최하품의 사과입니다. 사과 한 상자의 가격은 다음과 같이 결정됩니다.

  • 한 상자에 사과를 m개씩 담아 포장합니다.
  • 상자에 담긴 사과 중 가장 낮은 점수가 p (1 ≤ p ≤ k)점인 경우, 사과 한 상자의 가격은 p * m 입니다.

과일 장수가 가능한 많은 사과를 팔았을 때, 얻을 수 있는 최대 이익을 계산하고자 합니다.(사과는 상자 단위로만 판매하며, 남는 사과는 버립니다)

예를 들어, k = 3, m = 4, 사과 7개의 점수가 [1, 2, 3, 1, 2, 3, 1]이라면, 다음과 같이 [2, 3, 2, 3]으로 구성된 사과 상자 1개를 만들어 판매하여 최대 이익을 얻을 수 있습니다.

  • (최저 사과 점수) x (한 상자에 담긴 사과 개수) x (상자의 개수) = 2 x 4 x 1 = 8

사과의 최대 점수 k, 한 상자에 들어가는 사과의 수 m, 사과들의 점수 score가 주어졌을 때, 과일 장수가 얻을 수 있는 최대 이익을 return하는 solution 함수를 완성해주세요.

제한사항

  • 3 ≤ k ≤ 9
  • 3 ≤ m ≤ 10
  • 7 ≤ score의 길이 ≤ 1,000,000
    • 1 ≤ score[i] ≤ k
  • 이익이 발생하지 않는 경우에는 0을 return 해주세요.

입출력 예

score  result
3 4 [1, 2, 3, 1, 2, 3, 1] 8
4 3 [4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2] 33

 

 

코드 제출 :

# 제출
def solution(k, m, score):
    score = sorted(score, reverse=True)
    tmp = [score[i:i+m] for i in range(0,len(score),m) if len(score[i:i+m]) == m]
    return sum([min(apple)*m*1 for apple in tmp])

 

해설

더보기

score를 reversed sort하고 range로 m의 글자 갯수마다 뛰어넘는 걸 slicing으로 묶으면서 사과가 갯수에 맞을 때만 넣도록 하고 그걸 다시 맞는 점수로 한 걸 sum처리

# 다른 사람 풀이
def solution(k, m, score):
    return sum(sorted(score)[len(score)%m::m])*m

# k,m,score = 3,4,[1, 2, 3, 1, 2, 3, 1]
k,m,score =  4, 3, [4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2]
solution(k, m, score)

다른 사람 풀이 보고 똑똑하다 싶었는데, sorted(score)[len(score)%m::m]) 이거를 분석하면 sorted한 내용에서 score의 길이에서 %m한 숫자부터 시작함으로서 앞의 적은 건 버리고 딱 맞아 떨어지는 수부터 시작해서 m까지 자르게 하면 각각 상자의 갯수만 큼의 첫 수이자 가장 작은 수가 나오면서 이를 곱하고 한 상자에 들어가는 m을 곱하면 결과가 나오는 걸 배움.

 

점수 : 1400(+2)

 


 

명예의 전당 (1)

link : https://school.programmers.co.kr/learn/courses/30/lessons/138477

 

문제 설명

"명예의 전당"이라는 TV 프로그램에서는 매일 1명의 가수가 노래를 부르고, 시청자들의 문자 투표수로 가수에게 점수를 부여합니다. 매일 출연한 가수의 점수가 지금까지 출연 가수들의 점수 중 상위 k번째 이내이면 해당 가수의 점수를 명예의 전당이라는 목록에 올려 기념합니다. 즉 프로그램 시작 이후 초기에 k일까지는 모든 출연 가수의 점수가 명예의 전당에 오르게 됩니다. k일 다음부터는 출연 가수의 점수가 기존의 명예의 전당 목록의 k번째 순위의 가수 점수보다 더 높으면, 출연 가수의 점수가 명예의 전당에 오르게 되고 기존의 k번째 순위의 점수는 명예의 전당에서 내려오게 됩니다.

이 프로그램에서는 매일 "명예의 전당"의 최하위 점수를 발표합니다. 예를 들어, k = 3이고, 7일 동안 진행된 가수의 점수가 [10, 100, 20, 150, 1, 100, 200]이라면, 명예의 전당에서 발표된 점수는 아래의 그림과 같이 [10, 10, 10, 20, 20, 100, 100]입니다.

명예의 전당 목록의 점수의 개수 k, 1일부터 마지막 날까지 출연한 가수들의 점수인 score가 주어졌을 때, 매일 발표된 명예의 전당의 최하위 점수를 return하는 solution 함수를 완성해주세요.

 

제한사항

  • 3 ≤ k ≤ 100
  • 7 ≤ score의 길이 ≤ 1,000
    • 0 ≤ score[i] ≤ 2,000

입출력 예

score  result
3 [10, 100, 20, 150, 1, 100, 200] [10, 10, 10, 20, 20, 100, 100]
4 [0, 300, 40, 300, 20, 70, 150, 50, 500, 1000] [0, 0, 0, 0, 20, 40, 70, 70, 150, 300]

 

 

코드 제출 :

# 제출
def solution(k, score):
    answer = []
    fame  = []
    for s in score:
        fame.append(s)
        fame = sorted(fame, reverse=True)[:k]
        answer.append(fame[-1])
    return answer

 

해설

더보기

처음에 문제 이해를 잘 못하다가 fame명예의 전당에 k 갯수 유지하는 거랑 최하위를 아래로 넣고 역순으로 정렬한 거에서 위에서부터 k번째까지 자른다는 것만 이해하고 구현에 대해 헷갈려 하다가 남들이 한 질문 속 코드를 보고 정리되어 두 번 만에 성공.

다른 사람들 풀이 중에서 heapq를 이용한 걸 봤는데 개인적으로는 나쁘진 않지만 지금으로선 내가 이해한 방식으로 푸는 게 맞는 듯.

# 다른 사람 풀이
import heapq

def solution(k, score):
    max_heap = []
    answer = []

    for sc in score:
        heapq.heappush(max_heap, (-sc, sc))
        answer.append(max(heapq.nsmallest(k, max_heap))[1])

    return answer

 

 

점수 : 1401(+1)

 

 


로또의 최고 순위와 최저 순위

link : https://school.programmers.co.kr/learn/courses/30/lessons/77484

 

문제 설명

로또 6/45(이하 '로또'로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. [1]

순위  당첨 내용
1 6개 번호가 모두 일치
2 5개 번호가 일치
3 4개 번호가 일치
4 3개 번호가 일치
5 2개 번호가 일치
6(낙첨) 그 외

로또를 구매한 민우는 당첨 번호 발표일을 학수고대하고 있었습니다. 하지만, 민우의 동생이 로또에 낙서를 하여, 일부 번호를 알아볼 수 없게 되었습니다. 당첨 번호 발표 후, 민우는 자신이 구매했던 로또로 당첨이 가능했던 최고 순위와 최저 순위를 알아보고 싶어 졌습니다.알아볼 수 없는 번호를 0으로 표기하기로 하고, 민우가 구매한 로또 번호 6개가 44, 1, 0, 0, 31 25라고 가정해보겠습니다. 당첨 번호 6개가 31, 10, 45, 1, 6, 19라면, 당첨 가능한 최고 순위와 최저 순위의 한 예는 아래와 같습니다.

당첨 번호  31  10  45  19  결과
최고 순위 번호 31 0→10 44 1 0→6 25 4개 번호 일치, 3등
최저 순위 번호 31 0→11 44 1 0→7 25 2개 번호 일치, 5등
  • 순서와 상관없이, 구매한 로또에 당첨 번호와 일치하는 번호가 있으면 맞힌 걸로 인정됩니다.
  • 알아볼 수 없는 두 개의 번호를 각각 10, 6이라고 가정하면 3등에 당첨될 수 있습니다.
    • 3등을 만드는 다른 방법들도 존재합니다. 하지만, 2등 이상으로 만드는 것은 불가능합니다.
  • 알아볼 수 없는 두 개의 번호를 각각 11, 7이라고 가정하면 5등에 당첨될 수 있습니다.
    • 5등을 만드는 다른 방법들도 존재합니다. 하지만, 6등(낙첨)으로 만드는 것은 불가능합니다.

민우가 구매한 로또 번호를 담은 배열 lottos, 당첨 번호를 담은 배열 win_nums가 매개변수로 주어집니다. 이때, 당첨 가능한 최고 순위와 최저 순위를 차례대로 배열에 담아서 return 하도록 solution 함수를 완성해주세요.

입출력 예

lottos  win_nums  result
[44, 1, 0, 0, 31, 25] [31, 10, 45, 1, 6, 19] [3, 5]
[0, 0, 0, 0, 0, 0] [38, 19, 20, 40, 15, 25] [1, 6]
[45, 4, 35, 20, 3, 9] [20, 9, 3, 45, 4, 35] [1, 1]

 

[1]
실제로 사용되는 로또 순위의 결정 방식과는 약간 다르지만, 이 문제에서는 지문에 명시된 대로 로또 순위를 결정하도록 합니다.

 

 

코드 제출 :

# 제출
def solution(lottos, win_nums):
    answer = [0,0]
    rank = {6:1, 5:2, 4:3, 3:4, 2:5, 1:6, 0:6}
    for num in win_nums:
        if num in lottos:
            answer[0] += 1
            answer[1] += 1
    zero = lottos.count(0)
    answer[0] += zero
    return rank[answer[0]],rank[answer[1]]
# 짧게
def solution(lottos, win_nums):
    answer = 0
    rank = {6:1, 5:2, 4:3, 3:4, 2:5, 1:6, 0:6}
    zero = lottos.count(0)
    for num in win_nums:
        if num in lottos:
            answer += 1
    return rank[(answer+zero)],rank[answer]

 

해설

더보기
맞는 갯수를 rank 딕셔너리로 설정 후 맞는 최소 갯수와 0의 갯수를 count한 다음에 각각 리스트로 반환

 

점수 : 1402(+1)

 


체육복

link : https://school.programmers.co.kr/learn/courses/30/lessons/42862

 

문제 설명

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.

전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • 전체 학생의 수는 2명 이상 30명 이하입니다.
  • 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
  • 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

입출력 예

lost  reserve  return
5 [2, 4] [1, 3, 5] 5
5 [2, 4] [3] 4
3 [3] [1] 2

 

 

코드 제출 :

# 제출
def solution(n, lost, reserve):
    reserve = set(sorted(reserve))
    lost = set(sorted(lost))
    reserve_lost = reserve - lost
    lost_reserve = lost - reserve
    for i in reserve_lost:
        if i-1 in lost_reserve:
            lost_reserve.remove(i-1)
        elif i+1 in lost_reserve:
            lost_reserve.remove(i+1)
    return n-len(lost_reserve)

 

해설

더보기

처음에 "여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다." 이 문구를 신경 못쓰고

def solution(n, lost, reserve):
    lost = sorted(lost)
    for i in sorted(reserve):
        if i-1 in lost:
            lost.remove(i-1)
        elif i+1 in lost:
            lost.remove(i+1)
        elif i in lost:
            lost.remove(i)
    return n-len(lost)

이렇게 했다가 5,12,24 실패하고 n, lost, reserve = 5, [4, 2], [3, 5] 처럼 순서 안 맞는 거랑 n, lost, reserve = 5, [2, 4], [1, 4, 5] 같은 케이스 처리하니 해결됨.

 

점수 : 1407(+5)

 


완주하지 못한 선수

link : https://school.programmers.co.kr/learn/courses/30/lessons/42576

 

문제 설명

수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다.

마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수들의 이름이 담긴 배열 completion이 주어질 때, 완주하지 못한 선수의 이름을 return 하도록 solution 함수를 작성해주세요.

 

제한사항

  • 마라톤 경기에 참여한 선수의 수는 1명 이상 100,000명 이하입니다.
  • completion의 길이는 participant의 길이보다 1 작습니다.
  • 참가자의 이름은 1개 이상 20개 이하의 알파벳 소문자로 이루어져 있습니다.
  • 참가자 중에는 동명이인이 있을 수 있습니다.

입출력 예

participant  completion  return
["leo", "kiki", "eden"] ["eden", "kiki"] "leo"
["marina", "josipa", "nikola", "vinko", "filipa"] ["josipa", "filipa", "marina", "nikola"] "vinko"
["mislav", "stanko", "mislav", "ana"] ["stanko", "ana", "mislav"] "mislav"

 

 

코드 제출 :

# 제출
def solution(participant, completion):
    completion.sort()
    participant.sort()
    for i in range(len(completion)):
        if completion[i] != participant[i]:
            return participant[i]
    return participant[-1]

 

해설

더보기

처음에는 간단하게 생각해서

def solution(participant, completion):
    part = sorted(participant)
    for i in range(len(completion)):
        if completion[i] in participant:
            part.remove(completion[i])
    return part[0]

이렇게 했더니 정확도는 문제 없는데 시간 초과가 나서 보면 sorted하고 또 for문 안에 remove 돌리니까 그런가 싶어서 set으로 했더니 동명이인이 아예 날라가 버림.. 그래서 어차피 비교하는 거 sort를 각각 하고 비교문으로 같지 않으면 return을 하고 그게 아니면 결국 가장 마지막에 남은 사람이 완주 못했다는 걸로 이해해서 잡았더니 되긴 했으나

# 다른 사람 풀이
import collections

def solution(participant, completion):
    answer = collections.Counter(participant) - collections.Counter(completion)
    return list(answer.keys())[0]

collections의 Counter 객체 끼리 연산 되는 거 이제 기억함..:0

 

점수 : 1408(+1)

 


숫자 짝꿍

link : https://school.programmers.co.kr/learn/courses/30/lessons/131128

 

문제 설명

두 정수 X, Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 ≤ k ≤ 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(단, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다). X, Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다. X, Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다.

예를 들어, X = 3403이고 Y = 13203이라면, X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로 X = 5525이고 Y = 1255이면 X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5가 3개, Y에는 5가 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.)두 정수 X, Y가 주어졌을 때, X, Y의 짝꿍을 return하는 solution 함수를 완성해주세요.

 

제한사항

  • 3 ≤ X, Y의 길이(자릿수) ≤ 3,000,000입니다.
  • X, Y는 0으로 시작하지 않습니다.
  • X, Y의 짝꿍은 상당히 큰 정수일 수 있으므로, 문자열로 반환합니다.

입출력 예

result
"100" "2345" "-1"
"100" "203045" "0"
"100" "123450" "10"
"12321" "42531" "321"
"5525" "1255" "552"

 

 

코드 제출 :

# 제출
from collections import Counter

def solution(X, Y):
    answer = Counter(X) & Counter(Y)
    if len(answer) == 0:
        return '-1'
    elif (len(answer.keys()) == 1) and ('0' in answer.keys()):
        return '0'
    else:
        return ''.join([k*v for k,v in sorted(answer.items(), key=lambda item: -int(item[0]))])

 

해설

더보기

Counter 객체의 연산이 set 연산도 되는 걸 기억해서 교집합으로 찾은 다음에 조건으로서 빈 값이면 -1을, 값이 0만 여러개면 0 한 개만을 나머지는 dict의 sort를 오름차순으로 join처리 한 것.

 

점수 : 1413(+5)

 


기사단원의 무기

link : https://school.programmers.co.kr/learn/courses/30/lessons/136798

 

문제 설명

숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다.

각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.

예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다.

기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.

 

제한사항

  • 1 ≤ number ≤ 100,000
  • 2 ≤ limit ≤ 100
  • 1 ≤ power ≤ limit

 

입출력 예

number  limit  power  result
5 3 2 10
10 3 2 21

 

코드 제출 :

# 제출
def get_divisor(n):
    n = int(n)
    divisors = []
    divisors_back = []

    for i in range(1, int(n**(1/2)) + 1):
        if (n % i == 0):
            divisors.append(i)
            if (i != (n // i)):
                divisors_back.append(n//i)

    return divisors + divisors_back[::-1]

def solution(number, limit, power):
    tmp = [len(get_divisor(num)) for num in range(1, number+1)]
    for n in range(len(tmp)):
        if tmp[n] > limit:
            tmp[n] = power
    return sum(tmp)

 

해설

더보기

원래 기존의 약수를 반환하는 함수의 기본적으로는 [i for i in range(1, n+1) if n % i == 0] 를 썼지만 O(n)의 시간복잡도를 가져서 지금의 문제처럼 100000 의 크기일 경우 당연하게도 시간초과가 났다. 그래서 구현된 로직자체는 문제가 없지만 결국 get_divisor 함수의 시간복잡도를 줄여야 한다는 결론이 나서 약수 구하는 부분으로 효율성을 검색하다가 탐색공간의_배제 이 글을 보고 함수를 수정했더니 성공함. 사실 이전의 에라토스테네스의 체의 ver2처럼 제곱근으로 줄여서 진행하는 부분과 결은 비슷하다는 걸 깨달았다.

 

점수 : 1418(+5)

 


옹알이 (2)

link : https://school.programmers.co.kr/learn/courses/30/lessons/133499

 

문제 설명

머쓱이는 태어난 지 11개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음과 네 가지 발음을 조합해서 만들 수 있는 발음밖에 하지 못하고 연속해서 같은 발음을 하는 것을 어려워합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.

 

제한사항

  • 1 ≤ babbling의 길이 ≤ 100
  • 1 ≤ babbling[i]의 길이 ≤ 30
  • 문자열은 알파벳 소문자로만 이루어져 있습니다.

입출력 예

babbling  result
["aya", "yee", "u", "maa"] 1
["ayaye", "uuu", "yeye", "yemawoo", "ayaayaa"] 2

 

 

코드 제출 :

# 제출
def solution(babbling):
    answer = 0
    pron = ["aya", "ye", "woo", "ma"]
    for b in babbling:
        for i in range(len(pron)):
            if pron[i] in b:
                b = b.replace(pron[i], str(i))
        if ('00' in b) or ('11' in b) or ('22' in b) or ('33' in b):
            continue
        if b.isdigit():
            answer += 1
    return answer

 

해설

더보기

이해했던 부분은 ["aya", "ye", "woo", "ma"]에서 연속된 발음은 지나가야 하고 해당 발음 가능한 배열 안의 조합인데 이번엔 permutation을 쓰지 않고 해보는 방법으로 찾다가 결국 이중 for문을 써야겠다는 부분은 어쩔 수 없었다. babbling도 for문을 돌려야 하고 pron으로서 발음 가능한 것도 loop라서.

아무튼, 해당의 것을 조합할 때 패턴으로 뭐 잡지 하다가 index 번호로 돌리던 걸 인덱스 번호로 변환 시켜서 0,1,2,3이면 결국 00,01,02,03,10,11 이런 식으로 문자열끼리 더해서 조합이 되면 00,11,22,33만 뺀 문자열 숫자면 된다는 걸 다른사람 질문 보고 깨달았다.(dict으로 하시던 거 같던데)

그래서 바로 replace로 index 번호 문자열로 전부 바꾸고 00,11,22,33이면 continue를, 이외에 isdigit으로 01,23 등 다른 숫자 조합의 문자열이면 answer를 추가해서 해결. 바로바로 구현 안 나오는 거 보면 아직 좀 멀긴 함.

다만 다른 풀이들은 대부분 연속되지 않은 발음에 한하여 replace로 빈 칸을 만든 다름에 strip로 제거해서 공백이 된다면 다른 조합 이라는 뜻이므로 카운트 하는 방식인 걸 깨달음.. 저런 방식도 있었지..ㅠㅠ

다른 분 풀이 : https://khomep.shop/프로그래머스lv1-옹알이2-문제파이썬/

 

점수 : 1423(+5)

 


카드 뭉치

link : https://school.programmers.co.kr/learn/courses/30/lessons/159994

 

문제 설명

코니는 영어 단어가 적힌 카드 뭉치 두 개를 선물로 받았습니다. 코니는 다음과 같은 규칙으로 카드에 적힌 단어들을 사용해 원하는 순서의 단어 배열을 만들 수 있는지 알고 싶습니다.

  • 원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
  • 한 번 사용한 카드는 다시 사용할 수 없습니다.
  • 카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
  • 기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.

예를 들어 첫 번째 카드 뭉치에 순서대로 ["i", "drink", "water"], 두 번째 카드 뭉치에 순서대로 ["want", "to"]가 적혀있을 때 ["i", "want", "to", "drink", "water"] 순서의 단어 배열을 만들려고 한다면 첫 번째 카드 뭉치에서 "i"를 사용한 후 두 번째 카드 뭉치에서 "want"와 "to"를 사용하고 첫 번째 카드뭉치에 "drink"와 "water"를 차례대로 사용하면 원하는 순서의 단어 배열을 만들 수 있습니다.

문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때, cards1과 cards2에 적힌 단어들로 goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를 return하는 solution 함수를 완성해주세요.

 

제한사항

  • 1 ≤ cards1의 길이, cards2의 길이 ≤ 10
    • 1 ≤ cards1[i]의 길이, cards2[i]의 길이 ≤ 10
    • cards1과 cards2에는 서로 다른 단어만 존재합니다.
  • 2 ≤ goal의 길이 ≤ cards1의 길이 + cards2의 길이
    • 1 ≤ goal[i]의 길이 ≤ 10
    • goal의 원소는 cards1과 cards2의 원소들로만 이루어져 있습니다.
  • cards1, cards2, goal의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.

입출력 예

cards1  cards2  goal  result
["i", "drink", "water"] ["want", "to"] ["i", "want", "to", "drink", "water"] "Yes"
["i", "water", "drink"] ["want", "to"] ["i", "want", "to", "drink", "water"] "No"

 

 

코드 제출 :

# 제출
def solution(cards1, cards2, goal):
    answer = 'Yes'
    for i in range(len(goal)):
        print(i, cards1, cards2, goal)
        if cards1 and cards1[0] == goal[0]:
            cards1.pop(0)
            goal.pop(0)
        elif cards2 and cards2[0] == goal[0]:
            cards2.pop(0)
            goal.pop(0)
        else:
            answer = 'No'
            break
    return answer

 

해설

더보기

카드를 한 장씩 사용하고 한 번 사용한 카드는 다시 사용할 수 없다 하길래 pop으로 버려도 될 거 같아서 앞 순서부터 버리되 card1을 먼저 사용하고 안되면 elif로 그다음에 인식하게 해서 각자의 앞에서부터 버리고 전체 순서가 맞으면 Yes 하나라도 틀리면 No로 반환 처리. 처음에는 번갈아서 for문 돌리는 식을 하려고 했다가 실패해서 pop으로 한 걸 봐서 처리.

 

점수 : 1424(+1)

 


 

키패드 누르기

link : https://school.programmers.co.kr/learn/courses/30/lessons/67256

 

문제 설명

스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.

이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.

  1. 엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
  2. 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
  3. 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
  4. 가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.

순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

 

[제한사항]

  • numbers 배열의 크기는 1 이상 1,000 이하입니다.
  • numbers 배열 원소의 값은 0 이상 9 이하인 정수입니다.
  • hand는 "left" 또는 "right" 입니다.
    • "left"는 왼손잡이, "right"는 오른손잡이를 의미합니다.
  • 왼손 엄지손가락을 사용한 경우는 L, 오른손 엄지손가락을 사용한 경우는 R을 순서대로 이어붙여 문자열 형태로 return 해주세요.

입출력 예

numbers  hand  result
[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] "right" "LRLLLRLLRRL"
[7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] "left" "LRLLRRLLLRR"
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0] "right" "LLRLLRLLRL"

 

 

코드 제출 :

# 제출
def solution(numbers, hand):
    answer = ''
    pos = [10,12]
    for n in numbers:
        if n in [1,4,7]:
            pos[0]=n
            answer+='L'
        elif n in [3,6,9]:
            pos[1]=n
            answer+='R'
        else:
            n = 11 if n == 0 else n
            absL = abs(n-pos[0])
            absR = abs(n-pos[1])
            if sum(divmod(absL, 3)) == sum(divmod(absR, 3)):
                if hand == 'left':
                    pos[0] = n
                    answer += 'L'
                else:
                    pos[1] = n
                    answer += 'R'
            elif sum(divmod(absL, 3)) > sum(divmod(absR, 3)):
                pos[1] = n
                answer += 'R'
            else:
                pos[0] = n
                answer += 'L'
    return answer

 

해설

더보기

처음에는 단순하게 왼쪽, 중앙, 오른쪽 배열과 시작점의 문자열 ['*','#'] 을 가지고 하다가 초반에 시작점에서 0 과의 연산 등 문자열과 연산이 안 되는 경우를 발견해서 아예 다시 문자열도 숫자로 바꿔서 데이터 타입부터 통일하자 싶어서 그냥 쭉 1부터 쭉 쓰니까

# [1 2 3] --> [1 2 3]
# [4 5 6] --> [4 5 6]
# [7 8 9] --> [7 8 9]
# [* 0 #] --> [10 11 12]

위와 같이 되었고, 또 계산을 해보니까 위 아래는 3씩 차이가 나지만 양쪽으로는 1씩 차이나는 것을 알게 됨. 결국 위아래는 3으로 나누면 몫이 1이 되는 것이고 좌우는 3로 나눴을 때의 나머지인 셈이 되어서 divmod를 이용함. divmod를 쓰면 몫과 나머지 한꺼번에 나오니까 결국 먼 거리인지는 몫과 나머지의 합이 더 크면 더 먼 것으로 확인할 수 있음.

그래서 우선은 왼쪽 배열에 속하는 [1,4,7]과 오른쪽 배열에 속하는 [3,6,9]로 먼저 조건을 걸고, 0일 경우는 11로 전환한 다음에 번호인 n에서 현제 위치와의 차의 절대값을 구하고 거기서 위에서 언급한 divmod의 합을 좌, 우 비교해서 먼저 같으면 hand에 따라 처리하고 아니면 거리가 가까운 것에 따라 다시 처리하여 가까스로 해결.. 이거 하는데 틈틈히 했던 터라 집중 자꾸 깨져서 하루 넘김..

 

점수 : 1425(+1)

 


 

바탕화면 정리

link : https://school.programmers.co.kr/learn/courses/30/lessons/161990 

 

 

문제 설명

코딩테스트를 준비하는 머쓱이는 프로그래머스에서 문제를 풀고 나중에 다시 코드를 보면서 공부하려고 작성한 코드를 컴퓨터 바탕화면에 아무 위치에나 저장해 둡니다. 저장한 코드가 많아지면서 머쓱이는 본인의 컴퓨터 바탕화면이 너무 지저분하다고 생각했습니다. 프로그래머스에서 작성했던 코드는 그 문제에 가서 다시 볼 수 있기 때문에 저장해 둔 파일들을 전부 삭제하기로 했습니다. 컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다. 드래그는 바탕화면의 격자점 S(lux, luy)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdx, rdy)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다. 점 S(lux, luy)에서 점 E(rdx, rdy)로 드래그를 할 때, "드래그 한 거리"는 |rdx - lux| + |rdy - luy|로 정의합니다. 점 S에서 점 E로 드래그를 하면 바탕화면에서 두 격자점을 각각 왼쪽 위, 오른쪽 아래로 하는 직사각형 내부에 있는 모든 파일이 선택됩니다. 예를 들어 wallpaper = [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다.

https://school.programmers.co.kr/learn/courses/30/lessons/161990

이러한 바탕화면에서 다음 그림과 같이 S(0, 1)에서 E(3, 4)로 드래그하면 세 개의 파일이 모두 선택되므로 드래그 한 거리 (3 - 0) + (4 - 1) = 6을 최솟값으로 모든 파일을 선택 가능합니다.

https://school.programmers.co.kr/learn/courses/30/lessons/161990

(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.<br> 머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux, luy), 끝점이 (rdx, rdy)라면 정수 배열 [lux, luy, rdx, rdy]를 return하면 됩니다.

 

 

제한사항

1 ≤ wallpaper의 길이 ≤ 50 1 ≤ wallpaper[i]의 길이 ≤ 50 wallpaper의 모든 원소의 길이는 동일합니다. wallpaper[i][j]는 바탕화면에서 i + 1행 j + 1열에 해당하는 칸의 상태를 나타냅니다. wallpaper[i][j]는 "#" 또는 "."의 값만 가집니다. 바탕화면에는 적어도 하나의 파일이 있습니다. 드래그 시작점 (lux, luy)와 끝점 (rdx, rdy)는 lux < rdx, luy < rdy를 만족해야 합니다.

 

입출력 예

wallpaper  result
[".#...", "..#..", "...#."] [0, 1, 3, 4]
["..........", ".....#....", "......##..", "...##.....", "....#....."] [1, 3, 5, 8]
[".##...##.", "#..#.#..#", "#...#...#", ".#.....#.", "..#...#..", "...#.#...", "....#...."] [0, 0, 7, 9]
["..", "#."] [1, 0, 2, 1]

 

 

코드 제출 :

# 제출
def solution(wallpaper):
    min_row, max_row, min_col, max_col = 100,0,100,0
    for i, v1 in enumerate(wallpaper):
        for j, v2 in enumerate(v1):
            if v2 == "#":
                min_row = min(i,min_row)
                max_row = max(i,max_row)
                min_col = min(j,min_col)
                max_col = max(j,max_col)
    return [min_row, min_col, max_row+1, max_col+1]

 

해설

더보기

for loop 문을 이중으로 써도 되겠다 싶었음. 최대 값 50이고 greedy 처럼 전체 탐색을 해서 열과 행의 최소, 최대값을 찾는 문제로서 이해.

enumerate로 index와 값을 찾으면서 조건을 찾으면 min, max를 찾아놓고, max의 경우 좌표가 파일의 시작점이라서 실질적으로 포함하려면 max값은 +1을 해야 함.

 

점수 : 1426 (+1)

 


 

공원 산책

link : https://school.programmers.co.kr/learn/courses/30/lessons/172928

 

문제 설명

코딩테스트를 준비하는 머쓱이는 프로그래머스에서 문제를 풀고 나중에 다시 코드를 보면서 공부하려고 작성한 코드를 컴퓨터 바탕화면에 아무 위치에나 저장해 둡니다. 저장한 코드가 많아지면서 머쓱이는 본인의 컴퓨터 바탕화면이 너무 지저분하다고 생각했습니다. 프로그래머스에서 작성했던 코드는 그 문제에 가서 다시 볼 수 있기 때문에 저장해 둔 파일들을 전부 삭제하기로 했습니다.

컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다.

  • 드래그는 바탕화면의 격자점 S(lux, luy)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdx, rdy)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다.
  • 점 S(lux, luy)에서 점 E(rdx, rdy)로 드래그를 할 때, "드래그 한 거리"는 |rdx - lux| + |rdy - luy|로 정의합니다.
  • 점 S에서 점 E로 드래그를 하면 바탕화면에서 두 격자점을 각각 왼쪽 위, 오른쪽 아래로 하는 직사각형 내부에 있는 모든 파일이 선택됩니다.

예를 들어

= [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다.

이러한 바탕화면에서 다음 그림과 같이 S(0, 1)에서 E(3, 4)로 드래그하면 세 개의 파일이 모두 선택되므로 드래그 한 거리 (3 - 0) + (4 - 1) = 6을 최솟값으로 모든 파일을 선택 가능합니다.

(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.

머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux, luy), 끝점이 (rdx, rdy)라면 정수 배열 [lux, luy, rdx, rdy]를 return하면 됩니다.

제한사항

  • 1 ≤ wallpaper의 길이 ≤ 50
  • 1 ≤ wallpaper[i]의 길이 ≤ 50
    • wallpaper의 모든 원소의 길이는 동일합니다.
  • wallpaper[i][j]는 바탕화면에서 i + 1행 j + 1열에 해당하는 칸의 상태를 나타냅니다.
  • wallpaper[i][j]는 "#" 또는 "."의 값만 가집니다.
  • 바탕화면에는 적어도 하나의 파일이 있습니다.
  • 드래그 시작점 (lux, luy)와 끝점 (rdx, rdy)는 lux < rdx, luy < rdy를 만족해야 합니다.

입출력 예

wallpaper  result
[".#...", "..#..", "...#."] [0, 1, 3, 4]
["..........", ".....#....", "......##..", "...##.....", "....#....."] [1, 3, 5, 8]
[".##...##.", "#..#.#..#", "#...#...#", ".#.....#.", "..#...#..", "...#.#...", "....#...."] [0, 0, 7, 9]
["..", "#."] [1, 0, 2, 1]

 

 

코드 제출 :

# 제출
def solution(wallpaper):
    min_row, max_row, min_col, max_col = 100,0,100,0
    for i, v1 in enumerate(wallpaper):
        for j, v2 in enumerate(v1):
            if v2 == "#":
                min_row = min(i,min_row)
                max_row = max(i,max_row)
                min_col = min(j,min_col)
                max_col = max(j,max_col)
    return [min_row, min_col, max_row+1, max_col+1]

 

해설

더보기

for loop 문을 이중으로 써도 되겠다 싶었음. 최대 값 50이고 greedy 처럼 전체 탐색을 해서 열과 행의 최소, 최대값을 찾는 문제로서 이해.

enumerate로 index와 값을 찾으면서 조건을 찾으면 min, max를 찾아놓고, max의 경우 좌표가 파일의 시작점이라서 실질적으로 포함하려면 max값은 +1을 해야 함.


자꾸 늦게 올리네..ㅠㅠ 몇 개 안 남았는데..플젝..