Blame


1 12687dd9 2023-08-04 jrmu ;; The first three lines of this file were inserted by DrScheme. They record metadata
2 12687dd9 2023-08-04 jrmu ;; about the language level of this file in a form that our tools can easily process.
3 12687dd9 2023-08-04 jrmu #reader(lib "htdp-advanced-reader.ss" "lang")((modname |32.3|) (read-case-sensitive #t) (teachpacks ((lib "draw.ss" "teachpack" "htdp") (lib "arrow.ss" "teachpack" "htdp") (lib "gui.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ((lib "draw.ss" "teachpack" "htdp") (lib "arrow.ss" "teachpack" "htdp") (lib "gui.ss" "teachpack" "htdp")))))
4 12687dd9 2023-08-04 jrmu ;A solitaire board (board) is a (vectorof (vectorof booleans)), where true represents a filled square, false an empty square. In particular, for any given board, the n-th element is a vector containing n booleans. We call a triangular board with n-pegs to a side a size-n triangle. For example, the representation of a size-4 equilaterial triangular board:
5 12687dd9 2023-08-04 jrmu
6 12687dd9 2023-08-04 jrmu ;(vector (vector false)
7 12687dd9 2023-08-04 jrmu ; (vector true true)
8 12687dd9 2023-08-04 jrmu ; (vector true true true)
9 12687dd9 2023-08-04 jrmu ; (vector true true true true))
10 12687dd9 2023-08-04 jrmu
11 12687dd9 2023-08-04 jrmu ;A move is a list
12 12687dd9 2023-08-04 jrmu ;(list o n)
13 12687dd9 2023-08-04 jrmu ;where o,n are posns. o represents the original position of the peg and n represents the new position of the peg.
14 12687dd9 2023-08-04 jrmu
15 12687dd9 2023-08-04 jrmu (define-struct state (board move))
16 12687dd9 2023-08-04 jrmu
17 12687dd9 2023-08-04 jrmu ;A state is a structure
18 12687dd9 2023-08-04 jrmu ;(make-state b m)
19 12687dd9 2023-08-04 jrmu ;where b is a board and m is a move.
20 12687dd9 2023-08-04 jrmu
21 12687dd9 2023-08-04 jrmu ;By default, we specify the coordinates of a peg with a posn (x,y), where x refers to horizontal distance (the column number) and y refers to the vertical distance (the row number). The top position of any given board has an index (make-posn 1 1). When referencing a given peg in the board by using vector indices, we will explicitly state that we are using vector indices 0,0 to reference the top position in the board. Otherwise, assume (make-posn 1 1) specifies the first position in the board.
22 12687dd9 2023-08-04 jrmu
23 12687dd9 2023-08-04 jrmu ;enabled? : posn board -> boolean
24 12687dd9 2023-08-04 jrmu ;Determines whether or not the peg specified by apeg is enabled in aboard (enabled means that the peg is capable of jumping).
25 12687dd9 2023-08-04 jrmu
26 12687dd9 2023-08-04 jrmu (define (enabled? apeg aboard)
27 12687dd9 2023-08-04 jrmu (local ((define peg-x (posn-x apeg))
28 12687dd9 2023-08-04 jrmu (define peg-y (posn-y apeg))
29 12687dd9 2023-08-04 jrmu (define right-peg-x (+ peg-x 2))
30 12687dd9 2023-08-04 jrmu (define down-peg-y (+ peg-y 2))
31 12687dd9 2023-08-04 jrmu (define left-peg-x (- peg-x 2))
32 12687dd9 2023-08-04 jrmu (define up-peg-y (- peg-y 2))
33 12687dd9 2023-08-04 jrmu (define down-peg (make-posn peg-x down-peg-y))
34 12687dd9 2023-08-04 jrmu (define right-peg (make-posn right-peg-x peg-y))
35 12687dd9 2023-08-04 jrmu (define up-peg (make-posn peg-x up-peg-y))
36 12687dd9 2023-08-04 jrmu (define left-peg (make-posn left-peg-x peg-y))
37 12687dd9 2023-08-04 jrmu (define diagonal-up-peg (make-posn left-peg-x up-peg-y))
38 12687dd9 2023-08-04 jrmu (define diagonal-down-peg (make-posn right-peg-x down-peg-y)))
39 12687dd9 2023-08-04 jrmu (cond
40 12687dd9 2023-08-04 jrmu ;;first, is there even a peg?
41 12687dd9 2023-08-04 jrmu ;;if so, test jump down, jump right, jump up, jump left, jump diagonal (up), jump diagonal (down), in that order
42 12687dd9 2023-08-04 jrmu [(peg-exists? apeg aboard)
43 12687dd9 2023-08-04 jrmu (or (jump? apeg down-peg aboard)
44 12687dd9 2023-08-04 jrmu (jump? apeg right-peg aboard)
45 12687dd9 2023-08-04 jrmu (jump? apeg up-peg aboard)
46 12687dd9 2023-08-04 jrmu (jump? apeg left-peg aboard)
47 12687dd9 2023-08-04 jrmu (jump? apeg diagonal-up-peg aboard)
48 12687dd9 2023-08-04 jrmu (jump? apeg diagonal-down-peg aboard))]
49 12687dd9 2023-08-04 jrmu [else false])))
50 12687dd9 2023-08-04 jrmu
51 12687dd9 2023-08-04 jrmu ;peg-exists? : posn board -> boolean
52 12687dd9 2023-08-04 jrmu ;Determines if a peg exists given apeg and aboard. apeg is reported using an index that starts at 1,1. peg-exists? converts the coordinates to vector indices (in vector indices, 0,0 is the first element in the board).
53 12687dd9 2023-08-04 jrmu
54 12687dd9 2023-08-04 jrmu (define (peg-exists? apeg aboard)
55 12687dd9 2023-08-04 jrmu (local ((define peg-x-v (sub1 (posn-x apeg)))
56 12687dd9 2023-08-04 jrmu (define peg-y-v (sub1 (posn-y apeg))))
57 12687dd9 2023-08-04 jrmu (vector-ref (vector-ref aboard peg-y-v) peg-x-v)))
58 12687dd9 2023-08-04 jrmu
59 12687dd9 2023-08-04 jrmu ;jump? : posn posn board-> boolean
60 12687dd9 2023-08-04 jrmu ;Given old-peg, new-peg, and aboard, determine if it is possible to make a jump. jump? converts these coordinates to vector indices, where 0,0 represents the first element in board. Conversions are denoted by -v.
61 12687dd9 2023-08-04 jrmu
62 12687dd9 2023-08-04 jrmu (define (jump? old-peg new-peg aboard)
63 12687dd9 2023-08-04 jrmu (local ((define old-peg-x-v (sub1 (posn-x old-peg)))
64 12687dd9 2023-08-04 jrmu (define old-peg-y-v (sub1 (posn-y old-peg)))
65 12687dd9 2023-08-04 jrmu (define new-peg-x-v (sub1 (posn-x new-peg)))
66 12687dd9 2023-08-04 jrmu (define new-peg-y-v (sub1 (posn-y new-peg)))
67 12687dd9 2023-08-04 jrmu (define remove-peg-x-v (+ (/ (- new-peg-x-v old-peg-x-v) 2) old-peg-x-v))
68 12687dd9 2023-08-04 jrmu (define remove-peg-y-v (+ (/ (- new-peg-y-v old-peg-y-v) 2) old-peg-y-v))
69 12687dd9 2023-08-04 jrmu (define need-length-x (add1 new-peg-x-v))
70 12687dd9 2023-08-04 jrmu (define need-length-y (add1 new-peg-y-v)))
71 12687dd9 2023-08-04 jrmu (and (not (negative? new-peg-x-v))
72 12687dd9 2023-08-04 jrmu (not (negative? new-peg-y-v))
73 12687dd9 2023-08-04 jrmu (>= (vector-length aboard) need-length-y)
74 12687dd9 2023-08-04 jrmu (>= (vector-length (vector-ref aboard new-peg-y-v)) need-length-x)
75 12687dd9 2023-08-04 jrmu (not (vector-ref (vector-ref aboard new-peg-y-v) new-peg-x-v))
76 12687dd9 2023-08-04 jrmu (vector-ref (vector-ref aboard remove-peg-y-v) remove-peg-x-v))))
77 12687dd9 2023-08-04 jrmu
78 12687dd9 2023-08-04 jrmu ;next-states : board posn -> (listof states)
79 12687dd9 2023-08-04 jrmu ;Given aboard and apeg, create a (listof (make-state b moves)), ie, a (listof states), which return all possible board configurations with their corresponding moves. (since there may be more than one possible jump, we must list the results as a listof boards) 1,1 is the first position in the board, not 0,0.
80 12687dd9 2023-08-04 jrmu
81 12687dd9 2023-08-04 jrmu (define (next-states aboard apeg)
82 12687dd9 2023-08-04 jrmu (local ((define peg-x (posn-x apeg))
83 12687dd9 2023-08-04 jrmu (define peg-y (posn-y apeg))
84 12687dd9 2023-08-04 jrmu (define down-peg (make-posn peg-x (+ peg-y 2)))
85 12687dd9 2023-08-04 jrmu (define right-peg (make-posn (+ peg-x 2) peg-y))
86 12687dd9 2023-08-04 jrmu (define up-peg (make-posn peg-x (- peg-y 2)))
87 12687dd9 2023-08-04 jrmu (define left-peg (make-posn (- peg-x 2) peg-y))
88 12687dd9 2023-08-04 jrmu (define diagonal-up-peg (make-posn (- peg-x 2) (- peg-y 2)))
89 12687dd9 2023-08-04 jrmu (define diagonal-down-peg (make-posn (+ peg-x 2) (+ peg-y 2))))
90 12687dd9 2023-08-04 jrmu
91 12687dd9 2023-08-04 jrmu (filter (lambda (astate) (not (empty? (state-board astate))))
92 12687dd9 2023-08-04 jrmu (list (make-state (jump aboard apeg down-peg) (list apeg down-peg))
93 12687dd9 2023-08-04 jrmu (make-state (jump aboard apeg right-peg) (list apeg right-peg))
94 12687dd9 2023-08-04 jrmu (make-state (jump aboard apeg up-peg) (list apeg up-peg))
95 12687dd9 2023-08-04 jrmu (make-state (jump aboard apeg left-peg) (list apeg left-peg))
96 12687dd9 2023-08-04 jrmu (make-state (jump aboard apeg diagonal-up-peg) (list apeg diagonal-up-peg))
97 12687dd9 2023-08-04 jrmu (make-state (jump aboard apeg diagonal-down-peg) (list apeg diagonal-down-peg))))))
98 12687dd9 2023-08-04 jrmu
99 12687dd9 2023-08-04 jrmu ;jump : board posn posn -> board or empty
100 12687dd9 2023-08-04 jrmu ;Using aboard, return a new board with old-peg replaced with false and new-peg replaced with true. The intermediate peg is removed.
101 12687dd9 2023-08-04 jrmu
102 12687dd9 2023-08-04 jrmu (define (jump aboard old-peg new-peg)
103 12687dd9 2023-08-04 jrmu (local ((define old-peg-x (posn-x old-peg))
104 12687dd9 2023-08-04 jrmu (define old-peg-y (posn-y old-peg))
105 12687dd9 2023-08-04 jrmu (define new-peg-x (posn-x new-peg))
106 12687dd9 2023-08-04 jrmu (define new-peg-y (posn-y new-peg))
107 12687dd9 2023-08-04 jrmu (define remove-peg-x (+ (/ (- new-peg-x old-peg-x) 2) old-peg-x))
108 12687dd9 2023-08-04 jrmu (define remove-peg-y (+ (/ (- new-peg-y old-peg-y) 2) old-peg-y)))
109 12687dd9 2023-08-04 jrmu (cond
110 12687dd9 2023-08-04 jrmu [(jump? old-peg new-peg aboard)
111 12687dd9 2023-08-04 jrmu (build-board (vector-length aboard)
112 12687dd9 2023-08-04 jrmu (lambda (x y)
113 12687dd9 2023-08-04 jrmu (cond
114 12687dd9 2023-08-04 jrmu [(and (= x old-peg-x)
115 12687dd9 2023-08-04 jrmu (= y old-peg-y)) false]
116 12687dd9 2023-08-04 jrmu [(and (= x new-peg-x)
117 12687dd9 2023-08-04 jrmu (= y new-peg-y)) true]
118 12687dd9 2023-08-04 jrmu [(and (= x remove-peg-x)
119 12687dd9 2023-08-04 jrmu (= y remove-peg-y)) false]
120 12687dd9 2023-08-04 jrmu [else (vector-ref (vector-ref aboard (sub1 y)) (sub1 x))])))]
121 12687dd9 2023-08-04 jrmu [else empty])))
122 12687dd9 2023-08-04 jrmu
123 12687dd9 2023-08-04 jrmu ;build-board : N (N N -> X) -> (vectorof (vectorof X))
124 12687dd9 2023-08-04 jrmu ;Builds a size-n equilateral triangle according to f, where (f i j) specifies the value of the i,jth position of the board. The first value corresponds to (i,j)=(1,1). i represents the horizontal distance (the column number), j represents the vertical distance (the row number).
125 12687dd9 2023-08-04 jrmu
126 12687dd9 2023-08-04 jrmu (define (build-board n f)
127 12687dd9 2023-08-04 jrmu (build-vector n (lambda (i)
128 12687dd9 2023-08-04 jrmu (build-vector (add1 i) (lambda (j) (f (add1 j) (add1 i)))))))
129 12687dd9 2023-08-04 jrmu
130 12687dd9 2023-08-04 jrmu ;solitaire : board -> (listof moves), empty, or false
131 12687dd9 2023-08-04 jrmu ;Given aboard0, solve the solitaire problem and return a (listof moves). If aboard0 is itself a solution, return empty. If the board cannot be solved, return false.
132 12687dd9 2023-08-04 jrmu
133 12687dd9 2023-08-04 jrmu (define (solitaire aboard0)
134 12687dd9 2023-08-04 jrmu ;;previous-moves is an accumulator that represents the necessary moves to go from
135 12687dd9 2023-08-04 jrmu ;;aboard0 to aboard1
136 12687dd9 2023-08-04 jrmu (local
137 12687dd9 2023-08-04 jrmu ((define (solitaire-accu aboard1 previous-moves pegs)
138 12687dd9 2023-08-04 jrmu (cond
139 12687dd9 2023-08-04 jrmu [(solved? aboard1) previous-moves]
140 12687dd9 2023-08-04 jrmu [(empty? pegs) false]
141 12687dd9 2023-08-04 jrmu [else
142 12687dd9 2023-08-04 jrmu (local
143 12687dd9 2023-08-04 jrmu ((define first-los (next-states aboard1 (first pegs)))
144 12687dd9 2023-08-04 jrmu (define search-first-peg (solitaire/list-accu first-los previous-moves)))
145 12687dd9 2023-08-04 jrmu (cond
146 12687dd9 2023-08-04 jrmu [(boolean? search-first-peg)
147 12687dd9 2023-08-04 jrmu (solitaire-accu aboard1 previous-moves (rest pegs))]
148 12687dd9 2023-08-04 jrmu [else search-first-peg]))]))
149 12687dd9 2023-08-04 jrmu (define (solitaire/list-accu alos previous-moves)
150 12687dd9 2023-08-04 jrmu (cond
151 12687dd9 2023-08-04 jrmu [(empty? alos) false]
152 12687dd9 2023-08-04 jrmu [else
153 12687dd9 2023-08-04 jrmu (local
154 12687dd9 2023-08-04 jrmu ((define new-moves (append previous-moves
155 12687dd9 2023-08-04 jrmu (list (state-move (first alos)))))
156 12687dd9 2023-08-04 jrmu (define new-board (state-board (first alos)))
157 12687dd9 2023-08-04 jrmu (define search-first-move
158 12687dd9 2023-08-04 jrmu (solitaire-accu new-board new-moves (enabled-pegs new-board))))
159 12687dd9 2023-08-04 jrmu (cond
160 12687dd9 2023-08-04 jrmu [(boolean? search-first-move)
161 12687dd9 2023-08-04 jrmu (solitaire/list-accu (rest alos) previous-moves)]
162 12687dd9 2023-08-04 jrmu [else search-first-move]))])))
163 12687dd9 2023-08-04 jrmu (solitaire-accu aboard0 empty (enabled-pegs aboard0))))
164 12687dd9 2023-08-04 jrmu
165 12687dd9 2023-08-04 jrmu ;solitaire-accu : board (listof moves) (listof posns) -> (listof moves) or false
166 12687dd9 2023-08-04 jrmu ;Solves aboard1 if possible and returns the listof moves necessary to reach the solution state. Otherwise, returns false. pegs "remembers" the enabled-pegs in aboard1 that have yet to be tested.
167 12687dd9 2023-08-04 jrmu
168 12687dd9 2023-08-04 jrmu ;solitaire/list-accu : (listof states) (listof moves) -> (listof moves) or false
169 12687dd9 2023-08-04 jrmu
170 12687dd9 2023-08-04 jrmu
171 12687dd9 2023-08-04 jrmu ;solved? : board -> boolean
172 12687dd9 2023-08-04 jrmu ;Determines if aboard is solved
173 12687dd9 2023-08-04 jrmu
174 12687dd9 2023-08-04 jrmu (define (solved? aboard)
175 12687dd9 2023-08-04 jrmu (cond
176 12687dd9 2023-08-04 jrmu [(equal? aboard SOLVED-BOARD) true]
177 12687dd9 2023-08-04 jrmu [else false]))
178 12687dd9 2023-08-04 jrmu
179 12687dd9 2023-08-04 jrmu (define SOLVED-BOARD
180 12687dd9 2023-08-04 jrmu (build-board 6 (lambda (x y)
181 12687dd9 2023-08-04 jrmu (cond
182 12687dd9 2023-08-04 jrmu [(and (= x 1)
183 12687dd9 2023-08-04 jrmu (= y 1)) true]
184 12687dd9 2023-08-04 jrmu [else false]))))
185 12687dd9 2023-08-04 jrmu (define INITIAL-BOARD
186 12687dd9 2023-08-04 jrmu (build-board 6 (lambda (x y)
187 12687dd9 2023-08-04 jrmu (cond
188 12687dd9 2023-08-04 jrmu [(and (= x 1)
189 12687dd9 2023-08-04 jrmu (= y 1)) false]
190 12687dd9 2023-08-04 jrmu [else true]))))
191 12687dd9 2023-08-04 jrmu
192 12687dd9 2023-08-04 jrmu ;enabled-pegs : board -> (listof posns)
193 12687dd9 2023-08-04 jrmu ;Determines all enabled pegs in a given board.
194 12687dd9 2023-08-04 jrmu
195 12687dd9 2023-08-04 jrmu (define (enabled-pegs aboard)
196 12687dd9 2023-08-04 jrmu (filter (lambda (peg) (enabled? peg aboard))
197 12687dd9 2023-08-04 jrmu (build-peg-list (vector-length aboard) (lambda (x y) (make-posn x y)))))
198 12687dd9 2023-08-04 jrmu
199 12687dd9 2023-08-04 jrmu ;build-peg-list : N (N N -> X) -> (listof X)
200 12687dd9 2023-08-04 jrmu ;Builds a list that corresponds to positions of an n-sized equilaterial triangle.
201 12687dd9 2023-08-04 jrmu
202 12687dd9 2023-08-04 jrmu (define (build-peg-list n f)
203 12687dd9 2023-08-04 jrmu (foldr append empty
204 12687dd9 2023-08-04 jrmu (build-list n (lambda (i)
205 12687dd9 2023-08-04 jrmu (build-list (add1 i) (lambda (j) (f (add1 j) (add1 i))))))))
206 12687dd9 2023-08-04 jrmu
207 12687dd9 2023-08-04 jrmu (solitaire INITIAL-BOARD)
208 12687dd9 2023-08-04 jrmu
209 12687dd9 2023-08-04 jrmu ;Wish-list:
210 12687dd9 2023-08-04 jrmu ;
211 12687dd9 2023-08-04 jrmu ;next-states,
212 12687dd9 2023-08-04 jrmu ;jump,
213 12687dd9 2023-08-04 jrmu ;enabled-pegs,