Problem 51 » 履歴 » バージョン 2
Noppi, 2024/01/18 02:56
1 | 1 | Noppi | [ホーム](https://redmine.noppi.jp) - [[Wiki|Project Euler]] |
---|---|---|---|
2 | # [[Problem 51]] |
||
3 | |||
4 | ## Prime Digit Replacements |
||
5 | By replacing the 1<sup>st</sup> digit of the 2-digit number *3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime. |
||
6 | |||
7 | By replacing the 3<sup>rd</sup> and 4<sup>th</sup> digits of 56**3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property. |
||
8 | |||
9 | Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family. |
||
10 | |||
11 | ## 素数の桁置換 |
||
12 | *3の第1桁を置き換えることで, 13, 23, 43, 53, 73, 83という6つの素数が得られる. |
||
13 | |||
14 | 56**3の第3桁と第4桁を同じ数で置き換えることを考えよう. この5桁の数は7つの素数をもつ最初の例である: 56003, 56113, 56333, 56443, 56663, 56773, 56993. よって, この族の最初の数である56003は, このような性質を持つ最小の素数である. |
||
15 | |||
16 | 桁を同じ数で置き換えることで8つの素数が得られる最小の素数を求めよ. (注:連続した桁でなくても良い) |
||
17 | |||
18 | ```scheme |
||
19 | 2 | Noppi | (import (scheme base) |
20 | (gauche base)) |
||
21 | |||
22 | (define (prime? num) |
||
23 | (assume (exact-integer? num)) |
||
24 | (assume (positive? num)) |
||
25 | (cond |
||
26 | [(= num 1) #f] |
||
27 | [(= num 2) #t] |
||
28 | [(even? num) #f] |
||
29 | [(= num 3) #t] |
||
30 | [(zero? (mod num 3)) #f] |
||
31 | [else |
||
32 | (let loop ([n6-1 5]) |
||
33 | (let ([n6+1 (+ n6-1 2)]) |
||
34 | (cond |
||
35 | [(< num |
||
36 | (* n6-1 n6-1)) |
||
37 | #t] |
||
38 | [(zero? (mod num n6-1)) |
||
39 | #f] |
||
40 | [(< num |
||
41 | (* n6+1 n6+1)) |
||
42 | #t] |
||
43 | [(zero? (mod num n6+1)) |
||
44 | #f] |
||
45 | [else |
||
46 | (loop (+ n6+1 4))])))])) |
||
47 | |||
48 | (define digit-6-pattern |
||
49 | (let loop1 ([a 0] [lis '()]) |
||
50 | (if (< 3 a) |
||
51 | lis |
||
52 | (let loop2 ([b (+ 1 a)] [lis lis]) |
||
53 | (if (< 4 b) |
||
54 | (loop1 (+ a 1) lis) |
||
55 | (let ([temp (string->vector "*****c")]) |
||
56 | (vector-set! temp a #\a) |
||
57 | (vector-set! temp b #\b) |
||
58 | (loop2 (+ 1 b) |
||
59 | (cons (vector->string temp) |
||
60 | lis)))))))) |
||
61 | |||
62 | (define (sum-num-lis numstr) |
||
63 | (fold (^[c sum] |
||
64 | (let ([n (digit->integer c)]) |
||
65 | (if n |
||
66 | (+ sum n) |
||
67 | sum))) |
||
68 | 0 |
||
69 | (string->list numstr))) |
||
70 | |||
71 | (define (digit-6-list pattern) |
||
72 | (filter |
||
73 | (^[numstr] |
||
74 | (not (zero? |
||
75 | (mod (sum-num-lis numstr) |
||
76 | 3)))) |
||
77 | (let loop ([index 0] |
||
78 | [rest (string->list pattern)] |
||
79 | [temp '()] |
||
80 | [result '()]) |
||
81 | (let ([next-loop (^[select-num-list] |
||
82 | (fold-right |
||
83 | (^[n lis] |
||
84 | (loop (+ index 1) |
||
85 | (cdr rest) |
||
86 | (cons (integer->digit n) temp) |
||
87 | lis)) |
||
88 | result |
||
89 | select-num-list))]) |
||
90 | (cond |
||
91 | [(null? rest) |
||
92 | (cons (list->string (reverse temp)) |
||
93 | result)] |
||
94 | [(char=? (car rest) #\*) |
||
95 | (loop (+ index 1) |
||
96 | (cdr rest) |
||
97 | (cons #\* temp) |
||
98 | result)] |
||
99 | [(zero? index) |
||
100 | (next-loop (iota 9 1))] |
||
101 | [(= index 5) |
||
102 | (next-loop '(1 3 7 9))] |
||
103 | [else |
||
104 | (next-loop (iota 10))]))))) |
||
105 | |||
106 | (define all-6-list |
||
107 | (fold (^[pattern result] |
||
108 | (append (digit-6-list pattern) |
||
109 | result)) |
||
110 | '() |
||
111 | digit-6-pattern)) |
||
112 | |||
113 | (define (replace-numstr numstr n) |
||
114 | (string->number |
||
115 | (string-map (^c |
||
116 | (if (char=? c #\*) |
||
117 | (integer->digit n) |
||
118 | c)) |
||
119 | numstr))) |
||
120 | |||
121 | (define (prime-6digit? numstr) |
||
122 | (let ([select-num-list (iota 10)]) |
||
123 | (when (char=? (string-ref numstr 0) |
||
124 | #\*) |
||
125 | (set! select-num-list (cdr select-num-list))) |
||
126 | (let loop ([rest-num-list select-num-list] |
||
127 | [find-count 0]) |
||
128 | (cond |
||
129 | [(<= 8 find-count) |
||
130 | numstr] |
||
131 | [(null? rest-num-list) |
||
132 | #f] |
||
133 | [(prime? (replace-numstr |
||
134 | numstr |
||
135 | (car rest-num-list))) |
||
136 | (loop (cdr rest-num-list) (+ find-count 1))] |
||
137 | [else |
||
138 | (loop (cdr rest-num-list) find-count)])))) |
||
139 | |||
140 | (define all-valid-6-list |
||
141 | (fold (^[numstr lis] |
||
142 | (if (prime-6digit? numstr) |
||
143 | (cons numstr lis) |
||
144 | lis)) |
||
145 | '() |
||
146 | all-6-list)) |
||
147 | |||
148 | (define answer-51 |
||
149 | (replace-numstr (car all-valid-6-list) |
||
150 | 1)) |
||
151 | |||
152 | (format #t "51: ~d~%" answer-51) |
||
153 | 1 | Noppi | ``` |