[Codekata - Week2] Day 1~3

문성호·2020년 9월 10일
0
  • Codekata 2번째 주.
  • 1번째 주도 생각보다 녹녹치 않다고 생각했는데, 2번째 주는 갑자기 난이도가 상당히 올라갔다. 사전스터디 때 알고리즘 문제 많이 풀어둔게 어느 정도 적응하는데 도움이 된 듯.

Day1

*문제
로마자에서 숫자로 바꾸기  1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요. 로마 숫자를 숫자로 표기하면 다음과 같습니다.  
>Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000
>로마자를 숫자로 읽는 방법은 로마자를 왼쪽부터 차례대로 더하면 됩니다.
III = 3
XII = 12
XXVII = 27입니다. 

>그런데 4를 표현할 때는 IIII가 아니라 IV 입니다.
뒤의 숫자에서 앞의 숫자를 빼주면 됩니다.
9는 IX입니다. 
>I는 V와 X앞에 와서 4, 9
X는 L, C앞에 와서 40, 90
C는 D, M앞에 와서 400, 900 

My Solution

def roman_to_num(s):
  romanDict = {
    'I' : 1,
    'V' : 5,
    'X' : 10,
    'L' : 50,
    'C' : 100,
    'D' : 500,
    'M' : 1000
  }
  
  sum = 0
  index = 0
  
  while index < len(s):
    # print(sum, index)
    if index == len(s)-1:
      sum += romanDict[s[index]]
      break
    if s[index]=='I' and (s[index+1]=='V' or s[index+1]=='X'):
      sum += romanDict[s[index+1]]-romanDict[s[index]]
      index += 2
      print(sum, index)
      continue;
    
    if s[index]=='X' and (s[index+1]=='L' or s[index+1]=='C'):
      sum += romanDict[s[index+1]]-romanDict[s[index]]
      index += 2  
      print(sum, index)
      continue;
    
    if s[index]=='C' and (s[index+1]=='D' or s[index+1]=='M'):
      sum += romanDict[s[index+1]]-romanDict[s[index]]
      index += 2  
      print(sum, index)
      continue;
      
    sum += romanDict[s[index]]
    index += 1

  return sum
  • 다소 하드코딩한 느낌이 있지만, 시간이 많지 않아서 더 고민할 여유가 없었다.
  • 예외가 아닌 다른 Roman 숫자를 구하는 것은 어렵지 않지만, IV나 XL과 같은 특수한 경우를 예외로 처리해야하기 때문에 문제가 어려웠다.
  • 아이디어는 간단하다. IV이면 V-I=4 로 구하면 쉽다.
    그리고 2칸만큼의 Index를 뛰어넘어 다른 숫자는 합을 구하면 끝.
  • 직관적인 로직을 짜는 건 어렵지 않았지만, 더 잘 푸는 방법은 시간이 있으면 고민해봐야겠다.

Day 2

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

예를 들어, 
nums = [3,2,3]
return 3
nums = [2,2,1,1,1,2,2]
return 2

>* 가정
nums 배열의 길이는 무조건 2개 이상

My Solution

def more_than_half(nums):
  numSet = set(nums)
  for num in numSet:
    if nums.count(num) >= len(nums)/2:
      return num
     
  • count함수를 이용하면 간결하게 짤 수 있었던 문제다.
  • Set 자료형을 이용해 nums 배열에서 중복을 제거한 후, 각 숫자별로 nums의 등장횟수를 Count함수로 센 후, 절반 길이보다 큰지에 대해 검사하면 깔끔하게 풀 수 있다.

Day 3

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

종류는 '(', ')', '[', ']', '{', '}' 으로 총 6개 있습니다. 아래의 경우 유효합니다.

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

예를 들어 아래와 같습니다.  

s = "()"
return true

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

s = "(]"
return false

s = "([)]"
return false

s = "{[]}"
return true

My Solution

def is_valid(string):
  open = ['(', '{', '[']
  close= [')', '}', ']']
  open_bracket = []
  close_bracket = []

  if len(string) == 1:
    return False
    
  for i in range(len(string)):
    if string[i] in open:
      open_bracket.append(string[i])
    elif string[i] in close:
      close_bracket.append(string[i])
      if len(open_bracket) == 0:
        return False
      if close.index(close_bracket[-1]) != open.index(open_bracket[-1]):
        return False
      else:
        del open_bracket[-1]
        del close_bracket[-1]
    
  return True
  • 이 문제는 Stack의 원리를 응용하면 풀 수 있는 문제였다.
  • 괄호들은 열린 순서대로 닫혀야 한다. open_bracket 배열에는 여는 괄호를 넣고, close_bracket에는 닫힌 괄호가 들어오게 해서, Index를 돌리면서 짝이 맞는지 안 맞는지를 검사하면 된다. append함수로 계속 쌓이기 때문에, 나중에 제거할 때는 마지막 index들만 검사하면 된다.
  • Dictionary로 검사했다면 변수를 좀 더 깔끔하게 저장할 수 있었을지도.
profile
오늘을 모아 내일을

0개의 댓글