fork download
  1. (defun zigzag-scan (ary &optional (fn (lambda (&key subscripts
  2. index
  3. nth
  4. direction
  5. element)
  6. (list :nth nth
  7. :element element
  8. :subscripts subscripts
  9. :index index
  10. :direction direction)))
  11. &aux (northern-end 0)
  12. (eastern-end (1- (cadr (array-dimensions ary))))
  13. (southern-end (1- (car (array-dimensions ary))))
  14. (western-end 0))
  15. (let ((result '())
  16. (nth 0)
  17. (x 0)
  18. (y 0)
  19. (dir (if (and (= western-end eastern-end)
  20. (/= northern-end southern-end))
  21. 'S 'E)))
  22. (loop
  23. (push (funcall fn
  24. :nth nth
  25. :element (aref ary y x)
  26. :subscripts (list y x)
  27. :index (array-row-major-index ary y x)
  28. :direction dir)
  29. result)
  30.  
  31. (incf nth)
  32.  
  33. ;; 右下隅に到達したら終了。
  34. (when (and (= y southern-end)
  35. (= x eastern-end))
  36. (return (nreverse result)))
  37.  
  38. ;; 移動する。
  39. (ecase dir
  40. (E (incf x))
  41. (S (incf y))
  42. (SW (decf x) (incf y))
  43. (NE (incf x) (decf y)))
  44.  
  45. ;; 次に移動する方向を設定する。
  46. (setf dir
  47. (or (ecase dir
  48. (E (cond ((= y northern-end southern-end) 'E)
  49. ((= x western-end eastern-end) 'S)
  50. ((= y southern-end) 'NE)
  51. (t 'SW)))
  52. (S (cond ((= x western-end eastern-end) 'S)
  53. ((and (= x eastern-end) (= y southern-end) 'NE))
  54. ((= x western-end) 'NE)
  55. (t 'SW)))
  56. (SW (cond ((and (= x western-end) (/= y southern-end)) 'S)
  57. ((= y southern-end) 'E)))
  58. (NE (cond ((and (= y northern-end) (= x eastern-end)) 'S)
  59. ((= x eastern-end) 'S)
  60. ((= y northern-end) 'E))))
  61. dir)))))
  62.  
  63. (loop for (M N) in '((3 3) (4 2) (3 5) (1 8) (9 11))
  64. do (let* ((A (make-array (list M N)))
  65. (path (zigzag-scan A)))
  66. (loop initially (format t "~D ~D~%"
  67. (first (array-dimensions A))
  68. (second (array-dimensions A)))
  69. finally (format t "~2%")
  70. with width = (second (array-dimensions A))
  71.  
  72. for sq in (sort path #'< :key (lambda (sq) (getf sq :index)))
  73.  
  74. for index from 0
  75. when (zerop (mod index width))
  76. do (fresh-line)
  77.  
  78. do (format t "~2D~@{~A~}"
  79. (1+ (getf sq :nth))
  80. (ecase (getf sq :direction)
  81. (N #\↑) (NE #\↗) (E #\→) (SE #\↘)
  82. (S #\↓) (SW #\↙) (W #\←) (NW #\↖))))))
  83.  
Success #stdin #stdout 0s 203840KB
stdin
Standard input is empty
stdout
3 3
 1→ 2↙ 6↓
 3↓ 5↗ 7↙
 4↗ 8→ 9↗

4 2
 1→ 2↙
 3↓ 5↓
 4↗ 6↙
 7→ 8↗

3 5
 1→ 2↙ 6→ 7↙12↓
 3↓ 5↗ 8↙11↗13↙
 4↗ 9→10↗14→15↗

1 8
 1→ 2→ 3→ 4→ 5→ 6→ 7→ 8→

9 11
 1→ 2↙ 6→ 7↙15→16↙28→29↙45→46↙63↓
 3↓ 5↗ 8↙14↗17↙27↗30↙44↗47↙62↗64↙
 4↗ 9↙13↗18↙26↗31↙43↗48↙61↗65↙78↓
10↓12↗19↙25↗32↙42↗49↙60↗66↙77↗79↙
11↗20↙24↗33↙41↗50↙59↗67↙76↗80↙89↓
21↓23↗34↙40↗51↙58↗68↙75↗81↙88↗90↙
22↗35↙39↗52↙57↗69↙74↗82↙87↗91↙96↓
36↓38↗53↙56↗70↙73↗83↙86↗92↙95↗97↙
37↗54→55↗71→72↗84→85↗93→94↗98→99↗