파이썬 실전/로또 번호 생성기

파이썬 실전) 로또 번호 생성기 3. 고정수

마리사라 2021. 2. 5. 21:26
반응형

이번 강의는 여러 로또 번호 사이트에 있는 기능 중 하나인 고정수 설정 기능을 만들어 보려고 합니다.


1. 고정수

출처 : 로또지옥

로또 번호에서 고정수 또는 희망수는 로또 번호를 생성할 때, 본인이 입력한 번호를 반드시 포함시키는 방법을 말합니다. 이렇게 하면 랜덤으로 생성되는 번호의 개수는 확실히 줄어들지만, 당첨 확률이 높아지는 것은 아닙니다.

 

로또 번호는 중복이 되지 않으므로 (45 * 44 * 43 * 42 * 41 * 40)만큼의 경우의 수가 존재합니다. 즉, 로또 번호가 만들어 질 수 있는 가짓수는 약 60억 개(5,864,443,200)입니다. 이 중에서 고정수를 하나만 선택하는 경우에는 나머지 5자리만 만들면 되므로 경우의 수가 약 1.3억 개(130,320,960) 개로 줄어듭니다. 여기서 고정수가 하나 더 늘어난다면 4자리만 만들면 되기 때문에 약 300만 개(2,961,840)로 줄어듭니다. 이렇게만 본다면 60억 분의 1에서 300만 분의 1로 줄어든 것 같지만 실상은 다릅니다.

 

만약 제가 11이라는 숫자가 좋아서 고정수로 1과 11을 정했다고 해보겠습니다. 이 경우 나올수 있는 가짓수는 약 300만 개입니다. 로또 당첨 번호로 1이 나올 확률은 45분의 1입니다. 이제 번호가 44개가 남았으므로, 이 중에서 11이 나올 확률은 44분의 1입니다. 이제부터 나머지 4자리는 어떠한 수가 나와도 상관없으니 확률은 각각 43분의 4, 42분의 3, 41분의 2, 40분의 1이 됩니다. 이 모든 것을 다 곱한다면 확률은 약 2.2억의 1의 확률이 됩니다. 무작위로 로또를 찍었을 때 당첨될 확률이 8,145,060분의 1(814만 분의 1)인 것을 감안하면 확률이 더 낮아진 셈입니다.

 

고정수를 정하는것이 로또 1등과는 멀어진다는 셈입니다. 하지만 814만 분의 1이나 2.2억 분의 1이나 현실에서는 똑같이 일어나기 힘든 일이기 때문에 고정수를 만드는 것이 체감적으로 1등과 멀어지는 것은 아닙니다. 즉 고정수는 본인의 취향에 따라 만들어도 된다는 뜻입니다.


2. 코드

이제부터 이전 시간의 코드에 고정수를 입력하는 위젯을 추가해 보도록 하겠습니다. 고정수는 많이 만들수록 로또 1등에 당첨될 확률이 떨어지게 되므로 2개까지만 입력하도록 만들어 보겠습니다.

 

우선 고정수를 입력할 공간을 표시하기 위해 StaticBox를 만듭니다. StaticBox는 wxPython에서 주변에 테두리를 두르고, 제목을 입력할 수 있는 공간을 만드는 위젯입니다.

fixed_number_box = wx.StaticBox(panel, id=5, label="고정수", pos=(5, 100), size=(80, 50))

사이즈는 글쓴이 임의로 만들었기 때문에 조절하셔도 됩니다.

 

이제 고정수를 입력할 TextCtrl을 두 개 만들어 줍니다.

self.fixed_number_1 = wx.TextCtrl(fixed_number_box, id=6, size=(30, 20), pos=(5, 20))
self.fixed_number_2 = wx.TextCtrl(fixed_number_box, id=7, size=(30, 20), pos=(40, 20))

이때 parent가 평소의 panel이 아닌, StaticBox로 되어 있는 것을 볼 수 있습니다. 이렇게 하면 pos값은 StaticBox의 좌상단 끝부분이 (0, 0)이 되므로 주의해서 pos값을 입력해 주셔야 합니다.

 

또한 고정수를 적용하는지 선택할 체크박스도 만들어 줍니다.

self.fixed_number_check = wx.CheckBox(panel, id=8, pos=(100, 120))

체크박스는 wxPython에서 CheckBox로 만들 수 있습니다. 체크되었음을 확인할 때에는 GetValue로 True/False의 bool값이 전달됩니다.

 

이제 번호를 만들 때 고정수가 포함되도록 만들어 보겠습니다.

number = set()
if self.fixed_number_check.GetValue():
    try:
        fixed_number_1 = int(self.fixed_number_1.GetValue())
        number.add(fixed_number_1)
    except:
        pass
    try:
        fixed_number_2 = int(self.fixed_number_2.GetValue())
        number.add(fixed_number_2)
    except:
        pass

여기서 if문은 체크박스가 True일 때, 즉 체크되어 있을 때만 작동합니다. 이후 try/except문으로 결과가 나올 집합에 고정수를 넣어주게 됩니다. try/except문을 사용한 이유는 고정수를 입력하는 곳이 비어 있을 경우 에러가 나므로 고정수가 입력되어 있는 경우에는 try가 정상적으로 실행되고, 비어 있을 경우에는 except가 실행되어 pass 하게 됩니다.

 

이제 결과를 확인해 보겠습니다.

초기 실행 화면
체크박스를 체크하지 않고 실행한 화면
체크박스를 체크하고 실행한 화면

체크박스를 체크한 후 번호를 생성하면 고정수가 포함되어 번호가 생성됨을 볼 수 있습니다.


3. 마치며

이번 시간에는 여러 로또 번호 사이트들이 사용하는 필터링 중 하나인 고정수 기능을 추가해 보았습니다. 고정수는 실제로는 크게 도움은 안되니 저처럼 좋아하는 번호가 있지 않는 이상은 사용하지 않는 것이 당첨에 도움이 됩니다.

import random
import wx


class Mainframe(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(300, 450))
        panel = wx.Panel(self)
        self.count = wx.TextCtrl(panel, id=1, pos=(5, 5))
        self.count.SetHint("시행 횟수 입력")
        self.generate_button = wx.Button(panel, id=2, label='생성', pos=(5, 50))
        self.output = wx.ListBox(panel, id=3, choices=[], pos=(120, 5), size=(150, 400))

        fixed_number_box = wx.StaticBox(panel, id=5, label="고정수", pos=(5, 100), size=(80, 50))
        self.fixed_number_1 = wx.TextCtrl(fixed_number_box, id=6, size=(30, 20), pos=(5, 20))
        self.fixed_number_2 = wx.TextCtrl(fixed_number_box, id=7, size=(30, 20), pos=(40, 20))
        self.fixed_number_check = wx.CheckBox(panel, id=8, pos=(100, 120))

        self.Bind(wx.EVT_BUTTON, self.lotto, id=2)

    def lotto(self, event):
        for i in range(int(self.count.GetValue())):
            number = set()
            if self.fixed_number_check.GetValue():
                try:
                    fixed_number_1 = int(self.fixed_number_1.GetValue())
                    number.add(fixed_number_1)
                except:
                    pass
                try:
                    fixed_number_2 = int(self.fixed_number_2.GetValue())
                    number.add(fixed_number_2)
                except:
                    pass
            while len(number) < 6:
                number.add(random.randint(1, 45))
            number = list(number)
            number.sort()
            self.output.Append(str(number))


def run():
    app = wx.App()
    frame = Mainframe(None, -1, 'Lotto Number Generator')
    frame.Show()
    app.MainLoop()


run()
반응형