4659_비밀번호 발음하기 (Python)

0. 출처

1. 기록

  • 22/03/29 (화)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 문제에서 제시된 내용으로 구현한다.
>> 모음(a,e,i,o,u) 하나를 반드시 포함하여야 한다. -> 반드시 하나 이상 포함되어야 한다를 어떻게 코드로 작성할지?
>> 모음이 3개 혹은 자음이 3개 연속으로 오면 안 된다. -> ex. aei, bcd 등은 허용x
>> 같은 글자가 연속적으로 두번 오면 안되나, ee 와 oo는 허용한다. -> aa, bb, cc 등은 허용x

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
a
tv
ptoui
bontres
zoggax
wiinq
eep
houctuh
end

- 예제 출력 1 -
<a> is acceptable.
<tv> is not acceptable.
<ptoui> is not acceptable.
<bontres> is not acceptable.
<zoggax> is not acceptable.
<wiinq> is not acceptable.
<eep> is acceptable.
<houctuh> is acceptable.

(3) 코드

vowels = "aeiou"
while True:
    s = input()
    if s == "end":
        break
    v = 0
    k = 1
    for i in range(len(s)):
        if s[i] in vowels:
            v = 1
        if i > 0:
            if s[i] == s[i-1] and s[i] != 'e' and s[i] != 'o':
                k = 0
                break
        if i > 1:
            if s[i] not in vowels:
                if s[i-1] not in vowels:
                    if s[i-2] not in vowels:
                        k = 0
                        break
            if s[i] in vowels:
                if s[i-1] in vowels:
                    if s[i-2] in vowels:
                        k = 0
                        break
    if v == 1 and k == 1:
        print(f"<{s}> is acceptable.")
    else:
        print(f"<{s}> is not acceptable.")

(4) 정리

문자열 유형 문제의 구현이 난이도가 올라갈수록 복잡해지는 것 같습니다.
a,e,i,o,u 하나하나를 배열에 담아서 확인해야하나 생각했는데 'aeiou'를 문자열로 확인하는 방법이 있음을 배웠습니다.

(5) 참고

참고 풀이

14405_피카츄 (Python)

0. 출처

1. 기록

  • 22/03/29 (화)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>> "pi", "ka", "chu"를 이어 붙여서 만들 수 있으면
>> pikachu 처럼 이어서 나오는 경우를 말하는 건지..?
>> pi, ka, chu 가 분리되어 나와 있는 경우도 YES 로 출력한다.
>> 이때 pi, ka, chu 의 순서는 어떻게 입력되어도 상관없다.
>> pi, ka, chu 이외의 문자열이 들어있는 경우 NO 로 출력한다.
2. 시간복잡도
>>
3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
pikapi

- 예제 출력 1 -
YES

- 예제 입력 2 -
pipikachu

- 예제 출력 2 -
YES

- 예제 입력 3 -
pikaqiu

- 예제 출력 3 -
NO

(3) 코드

import re

standard = re.compile('(pi|ka|chu)*')
string = input()

if re.fullmatch(standard, string):          # pi 또는 ka 또는 chu 라는 단어만 들어있는 경우
    print("YES")
else:                                       # pi 또는 ka 또는 chu 라는 단어 이외의 단어가 들어있는 경우
    print("NO")

(4) 정리

처음에 문제 의도를 파악하지 못해 해맸다.
"pi" 또는 "ka" 또는"chu" 라는 단어만 들어있는 경우 "YES" 출력
"pi" 또는 "ka" 또는"chu" 라는 단어 이외의 단어가 들어있는 경우 "NO" 출력

위의 코드를 부정형으로 "pi" 또는 "ka" 또는"chu" 라는 단어 이외의 단어가 들어오는 경우 match 시키는 형식으로 짜보려고 했으나 실패했습니다.

(5) 참고

참고 자료
참고 풀이

15904_UCPC는 무엇의 약자일까? (Python)

0. 출처

1. 기록

  • 22/03/28 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>> 문자열 안에 u -> C -> P -> C 의 순서대로 있는지만 확인하면 된다.
>> 어떻게 확인할까
>> p = re.compile('[a-z]+')..? 

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
Union of Computer Programming Contest club contest

- 예제 출력 1 -
I love UCPC

- 예제 입력 2 -
University Computer Programming

- 예제 출력 2 -
I hate UCPC-

(3) 코드

import re

string = input()

p = re.compile('^.*U+.*C+.*P+.*C+.*$')


if re.match(p, string):
    print("I love UCPC")
else:
    print("I hate UCPC")

(4) 정리

(5) 참고

참고 풀이

15881_Pen Pineapple Apple Pen (Python)

0. 출처

1. 기록

  • 22/03/28 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>>
>>

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
15
ApPApPpAPpApPAp

- 예제 출력 1 -
2

- 예제 입력 2 -
7
pPApPAp

- 예제 출력 2 -
1

(3) 코드

num = input()
string = input()

answer = string.count('pPAp')

print(answer)

(4) 정리

처음에 string.count() 함수 이용해서 풀면되지 않나? 했는데
만약 string = 'pPApPAp' 인경우 count를 2번하게 되지 않나 하는 생각에 count() 함수의 정의에 대해서 찾아보았습니다.

"Return the number of non-overlapping occurrences of substring sub in string S[start:end].
Optional arguments start and end are interpreted as in slice notation."

문자열 S [ start : end ]의 서브스트링 서브의 오버랩되지 않는 발생 횟수를 반환합니다.
옵션의 인수 시작과 끝은 슬라이스 표기법과 같이 해석됩니다.

정의와 같이 오버랩되지 않는 발생 횟수가 반환되기때문에 위와 같은 문제에 걱정없이 사용해도 되겠습니다.

(5) 참고

다른 풀이

8595_히든 넘버 (Python)

0. 출처

1. 기록

  • 22/03/28 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>> 알파벳은 건너 뛰고 숫자를 발견시 숫자가 연속된지 확인한다.
>> 그러한 숫자들을 차례차례 더해서 출력한다.

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
14
ab13c9d07jeden

- 예제 출력 1 -
29

(3-1) 시간초과 코드

import re

num = int(input())
sentence = input()

rgx = re.compile("^[0-9]$")

answer = []
number = ''

for i in range(num):
    if re.match(rgx, sentence[i]) is not None:            # 숫자인 경우
        number += sentence[i]

    else:                                                 # 문자인 경우
        if number != '':
            answer.append(int(number))
        number = ''
        continue

print(sum(answer))

(3-2) 정답 코드

import re

num = input()
sentence = input()

def hidden_number(s):
    numbers = re.findall("\d+", sentence)
    answer = list(map(int, numbers))

    return sum(answer)

print(hidden_number(sentence))

(4) 정리

rgx 를 이용해서 숫자인지 문자인지 판단해주고 숫자인 경우 문자열을 이어주는 방식으로 합쳤다.
이후 알파벳이 나오면 합쳐준 숫자를 answer = [] 에 추가하고 마지막에 합계를 내는식으로 했는데 시간초과가 나와서 풀이를 찾아보았습니다.

(5) 참고

참고 풀이

2954_창영이의 일기장 (Python)

0. 출처

1. 기록

  • 22/03/28 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>> 앞에서 부터 차례대로 a,e,i,o,u 뒤의 두 알파벳을 지워버린다.

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
zepelepenapa papapripikapa

- 예제 출력 1 -
zelena paprika

- 예제 입력 2 -
bapas jepe doposapadnapa opovapa kepemipijapa 

- 예제 출력 2 -
bas je dosadna ova kemija

(3) 코드

line = input()
rst = []
i = 0
while i < len(line):
    if line[i] in ['a','e','i','o','u']:
        rst.append(line[i])
        i += 3
    else:
        rst.append(line[i])
        i += 1

print(''.join(rst))

(4) 정리

조건에 맞는 알파벳 뒤의 알파벳 2개를 del로 지워야하나..
지우면 인덱스번호 밀리는데 어떻게 처리하지 이러고 있다가 풀이를 찾아봤다.

(5) 참고

참고 풀이

5698_Tautogram (Python)

0. 출처

1. 기록

  • 22/03/28 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 여러 줄을 어떻게 입력받을지 생각해봐야 함 -> readlines() 이용
>> 입력 받은 줄에서 여러개의 단어를 어떻게 구분지을지 -> split('') 이용
>> 입력 받은 줄에서 여러개의 단어의 가장 앞 알파벳을 어떻게 비교할지

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

'''
- 예제 입력 1 -
Flowers Flourish from France
Sam Simmonds speaks softly
Peter pIckEd pePPers
truly tautograms triumph
this is NOT a tautogram
*

- 예제 출력 1 -
Y
Y
Y
Y
N
'''

(3-1) 풀이1

import sys

lines = sys.stdin.readlines()

for line in lines:
    print(line)
    line = line.rstrip()
    if '*' in line:
        exit()

    word_list = line.split(' ')
    word = word_list[0]             # 가장 첫번째 단어의
    first = word[0]                 # 첫번째 알파벳

    for i in range(len(word_list)):
        word = word_list[i]
        if i == len(word_list)-1:
            if word[0].startswith(first.upper()) or word[0].startswith(first.lower()):
                print("Y")
        elif word[0].startswith(first.upper()) or word[0].startswith(first.lower()):
            continue
        elif word[0] != first.upper() and word[0] != first.lower():
            print("N")
            break

(4) 정리

처음에 단어가 한 개만 입력되는 경우를 처리를 안해줘서 계속 '틀렸습니다'가 나와서 당황했습니다.
단어가 한 개만 입력되는 경우도 Tautogram으로 "Y"가 출력되도록 처리해야합니다.
또한 코드가 너무 길어 구현을 단순화하라는 조언도 받았습니다.

(5) 참고

참고 풀이

3447_버그왕 (Python)

0. 출처

1. 기록

  • 22/03/27 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조


1. 아이디어
>> 
>> 

2. 시간복잡도
>> 

3. 자료구조
>> 
>> 

(2) 예제 입력, 예제 출력

'''
- 예제 입력 1 -
print "No bugs here..."

void hello() {
BUGBUG
printfBUG("Hello, world!\n");
}

wriBUGBUGtelBUGn("Hello B-U-G");

- 예제 출력 1 -
print "No bugs here..."

void hello() {

printf("Hello, world!\n");
}

writeln("Hello B-U-G");
'''

(3-1) 풀이1

# input.txt

print "No bugs here..."

void hello() {
BUGBUG
printfBUG("Hello, world!\n");
}

wriBUGBUGtelBUGn("Hello B-U-G");
# 3447_버그왕.py

import sys

sys.stdin = open("input.txt", 'r')

def get_string_remove_BUG(s):
    string = list(s)
    while True:
        len_string = len(string)
        flag = True
        i = 0
        while i < len_string:
            if string[i:i+3] == ['B','U','G']:
                string[i:i+3] = []
                len_string -= 3
                flag = False
            else:
                i += 1
        if flag:
            break
    return ''.join(string)

while True:
    try:
        print(get_string_remove_BUG(input()))
    except:
        break

(3-2) 풀이2

import sys 
import re
code=sys.stdin.readlines() #여러 줄을 정답으로 받고

for i in code: #한 줄씩 검사하기

    while True:
        result=re.sub('BUG','',i) #BUG가 들어있으면 없애기

        #ABUBUGGB와 같은 경우는 AB가 되어야 하니까 while반복문으로 검사
        if 'BUG' in result: #있으면 한번 제거한 결과를 가지고 또 검사하도록
            i= result
        else: 
            print(result,end="") #줄바꿈까지 같이 출력되니까 end=""써주기
            break

(4) 정리

  1. 줄수 제한 없이 여러줄을 입력 받기
  2. 반복해서 BUG 찾기 등

브론즈 문제인데 어떻게 해야할지 전혀 감을 못잡았습니다.
전에는 무지성으로 모듈을 사용했다면,
참고한 풀이를 통해 이해를 기반한 모듈 사용의 중요성(?)을 배웠습니다.

sys.stdin의 동작방식이 궁금해서 찾아보았습니다.

input() 부터 알아보겠습니다.

"Read a string from standard input. The trailing newline is stripped."
"표준 입력으로부터 문자열을 읽어오고 후행 문자는 제거 된다" 라고 되어있습니다.
우선 표준 입력이란 제가 계속 콘솔창에 입력 예제 등을 '직접 입력'한 경우 등을 표준 입력이라 함을 알았습니다.
표준 입력의 정의를 찾아보면 "키보드로 입력 할 수도 있지만 파일로부터 입력을 지정 할 수도 있다"고 되어있습니다.

후행 문자는 뭔데?

\n 다음줄의 처음으로 줄바꿈 함
\r 커서를 그 줄의 맨 앞으로 이동시킴
초창기에는 이둘을 구분하였다고 하나 현재의 거의 대부분 시스템의 컴파일러 들은 \n만으로 다음줄 처음으로 이동하는 것으로 되어 있을겁니다.
따라서 \r을 쓰실일이 없다고 합니다.
즉, input() 사용시 엔터(\n)는 제거되고 입력됩니다.

그러면 sys.stdin 은?

"standard input file object; used by input()"
"표준 입력 파일 객체 : input() 함수에 의해 쓰여진다."
콘솔창에 직접 입력하는 방법 외로도 sys.stdin 을 사용하면 직접 입력을 대신하는 표준 입력이 됩니다.
이 경우 직접 입력 할 수도 있고 문자열등을 미리 입력한 파일 등을 불러와서 입력시킬 수도 있습니다.

sys.stdin.readlines() 함수

readlines() 는 여러줄을 입력할 수 있게끔 도와주는 함수입니다.
이때 콘솔창에서 직접입력해볼 수 있는데 보통 input() 함수는 엔터키로 콘솔창에서 탈출할 수 있지만 readlines() 함수의 경우 여러줄을 계속 입력해야되기 때문에 엔터키로 탈출할 수 없습니다. 그래서 여러줄 입력이 완료되면 ctrl+d 단축키로 탈출할 수 있습니다.

re모듈의 sub()함수

sub(패턴, 교체할 문자열, 문자열, 최대 교체 수, 플래그)
sub는 문자열에 맞는 패턴을 2번째 인자(교체할 문자열)로 교체합니다.
split의 최대 split 수와 동일하게 최대 교체 수를 지정하면 문자열에 맞는 패턴을 교체할 문자열로 교체하고 그 수가 도달하면 더이상 교체하지 않습니다.

import re


print(re.sub('a', 'z', 'ab'))
print(re.sub('a', 'zxc', 'ab'))
print(re.sub('a', 'z', 'aaaab'))
print(re.sub('a', 'z', 'aaaab', 1))


# zb
# zxcb
# zzzzb
# zaaab

(5) 참고

참고 풀이1
참고 풀이2
sys.stdin의 함수들
sys.stdin이 뭘 읽어오는거야?
어떻게 stdin이 읽어들이는 걸까?
Python의 sys모듈
이스케이프 시퀀스 정리
Standard input and output
re모듈 사용법

7576_토마토 (Python)

0. 출처

1. 기록

  • 22/03/25 (금)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조


1. 아이디어
>> BFS 이용 q에 토마토 위치를 담고  
>> 네 방향으로 익힌뒤 다시 익힌 토마토의 위치를 담고 카운트해준다.

2. 시간복잡도
>> o(v+n) ?

3. 자료구조
>> 이차원배열  
>> BFS  

(2) 예제 입력, 예제 출력

예제 입력 1
6 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1

예제 출력 1
8

예제 입력 2
6 4
0 -1 0 0 0 0
-1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1

예제 출력 2
-1

(3) 풀이

from collections import deque
from pprint import pprint

m, n = map(int, input().split())

a = n # 세로
b = m # 가로

graph = [list(map(int, list(input().split()))) for _ in range(a)]

# pprint(graph)

dx = [0, -1, 0, 1]
dy = [-1, 0, 1, 0]

q = deque()
for i in range(a):
    for j in range(b):
        if graph[i][j] == 1:
            q.append((i,j))

cnt = 0
while q:
    x, y = q.popleft()
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0<=nx<a and 0<=ny<b:
            if graph[nx][ny] == 0:
                graph[nx][ny] = graph[x][y] + 1
                q.append([nx,ny])
            else:
                continue
    cnt += 1

answer = 0
for i in range(a):
    for j in range(b):
        if graph[i][j] == 0:
            print(-1)
            quit()
        answer = max(answer, graph[i][j])

print(answer-1)

(4) 참고 및 정리

처음에 m(가로), n(세로) 순서로 입력되는 것을 x(세로), y(가로) 로 바꿨는데
밑에 부분에서 nx, ny 를 구할 때 x, y 를 직접 사용해서 꼬인 부분이 있었다. 항상 변수 사용에 주의하자!

이중 for 문을 빠져나오기 위해서는 break 를 사용하면 안됩니다.
추가적인 변수를 사용해주거나(흔히 flag = True 등) quit() 또는 exit() 함수를 이용해주면 쉽게 이중for문을탈출할 수 있습니다.

graph 자체에 날짜를 카운트 방법으로 추가적인 이차원 배열이나 변수를 사용하지않아도 되었습니다.
또한 max 함수를 이용해서 최댓값 비교도 손쉽게 할 수 있었습니다.

16918_봄버맨

0. 출처

1. 기록

  • 22/03/25 (금)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 3초라는 시간을 채우면 폭발하는게 중요
>> 특정 폭탄이 설치된 곳과 설치된 곳의 시간을 체크하는게 중요
>> 폭탄이 설치되지 않은 다른 곳에 모두 폭탄을 설치해야 됨 (BFS)
>> time_graph
>> bomb_graph


2. 시간복잡도
>> 어떻게 구하는거야?
>> 시간 복잡도 계산하는 법 알아봐야 겠다

3. 자료구조 
>> 이차원 배열
>> BFS 

(2) 예제 입력, 예제 출력

- 예제 입력 1 - (r, c, n초)
6 7 3
.......
...O...
....O..
.......
OO.....
OO.....

- 예제 출력 1 -
OOO.OOO
OO...OO
OOO...O
..OO.OO
...OOOO
...OOOO

- 예제 입력 2 -
6 7 4
.......
...O...
....O..
.......
OO.....
OO.....

- 예제 출력 2 -
OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO

- 예제 입력 3 -
6 7 5
.......
...O...
....O..
.......
OO.....
OO.....

- 예제 출력 3 -
.......
...O...
....O..
.......
OO.....
OO.....
'''

(3-1) 틀린 풀이

from pprint import pprint
from collections import deque

r, c, n = map(int, input().split())

bomb_graph = [list(map(str, list(input()))) for _ in range(r)]
time_graph = [[0]*c for _ in range(r)]

dx = [0, -1, 0, 1]
dy = [-1, 0, 1, 0]

def step1():
    for x in range(r):
        for y in range(c):
            if bomb_graph[x][y] == 'O':
                time_graph[x][y] += 1       # 1초 동안 아무것도 하지 않는다.

def step2():                                # 폭탄이 설치되지 않은 곳에 폭탄을 설치한다.
    for x in range(r):
        for y in range(c):
            if bomb_graph[x][y] == '.':     # 폭탄이 설치되어있지 않은 곳에
                bomb_graph[x][y] = 'O'      # 폭탄을 설치하고
                time_graph[x][y] += 1       # 시간 +1
            elif bomb_graph[x][y] == 'O':   # 이미 폭탄이 설치되있는 곳에는
                time_graph[x][y] += 1       # 시간만 +1

def step3():
    for x in range(r):
        for y in range(c):
            if bomb_graph[x][y] == 'O':     # 폭탄이 설치되어 있고
                time_graph[x][y] += 1       # 시간을 +1 했을 때
                if time_graph[x][y] >= 3:   # 시간이 3초이면
                    bomb_graph[x][y] = '.'  # 그 자리에 터뜨리고
                    for i in range(4):      # 4방향을 확인
                        nx = x + dx[i]
                        ny = y + dy[i]
                        if 0<=nx<r and 0<=ny<c:
                            if bomb_graph[nx][ny] == 'O':   # 폭탄이 있는 곳이면
                                bomb_graph[nx][ny] = '.'    # 폭탄을 없애고
                                time_graph[nx][ny] = 0      # 해당 시간을 0으로 초기화
    # pprint(bomb_graph)


time = 0

step1()
time += 1

while 1:
    if time >= n:
        break
    else:
        step2()
        time += 1

    if time >= n:
        break
    else:
        step3()
        time += 1

for i in range(r):
    for j in range(c):
        if j == (c-1):
            print(bomb_graph[i][j])
        else:
            print(bomb_graph[i][j], end='')

(3-2) 정답 풀이

from collections import deque

r, c, n = map(int, input().split())

bomb_graph = [list(map(str, list(input()))) for _ in range(r)]

time_graph = [[0]*c for _ in range(r)]

dx = [0, -1, 0, 1]
dy = [-1, 0, 1, 0]

def loc_bombs():                            # 폭탄 위치 찾아 q 에 저장
    for x in range(r):
        for y in range(c):
            if bomb_graph[x][y] == 'O':
                q.append((x, y))


def make_bombs():                              # 모든 자리에 폭탄 설치
    for x in range(r):
        for y in range(c):
            if bomb_graph[x][y] == '.':
                bomb_graph[x][y] = 'O'

def explode():                              # q 에 들어있는 좌표로 폭탄 터트림
    while q:
        x, y = q.popleft()
        bomb_graph[x][y] = '.'
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<=nx<r and 0<=ny<c:
                bomb_graph[nx][ny] = '.'


n -= 1  # 1초 동안 아무것도 하지 않는다
while n:
    q = deque()
    loc_bombs()
    make_bombs()
    n -= 1
    if n == 0:
        break
    explode()
    n -= 1

for i in range(r):
    for j in range(c):
        if j == (c-1):
            print(bomb_graph[i][j])
        else:
            print(bomb_graph[i][j], end='')

3. 참고 및 정리

3초가 된 폭탄은 동시에 터지도록 작성해야합니다.

틀린 풀이로 풀 경우 동시에 설치된 폭탄들이 위치에 따라 연속되어 있는 경우 3초가 되면 선순위에 있는게 먼저 터져 후순위에 있는 폭탄이 사라지게 되는 오류가 발생됩니다. (같은 시기에 설치된 폭탄은 '동시에' 터져야 함)
큐나 덱의 자료구조를 이용해 초기 폭탄 위치를 보관해줌으로서 이러한 문제점을 해결할 수 있습니다.

또한 이러한 자료구조를 이용함으로서 초기 설치한 폭탄과 나중에 설치한 폭탄을 구분지어줄 수 있습니다.


참고한 풀이

+ Recent posts