몽-구
몽구의 우당탕탕 개발 공부
몽-구
전체 방문자
오늘
어제
  • 분류 전체보기 (106)
    • PS (38)
      • 백준 (24)
      • 프로그래머스 (14)
    • Dev (58)
      • Kotlin (0)
      • Java (4)
      • Spring, SpringBoot (1)
      • C (8)
      • Python (10)
      • Dart (1)
      • 알고리즘 (7)
      • 자료구조 (3)
      • Git (1)
      • Linux (2)
      • VS Code (1)
      • 환경 설정 (8)
      • Conference (1)
      • 42Seoul (3)
      • Node.js (1)
      • ShellScript (1)
      • IntelliJ (0)
      • MacOS (2)
      • 기타 (3)
    • CS (1)
      • 데이터베이스 (1)
    • DS (4)
      • Coursera (4)
    • 리뷰 (1)
      • 제품 리뷰 (1)
    • 일상 (3)
      • 자동화 (1)
      • 목표 및 계획 (2)
      • 회고 (0)
    • 삶에 대한 태도 (1)
      • 유튜브를 보며 (1)

블로그 메뉴

  • GitHub

인기 글

반응형

태그

  • 백준온라인저지
  • 백준
  • 리눅스
  • 정렬
  • Algorithm
  • 프로그래머스
  • 코딩테스트
  • c언어
  • 백준알고리즘
  • Linux
  • 파이썬
  • BOJ
  • 알고리즘
  • sort
  • Python

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
몽-구

몽구의 우당탕탕 개발 공부

[프로그래머스][파이썬/Python] 시저 암호
PS/프로그래머스

[프로그래머스][파이썬/Python] 시저 암호

2020. 3. 7. 12:30
반응형

문제 설명

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

 

제한 조건

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

 

입출력 예

 

제출 코드

def solution(s, n):
    small = ','.join('abcdefghijklmnopqrstuvwxyz').split(',')
    capital = ','.join('ABCDEFGHIJKLMNOPQRSTUVWXYZ').split(',')
    s = ','.join(s).split(',')
    
    for i in range(len(s)):
        if s[i] in small: # 소문자일 경우
            if small.index(s[i]) + n <= 25:
                s[i] = small[small.index(s[i])+n]
            else:
                s[i] = small[small.index(s[i])+n-26]

        elif s[i] in capital: # 대문자일 경우
            if capital.index(s[i]) + n <= 25:
                s[i] = capital[capital.index(s[i])+n]
            else:
                s[i] = capital[capital.index(s[i])+n-26]
                
        else: # 공백일 경우
            continue
            
    return ''.join(s)

(1) line 2 ~ line 4

소문자의 각 문자를 하나씩 small이라는 리스트에 담고, 대문자의 각 문자를 하나씩 capital이라는 리스트에 담는다. 이후 입력값으로 받는 문자열 s 또한 각 문자를 하나씩 담는 리스트로 바꾼다.

 

(2) line 6

입력받은 문자열에 속한 모든 문자와 공백을 확인하기 위해 반복 횟수는 len(s)이다.

 

(3) line 7 ~ line 11

만약 특정 문자가 소문자라면, 리스트 'small'에서 해당 문자가 몇 번째 index에 있는지 확인한다. 그 인덱스에 n칸을 오른쪽으로 미룬 값을 return해야 하니 '해당 인덱스 + n' 을 체크한다.

 

'해당 인덱스 + n'이 리스트 'small'의 마지막 원소의 인덱스인 25 이하라면 list index out of range 에러가 발생하지 않기 때문에 그대로 해당 문자를 오른쪽으로 n칸 미룬 값으로 바꿔준다. 반대로 '해당 인덱스 + n'이 25를 초과하게 되면, 리스트 'small'의 처음으로 돌아간 다음 오른쪽으로 더 밀려가는 것으로 생각해야 한다. 입출력 예시 3번을 보면 더 알기 쉬운데, 'z'가 오른쪽으로 4칸 밀려났을 때 list 범위를 초과해버리기 때문에 한 칸을 이동했을 때 리스트 'small'의 처음인 a로 돌아가게끔 처리해줘야 하며, 이후 오른쪽으로 나머지 3칸을 더 이동하여 'd'가 된다.

 

(4) line 13 ~ line 17

위 과정과 똑같다.

 

(5) line 19

공백일 경우에는 아무리 밀어도 공백이라는 제한 조건이 있으므로 무시하고 continue를 해준다.

 

(6) line 22

입력받은 문자열 s의 각 문자를 오른쪽으로 n칸 미룬 새로운 문자열은 현재 각 문자 하나하나로 떨어져있는 리스트 형태이다. 그렇기 때문에 ''을 기준으로 합쳐준 문자열을 return해준다.

 

반성의 시간

맨 처음 코드를 짰을 때 굉장히 바보같은 실수를 했다. 일단 1차 제출 코드는 다음과 같다.

# 1차 제출 코드
def solution(s, n):
    small = 'abcdefghijklmnopqrstuvwxyz'
    capital = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    
    for i in range(len(s)):
        if s[i] in small: # 소문자일 경우
            if small.index(s[i]) + n <= 25:
            	s = s.replace(s[i], small[small.index(s[i])+n])
            else:
            	s = s.replace(s[i], small[small.index(s[i])+n]-26)

        elif s[i] in capital: # 대문자일 경우
            if capital.index(s[i]) + n <= 25:
                s = s.replace(s[i], capital[capital.index(s[i])+n])
            else:
                s = s.replace(s[i], capital[capital.index(s[i])+n]-26)
                
        else: # 공백일 경우
            continue
            
    return s

기존 문자에서 n칸을 오른쪽으로 밀어낸 후 문자를 바꿔내는 과정 중에서 문자열 메서드인 replace를 썼는데 계속 해서 list index out of range가 발생했다. 이유를 몰라서 그냥 리스트로 바꿔버린 후 풀어낸 것인데, 생각해보니 문자열에서 replace('a', 'b')를 해버리면 해당 문자열에 있는 모든 'a'가 'b'로 바뀐다는 것을 깨달았다. 참으로 멍청하다.

 

그래서 뒤늦게라도 문자열로도 충분히 할 수 있다는 생각이 들어 코드를 짜봤다. 물론 그렇게 깨끗하지는 않은 것 같다. 하지만 중요한 것은 문자열에서 특정 문자를 바꾸고 싶다면 앞과 뒤를 잘라내고 그 사이에 새로운 문자열을 붙여야 한다는 것이다! 기본적인 것들을 자꾸 까먹어서 참 문제다.

# 1차 제출 코드를 수정한 것
def solution(s, n):
    small = 'abcdefghijklmnopqrstuvwxyz'
    capital = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    
    for i in range(len(s)):
        if s[i] in small: # 소문자일 경우
            if small.index(s[i]) + n <= 25:
                if i != len(s)-1:
                    s = s[:i] + small[small.index(s[i])+n] + s[i+1:]
                else:
                    s = s[:i] + small[small.index(s[i])+n]
            else:
                if i != len(s)-1:
                    s = s[:i] + small[small.index(s[i])+n-26] + s[i+1:]
                else:
                    s = s[:i] + small[small.index(s[i])+n-26]

                
        elif s[i] in capital: # 대문자일 경우
            if capital.index(s[i]) + n <= 25:
                if i != len(s)-1:
                    s = s[:i] + capital[capital.index(s[i])+n] + s[i+1:]
                else:
                    s = s[:i] + capital[capital.index(s[i])+n]
            else:
                if i != len(s)-1:
                    s = s[:i] + capital[capital.index(s[i])+n-26] + s[i+1:]
                else:
                    s = s[:i] + capital[capital.index(s[i])+n-26]
                
        else: # 공백일 경우
            continue
            
    return s

 

 

 

Source : https://programmers.co.kr/learn/courses/30/lessons/12926

 

반응형
저작자표시 (새창열림)

'PS > 프로그래머스' 카테고리의 다른 글

[프로그래머스][파이썬/Python] (2019 카카오 코딩테스트) 오픈채팅방  (0) 2020.03.09
[프로그래머스][파이썬/Python] 프린터  (0) 2020.03.08
[프로그래머스][파이썬/Python] (2018 서머코딩/윈터코딩) 스킬트리  (0) 2020.03.06
[프로그래머스][파이썬/Python] 쇠막대기  (0) 2020.03.05
[프로그래머스][파이썬/Python] (2018 카카오 코딩테스트) 비밀지도  (0) 2020.03.04
    'PS/프로그래머스' 카테고리의 다른 글
    • [프로그래머스][파이썬/Python] (2019 카카오 코딩테스트) 오픈채팅방
    • [프로그래머스][파이썬/Python] 프린터
    • [프로그래머스][파이썬/Python] (2018 서머코딩/윈터코딩) 스킬트리
    • [프로그래머스][파이썬/Python] 쇠막대기
    몽-구
    몽-구
    소망보단 목표를, 생각보단 실천을

    티스토리툴바