プロジェクト

全般

プロフィール

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

Noppi, 2024/01/12 12:34

1 1 Noppi
[ホーム](https://redmine.noppi.jp) - [[Wiki|Project Euler]]
2
# [[Problem 28]]
3
4
## Number Spiral Diagonals
5
Starting with the number $1$ and moving to the right in a clockwise direction a $5$ by $5$ spiral is formed as follows:
6
7
|  |  |  |  |  |
8
|--|--|--|--|--|
9
| <span style="color:red"> **21** </span> | 22 | 23 | 24 | <span style="color:red"> **25** </span> |
10
| 20 | <span style="color:red"> **7** </span> | 8 | <span style="color:red"> **9** </span> | 10 |
11
| 19 | 6 | <span style="color:red"> **1** </span> | 2 | 11 |
12
| 18 | <span style="color:red"> **5** </span> | 4 | <span style="color:red"> **3** </span> | 12 |
13
| <span style="color:red"> **17** </span> | 16 | 15 | 14 | <span style="color:red"> **13** </span> |
14
15
It can be verified that the sum of the numbers on the diagonals is $101$.
16
17
What is the sum of the numbers on the diagonals in a $1001$ by $1001$ spiral formed in the same way?
18
19
## 螺旋状に並んだ数の対角線
20
1から初めて右方向に進み時計回りに数字を増やしていき, 5×5の螺旋が以下のように生成される:
21
22
|  |  |  |  |  |
23
|--|--|--|--|--|
24
| <span style="color:red"> **21** </span> | 22 | 23 | 24 | <span style="color:red"> **25** </span> |
25
| 20 | <span style="color:red"> **7** </span> | 8 | <span style="color:red"> **9** </span> | 10 |
26
| 19 | 6 | <span style="color:red"> **1** </span> | 2 | 11 |
27
| 18 | <span style="color:red"> **5** </span> | 4 | <span style="color:red"> **3** </span> | 12 |
28
| <span style="color:red"> **17** </span> | 16 | 15 | 14 | <span style="color:red"> **13** </span> |
29
30
両対角線上の数字の合計は101であることが確かめられる.
31
32
1001×1001の螺旋を同じ方法で生成したとき, 対角線上の数字の和はいくつか?
33
34
```scheme
35
(import (scheme base)
36
        (gauche base)
37
        (gauche array))
38
39 3 Noppi
(define (diagonal-positions xynums)
40
  (assume (exact-integer? xynums))
41
  (assume (positive? xynums))
42
  (let* (; 左上→右下
43
         [diagonal-pos1 (fold-right
44
                          (^[n lis] (cons `(,n . ,n) lis))
45
                          '()
46
                          (iota xynums))]
47
         ; 右上→左下
48
         [diagonal-pos2 (fold-right
49
                          (^[n lis] (cons `(,n . ,(- xynums 1 n)) lis))
50
                          '()
51
                          (iota xynums))]
52
         [diagonal-pos (append diagonal-pos1 diagonal-pos2)])
53
    (if (odd? xynums)
54
      ; 奇数方陣の時は中央が重複して列挙されるので1つを外して返す
55
      (cons `(,(div xynums 2) . ,(div xynums 2))
56
            (remove (^c (= (car c) (cdr c) (div xynums 2)))
57
                    diagonal-pos))
58
      diagonal-pos)))
59
60
(define (diagonal-nums xynums)
61
  (assume (exact-integer? xynums))
62
  (assume (positive? xynums))
63
  (let ([table (make-table xynums)])
64
    (map (^c (array-ref table (car c) (cdr c)))
65
         (diagonal-positions xynums))))
66
67 1 Noppi
(define (make-table xynums)
68 3 Noppi
  (assume (exact-integer? xynums))
69
  (assume (positive? xynums))
70
  (letrec ([walk-right! (^[n y x table]
71 1 Noppi
                          (cond
72
                            [(and (< (+ x 1) xynums)
73
                                  (not (array-ref table y (+ x 1))))
74
                             (array-set! table y (+ x 1) n)
75 3 Noppi
                             (walk-down! (+ n 1) y (+ x 1) table)]
76
                            [(and (<= 0 (- y 1))
77
                                  (not (array-ref table (- y 1) x)))
78
                             (array-set! table (- y 1) x n)
79
                             (walk-right! (+ n 1) (- y 1) x table)]
80 2 Noppi
                            [else table]))]
81 3 Noppi
           [walk-down! (^[n y x table]
82
                         (cond
83
                           [(and (< (+ y 1) xynums)
84
                                 (not (array-ref table (+ y 1) x)))
85
                            (array-set! table (+ y 1) x n)
86
                            (walk-left! (+ n 1) (+ y 1) x table)]
87
                           [(and (< (+ x 1) xynums)
88
                                 (not (array-ref table y (+ x 1))))
89
                            (array-set! table y (+ x 1) n)
90
                            (walk-down! (+ n 1) y (+ x 1) table)]
91
                           [else table]))]
92
           [walk-left! (^[n y x table]
93
                         (cond
94
                           [(and (<= 0 (- x 1))
95
                                 (not (array-ref table y (- x 1))))
96
                            (array-set! table y (- x 1) n)
97
                            (walk-up! (+ n 1) y (- x 1) table)]
98
                           [(and (< (+ y 1) xynums)
99
                                 (not (array-ref table (+ y 1) x)))
100
                            (array-set! table (+ y 1) x n)
101
                            (walk-left! (+ n 1) (+ y 1) x table)]
102
                           [else table]))]
103
           [walk-up! (^[n y x table]
104
                       (cond
105
                         [(and (<= 0 (- y 1))
106
                               (not (array-ref table (- y 1) x)))
107
                          (array-set! table (- y 1) x n)
108
                          (walk-right! (+ n 1) (- y 1) x table)]
109
                         [(and (<= 0 (- x 1))
110
                               (not (array-ref table y (- x 1))))
111
                          (array-set! table y (- x 1) n)
112
                          (walk-up! (+ n 1) y (- x 1) table)]
113
                         [else table]))])
114
    (let ([table (make-array (shape 0 xynums 0 xynums) #f)])
115 1 Noppi
      (array-set! table (div xynums 2) (div xynums 2) 1)
116 3 Noppi
      (walk-right! 2 (div xynums 2) (div xynums 2) table))))
117 1 Noppi
118 3 Noppi
(define answer-28
119
  (apply + (diagonal-nums 1001)))
120 1 Noppi
121 3 Noppi
(format #t "28: ~d~%" answer-28)
122 1 Noppi
```