어쩌다가 소설 '개미'를 읽게 되어서 그 유명한 개미수열을 한 번 Python으로 구해보고 싶어져서 한 번 구해봤습니다.


일단 이 수열은 원래 읽고 말하기 수열입니다. 한국에서는 소설 '개미'로 인해 유명해져서 개미 수열이라고 부른다고 하군요. 재미난 점(?)이 서양(아마 서양쪽이 맞을 겁니다)과는 다르게 우리나라에서는 '1'을 '일이 한 개'라고 읽고, 서양에서는 '1'을 '한 개의 일'(one 1)라고 읽기 때문에 실제로 소설이 한국어로 번역될 때 한국 사정을 고려하다보니 한국에 출판된 '개미'에 나오는 수열은 읽고 말하기 수열를 뒤집은 꼴입니다. 예를 들어서 원래 읽고 말하기 수열은

1,

11,

21,

1211,

...


이렇게 이어지는데 반면에 한국에 출판된 '개미' 에서는

1,

12,

1121,

...


이렇게 나옵니다. 뭐 이 구조 특성상 프로그래밍하는 데도 순서만 바꾸면 되는지라 저는 한국 소설에 나온 방식이 더 맘에 들고 실제로 '개미수열'하면 이렇게 알려져 있는 경우가 더 많은 거 같아서 후자의 방식을 선택하여 프로그래밍 해봤습니다.


Python 코드는 다음과 같습니다. 일반적인 터미널 출력과 더불어 파일 출력도 가능하게 만들었습니다.

#-*- coding: utf-8 -*-

n = input("출력할 수열의 끝 번호: ")
isSave = raw_input("파일로 저장할 것인가요?(Y/N)(기본: N): ")

if isSave == "Y":
    f = open("./Les-fourmis_sequence.txt", "w")

s = "1"
for i in xrange(n):
    if isSave == "Y":
        f.write(s + "\n")
    else :
        print "\t" + str(i + 1) + ": " + s

    x = s[0]
    count = 1

    s_dev = ""

    for j in xrange(1, len(s)):
        if s[j] != x:
            s_dev += str(x) + str(count)

            x = s[j]
            count = 1
        else:
            count += 1

    s = s_dev + str(x) + str(count)

if isSave == "Y":
    f.close()

이 수열의 특성상 거의 기하급수적으로 길이가 길어지기 때문에 1번째부터 15번째 수까지만 보여드리겠습니다.

1
11
12
1121
122111
112213
12221131
1123123111
12213111213113
11221131132111311231
12221231123121133112213111
1123112131122131112112321222113113
1221311221113112221131132112213121112312311231
11221131122213311223123112312112221131112113213111213112213111
122212311223113212223111213112213111211223123113211231211131132111311222113113
...


이 수열의 재미난 성질이 있다면

1. 초기값(1)이 달라지지 않는다면 각 수에서 1, 2, 3을 제외한 다른 숫자들은 나올 수 없다.

↳ 상당히 흥미로운 이야기입니다. 나중에 가능하면 한 번 증명해보고 싶네요.

2. 초기값이 22를 제외한 임의의 수이면 수열은 끊임없이 길어진다.

↳ 간단히 생각해보면 간단한 이야기입니다. 먼저 초기값이 어떠한 수이던 간에 2번째 수부터는 무조건 짝수입니다. 근데 초기값이 한 숫자로만 이뤄져있으면

     당연하게 2번째 수는 무조건 두 자리일 수밖에 없습니다. 따라서 22이면 22, 22, 22, ...으로만 이어집니다. 즉, 초기값이 22가 아니라면 어떻게든 그 수열

     의 길이는 끊임없이 길어지게 되어 있습니다.

3. 초기값이 22를 제외한 임의의 수이고 각 수열의 일반항의 길이를 Li라고 하면

라고 합니다. 이 상수를 콘웨이 상수라고 하며 대수적 수라고 하네요. 나중에 시간나면 이놈도 한 번 구해보면 나름 재미있을 거 같습니다. ㅋㅋㅋ


지금 이 글 쓰면서 수열의 100번째 수까지 구해서 저장하고 있는데... 이런 짓은 안 하시는게 정신건강에 좋습니다. 파일 용량이 텍스트 주제 5GB를 넘어가고 있네요...(물론 저는 1부터 200억 사이에 있는 소수를 구하면서 11GB에 육박하는 텍스트 파일을 가지고 있긴 힙니다 ㅋㅋㅋ) 게다가 시간도 만만찮게 오래 걸립니다. 대충 지금 실행시간 20분 넘어간 거 같네요. 한 번 나중에 시간 복잡도 O()를 구해보는 것도 좋을 거 같네요.


  1. 리키본사 2018.04.19 14:05 신고



    #### 카카오톡 #### bmx88


    #### 텔레그램 #### rk7977

  2. 리키본사 2018.04.24 13:19 신고



    #### 카카오톡 #### bmx88


    #### 텔레그램 #### rk7977

  3. 경마사업부 2018.06.19 02:22 신고

    정말 믿고 즐기실수있는 7년차 안전공원 소개해드립니다
    메이저급 업체에서 신규 가족을 추가 모집합니다


    저희 Dream Race는 7년차 무사고 운영하고 있는 메이저급 업체입니다.
    안전! 보안! 최고의 혜택! 실시간 배팅 사이트!
    철저한 보안으로 안전하게 모시겠습니다.


    국내 최다 경기 구성 : 일본경마, 일본경정, 일본경륜, 일본바이크, 국내경마, 국내경정, 국내경륜, 마카오경마, 마카오개경


    국내 경마, 경륜, 경정이 있는 요일만 서비스 - 일본경마, 개경주, 오토바이 경주는 365일 즐길수 있습니다.
    이제 Dream Race로 집에서 편안하게 경주를 즐기세요!


    ♠서비스 안내♠
    1. 끊김 없는 고화질 영상 지원(모바일 시청가능)
    2. 다양한 해외 경기 진행!
    3. 첫충 및 매 충전 포인트 지급!
    4. 배팅시 배팅 적립금 지급!
    5. 손실금 포인트 지급!
    6. 안정적 운영, 철통보안


    실제 배당과 동일하게 적용되며 국내경기외 경기들은 365일 매일 배팅가능합니다.
    회원 1만명이상이 7년동안 안정적으로 이용하고 있으며 철통 보안으로 안전하게 모시겠습니다.


    http://pskk77.com 드림 레이스 온라인 경마사업부

    (가입후 070전화 통화후 정회원 승인처리 되오니 승인전화 꼭 받아주세요)

(참고: https://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%EC%96%B4%EC%8A%88%ED%8A%B8%EB%9D%BC%EC%8A%A4_%ED%95%A8%EC%88%98)


어쩌다가 우연히 이 함수를 알게 되었는데, 그냥 개인 취향으로 맘에 들어서 언젠간 한 번 그려보고 싶었던 놈이였습니다. 오늘 새벽에 멍 때리다가 갑자기 생각나서 python numpy를 활용해서 그려봤네요. 거의 수학 공식 그대로를 코드로 바로 옮겨서 쓸 수 있다는 게 맘에 들었습니다. 실제로 이걸 C/C++, Java로 계산하자면(까마득...) 확실히 python이 편하긴 하네요.


코드는 다음과 같습니다.


import numpy as np import matplotlib.pyplot as plt a = 0.5 # 0 < a < 1 b = 5 # ab > 1 + 3/2 * pi x = np.arange(-5, 5, 0.0001) y = np.zeros(2 * 5 * 10000, dtype="float128") for n in xrange(1000): y += np.power(a, n) * np.cos(np.power(b ,n) * np.pi * x) if n % 100 == 0: print "Now: ", n plt.grid(True) plt.xlim(-5, 5) plt.ylim(-3, 3) plt.plot(x, y, "black", linewidth=0.1) # linewidth 조정 가능 plt.savefig("Weierstrass Function.png", dpi=1200) # 그냥 보시려면 plt.show()


이미지로 그려봤습니다. 나름 적절히 linewidth 타협을 봐서 세세하게 잘 보이면서 너무 얇지도 않게(?) 그렸습니다. 너무 얇다고 생각하시는 분은 linewidth를 0.1보다 크게 세팅하시면 됩니다.

* 그리다보면 warning으로 overflow가 뜰 수 있습니다. np.power의 특성 덕분인지는 모르겠으나 그래프 그리는데에는 큰 지장은 주지 않아서 그대로 사용했습니다. 원래는 a 초기값에서 step마다 a 자신을 초기값과 곱해서 늘려가게 짜보았으나 이건 overflow가 나버리면 아예 작동에 심각한 지장을 줘서 일단은 np.power로 했습니다. 따로 제대로된 해결책을 찾아봐야 할 것 같습니다.

+ Recent posts

티스토리 툴바