파이썬을 입문하는 사람이라면 꼭 이 사이트를 알아야 한다고 생각한다.

생가보다 많은 사람들이 모르는 사이트이기 때문에 이렇게 소개를 하고자 한다.

 

파이썬 튜터(Python Tutor)라는 사이트이다.

 

이 사이트에서는 코드를 입력하면, 해당 코드를 한 줄 한 줄 과정을 수동으로 조작하면서 시각화된 코드를 볼 수 있다.

파이썬 입문자에게 첫 번째 벽인 반복문의 경우, 이 사이트를 통해서 공부를 하면 매우 효과적이라고 생각된다.

 

http://www.pythontutor.com/

 

Python Tutor - Visualize Python, Java, C, C++, JavaScript, TypeScript, and Ruby code execution

VISUALIZE CODE EXECUTION Learn Python, Java, C, C++, JavaScript, and Ruby Python Tutor helps people overcome a fundamental barrier to learning programming: understanding what happens as the computer runs each line of code. You can use it to write Python, J

www.pythontutor.com


[파이썬 튜터 사용 방법]

1. 사이트에 들어가게 되면 다음과 같은 창이 뜬다.

빨간색으로 표시한 부분 (Start visualizing your code now)를 클릭하라

 

2. Start visualizing your code now를 클릭하면 다음과 같은 창이 뜰 것이다. 

   여기에 원하는 코드를 입력하면 된다.

코드를 입력하고 나면 1과 2중에 선택해서 클릭하면 된다.

3. 코드를 입력하고 난 후 위의 사진에서 보이는 것과 같이 1과 2 중에서 선택해서 클릭하면 된다.

   그런데 몇 주간 사용해본 결과 1번보다는 2번을 더 많이 사용하게 된다는 느낌이 들었다.

 

4. Live Programming Mode를 누르면 다음과 같은 창이 뜬다.

   별표로 표시된 막대를 끌어서 원하는 과정으로 옮길 수가 있다.

   또는 그 밑에 있는 버튼 4개(First, Prev, Next, Last)로 옮길 수도 있다.


[파이썬 튜터 사용 영상 - Live Programming Mode]


[파이썬 튜터 사용 영상 - visual  execution]

혹시 visual execution을 누르면 어떤 형태로 볼 수 있는지 궁금한 사람들을 위해서 유튜브 영상 링크를 걸었으니 확인하면 된다.

https://www.youtube.com/watch?v=4Cgxx8whqso 

 

 


 

 

참고로  Java Tutor C Tutor C++ Tutor JavaScript Tutor Ruby Tutor 도 존재하기 때문에 이에 대해서 공부하는 사람들은 이런 사이트들을 활용해도 매우 유용할 것으로 보인다.

베스킨라빈스 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

 


여기서 조금 애매했던 부분이 역순으로 하는 부분이다.

내가 계속 사용하려고 했던 방법은 reverse()함수를 사용하려고 했던 것인데, reverse()함수가 제대로 사용이 되지 않았다.

반면에 [ : : -1 ] slicing을 사용할 시에는 제대로 작동을 하였다.


https://stackoverflow.com/questions/37637829/difference-between-reverse-and-1

 

Difference between reverse and [::-1]

Just wanted to know the difference between reverse() and [::-1] in terms of references. For example p = [1,2,3] x = p[::-1] print(x) print(p) p.reverse() print(p ==p[::-1]) print(p == x) ...

stackoverflow.com


이 글을 통해서 reverse와 [: : -1]의 차이와 활용도를 제대로 알 필요가 있을 듯 하다.

 


코드를 다음과 같이 하면 된다.

1
2
3
4
5
6
7
8
9
10
a, b = input().split()
 
= int(a[::-1])
= int(b[::-1])
 
if a > b:
    print(a)
else:
    print(b)
 
cs

 

 

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

 

2908번: 상수

상근이의 동생 상수는 수학을 정말 못한다. 상수는 숫자를 읽는데 문제가 있다. 이렇게 수학을 못하는 상수를 위해서 상근이는 수의 크기를 비교하는 문제를 내주었다. 상근이는 세 자리 수 두

www.acmicpc.net

 


간단하게 문제에서 원하는 형태의 수식으로 평균을 구하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
num = int(input())
score = list(map(int, input().split()))
max_score = max(score)
sum = 0
 
for i in range(num):
    score[i] = score[i] / max_score * 100
 
for i in range(num):
    sum = sum + score[i]
average = sum/num
 
print(average)
 
cs

 

 

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

 

1546번: 평균

첫째 줄에 시험 본 과목의 개수 N이 주어진다. 이 값은 1000보다 작거나 같다. 둘째 줄에 세준이의 현재 성적이 주어진다. 이 값은 100보다 작거나 같은 음이 아닌 정수이고, 적어도 하나의 값은 0보

www.acmicpc.net

+ Recent posts