무작위화 및 파이썬 리스트

JOOYEUN SEO·2024년 8월 12일

100 Days of Python

목록 보기
4/76
post-thumbnail

🎲 무작위화(randomisation)

  • 컴퓨터는 결정적인(deterministic) 기계여서 항상 예측 가능한 방식으로 반복적인 행동을 수행하나,
    일정 수준의 예측 불가능성이 존재하는 컴퓨터 프로그램(게임 등)을 개발할 때 무작위화가 중요함
  • 의사(유사) 난수 수열 생성기
    • 생성 방법
      • 먼저 노이즈를 측정하거나, 시각을 밀리초로 표현하여 seed라는 난수를 정함
      • seed를 정해진 계산에 입력하여 그 출력값을 다음 seed로 사용하는 방식으로 수열 생성
      • 파이썬에서는 메르센 트위스터(Mersenne Twister) 라는 수식 사용
    • 단점
      • seed의 무작위성에만 의존
      • seed가 다시 나타나면 결국에는 패턴이 반복됨
    • 현실적으로 안전한 사용 방법
      • 컴퓨터가 모든 seed를 찾아보고 시행하는 데 긴 시간이 걸리도록 함
        (자물쇠 비밀번호를 0000부터 1씩 늘려가며 전부 확인하면 결국 풀 수 있지만 오래 걸리는 것과 같음)
      • seed의 길이가 늘어날수록 보안성도 높아짐

❖ Random 모듈

파이썬에서 손쉽게 난수를 생성할 수 있도록 개발한 모듈
Python Random Module Methods

💡 모듈(module)

  • 코드가 너무 길어질 경우, 코드를 개별 모듈로 나누어 프로그램에서 서로 다른 기능을 담당하게 한다
  • 많은 사람들이 협업하여 프로젝트를 진행하며, 각 개인은 서로 다른 작업을 하는 것과 같음
  • import random : 코드를 실행할 때 실행되는 파일 main.py에 모듈 파일을 import
  • module.methods : 해당 모듈의 메소드를 사용하는 방법

◇ 정수 난수 생성

  • random.randrange( [start,] stop [, step] )
    • start : 범위의 시작(포함) [ 디폴트 값 = 0 ]
    • stop : 범위의 끝(제외)
    • step : 범위 내에서 step 만큼의 간격으로 난수가 결정됨 [ 디폴트 값 = 1 ]
  • random.randint( a, b )
    • a : 범위의 시작(포함)
    • b : 범위의 끝(포함)
import random

# randrange(start, stop, step)
random_int1 = random.randrange(2, 11, 2)
print(random_int1)

# randint(a, b)
random_int2 = random.randint(2, 10)
print(random_int2)
#
8

#
5

◇ 부동 소수점 난수 생성

  • random.random()
    • [0.0, 1.0) 사이에 존재하는 부동 소수점 난수 반환
      (0부터 1까지의 범위, 1은 포함되지 않음)
    • 범위를 숫자 11이 아니라 nn까지로 확장하려면 생성된 난수   n*\;n
  • random.uniform( a, b )
    • a : 범위의 최소값(포함)
    • b : 범위의 최대값(포함)
import random

# random()
random_float1 = random.random()
print(random_float1)

# uniform(a, b)
random_float2 = random.uniform(10, 11)
print(random_float2)
#
0.725128120560556

#
10.315016926244143

💯 coding exercises

Heads or Tails
동전 던지기 시뮬레이터 프로그램(무작위로 heads 또는 tails)

  • 0과 1 둘 중 하나를 무작위로 생성 후 각 숫자에 앞면 또는 뒷면을 부여
import random

result = random.randint(0, 1)
if result == 1:
  print("Heads")
else:
  print("Tails")
Tails

❖ 리스트(list)

  • 서로 관계성이 있는 데이터 그룹을 저장하는 자료구조(데이터를 체계화하고 저장하는 방식)
  • 리스트에 저장된 순서가 데이터 간의 순서가 되며, 인덱스(오프셋)로 순서를 찾을 수 있음
    • 첫 항목의 인덱스는 0부터 시작
    • 인덱스 값이 음수일 경우 (1-1부터) 가장 마지막 요소에서 시작하여 거꾸로 순서를 셈
    • 인덱스로 특정 요소를 지정하여 값을 변경할 수 있음

list = [ value1, value2... ]

# 미국의 모든 주를 미국에 편입된 순서대로 리스트에 저장
states_of_america = [
    "Delaware", "Pensylvania", "New Jersey", "Georgia", "Connecticut", "Massachusetts",
    "Maryland", "South Carolina", "New Hampshire", "Virginia", "New York", "North Carolina",
    "Rhode Island", "Vermont", "Kentucky", "Tennessee", "Ohio", "Louisiana", "Indiana",
    "Mississippi", "Illinois", "Alabama", "Maine", "Missouri", "Arkansas", "Michigan",
    "Florida", "Texas", "Iowa", "Wisconsin", "California", "Minnesota", "Oregon", "Kansas",
    "West Virginia", "Nevada", "Nebraska", "Colorado", "North Dakota", "South Dakota",
    "Montana", "Washington", "Idaho", "Wyoming", "Utah", "Oklahoma", "New Mexico",
    "Arizona", "Alaska", "Hawaii"
]

# 인덱스로 값 변경
states_of_america[1] = "Pennsylvania"	# 잘못된 스펠링 수정
print(states_of_america[1])

# 인덱스로 마지막 요소 확인
print(states_of_america[-1])
#
Pennsylvania

#
Hawaii

◇ 오프셋(offset)

  • 인덱스와 같은 순서가 됨
  • 오브젝트의 시작 부분에서 주어진 요소까지의 변위차(이동한 거리)
  • 맨 처음 요소는 시작 부분에서 0만큼 이동(이동할 필요 x)하기 때문에 0의 오프셋을 가짐

◇ 리스트 관련 함수

the methods of list objects

  • list.append( elmnt ) : 리스트 맨 끝에 새 요소 추가
  • list.extend( iterable ) : 리스트 맨 끝에 새 리스트를 추가해 늘림
  • list.index( elmnt ) : 괄호 안의 값이 처음으로 등장하는 곳의 인덱스 반환
    ...
states_of_america = [
    "Delaware", "Pennsylvania", "New Jersey", "Georgia", "Connecticut", "Massachusetts",
    "Maryland", "South Carolina", "New Hampshire", "Virginia", "New York", "North Carolina",
    "Rhode Island", "Vermont", "Kentucky", "Tennessee", "Ohio", "Louisiana", "Indiana",
    "Mississippi", "Illinois", "Alabama", "Maine", "Missouri", "Arkansas", "Michigan",
    "Florida", "Texas", "Iowa", "Wisconsin", "California", "Minnesota", "Oregon", "Kansas",
    "West Virginia", "Nevada", "Nebraska", "Colorado", "North Dakota", "South Dakota",
    "Montana", "Washington", "Idaho", "Wyoming", "Utah", "Oklahoma", "New Mexico",
    "Arizona", "Alaska", "Hawaii"
]

# append()
states_of_america.append("NewState1")
print(states_of_america[-1])

# extend()
states_of_america.extend(["NewState2", "NewState3"])
print(states_of_america[-1])

# index()
print(states_of_america.index("New York"))
#
NewState1

#
NewState3

#
10

💯 coding exercises

Banker Roulette
뱅커 룰렛 프로그램(이름 목록에서 랜덤으로 걸린 사람이 식사 비용을 전부 내는 게임)

  • 이름 목록을 입력 시 ", "를 이용해 서로 다른 이름끼리 구분하여 작성
    (문제에서 자체적으로 입력값이 리스트가 되기 때문에 아래 코드에서는 names에 바로 리스트 삽입했음)
  • len() 함수 이용
  • 인덱스가 0부터 시작하는 것에 주의
# 
import random
names = ['Angela', 'Ben', 'Jenny', 'Michael', 'Chloe']

num_of_people = len(names)
random_num = random.randrange(num_of_people)
selected_person = names[random_num]
print(f"{selected_person} is going to buy the meal today!")
Michael is going to buy the meal today!

◇ 인덱스 오류

states_of_america = [
    "Delaware", "Pennsylvania", "New Jersey", "Georgia", "Connecticut", "Massachusetts",
    "Maryland", "South Carolina", "New Hampshire", "Virginia", "New York", "North Carolina",
    "Rhode Island", "Vermont", "Kentucky", "Tennessee", "Ohio", "Louisiana", "Indiana",
    "Mississippi", "Illinois", "Alabama", "Maine", "Missouri", "Arkansas", "Michigan",
    "Florida", "Texas", "Iowa", "Wisconsin", "California", "Minnesota", "Oregon", "Kansas",
    "West Virginia", "Nevada", "Nebraska", "Colorado", "North Dakota", "South Dakota",
    "Montana", "Washington", "Idaho", "Wyoming", "Utah", "Oklahoma", "New Mexico",
    "Arizona", "Alaska", "Hawaii"
]

# 가장 마지막 요소 하와이의 인덱스는 49
print(states_of_america[50])
IndexError: list index out of range
  • 데이터가 없는 곳의 인덱스를 출력하려고 해서 에러가 난 상황
  • 위처럼 숫자 하나 차이로 발생하는 오류를 off-by-one Error 이라고 함
  • 가장 자주 발생하는 오류 중 하나

◇ 중첩 리스트

  • 리스트 안의 리스트
  • 인덱스
    • list[0][0] : 1번째 리스트의 1번째 원소
    • list[1][0] : 2번째 리스트의 1번째 원소
  • 중첩 리스트 생성 과정
    1. 주어진 항목들을 세분화하고 싶은 카테고리로 분류해서 각각 (작은) 리스트를 작성
    2. (작은) 리스트들을 요소로 하는 (큰) 리스트 생성
# 가장 기생충이 많은 과일과 채소의 목록 (과일과 채소가 섞여 있음)
# dirty_dozen = [
#   "Strawberries", "Spinach", "Kale", "Nectarines", "Apples", "Grapes",
#   "Peaches", "Cherries", "Pears", "Tomatoes", "Celery", "Potatoes"
#]

fruits = ["Strawberries", "Nectarines", "Apples", "Grapes", "Peaches", "Cherries", "Pears"]
vegetables = ["Spinach", "Kale", "Tomatoes", "Celery", "Potatoes"]

# 중첩 리스트 전체 목록
dirty_dozen = [fruits, vegetables]
print(dirty_dozen)

# 중첩 리스트의 인덱스
print(dirty_dozen[0][0])
#
[['Strawberries', 'Nectarines', 'Apples', 'Grapes', 'Peaches', 'Cherries', 'Pears'], ['Spinach', 'Kale', 'Tomatoes', 'Celery', 'Potatoes']]

#
Strawberries

💯 coding exercises

Treasure Map
보물 지도 프로그램

  • 사용자가 원하는 위치를 (열, 행) 순서로 입력하면 해당 위치에 X를 표시해서 출력해야 함
  • 사용자가 대문자나 소문자를 바꿔 입력할 수 있으므로 lower() 등으로 통일하는 것 잊지 말기
  • index() 사용
  • 중첩 리스트의 인덱스 순서 주의하기(입력은 알파벳이 먼저이지만, 1번째 인덱스는 숫자)

실제 지도 모양

-ABC
1'⬜️''⬜️''⬜️'
2'⬜️''⬜️''⬜️'
3'⬜️''⬜️''⬜️'
line1 = ["⬜️","️⬜️","️⬜️"]
line2 = ["⬜️","⬜️","️⬜️"]
line3 = ["⬜️️","⬜️️","⬜️️"]
map = [line1, line2, line3]
print("Hiding your treasure! X marks the spot.")
position = input() # Where do you want to put the treasure?

# Write your code below this row 👇
alphabet = position[0].lower()
number = position[1]

if number == "1":
  first_index = map.index(line1)
elif number == "2":
  first_index = map.index(line2)
else:
  first_index = map.index(line3)
  
if alphabet == "a":
  map[first_index][0] = 'X'
elif alphabet == "b":
  map[first_index][1] = 'X'
else:
  map[first_index][2] = 'X'
# Write your code above this row 👆

print(f"{line1}\n{line2}\n{line3}")
B3
Hiding your treasure! X marks the spot.
['⬜️', '️⬜️', '️⬜️']
['⬜️', '⬜️', '️⬜️']
['⬜️️', 'X', '⬜️️']

이중 인덱스에서 1번째 인덱스를 먼저 구하고 나서 2번째 인덱스를 구하는 방식으로 접근
조건문으로 하나씩 지정해서 인덱스를 얻었으나 코드가 너무 길어져버렸음

🖍️ 답안

letter = position[0].lower()
abc = ["a", "b", "c"]					# letter와 비교할 문자를 담은 리스트 생성
letter_index = abc.index(letter)		# letter의 인덱스를 구함
number_index = int(position[1]) - 1		# number 인덱스는 바로 계산 가능(-1 필요)
map[number_index][letter_index] = "X"

🗂️ Day4 프로젝트 : 가위바위보

사용자와 컴퓨터가 가위, 바위, 보 중 하나를 무작위로 선택한 결과를 비교하여 승패를 결정하는 게임

🔍 유의 사항

  • 승패를 가리는 방법
    • 바위가 가위를 이김, 가위가 보를 이김, 보가 바위를 이김, 같은 것을 내면 무승부
    • 사용자가 0, 1, 2가 아닌 다른 숫자를 입력했을 경우 패배로 처리
      (조건문 중 가장 위에 올라와야 함)
  • 인덱스 오류
    • 사용자가 0, 1, 2가 아닌 다른 숫자를 입력했을 경우 그림을 불러오는 부분에서 인덱스 오류 발생
    • if문 조건을 유효하지 않은 숫자 입력 시 패배, else문에 나머지 코드 넣기

⌨️ 작성한 코드

rock = '''
    _______
---'   ____)
      (_____)
      (_____)
      (____)
---.__(___)
'''

paper = '''
    _______
---'   ____)____
          ______)
          _______)
         _______)
---.__________)
'''

scissors = '''
    _______
---'   ____)____
          ______)
       __________)
      (____)
---.__(___)
'''

#Write your code below this line 👇
import random
options = [rock, paper, scissors]

user_choice = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.\n"))
print("You chose : ")
print(options[user_choice])

com_choice = random.randint(0, 2)
print("Computer chose : ")
print(options[com_choice])

if user_choice > 2 or user_choice < 0:
    print("You type the wrong number. You lose")
elif user_choice > com_choice:
    if user_choice - com_choice == 1:
        print("You win!")
    else:
        print("You lose")
elif user_choice < com_choice:
    if com_choice - user_choice == 1:
        print("You lose")
    else:
        print("You win!")
else:
    print("draw")
5
IndexError: list index out of range

🐞 디버깅 결과

####### Debugging challenge: #########
#Try running this code and type 5.
#It will give you an IndexError and point to line 32 as the issue.
#But on line 38 we are trying to prevent a crash by detecting
#any numbers great than or equal to 3 or less than 0.
#So what's going on?
#Can you debug the code and fix it?
#Solution: https://repl.it/@appbrewery/rock-paper-scissors-debugged-end
# ...중략
import random
options = [rock, paper, scissors]

user_choice = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.\n"))

if user_choice > 2 or user_choice < 0:    # 유효하지 않은 숫자를 입력하면 바로 종료
    print("You type the wrong number. You lose")
else:									  # 나머지 코드들 실행
    print("You chose : ")
    print(options[user_choice])
    com_choice = random.randint(0, 2)
    print("Computer chose : ")
    print(options[com_choice])
    
    if user_choice > com_choice:
      if user_choice - com_choice == 1:   # 가위 vs 보, 보 vs 바위
          print("You win!")
      else:                               # 가위 vs 바위
          print("You lose")
    elif user_choice < com_choice:
      if com_choice - user_choice == 1:   # 가위 vs 보, 보 vs 바위
          print("You lose")
      else:                               # 가위 vs 바위
          print("You win!")
    else:
        print("draw")                     # 무승부
5
You type the wrong number. You lose

🖍️ 답안

# 디버깅 전
# ... 중략
game_images = [rock, paper, scissors]

user_choice = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.\n"))
print(game_images[user_choice])

computer_choice = random.randint(0, 2)
print("Computer chose:")
print(game_images[computer_choice])

if user_choice >= 3 or user_choice < 0: 			# 유효하지 않은 숫자 입력
  print("You typed an invalid number, you lose!") 
elif user_choice == 0 and computer_choice == 2:	# 바위 vs 가위
  print("You win!")
elif computer_choice == 0 and user_choice == 2:	# 바위 vs 가위
  print("You lose")
elif computer_choice > user_choice:				# 가위 vs 보, 보 vs 바위
  print("You lose")
elif user_choice > computer_choice:				# 가위 vs 보, 보 vs 바위
  print("You win!")
elif computer_choice == user_choice:				# 같은 모양
  print("It's a draw")

# 디버깅 후
# ... 중략
game_images = [rock, paper, scissors]

user_choice = int(input("What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.\n"))
if user_choice >= 3 or user_choice < 0: 
    print("You typed an invalid number, you lose!") 
else:
    print(game_images[user_choice])

    computer_choice = random.randint(0, 2)
    print("Computer chose:")
    print(game_images[computer_choice])

    if user_choice == 0 and computer_choice == 2:
        print("You win!")
    elif computer_choice == 0 and user_choice == 2:
        print("You lose")
    elif computer_choice > user_choice:
        print("You lose")
    elif user_choice > computer_choice:
        print("You win!")
    elif computer_choice == user_choice:
        print("It's a draw")
[ 출력 결과 ]

What do you choose? Type 0 for Rock, 1 for Paper or 2 for Scissors.
❚0

    _______
---'   ____)
      (_____)
      (_____)
      (____)
---.__(___)

Computer chose:

    _______
---'   ____)____
          ______)
          _______)
         _______)
---.__________)

You lose




▷ Angela Yu, [Python 부트캠프 : 100개의 프로젝트로 Python 개발 완전 정복], Udemy, https://www.udemy.com/course/best-100-days-python/?couponCode=ST3MT72524
▷ Brit Cruise, [Pseudorandom number generators], Khan Academy, https://www.khanacademy.org/computing/computer-science/cryptography/crypt/v/random-vs-pseudorandom-number-generators
▷ Vijaykrishna Ram, [Python random Module – Generate Random Numbers/Sequences], AskPython, https://www.askpython.com/python-modules/python-random-module-generate-random-numbers-sequences

0개의 댓글