@@ -42,23 +42,23 @@ pred len.aux o:list A, o:int.
4242% When `N` is bound, we count down from `N` to `0 `, removing one element of
4343% `Ls` with each unit of `N` removed. If we arrive at `[]` and `0 ` at the
4444% same time, we are done, and cannot possibly have more conclusions (thus the cut).
45- len Ls N :- not (var N),
46- ( len.aux [] 0
47- & pi T M M' \
48- len.aux [_|T] M :- M' is M - 1 ,
49- len.aux T M'
50- ) => len.aux Ls N, !.
45+ len Ls N :-
46+ if (var N)
47+ ( ( len.aux Ls N
48+ & pi L M M' \
49+ len.aux L M :- M' is M + 1 , len.aux [_| L] M'
50+ ) => len.aux [] 0 )
51+ ( ( len.aux [] 0
52+ & pi T M M' \ len.aux [_| T] M :- M' is M - 1, len.aux T M'
53+ ) => len.aux Ls N, ! ).
54+
5155% When `N` is free, then we count up, starting from `0 ` to `N`, constructing
5256% a list by adding a free variable to our list each time a unit is added to
5357% `N`. When the list we' re constructing can be unified with the input `Ls`
5458% then we' re at our `N`. If `Ls` is left partial in the tail, then we can
5559% keep generating longer lists for `Ls` on backtracking.
56- len Ls N :- var N,
57- ( len.aux Ls N
58- & pi L M M' \
59- len.aux L M :- M' is M + 1,
60- len.aux [_|L] M'
61- ) => len.aux [] 0 .
60+ % len Ls N :- var N,
61+
6262
6363% 1.05
6464pred rev o: list A, o: list A.
@@ -199,26 +199,32 @@ drop-nth N Xs Dropped :-
199199 std.map-filter Opt (a\b\some b = a) Dropped.
200200
201201% 1.17
202+ % `split N Ls Front Back` is true when Front is a prefix
203+ % of Ls of length N, and Back is the remaining suffix of
204+ % Ls. It is a fatal error if N is a negative number.
202205pred split i:int, i:list A, o:list A, o:list A.
203- split I J Xs Slice :- print "split > " I J Xs Slice , fail.
206+ split N Ls Front Back :- print "split > " N Ls Front Back , fail.
204207split N _ _ _ :- N < 0, std.fatal-error "split with negative number".
205- split 0 Xs [] Xs.
206- split _ [] [] [] .
208+ % split 0 Xs [] Xs.
209+ split 0 Xs _ Xs .
207210split N [X|Xs] [X|Front] Back :- split {calc (N - 1)} Xs Front Back.
208211
209212% 1.18
210213pred slice i:int, i:int, i:list A, o:list A.
211214slice I J Xs Slice :- print "slice > " I J Xs Slice, fail.
212- slice I J Xs Slice :- std.fatal-error " "
215+ slice I J _ _ :- J < I, std.fatal-error "slice with second index < first".
213216slice I J Xs Slice :- split I Xs _ Xs'
214- & split {calc (J - I)} Xs' Slice _
217+ & M is (J - I)
218+ & split M Xs' Slice _
215219 .
216220
217221% 1.19
218222% pred rotate i:list A, i:int, o:list A.
219223% rotate Ls N Ls' :- split N Ls Front Back, std.append Front Back Ls' .
224+
220225}
221226
227+
222228pred test i:prop.
223229test P :- ( P
224230 & !
@@ -238,6 +244,7 @@ main :- test (list.last [1, 2, 3, 4] (some 4))
238244 & test (list.nth [1,2,3,4] 2 (some 3))
239245 & test (list.len [1,2,3,4] 4)
240246 & test (list.len L 4 & L = [_, _, _, _])
247+ & test (not (list.len [1,2,3,4,5] 4))
241248 & test (list.reverse [1,2,3,4] [4,3,2,1])
242249 & test (list.reverse X [4,3,2,1] & X = [1,2,3,4])
243250 & test (list.is-palindrome ["x","a","m","a","x"])
@@ -262,6 +269,7 @@ main :- test (list.last [1, 2, 3, 4] (some 4))
262269 & test (list.duplicate-n 3 [1,2,3] [1,1,1,2,2,2,3,3,3])
263270 & test (list.drop-nth 3 [1,2,3,4,5,6,7,8] [1,2,4,5,7,8])
264271 & test (list.split 3 [1,2,3,4,5,6,7,8,9,10] [1,2,3] [4,5,6,7,8,9,10])
265- & test (list.slice 4 8 [1,2,3,4,5,6,7,8,9,10] ZZ, print ZZ)
272+ & test (list.slice 4 8 [1,2,3,4,5,6,7,8,9,10] [5,6,7,8,9])
273+ % & test (list.rotate ["a","b","c","d","e","f","g","h"] 3 ["d","e","f","g","h","a","b","c"])
266274 & print "ALL TESTS PASSED"
267275 .
0 commit comments