알고리즘(파이썬)

43번-45번

whateveryouwish 2024. 8. 8. 16:19

43번

 

문제 설명
숫자로 이루어진 문자열 t와 p가 주어질 때, t에서 p와 길이가 같은 부분문자열 중에서,
이 부분문자열이 나타내는 수가 p가 나타내는 수보다 작거나 같은 것이 나오는 횟수를 return하는
함수 solution을 완성하세요.

예를 들어, t="3141592"이고 p="271" 인 경우,
t의 길이가 3인 부분 문자열은 314, 141, 415, 159, 592입니다.
이 문자열이 나타내는 수 중 271보다 작거나 같은 수는 141, 159 2개 입니다.

제한사항
1 ≤ p의 길이 ≤ 18
p의 길이 ≤ t의 길이 ≤ 10,000
t와 p는 숫자로만 이루어진 문자열이며, 0으로 시작하지 않습니다.

 

def solution(t, p):
    answer = 0
    tt = len(t)
    pp = len(p)
    for i in range(0, (tt - pp + 1)) :
        t_3 = t[i:(i+pp)]
        if t_3 <= p :
            answer += 1
        
    return answer

 

아래는 문자열 인덱싱에 관한 뤼튼 답변

 

파이썬에서 문자열 인덱싱은 문자열 내의 특정 문자에 접근하는 방법입니다. 문자열은 0부터 시작하는 인덱스를 가지며, 각 문자는 해당 인덱스에 매핑됩니다. 아래에 문자열 인덱싱의 기본적인 사용법을 설명하겠습니다.

기본 인덱싱

 
# 문자열 정의
my_string = "Hello, World!"

# 인덱싱
first_character = my_string[0]  # 'H'
second_character = my_string[1]  # 'e'
last_character = my_string[-1]    # '!'

인덱스 설명

  • 양수 인덱스: 문자열의 시작부터 0부터 시작합니다. 예를 들어, my_string[0]은 첫 번째 문자 'H'를 반환합니다.
  • 음수 인덱스: 문자열의 끝에서부터 접근할 수 있습니다. -1은 마지막 문자, -2는 끝에서 두 번째 문자를 의미합니다.

문자열 슬라이싱

인덱싱뿐만 아니라 문자열의 일부분을 가져오는 슬라이싱도 가능합니다.

 
# 슬라이싱
substring = my_string[0:5]  # 'Hello'
substring_from_start = my_string[:5]  # 'Hello'
substring_to_end = my_string[7:]  # 'World!'
substring_negative = my_string[-6:-1]  # 'World'

슬라이싱 설명

  • my_string[start:end]: start 인덱스부터 end 인덱스 직전까지의 부분 문자열을 반환합니다.
  • 인덱스를 생략하면 시작 또는 끝을 자동으로 설정합니다.
    • [:5]: 0부터 4까지의 문자.
    • [7:]: 7번째 인덱스부터 끝까지의 문자.
    • [-6:-1]: 끝에서 여섯 번째 문자부터 끝에서 첫 번째 직전까지의 문자.

예시 코드

아래는 문자열 인덱싱과 슬라이싱의 예시를 포함한 전체 코드입니다.

 
my_string = "Hello, World!"

# 인덱싱
print(my_string[0])   # 'H'
print(my_string[7])   # 'W'
print(my_string[-1])  # '!'

# 슬라이싱
print(my_string[0:5])       # 'Hello'
print(my_string[7:12])      # 'World'
print(my_string[:5])        # 'Hello'
print(my_string[7:])        # 'World!'
print(my_string[-6:-1])     # 'World'

이렇게 파이썬에서 문자열 인덱싱과 슬라이싱을 사용하여 문자열의 특정 문자나 부분 문자열에 접근할 수 있습니다.

 

44번

 

문제 설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다.
다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서,
작아서 들고 다니기 편한 지갑을 만들어야 합니다.
이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호	가로 길이	세로 길이
1	60	50
2	30	70
3	60	30
4	80	40

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에
80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다.
하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로
모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다.
모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때,
지갑의 크기를 return 하도록 solution 함수를 완성해주세요.

제한사항

sizes의 길이는 1 이상 10,000 이하입니다.
sizes의 원소는 [w, h] 형식입니다.
w는 명함의 가로 길이를 나타냅니다.
h는 명함의 세로 길이를 나타냅니다.
w와 h는 1 이상 1,000 이하인 자연수입니다.

 

 

def solution(sizes):
    max_w = 0
    max_h = 0
    answer = 0
    for i in range(len(sizes)):
        # 가로와 세로를 비교하여 큰 값을 가로에, 작은 값을 세로에 저장
        if sizes[i][0] < sizes[i][1]:
            sizes[i][0], sizes[i][1] = sizes[i][1], sizes[i][0]
            
    for size in sizes:
        if size[0] > max_w:
            max_w = size[0]
        if size[1] > max_h:
            max_h = size[1]

        
    answer = (max_w) * (max_h)
    # 가로 세로 중 큰 값을 가로로 정렬
    # max(가로) * max(세로)
    return answer

 

2차원 배열이나 행렬을 다루는 것이 익숙치 않아서 뤼튼에 물어봐가며 풀었다.

len()을 사용할 때나 문제를 풀 때 저렇게 # 을 통해 머리 속을 정리해가며 풀면 도움이 되는 것 같다.

 

아래는 2차원 배열에 관한 뤼튼의 설명

 

파이썬에서 2차원 배열은 리스트의 리스트로 구현할 수 있습니다. 2차원 배열은 행(row)과 열(column)로 구성된 데이터를 나타내는 데 사용됩니다. 아래에 2차원 배열의 생성, 접근, 수정 방법을 설명하겠습니다.

2차원 배열 생성

2차원 배열을 생성하는 방법은 여러 가지가 있지만, 가장 기본적인 방법은 리스트를 중첩하여 만드는 것입니다.

 
# 2차원 배열 생성
array_2d = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

2차원 배열 접근

2차원 배열의 특정 요소에 접근하려면 두 개의 인덱스를 사용합니다. 첫 번째 인덱스는 행을, 두 번째 인덱스는 열을 나타냅니다.

 
# 특정 요소 접근
element = array_2d[1][2]  # 6 (2번째 행, 3번째 열)

2차원 배열 수정

특정 요소를 수정하는 것도 가능합니다. 인덱스를 사용하여 원하는 위치에 새로운 값을 할당하면 됩니다.

 
# 요소 수정
array_2d[0][1] = 20  # 1행 2열의 값을 20으로 변경

2차원 배열 출력

2차원 배열을 출력할 땐 반복문을 사용하여 각 행을 출력할 수 있습니다.

 
# 2차원 배열 출력
for row in array_2d:
    print(row)

전체 예시 코드

아래는 2차원 배열을 생성하고, 접근하고, 수정하는 전체 예시 코드입니다.

 
# 2차원 배열 생성
array_2d = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# 특정 요소 접근
print("원래 값:", array_2d[1][2])  # 6 (2번째 행, 3번째 열)

# 요소 수정
array_2d[0][1] = 20  # 1행 2열의 값을 20으로 변경
print("수정된 값:", array_2d[0][1])  # 20

# 2차원 배열 출력
print("전체 배열:")
for row in array_2d:
    print(row)

출력 결과

위 코드를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.

원래 값: 6
수정된 값: 20
전체 배열:
[1, 20, 3]
[4, 5, 6]
[7, 8, 9]

NumPy를 이용한 2차원 배열

파이썬에서 더 효율적으로 2차원 배열을 다루고 싶다면 NumPy 라이브러리를 사용할 수 있습니다. NumPy를 사용하면 배열 생성, 연산, 슬라이싱 등이 더 간편해집니다.

 
import numpy as np

# NumPy로 2차원 배열 생성
array_2d_np = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

print(array_2d_np)

NumPy를 사용하면 배열에 대한 다양한 수학적 연산도 쉽게 수행할 수 있습니다.

 

아래는 각 행과 열의 최댓값을 구하는 방법

 

2차원 배열에서 각 행과 열의 최댓값을 구하는 방법을 설명하겠습니다. 파이썬의 기본 리스트를 사용할 경우와 NumPy 라이브러리를 사용할 경우 두 가지 방법을 소개하겠습니다.

1. 기본 리스트를 사용할 경우

기본 파이썬 리스트를 사용하여 각 행과 열의 최댓값을 구하는 방법은 다음과 같습니다.

 
# 2차원 배열 생성
array_2d = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# 각 행의 최댓값 구하기
row_max = [max(row) for row in array_2d]
print("각 행의 최댓값:", row_max)

# 각 열의 최댓값 구하기
col_max = [max(column) for column in zip(*array_2d)]
print("각 열의 최댓값:", col_max)

설명

  • 각 행의 최댓값: 리스트 컴프리헨션을 사용하여 각 행(row)의 최댓값을 구합니다.
  • 각 열의 최댓값: zip(*array_2d)를 사용하여 열(column) 단위로 데이터를 묶은 후, 각 열의 최댓값을 구합니다.

2. NumPy를 사용할 경우

NumPy를 사용하면 더 간단하게 최댓값을 구할 수 있습니다. NumPy는 배열에 대해 다양한 연산을 지원합니다.

 
import numpy as np

# NumPy로 2차원 배열 생성
array_2d_np = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

# 각 행의 최댓값 구하기
row_max_np = np.max(array_2d_np, axis=1)
print("각 행의 최댓값:", row_max_np)

# 각 열의 최댓값 구하기
col_max_np = np.max(array_2d_np, axis=0)
print("각 열의 최댓값:", col_max_np)

설명

  • np.max(array_2d_np, axis=1): axis=1을 지정하면 각 행의 최댓값을 반환합니다.
  • np.max(array_2d_np, axis=0): axis=0을 지정하면 각 열의 최댓값을 반환합니다.

전체 예시 코드

두 가지 방법을 모두 포함한 전체 예시 코드는 다음과 같습니다.

 
# 1. 기본 리스트 방법
array_2d = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# 각 행의 최댓값 구하기
row_max = [max(row) for row in array_2d]
print("각 행의 최댓값 (리스트):", row_max)

# 각 열의 최댓값 구하기
col_max = [max(column) for column in zip(*array_2d)]
print("각 열의 최댓값 (리스트):", col_max)

# 2. NumPy 방법
import numpy as np

array_2d_np = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
])

row_max_np = np.max(array_2d_np, axis=1)
print("각 행의 최댓값 (NumPy):", row_max_np)

col_max_np = np.max(array_2d_np, axis=0)
print("각 열의 최댓값 (NumPy):", col_max_np)

출력 결과

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.

각 행의 최댓값 (리스트): [3, 6, 9]
각 열의 최댓값 (리스트): [7, 8, 9]
각 행의 최댓값 (NumPy): [3 6 9]
각 열의 최댓값 (NumPy): [7 8 9]

이렇게 하면 2차원 배열에서 각 행과 열의 최댓값을 효과적으로 구할 수 있습니다.

 

 

45번

 

문제 설명
어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다.
예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다.
"z"는 1만큼 밀면 "a"가 됩니다.
문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한 조건
공백은 아무리 밀어도 공백입니다.
s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
s의 길이는 8000이하입니다.
n은 1 이상, 25이하인 자연수입니다.

입출력 예
s	n	result
"AB"	1	"BC"
"z"	1	"a"
"a B z"	4	"e F d"

 

 

def solution(s, n):
    answer = ''
    
    for a in s:
        if a == ' ':
            answer += a
        elif a.islower():
            caesar = chr((ord(a) - ord('a') + n) % 26 + ord('a'))
            answer += caesar
        elif a.isupper():
            caesar = chr((ord(a) - ord('A') + n) % 26 + ord('A'))
            answer += caesar
            
    return answer

 

공백이 포함되어있는 문자열이기 때문에 공백의 경우는 건드리지 않아야한다.

참고로 ascii 코드로 변환했을 때 공백 ' '은 32이고

a-z 는 97-122

A-Z 는 65-90 이다.

 

중요한 파트를 정리하면

  • 소문자 암호화:
    • ord(a)를 사용하여 현재 문자의 아스키 코드 값을 가져옵니다.
    • ord('a')를 빼서 'a'를 기준으로 0부터 25까지의 인덱스를 계산합니다.
    • 이 인덱스에 n을 더하여 이동한 인덱스를 계산합니다.
    • 26으로 나눈 나머지를 구하여 알파벳의 순환을 처리합니다.
    • 마지막으로 ord('a')를 더하여 새로운 소문자를 아스키 코드로 변환 후, chr() 함수를 사용하여 문자로 변환합니다.
    • 결과적으로 caesar 변수에 암호화된 소문자가 저장됩니다.

대문자도 마찬가지이다.

 

 
        elif a.islower():
  • 소문자 체크: 현재 문자가 소문자인지 확인합니다. 
  • 대문자 체크의 경우 a.isupper() 로 바꿔 사용하면 됩니다.