일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- projecteuler
- Compressible Flow
- Heat Equation
- 힙
- 통계학
- 파이썬
- Fluid Dynamics
- 유체역학
- Crank-Nicolson
- 우선순위큐
- heap
- Fluids
- 프로젝트오일러
- 회귀
- Navier-Stokes
- 프로그래머스
- FTCS
- Finite Difference Method
- Blasius
- 이중우선순위큐
- Laminar
- Boundary Layers
- 예제
- 디스크 컨트롤러
- regression
- programmers
- Turbulent
- Python
- python3
- Statistics
- Today
- Total
Sudal's Garage
Project Euler 26 본문
Question:
A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857) 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1
Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
문제:
위 분수는 분자가 1이고 분모는 양의 정수인 분수이다. 분모가 2부터 10까지인 단위 분수를 나열하면 다음과 같다.
1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857) 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1
0.1(6) 은 0.166666...을 의미한다. 괄호안에 순환마디를 나타내는데, 순환마디란 순환소수에서 일정하게 되풀이 되는 한 부분을 말한다. 1/7 은 순환마디의 길이가 6인 순환소수이다.
d < 1000 인 양의 정수 d 중 1/d 의 순환마디가 가장 긴 것을 구하여라.
Solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
첫번째로 작성했던 코드
먼저, 소수 (prime number) 를 역수 취했을 때에 순환소수가 됨으로, 소수들만 판별하기로 했다.
실제 나눗셈을 하는 것 처럼, 10부터 차례차례 나눠나가는 방식을 사용하고,
list에 나머지들을 저장해 넣었다. 후에, 일일이 slice 를 이용해 반복되는 문구가 있다면
cycle = True로 설정해 순환됨을 확인하고, 길이를 비교해넣었다.
하지만 숫자 하나당 list 가 너무 길어지고 slice하는 횟수도 많아져서 시간이 너무 오래 걸린다.
위 코드는 3분 정도 걸린다 ...
elif len(remainder) == 2:
이 라인은 1/3 = 0.3333... 과 1/101 = 0.00990099... 같은 차이를 구분하기 위해 넣었다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from itertools import count from sympy import primerange import time longest = 0 longest_d = 0 start = time.time() for d in primerange(1,1000): r = 10 remainder = dict() for i in count(0): if r == 0: #무한소수가 아님 break elif r in remainder: if longest < i: longest = i longest_d = d break break remainder[r] = i r = 10 * (r % d) print('''The longest length of cycle: {0} The number has the longest cycle: {1} Found in ...{2:.2f}s'''.format(longest,longest_d,time.time() - start)) |
두번째로 작성한 코드.
itertools 안의 count 메소드를 이용했다.
방식은 비슷하지만, 나눈 나머지의 10배(r)를 dictionary에 저장한다.
만약 같은 r이 dictionary에 있다면 dictionary의 길이를 판별한다.
복잡한 과정없이 1/3 = 0.333... 1/101 = 0.00990099... 같은 케이스를 한 번에 구별할 수 있다.
0.02s 걸렸다! 9000배 빨라졌다!!
'Programming > Project Euler - python' 카테고리의 다른 글
Project Euler 29 (0) | 2019.03.17 |
---|---|
Project Euler 28 (0) | 2019.03.16 |
Project Euler 27 (0) | 2019.03.15 |
Project Euler 25 (0) | 2019.03.13 |
Project Euler 24 (0) | 2019.03.12 |