Skip to content

Commit c4b6bf4

Browse files
committed
Fix slice predicate
1 parent 1cc65bb commit c4b6bf4

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

problems/lists.org

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ Example:
257257
> slice 4 8 [1,2,3,4,5,6,7,8,9,10] L.
258258

259259
Success:
260-
L = [3,4,5,6,7]
260+
L = [5,6,7,8,9]
261261
#+end_src
262262

263263
* 1.19 (**) Rotate a list N places to the left.

solutions/lists.mod

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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
6464
pred 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.
202205
pred 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.
204207
split 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.
207210
split N [X|Xs] [X|Front] Back :- split {calc (N - 1)} Xs Front Back.
208211
209212
% 1.18
210213
pred slice i:int, i:int, i:list A, o:list A.
211214
slice 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".
213216
slice 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+
222228
pred test i:prop.
223229
test 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

Comments
 (0)