오일러 프로젝트 37

소수 3797에는 왼쪽부터 자리수를 하나씩 없애거나 (3797, 797, 97, 7), 오른쪽부터 없애도 (3797, 379, 79, 7) 모두 소수가 되는 성질이 있습니다. 이런 성질을 가진 소수는 단 11개만이 존재합니다. 이것을 모두 찾아서 합을 구하세요. (참고, 한자리 소수인 2, 3, 5, 7 은 제외합니다.)

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

어떤 소수의 왼쪽과 오른쪽에서 자리수를 하나씩 지워나갔을 때, 그 숫자도 계속 소수가 되는 소수를 찾는 문제이다. 이 문제는 순환 소수와 비슷한 구석이 있다. 소수(prime number)의 끝자리(1의 자리)에 올 수 있는 숫자는 무엇일까? 우선 0, 2, 4, 6, 8로 끝나는 수는 짝수이므로 올 수 없다. 5로 끝나는 수도 5의 배수이므로 올 수 없다. 결국 (두자리 이상의) 소수의 1의 자리에는 1, 3, 7, 9 만이 올 수 있다.

왼쪽이나 오른쪽에서 숫자를 하나씩 지워나간다면 결국 숫자를 이루는 모든 수들이 1의 자리에 오게 되므로, 애초에 이 성질을 가진 수들은 모두 1, 3, 7, 9로만 이루어 질 것이며, 한 자리 소수가 되어야 하므로 첫 자리와 끝 자리 숫자는 3 혹은 7만 가능하다. 첫째자리는 그 조건이 조금 더 완화되어 2와 5가 올 수 있다. (실제 풀이에 도움되는 정보는 아니다.)

왼쪽에서 숫자를 하나씩 제거하는 것과 오른쪽에서 숫자를 하나씩 제거하는 것을 따로 생각하면 복잡/귀찮을 수 있지만, 이것을 중간 지점에서 가른 것을 모은 것이라고 이해하면 의외로 간단한 코드로 풀린다. 예를 들어 ‘12345’를 100으로 나눈 몫과 나머지는 각각 (123, 45) 인데, 이는 오른쪽에서 두 숫자를 지운 것과, 왼쪽에서 세 숫자를 지운 것에 해당한다.

아래의 span() 함수는 나눗셈을 통해서 숫자들을 가른 결과를 리스트로 반환한다.

from math import log10

def span(n: int) -> list[int]:
  res = [n]
  l = int(log10(n))
  for i in range(l):
    res.extend(divmod(n, 10**(i + 1)))
  return res

span(123)
# -> [123, 12, 3, 1, 23]

우리가 찾고자 하는 값은 span() 함수를 적용하여 얻는 정수들이 모두 소수인 경우가 되겠다. 따라서 값을 검사하는 test() 함수는 아래와 같이 간단하게 작성할 수 있다.

test = lambda x: all(map(isprime, span(x)))

문제의 조건에서는 양 끝의 숫자가 2, 3, 7 (2는 왼쪽 끝자리에만 올 수 있다)이어야하므로, 테스트를 통과할 수 있는 가장 작은 수는 23이다. 23부터 시작하여 조건을 만족하는 수 11개를 찾으면 된다. 참고로 이 문제의 조건을 만족하는 가장 큰 소수는 739397로 백만 보다 작기 때문에 요즘(2023년) 기준으로 왠만한 컴퓨터 사양에서는 파이썬으로도 충분히 1초 이내에 답을 구할 수 있다.

def main():
  # n : 테스트할 정수
  # k : 찾아야 할 소수
  # s : 누적합
  # i : 4, 6 중에서 어떤 값을 더할 지
  n, k, s, i = 23, 11, 0, 0
  ds = (4, 6)
  while k > 0:
    if test(n):
      k, s  = k - 1, s + n
    n, i = n + ds[i], i ^ 1
  return s

참고로 증가치를 번갈아가면서 적용하기 위해서는 i 값이 0, 1, 0, 1 을 반복해야 하는데 (i + 1) % 2 로 구할수도 있지만, XOR 연산을 사용하면 더 빠르고 간단하게 0, 1을 번갈아 만들 수 있다.

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