오일러 프로젝트 24

어떤 대상을 순서에 따라 배열한 것을 순열이라고 합니다. 예를 들어 3124는 숫자 1, 2, 3, 4로 만들 수 있는 순열 중 하나입니다. 이렇게 만들 수 있는 모든 순열을 숫자나 문자 순으로 늘어놓은 것을 사전식(lexicographic) 순서라고 합니다. 0, 1, 2로 만들 수 있는 사전식 순열은 다음과 같습니다.

012,   021,   102,   120,   201,   210…

0, 1, 2, 3, 4, 5, 6, 7, 8, 9로 만들 수 있는 사전식 순열에서 1,000,000번째는 무엇입니까?

http://euler.synap.co.kr/prob_detail.php?id=24

접근

순열을 구하는 제너레이터를 만들어서 사용하거나, itertools.permutations() 와 같은 함수를 사용하면 모든 순열을 얻을 수 있지만, 이 방법을 사용하면 1백만번째 순열을 구하기 위해서 반복문을 백만번 돌려야 한다는 함정이 있다. 다른 방법으로 빠르게 구할 수 있는지를 알아보자. 방법이 있다면 N번째 순열을 구하는 함수를 작성할 수도 있을 것이다.

10개의 숫자는 너무 많으니까, 1, 2, 3, 4 의 네 개의 숫자의 모든 순열 중에서 15번째 순열이 무엇이 될지 생각해보자. 먼저 4개의 숫자로 만들 수 있는 모든 순열은 4! = 1 * 2 * 3 * 4 = 24개 이다. 이 중에서 1로 시작하는 것들은 1을 맨 앞자리에 고정하면 3!개가 된다는 것은 쉽게 생각할 수 있다. 즉 1로 시작하는 것이 6개, 2로 시작하는 것이 6개 이니, 15를 6으로 나눈 몫이 2이고 나머지가 3이니까, 15번째 순열은 3으로 시작하는 것 중에서 6번째라는 것을 알 수 있다. 남은 1, 2, 4에 대해서도 같은 방법을 사용할 수 있다. 31, 32, 34로 시작하는 순열은 각각 2개씩 있으므로 3을 2로 나눈 몫은 1이니 32로 시작하는 것 중에서 첫 번째 (나머지가 1)가 15번째 순열이 될 것이라는 것을 알 수 있다.

위 로직을 구현한 코드는 아래와 같다. 참고로 이 코드는 0부터 시작하기 때문에 문제의 답을 구하기 위해서는 999,999를 넘겨주어야 한다.

from functools import reduce
from typing import Sequence, TypeVar

T = TypeVar('T')

factorial = lambda n: reduce(lambda x, y: x * y, range(1, n+1), 1)

def pos_in_perm(n: int, xs: Sequence[T]) -> tuple[T, ...]:
    if n == 0:
        return (*xs,)
    l = len(xs)
    n = n % factorial(l)
    q, r = divmod(n, factorial(l -1))
    return (xs[q], *pos_in_perm(r, (*xs[:q], *xs[q+1:])))


print(''.join(str(c) for  c in pos_in_perm(999_999, range(10))))

Read more

워드프레스에서 고스트로 이전

워드프레스에서 고스트로 이전

이 글을 쓰면서도 믿기 힘든 사실인데, 블로그라는 걸 처음 시작한지가 20년이 되었습니다. 이글루스에서 처음 시작했다가, SK컴즈가 인수한다고 발표함과 동시에 워드프레스로 플랫폼을 옮겼죠. 워드프레스오 옮긴 이후에는 호스팅 환경을 이리 저리 옮기긴 했지만 거의 18년 가까이 워드프레스를 사용해온 것 같습니다. 그 동안 워드프레스는 블로깅 툴에서 명실상부한 범용CMS로 발전했습니다. 사실 웬만한 홈페이지들은 이제

By sooop
띄어쓰기에 대한 생각

띄어쓰기에 대한 생각

업무 메일을 쓸 때 가장 많이 쓰는 말 중에 하나가 메일 말미에 ‘업무에 참고 부탁 드립니다.‘인데요, 어느 날부터 아웃룩에서 이 ‘부탁 드립니다’가 틀렸다고 맞춤법 지적을 하기 시작했습니다. 맞는 말은 ‘부탁드립니다’라고 붙여 쓰는 거라고. 사실 아래아한글 시절부터 이전의 MS워드까지, 워드프로세서들의 한국어 맞춤법 검사 실력은 거의 있으나 마나 한

By sooop

구글 포토에서 아이클라우드로 탈출한 후기

한 때 구글 포토가 백업 용량을 무제한으로 제공해 주겠다고해서, 구글 포토를 사용해서 사진을 백업해왔습니다. 물론 이 이야기의 결말은 저나 이 글을 읽고 있는 여러분이나 모두 알고 있습니다. 사실 AI에게 학습 시킬 이미지 데이터를 모으기 위한 것일 뿐이라거나 하는 이야기는 그 당시에도 있었습니다만, 에이 그래도 구글인데 용량은 넉넉하게 주겠지…하는 순진한

By sooop

Julia의 함수 사용팁

연산자의 함수적 표기 Julia의 연산자는 기본적으로 함수이며, 함수 호출 표기와 같은 방식으로 호출하는 것이 가능합니다. 또한 그 자체로 함수이기 때문에 filter(), map() 과 같이 함수를 인자로 받는 함수에도 연산자를 그대로 적용하는 것이 가능합니다. 특히 + 연산자는 sum() 함수와 같이 여러 인자를 받아 인자들의 합을 구할 수 있습니다. 2 + 3 # = 5 +(2,

By sooop