TIL 35. CodeKata-Python 2주차 리뷰

문승준·2021년 10월 10일
0
post-thumbnail

1. 로마자를 숫자로 바꾸기

1-1. 문제

1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요.

로마 숫자를 숫자로 표기하면 다음과 같습니다.

SymbolValue
I1
V5
X10
L50
C100
D500
M1000

로마자를 숫자로 읽는 방법은 로마자를 왼쪽부터 차례대로 더하면 됩니다.

III = 3
XII = 12
XXVII = 27

그런데 4와 9를 표현할 때는 뒤의 숫자에서 앞의 숫자를 빼주면 됩니다.
4는 IIII가 아니라 IV 입니다.
9는 IX입니다.

I는 V, X 앞에 와서 4, 9
X는 L, C 앞에 와서 40, 90
C는 D, M 앞에 와서 400, 900

1-2. 풀이

def roman_to_num(s):
  symbols = ['I', 'V', 'X', 'L', 'C', 'D', 'M']
  value = [1, 5, 10, 50, 100, 500, 1000]
  result = 0

  for i in range(len(symbols)):
    result += s.count(symbols[i]) * value[i]

    if i % 2 == 0 and i < 6:
      result -= s.count(symbols[i] + symbols[i+1]) * value[i] * 2
      result -= s.count(symbols[i] + symbols[i+2]) * value[i] * 2

  return result
  • 동일한 인덱스를 사용하기 위해 symbol과 value를 각각 배열로 만든다.

  • 각 symbol 요소의 개수에 따라 대응하는 value 값을 곱해주고 그 값을 result로 모두 더한다.

  • 4와 9를 표현하는 경우를 예외 처리한다.
    -> 만약 I, X, C 가 먼저오고 (M은 제외)
    -> 바로 다음 글자 혹은 다다음 글자와 붙어서 나오면
    -> value값에 2를 곱해서 빼준다. (원래는 value값만 빼면 되지만 result값에 이미 value가 더해져있기 때문에)


2. 배열에서 과반수가 넘는 숫자 찾기

2-1. 문제

숫자로 이루어진 배열인 nums를 인자로 전달합니다.
숫자중에서 과반수(majority, more than a half)가 넘은 숫자를 반환해주세요.

예를들어,

nums = [3,2,3]
return 3

nums = [2,2,1,1,1,2,2]
return 2

배열의 길이는 2 이상으로 가정합니다.

2-2. 풀이

def more_than_half(nums):
  set_nums = set(nums)
  current = 0

  for num in set_nums:
    if current < nums.count(num):
      current = nums.count(num)
      result = num

# 과반수가 되지 않는 경우 예외처리
  if current =< len(nums)/2:
    return print("과반수가 안된다")

  return result
  • 개수가 가장 많은 요소를 찾아서 반환한다.
  1. 어떤 종류의 요소가 있는지 알기 위해 numsset 타입으로 변경한다.

  2. 각 고유한 요소가 nums 배열에 몇개 있는지 확인하고 current에 담는다.

  3. 요소의 개수가current보다 크다면 다시 current를 갱신한다.

  4. 가장 많은 개수를 가진 요소라면 더 이상 current를 갱신하지 않는다. 이때 해당 요소를 반환한다.

특정 요소의 개수가 가장 많더라도 과반수가 안되는 경우를 위해 예외처리를 추가했다.
과반수가 되려면 요소의 개수가 절반보다 많아야하기 때문에 절반과 같거나 더 작다면 인정하지 않는다.


3. 🤯괄호 짝이 유효한지 확인하기

3-1. 문제

s는 여러 괄호들로 이루어진 String 인자입니다. s가 유효한 표현인지 아닌지 true/false로 반환해주세요.

종류는 '(', ')', '[', ']', '{', '}' 으로 총 6개 있습니다.

한 번 괄호를 시작했으면, 같은 괄호로 끝내야 하고 괄호 순서가 맞아야 합니다.

s = "()"
return true

s = "()[]{}"
return true

s = "(]"
return false

s = "([)]"
return false

s = "{[]}"
return true

3-2. 풀이

def is_valid(string):

  finish = [')', ']', '}']

  if len(string) % 2 == 1 or (string[0] in finish):
    return False

  for i in range(0,len(string)-1,2):
    if string[i]==string[i+1]:
      return True
    else:
      return False
  • 예외처리를 위해 전체 갯수가 홀수거나, 첫번째 요소가 닫는 괄호이면 바로 False를 반환한다.

  • 0번 인덱스부터 2칸씩 이동하며 바로 다음요소와 같은 값인지 비교한다.

  • Test는 통과했으나 예외상황을 더 생각해보자

  • for문 안에 if문이 True일때 계속 진행하는 방법을 생각해보자
    -> 그냥 True만 해놨는데 다른 방법이 있을 거다.


4. 배열에서 자주 등장한 숫자 반환하기

4-1. 문제

nums는 숫자로 이루어진 배열입니다.
자주 등장하는 순서대로 숫자를 k 개수만큼 return 해주세요.

nums = [1,1,1,2,2,3],
k = 2
return [1,2]

nums = [1]
k = 1
return [1]

4-2. 풀이

def top_k(nums, k):
  nums_set  = set(nums)
  nums_list = []
  result    = []

  for num in nums_set:
    nums_list.append((num, nums.count(num)))

  nums_list.sort(key=lambda x: x[1], reverse=True)

  for i in range(k):
    result.append(nums_list[i][0])

  return result

# sort 내부의 람다 함수
# def sort_second(x):
#   return x[1]
  • 요소와 요소의 등장 횟수를 딕셔너리 형태로 담으려 했으나 정렬을 못하는 문제가 있었다.

  • 딕셔너리 대신 튜플로 묶어서 배열에 담아주었고, sort(key=func)로 튜플 내부까지 접근해 정렬이 가능했다.

  1. 고유한 요소들만 찾기위해 배열을 set으로 바꾼다.

  2. nums_list 배열에는 (요소, 요소 등장 횟수) 튜플을 모두 담는다.

  3. sort() 메소드로 각 튜플에서 요소 등장 횟수를 내림차순으로 정렬한다. -> 람다표현식 사용

  4. k번 만큼 각 튜플의 요소result 배열에 담는다.


5. 그래프의 가장 넓은 면적 구하기

5-1. 문제

인자인 height는 숫자로 이루어진 배열입니다. 그래프로 생각한다면 y축의 값이고, 높이 값을 갖고 있습니다.

아래의 그래프라면 height 배열은 [1, 8, 6, 2, 5, 4, 8, 3, 7] 입니다.

예시 사진

저 그래프에 물을 담는다고 생각하고, 물을 담을 수 있는 가장 넓은 면적의 값을 반환해주세요.

배열의 길이는 2 이상인 것으로 가정합니다.

5-2. 풀이

def get_max_area(height):
  area = []
  
  for i in range(len(height)):
    for j in range(i+1,len(height)):    
      this_area = (j-i) * min(height[i],height[j])
      area.append(this_area)
      
  return max(area)
  • 면적 = 가로 (두 요소의 인덱스 차이값) * 세로 (둘 중 작은 요소의 값)
  1. 중복되지 않게 두개의 요소를 골라서 면적을 구하자.

  2. 인덱스 기준으로 j는 무조건 i보다 뒤에 오기 때문에 가로값은 j-i 가 된다.

  3. 두 요소의 값 중에서 작은 값이 세로값이 된다.

  4. 모든 경우의 면적 값을 배열에 담는다.

  5. 그 배열에서 가장 큰 값을 반환한다.

profile
개발자가 될 팔자

0개의 댓글