Learn to share,Share to learn
람다, 그리고 sorted와 split 본문
문제
세준이는 양수와 +, -, 그리고 괄호를 가지고 식을 만들었다. 그리고 나서 세준이는 괄호를 모두 지웠다.
그리고 나서 세준이는 괄호를 적절히 쳐서 이 식의 값을 최소로 만들려고 한다.
괄호를 적절히 쳐서 이 식의 값을 최소로 만드는 프로그램을 작성하시오.
입력
첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 많이 연속되는 숫자는 없다. 수는 0으로 시작할 수 있다. 입력으로 주어지는 식의 길이는 50보다 작거나 같다.
출력
첫째 줄에 정답을 출력한다.
문제는 보자마자 로직이 생각날정도로 쉽지만, 구현을 어떻게 해야하는가 고민했다. 첫 - 값 뒤에는 전부 뺄셈으로 들어가면 되겠는데? 근데 이 값을 어떻게 하나하나 나누고 정수로 인식해서 계산해야할까? split을 쓰면 될거같긴한데.. 문법적으로 모르는 부분이였다.
#-가 나오면 그다음부터는 전부 -로 바꿔 계산
expression = input()
def min_value(expression):
numbers = expression.split('-')
result = sum(map(int,numbers[0].split('+')))
for num in numbers[1:]:
result -= sum(map(int,num.split('+')))
return result
print(min_value(expression))
55-50+40라는 예시를 보자. - 로 split 되어 55 와 50+40으로 numbers에 들어간다.
그 값을 result = sum(map(int,numbers[0].split('+')))에서 첫 - 이전 값을, +를 기준으로 split 하고, int로 만들어주고 더하는거다. 한줄에 꽤나 많은것이 들어가있다.
그다음은, -로 split된 50+40을 +를 기준으로 split하고 result에서 빼는것이다.
문제
옛날 옛적에 수학이 항상 큰 골칫거리였던 나라가 있었다. 이 나라의 국왕 김지민은 다음과 같은 문제를 내고 큰 상금을 걸었다.
길이가 N인 정수 배열 A와 B가 있다. 다음과 같이 함수 S를 정의하자.
S = A[0] × B[0] + ... + A[N-1] × B[N-1]
S의 값을 가장 작게 만들기 위해 A의 수를 재배열하자. 단, B에 있는 수는 재배열하면 안 된다.
S의 최솟값을 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 N이 주어진다. 둘째 줄에는 A에 있는 N개의 수가 순서대로 주어지고, 셋째 줄에는 B에 있는 수가 순서대로 주어진다. N은 50보다 작거나 같은 자연수이고, A와 B의 각 원소는 100보다 작거나 같은 음이 아닌 정수이다.
출력
첫째 줄에 S의 최솟값을 출력한다.
이것도 로직은 간단하다. 최대값 최솟값을 서로 매칭시키면 되겠다.
def minimize_S(N, A, B):
# A를 오름차순으로 정렬
A.sort()
# B의 원소에 대응하는 A의 요소들의 인덱스를 얻기 위해 B를 인덱스와 함께 정렬
idx_B = sorted(range(N), key=lambda x: B[x], reverse=True)
# S 계산
S = 0
for i in range(N):
S += A[i] * B[idx_B[i]]
return S
# 입력 처리
N = int(input())
A = list(map(int, input().split()))
B = list(map(int, input().split()))
# 결과 출력
print(minimize_S(N, A, B))
이번엔 인덱스와 람다의 문법에 대해 몰랐다. 일단 핵심은 idx_B = sorted(range(N), key=lambda x: B[x], reverse=True) 요부분이겠지? 요부분을 이해하기전 람다에 대해 좀 더 알아보자.
기본 예시: 단순 계산
- 두 숫자 더하기:
여기서 lambda x, y: x + y는 두 숫자를 더하는 함수add = lambda x, y: x + y print(add(5, 3)) # 결과: 8
- 제곱 계산:
lambda x: x * x는 하나의 숫자를 제곱하는 함수square = lambda x: x * x print(square(4)) # 결과: 16
리스트 정렬 예시
- 튜플 리스트 정렬:
여기서 lambda x: x[0]는 튜플의 첫 번째 요소를 기준으로 정렬tuples = [(1, 'one'), (3, 'three'), (2, 'two')] tuples.sort(key=lambda x: x[0]) print(tuples) # 결과: [(1, 'one'), (2, 'two'), (3, 'three')]
- 사전형 리스트 정렬:
lambda x: x['age']는 사전형 객체의 'age' 키에 해당하는 값을 기준으로 정렬data = [{'name': 'John', 'age': 30}, {'name': 'Jane', 'age': 25}, {'name': 'Dave', 'age': 35}] data.sort(key=lambda x: x['age']) print(data) # 결과: [{'name': 'Jane', 'age': 25}, {'name': 'John', 'age': 30}, {'name': 'Dave', 'age': 35}]
고급 예시: filter()와 map()
- 특정 조건에 맞는 요소 필터링:
filter(lambda x: x % 2 == 0, numbers)는 짝수만 필터링numbers = [1, 2, 3, 4, 5, 6] even = list(filter(lambda x: x % 2 == 0, numbers)) print(even) # 결과: [2, 4, 6]
- 리스트의 각 요소에 함수 적용:
map(lambda x: x ** 2, numbers)는 리스트의 각 요소를 제곱numbers = [1, 2, 3, 4, 5] squared = list(map(lambda x: x ** 2, numbers)) print(squared) # 결과: [1, 4, 9, 16, 25]
뭔지 대충 감이 온다. https://wikidocs.net/64 도 참고하자
그러니까 함수를 쉽게 만든다~ 생각하면 편하다. 위의 코드에서 sorted함수는 정렬을 해주는 함수인데, 정렬기준을 람다로 하는거고, 그 람다는 x를 받는데, 그 x란 B[x]인거고, 그에따라 순서대로 정렬한다 이렇게 이해하면 되겠다.
앞의 range(N)이 인덱스값, 01234이고, B[x]의 값에 따라 그걸 순서대로 정렬한다는것이다.
이 문법을 몰랐다. 만약 알고 있었어도 B[idx_B[i]]로 쓸수 있다는걸 몰랐기에 이번 문제는 기억해둘만 하다.
구현문제들을 더 풀어볼 필요성을 느끼고 있다. 그런데 알고리즘 분류에따라 구현을 풀려니까, 또 내가 아직 익숙하지않은 알고리즘을 알아야 풀리는경우도 많아 딜레마를 겪고있다 ㅋㅋ
'알고리즘' 카테고리의 다른 글
1181 집합 원소 길이별 정렬 (1) | 2024.01.25 |
---|---|
DFS,BFS (2) | 2024.01.25 |
파이썬의 대규모 입출력 sys (0) | 2024.01.19 |
1269 집합의 사용 (0) | 2024.01.18 |
1764 집합 응용, get, isdigit 사용법 (0) | 2024.01.18 |