:: 게시판
:: 이전 게시판
|
- PGR21 관련된 질문 및 건의는 [건의 게시판]을 이용바랍니다.
- (2013년 3월 이전) 오래된 질문글은 [이전 질문 게시판]에 있습니다. 통합 규정을 준수해 주십시오. (2015.12.25.)
통합규정 1.3 이용안내 인용"Pgr은 '명문화된 삭제규정'이 반드시 필요하지 않은 분을 환영합니다.법 없이도 사는 사람, 남에게 상처를 주지 않으면서 같이 이야기 나눌 수 있는 분이면 좋겠습니다."
22/12/16 12:25
아 자문자답입니다.
문제를 잘못 이해했습니다. 1번을 고른 상태에서 3번 문이 꽝임을 보여준 후에, 플레이어가 1번과 2번 중 아무거나 고르는 것이 아니라 무조건 2번으로 가야 하는 건데 전자로 이해해서 잘못 나온 거 같네요.
22/12/16 12:30
이런. 사회자가 문을 보여준 이후로 선택을 강제로 바꾸게 만들어도 여전히 1/2가 나오네요. 뭐가 문제야!
import random iteration = 100000 win = 0 # Times that the player has chosen each door a = b = c = 0 # Times that each door was with a car acar = bcar = ccar = 0 for i in range(0, iteration): open_door = "" choice = "" car = "" random_value = random.random() second_random_value = random.random() third_random_value = random.random() fourth_random_value = random.random() # assigning the door with the car if random_value < 1/3: car = "a" elif 1/3 < random_value < 2/3: car = "b" else: car = "c" # player makes an arbitrary decision if fourth_random_value < 1/3: choice = "a" elif 1/3 < fourth_random_value < 2/3: choice = "b" else: choice = "c" # Now Monty opens a door with a sheep that the player did not pick if car == "a": if choice == "a": if second_random_value < 1/2: open_door = "b" else: open_door = "c" if choice == "b": open_door = "c" if choice == "c": open_door = "b" if car == "b": if choice == "a": open_door = "c" if choice == "b": if second_random_value < 1/2: open_door = "a" else: open_door = "c" if choice == "c": open_door = "a" if car == "c": if choice == "a": open_door = "b" if choice == "b": open_door = "a" if choice == "c": if second_random_value < 1/2: open_door = "a" else: open_door = "b" # and then the player changes decision if open_door == "a": if choice == "b": choice = "c" if choice == "c": choice = "b" elif open_door == "b": if choice == "a": choice = "c" if choice == "c": choice = "a" elif open_door == "c": if choice == "a": choice = "b" if choice == "b": choice = "a" if choice == car: win += 1 # for debugging if choice == "a": a += 1 elif choice == "b": b += 1 else: c += 1 if car == "a": acar += 1 elif car == "b": bcar += 1 else: ccar += 1 # for debugging print("The", iteration, "times simulated probability of winning is", win/iteration) print("The player picked a, b, c for each of", a, b, c, "times") print("The actual cases for a,b,c doors were ", acar, bcar, ccar, "times")
22/12/16 12:31
네. 사회자가 정답 아닌 문을 하나 열어서 [정답 후보 문이 2개 남은 상태에서]
플레이어가 랜덤하게 둘 중 하나를 고르면 확률은 50%가 나오는 게 자연스럽습니다. 그런데 코드를 바꿔도 1/2가 나온다니... 흥미롭군요.
22/12/16 12:31
중간에 바꿀때 선택을 랜덤으로 바꾸면 5대5가 나오는게 맞는것 같습니다. 첫번째 초이스와 두번째 초이스가 같은건지 다른건지 구분하는 코드가 있어야 한다고 적고 있었는데
이미 자문자답 하셨군요 하핫
22/12/16 12:33
네 첫번째 초이스를 기반으로 사회자가 여는 문을 고르고, 그 이후에 선택을 강제로 바꾸게 만들어도 1/2가 나오네요 ㅠㅠ
22/12/16 12:33
제가 최근에 엑셀로 몬티홀 문제에서 발생 가능한 케이스들 및 그 비율을 비교해서 만든 게 있는데 혹시 참고가 되실지 모르겠습니다.
----------------------------------------------------------------------------------------- - 사회자가 정답을 아는 경우(원래의 몬티홀 문제)에 각각의 케이스들 및 그 비율을 시각화해보았습니다. 자동차(정답) 위치 기준: https://imgur.com/lCuue4g 최초 선택 위치 기준: https://imgur.com/ssfdvGF 위 이미지들을 참조하면, 사회자가 정답을 아는 경우에는, [참가자가 최초 선택한 문이 정답일 경우], 사회자는 두 가지 선택지를 가집니다. [참가자가 최초 선택한 문이 정답이 아닐 경우], 사회자는 한 가지 선택지만을 가집니다. 이 차이가 전체 확률 계산에서 중요한 차이를 가져옵니다. ------------------------------- 한편, 사회자가 정답을 모르는 경우, 각각의 케이스들 및 그 비율을 시각화해보면 아래와 같이 할 수 있을 것 같습니다. 자동차(정답) 위치 기준: https://imgur.com/KJXvZmB 최초 선택 위치 기준: https://imgur.com/P6mRg28 (모르는 경우에 대해서는 깊게 생각해본 적이 없어서 정확하지 않을 수 있습니다
22/12/16 12:34
네 그 부분은 고려를 해놓았습니다. 본문에서도 적었지만 플레이어가 처음에 정답을 맞췄을 때는 사회자의 선택지가 2개지만, 플레이어가 틀렸을 경우 사회자의 선택지는 하나만 남게 되지요.
22/12/16 12:33
# and then the player changes decision
if choice == "a": if open_door == "b": choice = "c" if open_door == "c": choice = "b" elif choice == "b": if open_door == "a": choice = "c" if open_door == "c": choice = "a" elif choice == "c": if open_door == "a": choice = "b" if open_door == "b": choice = "a" 이렇게 하니까 나오네요
22/12/16 12:35
if choice == "b":
choice = "c" if choice == "c": choice = "b" 요 부분에 버그가 있네요. choice를 c로 바꾼담에 아래 if에서 한번 더걸려서다시 b로 바뀝니다. # and then the player changes decision if open_door == "a" and choice == 'b': choice = "c" elif open_door == "a" and choice == 'c': choice = "b" elif open_door == "b" and choice == 'c': choice = "a" elif open_door == "b" and choice == 'a': choice = "c" elif open_door == "c" and choice == 'b': choice = "a" elif open_door == "c" and choice == 'a': choice = "b" 요렇게 하시면 2/3 나옵니다.
22/12/16 12:38
아!!!!!!!!!! 이거네요!!!!!!!!!
if choice == "b": choice = "c" elif choice == "c": choice = "b" 로 바꿔주니까 문제가 사라졌습니다! 감사합니다 진짜로! 앓던 체증이 싹 내려가네요!!!
22/12/16 12:39
와 그냥 if문 써도 되겠지 싶었는데 elif 안 쓰고 그냥 if로 도배한 게 문제였군요. 와 이걸 어떻게 알아보셨는지 구세주시여 ㅠㅠㅠ
22/12/16 12:55
어제부터 "아니 이렇게 완벽한 코드가 왜 안 돌아가는 거야!"하고 골머리를 싸맸는데 그게 해결되니까 쾌감이 장난 아니네요 흐흐
22/12/16 13:08
크크 맞습니다. 그 뽕맛때문에 프로그래머 됐습니다...
어느 연구에서 봤는데 함수 하나가 7줄 넘어가면 버그가 한개 이상 있다고 합니다. 1, 한 함수 사이즈를 작게 여러개로 쪼개기 2. 들여쓰기 단계 적게 가져가기 요 두가지는 항상 맞는건 아니지만 버릇을 들이면 코드 가독성이 많이 개선됩니다.
22/12/16 13:39
import random
iteration = 1000 cwin = 0 # 바꿨을때 이기는 수 dcwin = 0 # 안바꿨을때 이기는 수 # Times that the player has chosen each door # Times that each door was with a car answer = 0 li = [] for i in range(1,4): li.append(i) for i in range(0, iteration): non_answer = li[:] answer = random.randrange(1,4) pchoice = random.randrange(1,4) non_answer.remove(answer) if pchoice != answer : non_answer.remove(pchoice) open = random.choice(non_answer) print(f" 정답은 {answer} 고른건 {pchoice} 사회자가 open 한건 {open}") if answer != pchoice: cwin+=1 else: dcwin+=1 print(cwin) print(dcwin) if 문을 조금 줄여봤습니다.
22/12/16 14:54
심심풀이로 하시는 듯 한데, 이런 선택지 같은 것들은 문자로 하는 것 보다는 숫자로 하는 것이 활용도가 훨씬 쉽습니다.
일단 문 세 개를 0,1,2로 하고, 자동차가 있는 문을 셋 중에 하나 랜덤으로, 그리고 첫 선택지도 랜덤으로 둡니다. 그리고 사회자가 여는 문을, (1) 첫 선택이 자동차였을 경우 남은 문 둘 중에 하나로 선택해야 하죠. 이 때 그냥 1,2 중 랜덤으로 하나를 고르고, 첫 선택에 더해주면 됩니다. 다만 첫 선택이 1이었을 때 랜덤으로 2가 나오거나, 첫 선택이 2라면 사회자가 여는 문이 3이상이 되어버리므로, % 연산자로 나머지만 남기면 됩니다. (2) 반대로 첫 선택이 자동차가 아니었을 경우 그냥 남은 문이 되는데, 0,1,2로 설정할 경우 총 합이 3이 되니 3에서 자동차가 있는 문 번호, 첫 선택한 번호를 차례로 빼주면 남은 문이 됩니다. (ex 0번에 차가 있고 첫 선택이 2번일 경우, 3-0-2=1) 이러면 전체 줄 수를 매우 컴팩트하게 줄일 수 있어요. #################################################### import random num = 100000 keep = 0 change = 0 for i in range(num): car = random.randrange(3) choice = random.randrange(3) if car==choice: a = random.randrange(2) opendoor = (choice + a + 1 )%3 else: opendoor = 3-choice-car if choice==car: keep+=1 if 3-choice-opendoor==car: change+=1 print(keep/num, change/num) ####################################################
22/12/17 12:38
car = choice(unselected_doors)
first_choice = select_a_door(unselected_doors) car는 unselected_doors 중에서 랜덤 선택 후 unselected_doors는 그대로 두고, first_choice는 unselected_doors 중에서 랜덤 선택 후 unselected_doors에서 제외합니다. ---- from random import choice doors = 10 opens = 8 total = 100000 keep, change = 0, 0 debug = False def select_a_door(unselected_doors): selected_door = choice(unselected_doors) unselected_doors.remove(selected_door) return selected_door def open_doors_by_host(unselected_doors, car): open_doors = [] is_car_unselected = car in unselected_doors if is_car_unselected: unselected_doors.remove(car) for i in range(opens): open_doors.append(select_a_door(unselected_doors)) if is_car_unselected: unselected_doors.append(car) return open_doors for i in range(total): unselected_doors = list(range(doors)) car = choice(unselected_doors) first_choice = select_a_door(unselected_doors) open_doors = open_doors_by_host(unselected_doors, car) changed_choice = select_a_door(unselected_doors) if debug: print(f'car: {car}, first_choice: {first_choice}, open_doors: {open_doors} changed_choice: {changed_choice}') if car == first_choice: keep += 1 elif car == changed_choice: change += 1 # endfor print(f'keep: {keep / total}, change: {change / total}')
|