@@ -92,39 +92,25 @@ The bits refer to the pyramid cards in this order:
9292 " Return a vector of all 1430 valid PYRAMID-FLAGS values.
9393The rule is a pyramid card can't be removed unless all the cards covering it
9494from below are removed first."
95- (labels ((power-set (list )
96- " Return a list of all subsets of elements in the list."
97- (loop with length = (length list )
98- for flags from 0 below (ash 1 length )
99- collect (loop for index from 0 below length
100- when (logbitp index flags)
101- collect (elt list index))))
102- (optional-masks (bits num-bits)
103- " Return a list of masks indicating previous row optional cards."
104- (loop for i from 0 to (- num-bits 2 )
105- for mask = #b11 then (ash mask 1 )
106- unless (logtest mask bits)
107- collect (ash 1 i)))
108- (previous-rows (bits num-bits)
109- " Return all valid card existence bit flags for the previous row."
110- (loop with all-bits-on = (1- (ash 1 (1- num-bits)))
111- for masks in (power-set (optional-masks bits num-bits))
112- collect (logandc2 all-bits-on (reduce #' logior masks))))
113- (pyramid-flags (&rest row-flags)
114- " Return a PYRAMID-FLAGS given card existence bits for each row."
115- (reduce #' logior (mapcar #' ash row-flags ' (0 1 3 6 10 15 21 )))))
116- (let ((all ' ()))
117- ; ; for all possible combinations of cards on the bottom row, calculate
118- ; ; all possible combinations of cards for each previous row, then combine
119- ; ; them all into PYRAMID-FLAGS values
120- (dotimes (r7 (ash 1 7 ) (sort (coerce all ' vector) #' < ))
121- (dolist (r6 (previous-rows r7 7 ))
122- (dolist (r5 (previous-rows r6 6 ))
123- (dolist (r4 (previous-rows r5 5 ))
124- (dolist (r3 (previous-rows r4 4 ))
125- (dolist (r2 (previous-rows r3 3 ))
126- (dolist (r1 (previous-rows r2 2 ))
127- (push (pyramid-flags r1 r2 r3 r4 r5 r6 r7) all)))))))))))
95+ (labels ((make-pyramid-flags (pyramid)
96+ (reduce #' logior (mapcar #' ash pyramid ' (0 1 3 6 10 15 21 ))))
97+ (valid-row-p (row row-size next-row)
98+ (loop for i from 0 below row-size
99+ always (or (logbitp i row)
100+ (zerop (mask-field (byte 2 i) next-row)))))
101+ (add-row (row-size pyramids)
102+ (loop for row from 0 below (ash 1 row-size)
103+ nconc (loop for pyramid in pyramids
104+ when (valid-row-p row row-size (first pyramid))
105+ collect (cons row pyramid))))
106+ (build-flags (row-size pyramids)
107+ (if (zerop row-size)
108+ (sort (map ' vector #' make-pyramid-flags pyramids) #' < )
109+ (build-flags (1- row-size) (add-row row-size pyramids)))))
110+ ; ; This needs to be fast or there will be delays during compilation.
111+ ; ; Basically this builds valid pyramids recursively bottom-up as lists of
112+ ; ; row flags, then converts each pyramid into a pyramid-flags value.
113+ (build-flags 6 (loop for row from 0 below (ash 1 7 ) collect (list row)))))
128114
129115(defvar *pyramid-flags* (all-pyramid-flags)
130116 " All valid PYRAMID-FLAGS values." )
0 commit comments