プロジェクト

全般

プロフィール

Problem 51 » 履歴 » バージョン 3

Noppi, 2024/01/18 04:11

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 3 Noppi
(define (small-prime-6digit numstr)
149
  (cond
150
    [(and (not (char=?
151
                 (string-ref numstr 0)
152
                 #\*))
153
          (prime? (replace-numstr numstr 0)))
154
     (replace-numstr numstr 0)]
155
    [(prime? (replace-numstr numstr 1))
156
     (replace-numstr numstr 1)]
157
    [else (replace-numstr numstr 2)]))
158
159 1 Noppi
(define answer-51
160 3 Noppi
  (apply min
161
         (map small-prime-6digit
162
              all-valid-6-list)))
163 2 Noppi
164 1 Noppi
(format #t "51: ~d~%" answer-51)
165
```