🧩 Algorithm/프로그래머스

[programmers] 카드 뭉치, 공원 산책, 2개 이하로 다른 비트

nerowiki 2024. 4. 20. 11:08
728x90
💡 오늘의 학습 키워드
- 카드 뭉치
- 공원 산책
- 2개 이하로 다른 비트

 

🥉 카드 뭉치

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/159994

 

문제 설명

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

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

예를 들어 첫 번째 카드 뭉치에 순서대로 ["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. 1 ≤ cards1의 길이, cards2의 길이 ≤ 10
    1-1. 1 ≤ cards1[i]의 길이, cards2[i]의 길이 ≤ 10
    1-2. cards1과 cards2에는 서로 다른 단어만 존재합니다.
2. 2 ≤ goal의 길이 ≤ cards1의 길이 + cards2의 길이
    2-1. 1 ≤ goal[i]의 길이 ≤ 10
    2-2. goal의 원소는 cards1과 cards2의 원소들로만 이루어져 있습니다.
3. cards1, cards2, goal의 문자열들은 모두 알파벳 소문자로만 이루어져 있습니다.

 

문제 회고

💡 어떤 문제가 있었고, 나는 어떤 시도를 했는지 그리고 새롭게 안 사실은 무엇인지

문제 접근을 잘못하여 카드 뭉치들을 완전 탐색하여 어떻게 목표한 문장을 만들지 고민했습니다.
카드 뭉치를 한 장씩 돌아가면서 뽑는 게 아니므로 목표 문장에서 단어를 뽑아 카드 뭉치과 비교해 나가야 합니다.

 

여기서 목표 단어와 카드 뭉치를 비교하는 방식은 다음 2가지가 있습니다.

  1. 인덱스 값 p1, p2를 만들고 1씩 올려가면서 해당 인덱스에 위치한 목표 단어와 카드 뭉치를 비교합니다.
  2. 목표 단어와 카드 뭉치의 인덱스 0에 있는 단어를 비교한 후 일치할 경우 삭제 합니다.

 리스트의 값을 삭제하는 방법으로 remove( ), pop( ), del, slice 4가지 방법이 있습니다.

slice는 리스트의 값을 지우는 방식이 아닌 원하고자 하는 범위만큼 새로운 리스트를 생성하는 방식입니다.
ex) a[1:] 

remove( )는 인덱스가 아닌 값을 입력하는 방식입니다. 따라서 만약 지우고자 하는 값이 리스트 내에
2개 이상 있다면 순서 상 가장 앞에 있는 값을 지워줍니다.

pop( )과 del 은 지우고자 하는 인덱스를 받아서 지우는 방식입니다. 
del은 pop( )과 다르게 리스트의 범위를 지정하여 삭제할 수 있습니다.
ex) del a[:2]

pop( )은 지워진 인덱스의 값을 반환하지만 del은 반환하지 않는 차이점이 있습니다. 
따라서 성능 상 pop( )보다 del 이 수행속도가 미세하게 더 빠르다는 특징이 있습니다.

4가지 방법 중 속도 상 del이 가장 빠르고 remove( ), pop( )은 비슷하고 slice가 가장 느립니다.
각자의 특징에 맞게 사용하며 원본 리스트가 변질되지 않아야 한다면 slice가 적합할 수 있습니다.

 

해당 문제에서는 성능 상 가장 빠르게 수행되는 del을 사용해 풀이를 진행했습니다.

 

💡 내가 해결한 방식은?
def solution(cards1, cards2, goal):
    # goal 의 문장을 순회
    for word in goal:
        # cards1, cards2 인덱스와 goal의 단어를 비교 반복
        # 만약 존재한다면 p1, p2 인덱스의 단어 삭제
        # 단어 없을 경우 "No" 반환
        if len(cards1) > 0 and cards1[0] == word:
            del cards1[0]
        elif len(cards2) > 0 and cards2[0] == word:
            del cards2[0]
        else:
            return "No"
        
    return "Yes"

 


🥈 공원 산책

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/172928

 

문제 설명

더보기
지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양 공원에서 로봇 강아지가 산책을 하려합니다.
산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.

- ["방향 거리", "방향 거리" … ]

예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다.
로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.

- 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
- 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.

위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0),
우측 하단의 좌표는 (H - 1, W - 1) 입니다.
공원을 나타내는 문자열 배열 park, 로봇 강아지가 수행할 명령이 담긴 문자열 배열 routes가
매개변수로 주어질 때, 로봇 강아지가 모든 명령을 수행 후 놓인 위치를 [세로 방향 좌표, 가로 방향 좌표] 순으로
배열에 담아 return 하도록 solution 함수를 완성해주세요.
제한 사항
1. 3 ≤ park의 길이 ≤ 50
    1-1. 3 ≤ park[i]의 길이 ≤ 50
    1-2. park[i]는 다음 문자들로 이루어져 있으며 시작지점은 하나만 주어집니다.
               - S : 시작 지점
               - O : 이동 가능한 통로
               - X : 장애물 * park는 직사각형 모양입니다.
2. 1 ≤ routes의 길이 ≤ 50
    2-1. routes의 각 원소는 로봇 강아지가 수행할 명령어를 나타냅니다.
    2-2. 로봇 강아지는 routes의 첫 번째 원소부터 순서대로 명령을 수행합니다.
    2-3. routes의 원소는 "op n"과 같은 구조로 이루어져 있으며, op는 이동할 방향, n은 이동할 칸의 수를 의미합니다.
    2-4. op는 다음 네 가지중 하나로 이루어져 있습니다.
               - N : 북쪽으로 주어진 칸만큼 이동합니다.
               - S : 남쪽으로 주어진 칸만큼 이동합니다.
               - W : 서쪽으로 주어진 칸만큼 이동합니다.
               - E : 동쪽으로 주어진 칸만큼 이동합니다.
    2-5. 1 ≤ n ≤ 9

 

문제 회고

💡 어떤 문제가 있었고, 나는 어떤 시도를 했는지 그리고 새롭게 안 사실은 무엇인지

이동 벡터를 활용하여 지도 이동을 하는 문제입니다. 문제 해결 과정은 다음과 같습니다.

  1. 시작 위치가 동적으로 바뀌므로 산책 시작 위치를 먼저 구해줍니다.
  2. 위치 이동에 사용할 이동 벡터를 초기화합니다.
  3. 입력 받은 이동 명령어 리스트를 순회하여 이동 위치를 갱신합니다.
    1. 입력 받은 이동 거리를 1 칸씩 순회합니다.
    2. 이동 벡터를 사용하여 입력 방향에 맞는 이동 후 위치를 구합니다.
    3. 공원을 벗어나거나 장애물이 있을 경우 원래 위치로 돌아간 후 반복문을 나갑니다.
  4.   이동을 모두 마친 최종 위치를 반환합니다.

c++에서 이동 벡터를 dx, dy로 나누어 초기화 하는 방식을 사용해 왔는데,
파이썬에서는 directions 딕셔너리 안 value 에 좌표 값을 한번에 넣는 방식을 사용했습니다.

지도에서 원하는 장소를 조건에 맞게 탐색하는 기본 문제였습니다.

 

💡 내가 해결한 방식은?
def solution(park, routes):
    # 산책 시작 위치 찾기
    for i in range(len(park)):
        for j in range(len(park[i])):
            if park[i][j] == 'S':
                start_row, start_col = i, j
                row, col = start_row, start_col
                break
    
    # 이동 벡터 초기화
    directions = {'E': (0, 1), 'W' : (0, -1), 'S': (1, 0), 'N' : (-1, 0)}

    # 이동 요청 값 순회
    for route in routes:
        direction, distance = route.split()
        distance = int(distance)

        # 1칸씩 이동하면서 이동 위치 판별
        for _ in range(distance):
            # 이동 후 위치 세팅
            curr_row, curr_col = row + directions[direction][0], col + directions[direction][1]
            # 공원 벗어난 경우
            if curr_row < 0 or curr_col < 0 or curr_row >= len(park) or curr_col >= len(park[0]):
                row, col = start_row, start_col
                break
            # 장애물 만난 경우
            if park[curr_row][curr_col] == 'X':
                row, col = start_row, start_col
                break
            row, col = curr_row, curr_col
        start_row, start_col = row, col

    return [row, col]

 


🥇 2개 이하로 다른 비트

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/77885

 

문제 설명

더보기
양의 정수 x에 대한 함수 f(x)를 다음과 같이 정의합니다.

- x보다 크고 x와 비트가 1~2개 다른 수들 중에서 제일 작은 수

예를 들어, f(2) = 3 입니다.
다음 표와 같이 2보다 큰 수들 중에서 비트가 다른 지점이 2개 이하이면서 제일 작은 수가 3이기 때문입니다.
비트 다른 비트의 개수
2 000...0010  
3 000...0011 1
f(7) = 11 입니다.
다음 표와 같이 7보다 큰 수들 중에서 비트가 다른 지점이 2개 이하이면서 제일 작은 수가 11이기 때문입니다.
비트 다른 비트의 개수
7 000...0111  
8 000...1000 4
9 000...1001 3
10 000...1010 3
11 000...1011 2
정수들이 담긴 배열 numbers가 매개변수로 주어집니다. numbers의 모든 수들에 대하여 각 수의 f 값을 배열에 차례대로 담아 return 하도록 solution 함수를 완성해주세요.
제한 사항
1. 1 ≤ numbers의 길이 ≤ 100,000
2. 0 ≤ numbers의 모든 수 ≤ 10^15

 

문제 회고

💡 어떤 문제가 있었고, 나는 어떤 시도를 했는지 그리고 새롭게 안 사실은 무엇인지

 

💡 내가 해결한 방식은?

 


✍️  TIL