import sys
input = sys.stdin.readline

S = input().strip()    # S 입력 (가능 여부 판독 문자)
T = input().strip()    # T 입력 (조건 문자)

while S != T and len(T) > 0:    # T와 S가 같지 않고 T의 길이가 0보다 큰 경우에만 진행
    if T[-1] == 'B':    # T의 마지막 문자가 B일 경우
        T = T[::-1][1:]    # T를 뒤집고 처음 문자를 제외하여 T에 저장 (즉, 마지막 B를 제거한 역순)
    else:    # T의 마지막 문자가 A일 경우
        T = T[::-1][1:][::-1]    # T를 뒤집고 처음 문자를 제외한 후 다시 뒤집어 T에 저장 (즉, 마지막 A만 제거함)
print(1 if S == T else 0)    # S와 T가 같은 경우 1을 출력하고 같지 않을 경우 0을 출력

S부터 시작하지 않은 이유는 S 뒤에 A가 와야할지 B가 와야할지 모르기 때문이다.

반대로 역으로 보았을 때 T의 마지막 문자에 따라서 진행해주면 되기 때문에 T를 보고 해주면 된다.

 

다른 풀이들을 보니 list로 이용해서 푸는 풀이가 많던데 str를 이용하여 풀고 싶어 A에서는 돌리는 행위가 두 번 들어가 있다..

해당 부분이 불편하면 다른 메소드를 쓰면 되겠지만 왠지 시간초과가 발생할 수도 있을 것 같아서 그냥 두 번 돌렸다.

Python에서 find 내장함수를 사용하면 쉽게 해결할 수 있습니다.

 

문제 자체가 find의 사용을 요구하는 것처럼 보였는데, 실제로 find에서 단어가 존재하지 않으면 -1을 출력합니다.

 

따라서, find를 이용하면 쉽게 해결할 수 있는 문제였습니다! (+ Python에서의 ASCII 사용법인 chr과 ord도 사용해야 합니다.)

 

import sys
input = sys.stdin.readline

answer = []    # 정답을 저장할 리스트 생성
word = input().strip()    # 단어 입력

for i in range(ord('a'), ord('z')+1):    # a부터 z까지 반복
    answer.append(word.find(chr(i)))    # 알파벳의 위치를 단어에서 찾고 정답에 추가 (없을 경우 -1이 자동 추가)

print(*answer)    # 정답 출력

 

파이썬에서 ASCII 코드를 사용하는 방법은 간단하다.

 

문자를 숫자로 바꾸는 경우 ord()를 사용하는데 해당 함수를 사용하면 된다.

 

(숫자를 문자로 바꾸는 방법은 chr())

import sys
input = sys.stdin.readline

S = input().strip()    # 단어 입력
answer = [0] * 26    # count할 리스트 생성

for ch in S:
    answer[ord(ch)-97] += 1 

print(*answer)    # 정답 출력

지난 번에 GCD 합 문제를 풀면서 Fraction을 이용한 적이 있는데, 해당 library를 이용하면 쉽게 풀 수 있다!

 

사실, 해당 library 안 써도 쉽게 풀 수 있을 것 같기는 하다..ㅋㅋㅋ

 

Fraction library는 두 수를 기약 분수 꼴로 나타내 준다.

 

문제는 기약 분수 꼴로 나타낼 때 완전히 정수로 나눠진다면 분모에 1이 남겨지지 않고 정수로 그대로 출력된다는 점이다.

 

따라서 완전히 정수로 나눠질 때 분모에 1을 추가해주는 작업을 따로 해주면 된다!

 

import sys
from fractions import Fraction    # 기약 분수로 나타내는 Python Library
input = sys.stdin.readline

N = int(input())    # 링의 개수를 입력
rings = list(map(int, input().strip().split(' ')))    # 링의 반지름들을 입력

for i in range(1, N):    # 첫 번째 링을 제외한 나머지 링들에 대해서 진행
    if rings[0] % rings[i] == 0:    # 두 수가 정수꼴로 나눠지면
        print(str(int(rings[0]/rings[i])) + '/' + '1')    # 분모가 1인 분수꼴로 표현
    else:    # 두 수가 정수꼴로 나눠지지 않는다면
        print(Fraction(rings[0], rings[i]))    # Fraction을 이용해 분수로 표현

바로 직전에 풀어보았던 GCD 합 문제처럼 combinations library를 이용하면 쉽게 풀 수 있는 문제였다.

 

from itertools import combinations    # 수학에서의 조합을 사용할 수 있게 해주는 library
import sys
input = sys.stdin.readline    # 시간 초과 error를 해결하기 위한 input함수 재정의

result = []    # 정답 저장

N = int(input())    # 수열 S의 크기
S = list(map(int, input().strip().split(' ')))    # 수열 S

for i in range(1, N+1):    # 수열 S의 크기만큼 반복
    for args in list(combinations(S, i)):    # 수열 S에서 i개를 꺼내어 조합
        result.append(sum(args))    # 조합으로 나온 수 i개를 합하여 나온 결과를 저장

result = set(sorted(result))    # 중복 제거를 위해 집합으로 변환

for i in range(1, max(result) + 2):    # 1부터 result의 결과보다 1 큰 수까지 반복
    if i not in result:    # 정수 i가 result에 존재하지 않을 경우 출력 후 마침
        print(i)
        break

 

combinations의 수학적 정의를 생각해보면, nCx에서 x가 n/2를 넘어가면 n-x로 바뀌는 경우 시간이 더 적게 소모된다.

 

해당 부분을 적용하면 시간적인 부분에서 더 감소하지 않을까 생각하여 다시 제출하였다.

 

from itertools import combinations    # 수학에서의 조합을 사용할 수 있게 해주는 library
import sys
input = sys.stdin.readline    # 시간 초과 error를 해결하기 위한 input함수 재정의

result = []    # 정답 저장

N = int(input())    # 수열 S의 크기
S = list(map(int, input().strip().split(' ')))    # 수열 S

for i in range(1, N+1):    # 수열 S의 크기만큼 반복
    if i > N/2:    # 현재 정수가 N/2보다 크다면
        for args in list(combinations(S, N-i)):    # 수열 S에서 N-i개를 꺼내어 조합
            result.append(sum(S) - sum(args))    # 조합으로 나온 수 i개를 합하여 나온 결과를 전체 수열의 합에 뺀 후 저장
    else:    # 현재 정수가 N/2보다 작다면
        for args in list(combinations(S, i)):    # 수열 S에서 i개를 꺼내어 조합
            result.append(sum(args))    # 조합으로 나온 수 i개를 합하여 나온 결과를 저장

result = set(sorted(result))    # 중복 제거를 위해 집합으로 변환

for i in range(1, max(result) + 2):    # 1부터 result의 결과보다 1 큰 수까지 반복
    if i not in result:    # 정수 i가 result에 존재하지 않을 경우 출력 후 마침
        print(i)
        break

 

 

이번에는 아이디어 적인 부분에서 나름 창의적으로 한 것 같아서 풀이를 공유하기 설렌다!

 

내가 생각한 아이디어는 다음과 같다.

 

1. 두 수를 분수꼴로 나타낸다. (이 때, 분수는 기약분수가 된다.)

 

2. 나눠진 수를 분자로 나누면 GCD 등장!

 

이 아이디어면 소수를 따로 판별할 필요 없이 가능하다.

 

예시를 두 개 들어서 설명해 보겠다.

 

숫자 30과 45가 있다고 가정해 보면, 1번에 의해 30/45인 2/3이 나타나게 된다.

 

이후 2번에 의해 30/2 = 15가 나타나게 되는데, 이는 GCD이다.

 

하나 더, 숫자 3과 7이 있다고 가정해 보면, 1번에 의해 3/7이 나타나게 된다.

 

이후 2번에 의해 3/3 = 1이 나타나게 되는데, 이 역시 GCD이다.

 

 

이 행위가 가능한 이유를 보면, "기약 분수"로 표현한다는 것 자체가 GCD로 나눠진 값이다.

 

즉, GCD로 나눠진 값을 원래 값으로 나누면 GCD가 나타나게 되는 것!

 

이 아이디어를 구현하기 위해서 combinations와 Fraction library를 import 하였다.

 

from itertools import combinations    # 수학에서의 조합을 사용할 수 있게 해주는 library
from fractions import Fraction    # 분수식으로 표현할 수 있게 해주는 library
import sys
input = sys.stdin.readline    # 시간 초과 error를 해결하기 위한 input함수 재정의

n = int(input())    # 테스트 케이스의 개수
for _ in range(n):
    answer = 0    # 정답을 저장하는 변수
    num, *numbers = map(int, input().strip().split(' '))    # 개수와 숫자들을 모두 입력받는 방법

    for (num1, num2) in list(combinations(numbers, 2)):    # numbers에서 2개씩 뽑는 조합을 진행
        f = Fraction(num1, num2)    # num1과 num2를 분수식으로 표현 (이 때, 기약분수로 표현됨)
        answer += num1 // f.numerator    # num1을 분자로 나눈다면 GCD (num2을 분모로 나눠도 동일)

    print(answer)    # 정답 출력

 

숫자를 입력받는 방법을 모른다면 Asterisk를 검색해보길 권장한다.

다음으로 푼 문제가 쇠막대기 문제이다.

 

레이저만 개수를 세어 주는 것이 아니라 막대기가 레이저에 의해서 나누어지는 것을 주의깊게 보아야 한다.

 

특히, 이번 문제는 조금 관점을 다르게 보면 쉽게 풀 수 있던 문제였다.

 

반복문을 돌면서 레이저를 만나는 경우에는 현재 레이저가 있는 층의 number만큼 막대가 분할되고, 층이 끝난다면 1만 추가해주면 되는 아이디어였다!

 

import sys
input = sys.stdin.readline    # 시간 초과 error를 해결하기 위한 input함수 재정의

sticks = input().strip()    # 문장을 입력받는다.
laser_stack = []    # 층또는 레이저가 쌓일 list
answer = 0    # 정답은 0부터 시작

for idx in range(len(sticks)):
    if sticks[idx] == '(':    # 층 또는 레이저가 시작될 경우
        laser_stack.append('(')    # stack에 추가
    else:    # 층이 끝나거나 레이저가 끝난 경우
        laser_stack.pop()    # 층 끝남 및 레이저만 존재한 경우 레이저 제거
        if sticks[idx-1] == '(':    # 즉, 레이저인 경우
            answer += len(laser_stack)    # 레이저가 한 번 발사 될 때 마다 해당 층부터 아래 층까지 조각남
        else:    # 레이저가 아닌 층이 끝난 경우
            answer += 1    # 레이저 두 번이면 쇠 막대기 하나는 세 개로 쪼개지기 때문

print(answer)    # 정답 출력

 

사실 아이디어가 생각나지 않아서 다른 블로그에 올라온 내용을 참고했다.

참고한 블로그 : https://inuplace.tistory.com/844

 

else문에서 laser_stack.pop()을 먼저 실행한 이유는 레이저든 아니든 pop을 실행해주어야 했기 때문이다.

import sys
input = sys.stdin.readline    # 시간 초과 error를 해결하기 위한 input함수 재정의

sentence = input().strip()    # 문장을 입력받는다.
answer = []    # 정답을 입력할 리스트 생성
temp = ''    # <>안에 값이 들어가 있지 않다면 저장할 빈문자열 생성
flag = False    # 해당 문자가 >와 < 사이에 존재한다면 False, <와 >사이에 존재한다면 True

for idx, ch in enumerate(sentence):    # 문장 안에 있는 각각의 문자마다 반복
    if ch == '<':    #  문자가 <인 경우
        if not flag:    # 만약 이전까지 >와 <사이에 존재했었다면
            answer.append(temp[::-1])    # 해당 단어를 거꾸로 반환하여 정답에 저장
            temp = ''    # 빈문자열로 재할당
        answer.append(ch)    # 정답에 < 문자 추가
        flag = True    # <가 시작하므로 flag를 True로 바꿔주어야 함
    elif ch == '>':    # 문자가 > 인 경우
        answer.append(ch)    # 정답에 > 문자 추가
        flag = False    # 다음 문자부터 > 뒤에 해당하므로 False
    elif ch == ' ':    # 문자가 빈칸이라면
        answer.append(temp[::-1])    # temp 속 문자들을 거꾸로 반환하여 정답에 저장
        answer.append(ch)    # 공백 문자도 정답에 저장
        temp = ''    # temp는 다시 빈 단어로 만들어준다.
    else:    # 문자가 일반 문자라면
        if flag:    # flag가 True인 경우. 즉, <와 > 사이에 존재하는 문자일 경우
            answer.append(ch)    # 정답에 문자 바로 추가
        else:    # flag가 False인 경우. 즉, >뒤에 존재하는 문자일 경우
            temp += ch    # temp에 문자 저장
    if idx == len(sentence) - 1:    # 마지막 문자일 경우
        answer.append(temp[::-1])    # temp에 있는 문자 거꾸로 반환하여 정답에 저장

print(''.join(answer))    # 정답을 문자열 형태로 출력

지난 번 단어 뒤집기 문제보다 조금 더 복잡한 문제이다.

 

split으로 가능했던 반면, 이번에는 문자 하나하나에 대한 탐색과 조건 설정을 까다롭게 해주어야 했었다.

 

 

+ Recent posts