친절하게 힌트까지 있는 문제이다.

일단 문제는 굉장히 간단한데 문제는 백준의 시간 초과이다.

이전에 올린 문제 (https://gettingtoknowit.tistory.com/99)와 같이 sys를 사용해야 시간 초과가 걸리지 않는다.

 

[백준] 10828_스택 파이썬

우선 간단히 스택 구조에 대해서 정리해보자면, 스택(stack)은 LIFO(Last In First Out) 구조이다. 즉, 가장 최근에 스택에 추가한 항목이 가장 먼저 나오는 항목이 된다. 아마 C/C++로 했으면 코드가 길어

gettingtoknowit.tistory.com


코드는 다음과 같이 하면 되지만, 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import sys
= int(sys.stdin.readline())
num_list = []
for _ in range(k):
    num = int(sys.stdin.readline())
    if num != 0:
        num_list.append(num)
    else:
        num_list.pop()
 
total = 0
for i in num_list:
    total += i
print(total)
cs

 

위의 코드를 sum으로 더 간단하게 만드는 것 또한 가능하다.

1
2
3
4
5
6
7
8
9
import sys
= int(sys.stdin.readline())
num_list = []
for _ in range(k):
    num = int(sys.stdin.readline())
    if num != 0:
        num_list.append(num)
    else:
        num_list.pop()
print(sum(num_list))
cs

 

 

문제 출처: https://www.acmicpc.net/problem/10773

 

10773번: 제로

첫 번째 줄에 정수 K가 주어진다. (1 ≤ K ≤ 100,000) 이후 K개의 줄에 정수가 1개씩 주어진다. 정수는 0에서 1,000,000 사이의 값을 가지며, 정수가 "0" 일 경우에는 가장 최근에 쓴 수를 지우고, 아닐 경

www.acmicpc.net


우선 간단히 스택 구조에 대해서 정리해보자면, 스택(stack)은 LIFO(Last In First Out) 구조이다. 즉, 가장 최근에 스택에 추가한 항목이 가장 먼저 나오는 항목이 된다.

이미지 출처: https://www.programiz.com/dsa/stack

 

아마 C/C++로 했으면 코드가 길어지고 조금은 어려웠을지도 모르겠다고 느껴지겠지만,

확실히 파이썬으로 하니 간단하게 처리할 수 있었다.

파이썬에서는 C++처럼 스택에 대한 STL은 없지만, list의 append, pop 메서드를 활용하여 간단하게 처리할 수 있다.

 

자세한 부분은 https://docs.python.org/ko/3/tutorial/datastructures.html를 참고하면 된다.

 

5. 자료 구조 — Python 3.9.6 문서

5. 자료 구조 이 장에서는 여러분이 이미 배운 것들을 좀 더 자세히 설명하고, 몇 가지 새로운 것들을 덧붙입니다. 5.1. 리스트 더 보기 리스트 자료 형은 몇 가지 메서드들을 더 갖고 있습니다. 이

docs.python.org


대신 백준에서 파이썬 코드를 제출할 때, input()을 활용하면 시간 초과가 뜬다. 

다라서, sys.stdin.readline()을 사용해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import sys
num = int(sys.stdin.readline())
stack = []
= 0
for i in range(num):
    stack_word = sys.stdin.readline()
    if stack_word[:4== "push":
        stack.append(int(stack_word[5:]))
    if stack_word[:3== "pop":
        if len(stack) != 0:
            print(stack.pop())
        else:
            print(len(stack) - 1)
    elif stack_word[:4== "size":
        print(len(stack))
    elif stack_word[:5== "empty":
        if len(stack) == 0:
            print(1)
        else:
            print(0)
    elif stack_word[:3== "top":
        if len(stack) == 0:
            print(-1)
        else:
            print(stack[-1])
    else:
        pass
    i += 1
 
cs

 

 

문제 출처: https://www.acmicpc.net/problem/10828

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지

www.acmicpc.net


생각보다 시간을 썼던 문제이지만, 논리만 잘 세우면 금방 해결할 수 있는 문제이다.

첫 번째 for문에서 member_list.append만 제대로 해주면 된다. 

 

그리고 lambda를 잘 사용해서 정렬 처리를 하는 게 또 다른 핵심이라고 보면 될 듯하다.

1
2
3
4
5
6
7
8
9
10
11
12
num = int(input())
member_list = []
for _ in range(num):
    age, name = map(str, input().split())
    age = int(age)
    member_list.append((age, name))
# print(member_list)
# 나이가 같으면 먼저 가입한 사람이 앞에 오는 순서
member_list.sort(key = lambda x: x[0])
# print(member_list)
for i in member_list:
    print(i[0], i[1])
cs

 

 

문제 출처: https://www.acmicpc.net/problem/10814

 

10814번: 나이순 정렬

온라인 저지에 가입한 사람들의 나이와 이름이 가입한 순서대로 주어진다. 이때, 회원들을 나이가 증가하는 순으로, 나이가 같으면 먼저 가입한 사람이 앞에 오는 순서로 정렬하는 프로그램을

www.acmicpc.net

베스킨라빈스 31 게임의 자세한 내용은 다음 링크를 참고하자

https://namu.wiki/w/%EB%B0%B0%EC%8A%A4%ED%82%A8%EB%9D%BC%EB%B9%88%EC%8A%A4(%EA%B2%8C%EC%9E%84) 

 


간단히 정리해보면, 

1. 나와 컴퓨터 모두 한 턴에 1회 ~ 3회까지만 숫자를 외칠 수 있음

2. 31을 외치는 사람이 지는 것이다.

 

이런 규칙으로 컴퓨터와 대결하는 간단히 프로그램을 파이썬으로 작성해보면 다음같이 작성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def baskin31():
    import random
    current_number = 0  # 현재 숫자
    while True:
        # list(map(int, input().split()))을 통해서 input값을 빈칸을 구분자로 하여 int형으로 받아서 list로 저장하라는 뜻이다.
        player = list(map(int, input("Player는 숫자를 입력하세요: ").split()))
        # player는 숫자 3개까지만 입력이 가능하다
        if len(player) > 3:
            print("숫자는 3개까지만 입력이 가능합니다.")
            continue
        # 숫자는 이전 값(=현재 숫자) 보다 1만큼 큰 숫자로 시작해야 한다.
        if player[0!= current_number + 1:
            print("이전의 숫자보다 1만큼 큰 숫자로 시작해야 합니다.")
            continue
        # 숫자는 연속적으로 입력되어야 한다.
        if len(player) == 3:
            if player[2- player[1!= 1 or player[1- player[0!= 1:
                print("연속된 숫자가 입력되어야 합니다.")
                continue
            else:
                current_number = player[2]
        elif len(player) == 2:
            if player[1- player[0!= 1:
                print("연속된 숫자가 입력되어야 합니다.")
                continue
            else:
                current_number = player[1]
        elif len(player) == 1:
            current_number = player[0]
 
        # 현재 숫자는 player 리스트의 가장 끝 index에 해당하는 정수값이다.
        current_number = player[-1]
        print(f"현재 숫자 : {current_number}")
 
        # player가 31 이상의 숫자를 선택할 시에 패배한다.
        if current_number >= 31:
            print("\nPlayer가 패배했습니다.")
            break
 
        # 현재 숫자에서 31이 되기까지 남은 차례를 remaining_turn이다. line 52에서 사용된다.
        remaining_turn = 31 - current_number
        computer = list()
        computer_turn = random.randint(13)
        for i in range(computer_turn):
            current_number += 1
            computer.append(current_number)
            # 컴퓨터 입장에서 승리를 하기 위해서 31 이전의 숫자까지 선택한다.
            # 하지만 31밖에 선택지가 없으면 31을 선택 후 끝낸다.
            if current_number >= 31:
                print(f"컴퓨터 : 31")
                break
            if computer_turn <= remaining_turn:
                print(f"컴퓨터 : {current_number}")
                continue
        print(f"현재 숫자 : {current_number}\n")
 
        # 컴퓨터가 31을 선택할 시에 player의 승리
        if computer[-1== 31:
            print("Player가 승리했습니다.")
            break
 
 
# 숫자 게임을 시작하자
print('=' * 30)
print("\t베스킨라빈스31 게임 시작!")
print('=' * 30)
baskin31()
 
cs

 


간단하게 에라토스테네스의 체를 사용하면 풀 수 있는 문제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def isPrime(num):
    if num == 1:
        return False
    else:
        for i in range(2int(num**0.5+ 1):
            if num % i == 0:
                return False
        return True
 
 
= int(input())
num = list(map(int, input().split()))
cnt = 0
for i in range(n):
    if isPrime(num[i]) is True:
        cnt += 1
print(cnt)
 
cs

처음에 line 13에 있는 cnt =0 이라는 코드를 넣지 않고 돌렸었는데, 이렇게 되면 런타임 에러(NameError)가 뜬다.

이렇게 되는 이유는 아마 채점프로그램의 문제인 것 같기도 한데, 또 특이한 점은 atom의 hydrogen을 통해서 프로그램을 실행시켰을 때도 계속 cnt가 초기화가 되지 않고 쌓이는 현상이 나타난다는 것이다.

 

정확하지는 않지만, 초기화가 이루어지지 않을 경우, cnt가 할당된 메모리가 해제가 되지 않고 계속 쌓이기 때문인 듯 싶다.

 

아무튼, cnt = 0으로 제대로 변수를 초기화시켜주면 코드는 제대로 작동한다.


참고로 에라토스테네스의 체는 이전에 풀었던 문제은 다음 링크를 참조하자.

https://gettingtoknowit.tistory.com/89

 

[백준] 1929_소수 구하기 파이썬 (시간초과 VS 에라토스테네스의 체)

시간초과와의 싸움이었다. 간단히 구하는 것은 가능하지만 계속 오버타임이 발생했다. 처음에 썼던 코드 2개를 올려보면 다음과 같다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 def count_prime_number(n, m):    ..

gettingtoknowit.tistory.com

 


 

문제 출처: https://www.acmicpc.net/problem/1978

 

1978번: 소수 찾기

첫 줄에 수의 개수 N이 주어진다. N은 100이하이다. 다음으로 N개의 수가 주어지는데 수는 1,000 이하의 자연수이다.

www.acmicpc.net

 


해당 문제가 어려운 이유는 우리가 흔히 아는 반복문을 통해서 풀면 "시간 초과"가 나오기 때문이다.

시간 제한을 보면 "0.15초"라고 되어있다

 

해당 문제는 수학적으로 생각이 꽤 필요하다고 생각된다.

 

결국 반복문 없이 단 번에 해결이 되도록 해야 한다는 것인데....

방법을 결국 스스로 찾지 못하고 결국 구글링의 힘을 빌려버렸다.

 

그랬더니 공통적인 방법은 %연산자를 통해서 수학적으로 문제를 접근해야 한다는 점이다.

 


우선 while문으로 해서 시간초과에 걸린 방법은 다음과 같다. 

1
2
3
4
5
6
7
8
9
10
11
a,b,v = map(int,input().split())
day = 1
height = 0
while True:
    height += a
    if height >= v:
        break
    else:
        height = height - b
        day += 1
print(day)
cs

하지만 결국에는 다음과 같이 코딩을 해야 비로소 0.15초 시간 제한 안에 들어갈 수 있다...

1
2
3
4
5
6
a,b,v=map(int,input().split())
 
if (v-b)%(a-b)==0:
    print((v-b)//(a-b))
else:
    print((v-b)//(a-b)+1)
cs

 

문제 출처: https://www.acmicpc.net/problem/2869

 

2869번: 달팽이는 올라가고 싶다

첫째 줄에 세 정수 A, B, V가 공백으로 구분되어서 주어진다. (1 ≤ B < A ≤ V ≤ 1,000,000,000)

www.acmicpc.net

하도 시간초과로 인해서 틀리는 문제가 발생해서 실행 시간을 측정할 수 있는 코드를 정리했다.

단위는 초로 나온다.

1
2
3
4
5
6
7
8
import time
start = time.time()  # 시작 시간 저장
 
 
# 작업 코드
 
 
print("time :", time.time() - start)  # 현재시각 - 시작시간 = 실행 시간
cs

 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while True:
    flag = 1   # 숫자 하나만 들어갈 경우, yes로 처리하기 위해서 1로 초기화
    num = list(input())
    if num[0== '0':
        break
    else:
        for i in range(len(num)//2):
            if num[i] == num[len(num)-1-i]:
                flag = 1
            else:
                flag = 0
                break  # 1223 같은 수를 위해서 반드시 필요
        if flag == 1:
            print("yes")
        else:
            print("no")
 
cs

2번 시도해서 틀렸던 문제.

첫 번째 이유는 flag = 0으로 초기화했다는 점이다. flag = 1로 초기화를 해야 일의 자리 숫자를 입력했을 경우, yes로 처리 할 수 있다.

 

두 번째 이유는 for문의 if-else에서 break를 넣지 않았다는 점이다. 

코드의 주석에 나와있듯이 반례는 1223을 들 수 있다. 

break가 없으면, 1 <-> 3 에서 flag = 0이 되었다가 2 <-> 2에서 1로 덧씌워져 yes로 출력된다.

따라서, break를 통해 만약 no이면 바로 if-else문을 빠져나올 수 있도록 처리하면 된다.

 

 

문제 출처: https://www.acmicpc.net/problem/1259

 

1259번: 팰린드롬수

입력은 여러 개의 테스트 케이스로 이루어져 있으며, 각 줄마다 1 이상 99999 이하의 정수가 주어진다. 입력의 마지막 줄에는 0이 주어지며, 이 줄은 문제에 포함되지 않는다.

www.acmicpc.net

 


푸는데 어려움을 겪었다.

 

처음 생각했던 방법은 시간초과가 나올 것 같은 방법이었다.

배열을 만들어 a~z까지 방을 만들고, for문을 통해서 단어를 하나하나 갯수를 배열에 채우는 것이었다.

 

이 방법 말고 다음으로 택했던 방법은 dict를 사용하는 것이었다.

의도는 단어를 이루는 알파벳을 key로 하고, 갯수를 value로 해서 key와 value를 계속 update 시키는 것이었다.

그런데, 문제에 봉착한 부분이 있었는데, 그 부분은 다음의 코드를 통해 알 수 있다.

1
2
3
4
5
6
7
8
9
word = input()
word = word.lower()
dictionary = {}
for i in word:
    if i not in dictionary:
        dictionary = dict(i = 1)
    else:
        dictionary[i] = dictionary[i] + 1
print(max(dictionary))
cs

보면 알 수 있겠지만, 틀린 이유는 dictionary에 코드처럼 'i'를 넣으면, for문의 i에 해당하는 값이 들어가지 않고, 진짜로 'i' 값이 들어간다. 따라서, max를 출력하게 되면 i 혼자 출력하게 된다.

즉, 틀린 코드다.

 

뭔가 방법이 있을 것 같긴 한데... 아직 찾지 못하였다.

혹시 방법을 안다면 댓글에 조언 및 언급을 해주시면 정말로 감사하겠습니다 ....

 


아무튼 dict()로 해결을 하지 못해서 다시 처음부터 다시 시작했다 (사실 결국 인터넷 검색을 했... ㅠ)

그렇게 해서 결국 찾은 방법은 set()와 count()를 사용하는 것이다. 

set()는 중복되는 값을 없애는 것이고, count()는 set에 있는 원소들이 실제로 각각 몇 개씩 있는지 세는 것이다.

이런 함수를 잘 알고 있어야 한다는 사실을 한 번 또 느낀다.

 

따라서 다음과 같은 코드로 간단히 해결이 된다.

1
2
3
4
5
6
7
8
9
10
11
12
word = input().lower()      # word = mississipi / baaa
words = list(set(word)) # set를 통해서 중복 없애기 ==> word_list = ['m', 'i', 's', 'p'] / ['b', 'a']
cnt = []
 
for i in words:         # i = m, i, s, p / b, a
    count = word.count(i)  # count()를 통해서 set의 원소의 갯수를 센다.
    cnt.append(count)       # cnt = [4, 4, 1, 1] / [1, 3]
 
if cnt.count(max(cnt)) >= 2:
    print("?")
else:
    print(words[(cnt.index(max(cnt)))].upper())
cs

 

문제 출처: https://www.acmicpc.net/problem/1157

 

1157번: 단어 공부

알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

www.acmicpc.net

 


간단한 논리구조로 해당 문제를 풀 수 있다.

1) int로 3개의 숫자를 입력받고,

2) 입력 받은 수의 곱의 결과값의 자료형을 list로 변환시킨다.

(여기서 해맸다.. for문을 통해 하고 싶지 않고 map을 통해 하고 싶었다... 그런데 map에서 str(A*B*C) 부분을 str을 사용해야 한다는 점을 계속 간과해서 해맸다.)

3) 이후로는 이중 for문을 통해서 list의 문자 하나씩 i를 통해 비교를 하는데,

4) i와 j를 비교한다 (j는 nums 배열의 방 번호를 뜻하도록 for문에서 0~9까지 비교하도록 한다)

5) 이후에 다시 for문을 통해서 nums 배열을 출력하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
= int(input())
= int(input())
= int(input())
res = list(map(intstr(A*B*C)))  # 이 부분을 유의하자. int -> list로 바꾼다.
nums = [0]*10
for i in res:
    for j in range(10):
        if j == int(i):
            nums[j] += 1
for j in range(10):
    print(nums[j])
 
cs

 

 

문제 출처: https://www.acmicpc.net/problem/2577

 

2577번: 숫자의 개수

첫째 줄에 A, 둘째 줄에 B, 셋째 줄에 C가 주어진다. A, B, C는 모두 100보다 크거나 같고, 1,000보다 작은 자연수이다.

www.acmicpc.net

 

+ Recent posts