Untitled

  1. 도입부

    작년 10월부터 Wordle 이라는 게임이 유행이다. 이 게임은 5개 영단어를 넣어서 글자를 맞추는 숫자야구 게임이다. 게임 플레이는 여기서 할 수 있다: https://www.powerlanguage.co.uk/wordle/

    이 글은 Wordle을 어떻게 하면 효과적으로 풀수 있는지에 대한 고찰이다.

  2. Wordle 글자 빈도수 체크

    이 게임에는 JavaScript 코드가 있는데, 여기에 5개 단어 리스트가 그대로 올라가 있다. 즉 user side에서 답을 체크한다는 것이다. 다만 어떤 단어를 고르는지에 대한 코드는 obfuscated되어 있어 간파하지 못했다.

    신준영 회원의 도움을 받아 JavaScript 코드에서 5글자 단어 리스트를 쭉 뽑을 수 있었다:

    l5w.txt

    이 파일을 가지고 글자의 빈도수를 체크해봤더니 아래와 같은 bar chart가 나왔다. 가로축은 각각의 글자, 세로축은 발견된 개수이고, 글자는 발견된 개수 순서대로 정렬되어 있다.

    60153c2e-5df5-42b6-9bee-49cc8d6ec203.png

    이걸 불러와서 plot 하는 코드는 아래와 같다. Jupyter 같은데서 돌리길 추천한다

    import pandas as pd
    
    # load file (parsing)
    f = open('l5w.txt')
    s = f.read().split(',')
    
    for i in range(len(s)):
        s[i] = s[i][1:-1]
    
    s = pd.Series(s)
    
    # count frequency
    freq_tmp={}
    for char in 'abcdefghijklmnopqrstuvwxyz':
        freq_tmp[char] = s.str.count(char).sum()
    
    df = pd.DataFrame.from_dict(freq_tmp, orient='index', columns=['count'])
    df = df.sort_values(by='count', ascending=False)
    
    # draw
    df.plot.bar()
    

    글자 빈도수는 $SEAORILTNUDYCPMHGBKFWVZJXQ$ 순서다.

  3. 인간의 뇌를 사용한 전략

    빈도 순서대로 이 글자를 Wordle에 5개씩 입력해나가며 체크하면 매우 높은 확률로 글자들이 걸려서 정답에 다다르는 힌트가 많아질 것이라는걸 직감할 수 있다. 다만 Wordle에 입력될 때는 무작위 글자가 아닌 5글자 단어여야 하기 때문에, 최대한 글자 중복 없이 단어를 만들어내야 한다.

    본인은 이것에 대해 오로지 두뇌로만 고민하였고 다음과 같은 방법을 찾아냈다.

    $$ AROSE\rarr UNTIL\rarr DUMPY $$

    순서대로 입력하면 $SEAORILTNUDYCPMHGBKFWVZJXQ$ 중에서 앞의 15글자 중 C를 제외한 14글자 $SEAORILTNUDYPM$ 을 모두 체크할 수 있다. 영단어도 적절하게 ‘키작은 놈 앞에 일어났다’ 같이 그럴듯한 문장이 되는 느낌이다.

    특히 빈도 순서대로 읽어나갈수록 모음이 적어지고, $UNTIL$까지 치면 모음이 바닥나기 때문에, 반드시 1개 이상의 모음이 그 다음번부터는 중복 삽입되게 된다. 그래서 $DUMPY$를 떠올릴 때는 생각을 좀 많이 했었다.

    나머지 $CHGBKFWVZJXQ$ 에 대해서는 모음을 1개만 써서 빈도순대로 해결하는 효과적인 방법은 아직 못 찾았으나, 덜 효과적인 (빈도를 좀 덜 고려하는) 방법은 떠올릴 수 있다. 가령  $WHACK$이 될 수 있다. 단점은 앞서 말했듯 빈도가 좀 떨어지는 W가 사용된다. 즉,

    $$ AROSE\rarr UNTIL\rarr DUMPY \rarr WHACK $$

    이러면 이제 $GBFVZJXQ$ 만 남았다.

  4. 컴퓨터 도움을 받아 전략 수정

    이제 뇌를 쓰기에는 더이상 영어 단어 생각이 안나서 아래와 같이 간단하게 코드를 더 짰다.

    # set condition
    cond = ~s.str.contains('_') # no string contains -> cond is all True
    
    # filter not contained characters
    for char in 'seaor':
        cond &= s.str.contains(char)
    
    # remove wrong candidates
    print(s[cond])
    

    위 코드에서 ‘seaor’ 부분을 원하는 글자로 바꾸면 된다. 이제 이 코드 조각에 $SEAOR$ 를 넣어보면 아래와 같이 나온다.

    $$ SEAOR\rarr\{AROSE,AEROS,SOARE\} $$

    $ILTNU$ 넣으면

    $$ ILTNU\rarr\{UNTIL,UNLIT\} $$

    $DYCPM$은 없고, $YCPM, DCPM, DYPM, DYCM, DYCP$ 중에서 가능한건 아래와 같다

    $$ \begin{aligned}YCPM&\rarr\{CAMPY\} \\ DYPM&\rarr\{DUMPY,DAMPY\}\end{aligned} $$

    $YCPM$을 쓰게 되면 $DHGBKFWVZJXQ$, $DYPM$을 쓰게 되면 $CHGBKFWVZJXQ$가 남는다. 이제 남는 글자 중에서, 어느 쪽이든 빈도 순서대로 앞에서부터 5글자나 4글자를 쓰는건 실패한다. 직접 머리로 생각해서 $WHACK$ 이라는 단어를 찾아낸게 신기하다.

  5. 결론

    여기서 한 단계 더 들어가려면 프로그램을 좀더 deep하게 쨔아 한다. 하지만 사실 Wordle은 대부분 이렇게 3번 넣어보면 글자가 거의 다 유추되기 때문에 더이상 탐색할 필요가 없을 것 같다. 운 안좋게 빈도 낮은 글자가 걸리면 그 날은 틀려야 하는 것이다.

    결과적으로 최종적인 글자 점검 순서는 아래와 같겠다. 상황에 맞춰서 잘 쓰면 되겠다.

    $$ \begin{aligned}&\{AROSE,AEROS,SOARE\} \\ &\rarr\{UNTIL,UNLIT\} \\ &\rarr\{DUMPY,DAMPY, CAMPY\} \\ &\rarr\{WHACK,...\}\end{aligned} $$