aboutsummaryrefslogtreecommitdiff
path: root/challenge-073/jeongoon/common-lisp/ch-1.lsp
blob: bd1c62409577fdaf2d58732a40edba5290efeed9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
;; Ref:
;; http://cl-cookbook.sourceforge.net/loop.html
;; http://clhs.lisp.se/Body/f_mk_ar.htm
;; https://stackoverflow.com/questions/3950601/swapping-elements-in-a-common-lisp-list
;; http://clhs.lisp.se/Body/v_rnd_st.htm#STrandom-stateST
;; https://stackoverflow.com/questions/13359025/adding-to-the-end-of-list-in-lisp

;; I've done with array not list -- which seems wrong choice...

;; tested with
;; sbcl --script ch-1.lsp <number>

(defun get-command-line () ;; from #072
  (or
   #+CLISP *args*
   #+SBCL *posix-argv*
   #+LISPWORKS system:*line-arguments-list*
   #+CMU extensions:*command-line-words*
   nil))

(defun get-random-pairs (n)
  (let ((*random-state* (make-random-state t)))
       (loop for cnt from 1 to n
             collect (list (random n) (random n)))))

(defun make-range (minv maxv &optional (step 1)) ;; from #072
  (when (<= minv maxv)
    (cons minv (make-range (+ minv step) maxv step))))

(defun make-vector-range (min max &optional (step 1))
  (let* ((range (make-range min max step))
         (size (length range)))
    (make-array (list size) :initial-contents range)))

;; not used here
(defun minimum-in-vector (arr &optional (i 0))
  (let ((j (+ i 1)))
    (if (= (length arr) j)
        (aref arr i)
      ;; else
      (when (> (length arr) j)
        (min (aref arr i) (minimum-in-vector arr j))))))

(defun shuffle-array-by-swapping (arr)
  (let* ((size (length arr))
         (shuffle-pairs (get-random-pairs size)))
    (loop for pair in shuffle-pairs
          do (let ((le (first pair)) (ri (second pair)))
               (when (not (and (null le) (null ri)))
                 ;; rotatef: change in place ; I think *f means put in pyhsical memory
                 (rotatef (aref arr le) (aref arr ri)))))))

;; tranlated from groupMinimumList in perl/ch-1.pl
(defun group-minimum-list (arr group-size)
  (let* ((total-size     (length arr))
        (min-val        nil)
        (idx-init       (- 1 group-size))
        (idx-max        (- total-size group-size))
        (idx-memo       -1)
        (result         ()))

    (loop for b from 0 below total-size  ;; b:index for value to be checked
                                         ;;   or last  index in the gorup
          do (let* ((idx (+ idx-init b)) ;; idx: first index in the group
                    (idx-memo-inboundp (> idx-memo idx))
                    (group-inboundp (and (<= 0 idx) (<= idx idx-max)))
                    (cur-val (aref arr b)))

               (if (and group-inboundp (not idx-memo-inboundp))
                   ;; compare everything in the group
                   (progn
                     (setq idx-memo idx) ;; restart from first index in the grp
                     (setq min-val (aref arr idx))
                     (loop for d from 1 below group-size
                           do(let* ((j (+ idx d))
                                    (cur-val (aref arr j)))
                               (when (>= min-val cur-val)
                                 (setq idx-memo j)
                                 (setq min-val cur-val)))))
                 ;; else
                 (when (or (null min-val) (<= cur-val min-val))
                   (setq min-val cur-val)
                   (setq idx-memo b)) ;; *real index* in the list not idx
                 )

               (when group-inboundp
                 (if (null result)
                     (setq result (list min-val))
                   (nconc result (list min-val))))))
    result ))

(defparameter *cmdline* (get-command-line))

(defun print-usage ()
  (format t "Usage: sbcl --script ch-1.lsp <sliding-size>" (car *cmdline*)))

(when (not (= (length *cmdline*) 2))
  (format t "Wrong Number of arguments: expected 1: but got: ~d~%" (- (length *cmdline*) 1))
  (print-usage)
  (quit))

;; *slide-size*
(defparameter *slide-size* (parse-integer (second *cmdline*)))

(when (< *slide-size* 3)
  (format t "Too short slide size: ~d: using 3~%" *slide-size*)
  (setq *slide-size* 3))

;; *frame-size* ; which is 3 times larger than slide at least
(defparameter *frame-size* (* 10 (round (* 0.3 *slide-size*) 1)))

(format t "Frame Size: ~d~%Slide Size: ~d~%" *frame-size* *slide-size*)

(defparameter *example* (make-vector-range 0 (- *frame-size* 1)))
(shuffle-array-by-swapping *example*)
(format t "Input: ~S~%" *example*) ;; used array not list :-/
(defvar result (group-minimum-list *example* *slide-size*))
(format t "Output: ~S~%" result)