[Python] 알고리즘 연습 14 (프로그래머스)

Lake·2024년 5월 23일

Python 문제

목록 보기
14/22
post-thumbnail

대충 만든 자판 (연습문제)

  • 휴대폰의 자판은 컴퓨터 키보드 자판과는 다르게 하나의 키에 여러 개의 문자가 할당될 수 있습니다. 키 하나에 여러 문자가 할당된 경우, 동일한 키를 연속해서 빠르게 누르면 할당된 순서대로 문자가 바뀝니다.

    예를 들어, 1번 키에 "A", "B", "C" 순서대로 문자가 할당되어 있다면 1번 키를 한 번 누르면 "A", 두 번 누르면 "B", 세 번 누르면 "C"가 되는 식입니다.

    같은 규칙을 적용해 아무렇게나 만든 휴대폰 자판이 있습니다. 이 휴대폰 자판은 키의 개수가 1개부터 최대 100개까지 있을 수 있으며, 특정 키를 눌렀을 때 입력되는 문자들도 무작위로 배열되어 있습니다. 또, 같은 문자가 자판 전체에 여러 번 할당된 경우도 있고, 키 하나에 같은 문자가 여러 번 할당된 경우도 있습니다. 심지어 아예 할당되지 않은 경우도 있습니다. 따라서 몇몇 문자열은 작성할 수 없을 수도 있습니다.

    이 휴대폰 자판을 이용해 특정 문자열을 작성할 때, 키를 최소 몇 번 눌러야 그 문자열을 작성할 수 있는지 알아보고자 합니다.

    1번 키부터 차례대로 할당된 문자들이 순서대로 담긴 문자열배열 keymap과 입력하려는 문자열들이 담긴 문자열 배열 targets가 주어질 때, 각 문자열을 작성하기 위해 키를 최소 몇 번씩 눌러야 하는지 순서대로 배열에 담아 return 하는 solution 함수를 완성해 주세요.

    단, 목표 문자열을 작성할 수 없을 때는 -1을 저장합니다.

    • 제한사항
      • 1 ≤ keymap의 길이 ≤ 100
        • 1 ≤ keymap의 원소의 길이 ≤ 100
        • keymap[i]는 i + 1번 키를 눌렀을 때 순서대로 바뀌는 문자를 의미합니다.
          - 예를 들어 keymap[0] = "ABACD" 인 경우 1번 키를 한 번 누르면 A, 두 번 누르면 B, 세 번 누르면 A 가 됩니다.
        • keymap의 원소의 길이는 서로 다를 수 있습니다.
        • keymap의 원소는 알파벳 대문자로만 이루어져 있습니다.
      • 1 ≤ targets의 길이 ≤ 100
        • 1 ≤ targets의 원소의 길이 ≤ 100
        • targets의 원소는 알파벳 대문자로만 이루어져 있습니다.

제출한 코드 :

def solution(keymap, targets):
    answer = []
    
    for target in targets:
        minkey = 0 
        
        for i in target: 
            c = 101 
            flag = False 
            
            for k in keymap:
                key = k.find(i)
    
                if key == -1: 
                    continue
                c = min(key+1, c) 
                flag = True 
                
            if flag: 
                minkey += c
            else: 
                answer.append(-1)
                break
        else: 
            answer.append(minkey) 
            
    return answer

둘만의 암호 (연습문제)

  • 두 문자열 sskip, 그리고 자연수 index가 주어질 때, 다음 규칙에 따라 문자열을 만들려 합니다. 암호의 규칙은 다음과 같습니다.

문자열 s의 각 알파벳을 index만큼 뒤의 알파벳으로 바꿔줍니다.
index만큼의 뒤의 알파벳이 z를 넘어갈 경우 다시 a로 돌아갑니다.
skip에 있는 알파벳은 제외하고 건너뜁니다.
예를 들어 s = "aukks", skip = "wbqd", index = 5일 때, a에서 5만큼 뒤에 있는 알파벳은 f지만 [b, c, d, e, f]에서 'b'와 'd'는 skip에 포함되므로 세지 않습니다. 따라서 'b', 'd'를 제외하고 'a'에서 5만큼 뒤에 있는 알파벳은 [c, e, f, g, h] 순서에 의해 'h'가 됩니다. 나머지 "ukks" 또한 위 규칙대로 바꾸면 "appy"가 되며 결과는 "happy"가 됩니다.

두 문자열 sskip, 그리고 자연수 index가 매개변수로 주어질 때 위 규칙대로 s를 변환한 결과를 return하도록 solution 함수를 완성해주세요.

  • 제한사항
    • 5 ≤ s의 길이 ≤ 50
    • 1 ≤ skip의 길이 ≤ 10
    • sskip은 알파벳 소문자로만 이루어져 있습니다.
      • skip에 포함되는 알파벳은 s에 포함되지 않습니다.
    • 1 ≤ index ≤ 20

제출한 코드 :

def rotate(aci):
    return (aci - 96) % 26 + 97

def solution(s, skip, index):
    answer = ''

    for c in s:        
        aci = ord(c)
        for i in range(index):
            aci = rotate(aci)
            while chr(aci) in skip:
                aci = rotate(aci)
        ret = chr(aci)
        answer += chr(aci)

    return answer

햄버거 만들기 (연습문제)

  • 햄버거 가게에서 일을 하는 상수는 햄버거를 포장하는 일을 합니다. 함께 일을 하는 다른 직원들이 햄버거에 들어갈 재료를 조리해 주면 조리된 순서대로 상수의 앞에 아래서부터 위로 쌓이게 되고, 상수는 순서에 맞게 쌓여서 완성된 햄버거를 따로 옮겨 포장을 하게 됩니다. 상수가 일하는 가게는 정해진 순서(아래서부터, 빵 – 야채 – 고기 - 빵)로 쌓인 햄버거만 포장을 합니다. 상수는 손이 굉장히 빠르기 때문에 상수가 포장하는 동안 속 재료가 추가적으로 들어오는 일은 없으며, 재료의 높이는 무시하여 재료가 높이 쌓여서 일이 힘들어지는 경우는 없습니다.

    예를 들어, 상수의 앞에 쌓이는 재료의 순서가 [야채, 빵, 빵, 야채, 고기, 빵, 야채, 고기, 빵]일 때, 상수는 여섯 번째 재료가 쌓였을 때, 세 번째 재료부터 여섯 번째 재료를 이용하여 햄버거를 포장하고, 아홉 번째 재료가 쌓였을 때, 두 번째 재료와 일곱 번째 재료부터 아홉 번째 재료를 이용하여 햄버거를 포장합니다. 즉, 2개의 햄버거를 포장하게 됩니다.

    상수에게 전해지는 재료의 정보를 나타내는 정수 배열 ingredient가 주어졌을 때, 상수가 포장하는 햄버거의 개수를 return 하도록 solution 함수를 완성하시오.

    • 제한사항
      • 1 ≤ ingredient의 길이 ≤ 1,000,000
      • ingredient의 원소는 1, 2, 3 중 하나의 값이며, 순서대로 빵, 야채, 고기를 의미합니다.

제출한 코드 :

def solution(ingredient):
    s = []
    cnt = 0
    for i in ingredient:
        s.append(i)
        if s[-4:] == [1, 2, 3, 1]:
            cnt += 1
            for _ in range(4):
                s.pop()
    return cnt

성격 유형 검사하기 (2022 KAKAO TECH INTERNSHIP)

  • 나만의 카카오 성격 유형 검사지를 만들려고 합니다.
    성격 유형 검사는 다음과 같은 4개 지표로 성격 유형을 구분합니다. 성격은 각 지표에서 두 유형 중 하나로 결정됩니다.

    지표 번호 성격 유형
    1번 지표  라이언형(R), 튜브형(T)
    2번 지표  콘형(C), 프로도형(F)
    3번 지표  제이지형(J), 무지형(M)
    4번 지표  어피치형(A), 네오형(N)

    4개의 지표가 있으므로 성격 유형은 총 16(=2 x 2 x 2 x 2)가지가 나올 수 있습니다. 예를 들어, "RFMN"이나 "TCMA"와 같은 성격 유형이 있습니다.

    검사지에는 총 n개의 질문이 있고, 각 질문에는 아래와 같은 7개의 선택지가 있습니다.
    • 매우 비동의
    • 비동의
    • 약간 비동의
    • 모르겠음
    • 약간 동의
    • 동의
    • 매우 동의

      각 질문은 1가지 지표로 성격 유형 점수를 판단합니다.

      예를 들어, 어떤 한 질문에서 4번 지표로 아래 표처럼 점수를 매길 수       있습니다.

      선택지         성격 유형 점수
      매우 비동의  네오형 3점
      비동의         네오형 2점
      약간 비동의  네오형 1점
      모르겠음      어떤 성격 유형도 점수를 얻지 않습니다
      약간 동의     어피치형 1점
      동의            어피치형 2점
      매우 동의     어피치형 3점

      이때 검사자가 질문에서 약간 동의 선택지를 선택할 경우 어피치형(A)       성격 유형 1점을 받게 됩니다. 만약 검사자가 매우 비동의 선택지를       선택할 경우 네오형(N) 성격 유형 3점을 받게 됩니다.

      위 예시처럼 네오형이 비동의, 어피치형이 동의인 경우만 주어지지 않고,       질문에 따라 네오형이 동의, 어피치형이 비동의인 경우도 주어질 수       있습니다.
      하지만 각 선택지는 고정적인 크기의 점수를 가지고 있습니다.

      - 매우 동의매우 비동의 선택지를 선택하면 3점을 얻습니다.
      - 동의비동의 선택지를 선택하면 2점을 얻습니다.
      - 약간 동의약간 비동의 선택지를 선택하면 1점을 얻습니다.
      - 모르겠음 선택지를 선택하면 점수를 얻지 않습니다.

      검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은       점수를 받은 성격 유형이 검사자의 성격 유형이라고 판단합니다. 단,       하나의 지표에서 각 성격 유형 점수가 같으면, 두 성격 유형 중 사전       순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단합니다.

      질문마다 판단하는 지표를 담은 1차원 문자열 배열 survey와 검사자가       각 질문마다 선택한 선택지를 담은 1차원 정수 배열 choices가       매개변수로 주어집니다. 이때, 검사자의 성격 유형 검사 결과를 지표       번호 순서대로 return 하도록 solution 함수를 완성해주세요.

      - 제한사항
        - 1 ≤ survey의 길이 ( = n) ≤ 1,000
          - survey의 원소는 "RT", "TR", "FC", "CF", "MJ", "JM",             "AN","NA" 중 하나입니다.
          - survey[i]의 첫 번째 캐릭터는 i+1번 질문의 비동의 관련             선택지를 선택하면 받는 성격 유형을 의미합니다.
          - survey[i]의 두 번째 캐릭터는 i+1번 질문의 동의 관련 선택지를             선택하면 받는 성격 유형을 의미합니다.
          - choices의 길이 = survey의 길이
            - choices[i]는 검사자가 선택한 i+1번째 질문의 선택지를               의미합니다.
            - 1 ≤ choices의 원소 ≤ 7
              choices 뜻
              1         매우 비동의
              2         비동의
              3         약간 비동의
              4         모르겠음
              5         약간 동의
              6         동의
              7         매우 동의

제출한 코드 :

def solution(survey, choices):
    # 유형별 목록(같은 지표에서는 알파벳 순), score = 카테고리별 획득 점수
    category = ["R","T","C","F","J","M","A","N"]
    score = [0 for str in category]
    answer = ""

    # choices에 따른 점수 부여
    for i in range(len(choices)):
        if 4 < choices[i] <= 7:
            score[category.index(survey[i][-1])] += choices[i]-4

        if choices[i] == 4:
            pass
        if 1 <= choices[i]<4:
            score[category.index(survey[i][0])] += 4 - choices[i]

    # 지표별 최종 유형 결정
    for i in range(len(score) // 2):
        if score[2 * i] >= score[2 * i + 1]:
            answer += category[2 * i]
        else:
            answer += category[2 * i + 1]

    return answer

바탕화면 정리 (연습문제)

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

    컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 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 = [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다.

      이러한 바탕화면에서 다음 그림과 같이 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 + 1j + 1열에 해당하는 칸의 상태를 나타냅니다.
      • wallpaper[i][j]는 "#" 또는 "."의 값만 가집니다.
      • 바탕화면에는 적어도 하나의 파일이 있습니다.
      • 드래그 시작점 (lux, luy)와 끝점 (rdx, rdy)는 lux < rdx, luy < rdy를 만족해야 합니다.

제출한 코드 :

def solution(wallpaper):
    answer = []
    maxx, minx, maxy, miny = 0, 100, 0, 100

    r = len(wallpaper)
    c = len(wallpaper[0])

    for x in range(r):
        for y in range(c):
            if wallpaper[x][y] == "#":
                minx = min(minx, x)
                miny = min(miny, y)
                maxx = max(maxx, x)
                maxy = max(maxy, y)


    return [minx, miny, maxx+1, maxy+1]

0개의 댓글