Problem 32 » 履歴 » バージョン 1
Noppi, 2024/01/13 06:38
1 | 1 | Noppi | [ホーム](https://redmine.noppi.jp) - [[Wiki|Project Euler]] |
---|---|---|---|
2 | # [[Problem 32]] |
||
3 | |||
4 | ## Pandigital Products |
||
5 | We shall say that an $n$-digit number is pandigital if it makes use of all the digits $1$ to $n$ exactly once; for example, the $5$-digit number, $15234$, is $1$ through $5$ pandigital. |
||
6 | |||
7 | The product $7254$ is unusual, as the identity, $39 \times 186 = 7254$, containing multiplicand, multiplier, and product is $1$ through $9$ pandigital. |
||
8 | |||
9 | Find the sum of all products whose multiplicand/multiplier/product identity can be written as a $1$ through $9$ pandigital. |
||
10 | |||
11 | HINT: Some products can be obtained in more than one way so be sure to only include it once in your sum. |
||
12 | |||
13 | ## パンデジタル積 |
||
14 | すべての桁に 1 から n が一度だけ使われている数をn桁の数がパンデジタル (pandigital) であるということにしよう: 例えば5桁の数 15234 は1から5のパンデジタルである. |
||
15 | |||
16 | 7254 は面白い性質を持っている. 39 × 186 = 7254 と書け, 掛けられる数, 掛ける数, 積が1から9のパンデジタルとなる. |
||
17 | |||
18 | 掛けられる数/掛ける数/積が1から9のパンデジタルとなるような積の総和を求めよ. |
||
19 | |||
20 | ヒント: いくつかの積は, 1通り以上の掛けられる数/掛ける数/積の組み合わせを持つが1回だけ数え上げよ. |
||
21 | |||
22 | ```scheme |
||
23 | (import (scheme base) |
||
24 | (gauche base) |
||
25 | (scheme sort)) |
||
26 | |||
27 | (define (my-permutation lis) |
||
28 | (let perm-sub ([rest lis] [sub '()] [result '()]) |
||
29 | (if (null? rest) |
||
30 | (cons (reverse sub) result) |
||
31 | (fold-right (^[n result] |
||
32 | (perm-sub (delete n rest) (cons n sub) result)) |
||
33 | result |
||
34 | rest)))) |
||
35 | |||
36 | (define (unique lis) |
||
37 | (let loop ([prev #f] [rest lis] [result '()]) |
||
38 | (cond |
||
39 | [(null? rest) (reverse result)] |
||
40 | [(and prev |
||
41 | (= prev (car rest))) |
||
42 | (loop prev (cdr rest) result)] |
||
43 | [else |
||
44 | (loop (car rest) |
||
45 | (cdr rest) |
||
46 | (cons (car rest) result))]))) |
||
47 | |||
48 | ; 有効な a * b = c のそれぞれの桁数は次の通り |
||
49 | ; (1 4 4) |
||
50 | ; (2 3 4) |
||
51 | ; (3 2 4) |
||
52 | ; (4 1 4) |
||
53 | ; ただし、a * b = b * a なので後半は必要ない |
||
54 | (define pandigital-num-triplets |
||
55 | (let ([perm-list (my-permutation (iota 9 1))]) |
||
56 | (let loop ([rest perm-list] [result '()]) |
||
57 | (if (null? rest) |
||
58 | result |
||
59 | (let* ([digital (car rest)] |
||
60 | [rest (cdr rest)] |
||
61 | [digital-vec (list->vector digital)] |
||
62 | [a1 (vector-ref digital-vec 0)] |
||
63 | [b1 (+ (* (vector-ref digital-vec 1) 1000) |
||
64 | (* (vector-ref digital-vec 2) 100) |
||
65 | (* (vector-ref digital-vec 3) 10) |
||
66 | (vector-ref digital-vec 4))] |
||
67 | [c (+ (* (vector-ref digital-vec 5) 1000) |
||
68 | (* (vector-ref digital-vec 6) 100) |
||
69 | (* (vector-ref digital-vec 7) 10) |
||
70 | (vector-ref digital-vec 8))] |
||
71 | [a2 (+ (* (vector-ref digital-vec 0) 10) |
||
72 | (vector-ref digital-vec 1))] |
||
73 | [b2 (+ (* (vector-ref digital-vec 2) 100) |
||
74 | (* (vector-ref digital-vec 3) 10) |
||
75 | (vector-ref digital-vec 4))] |
||
76 | [new-result result]) |
||
77 | (when (= (* a1 b1) c) |
||
78 | (set! new-result (cons `(,a1 ,b1 . ,c) new-result))) |
||
79 | (when (= (* a2 b2) c) |
||
80 | (set! new-result (cons `(,a2 ,b2 . ,c) new-result))) |
||
81 | (loop rest new-result)))))) |
||
82 | |||
83 | (define pandigital-nums |
||
84 | (unique |
||
85 | (list-sort < (map (cut cddr <>) |
||
86 | pandigital-num-triplets)))) |
||
87 | |||
88 | (define answer-32 |
||
89 | (apply + pandigital-nums)) |
||
90 | |||
91 | (format #t "32: ~d~%" answer-32) |
||
92 | ``` |