I am trying to define a function that takes a list as an argument and returns a boolean (#t or #f) indicating if the list is sorted in ascending order. The output of the function should be something like this:
(sorted? '(1 2 3 4 5)) ; => #t (sorted? '(1 2 5 6 4)) ; => #f (sorted? '("frank" "adam" "eve")) ; => #f (sorted? '("adam" "eve" "frank")) ; => #t
Here's my attempt at a solution:
(define (sorted? lst) (cond [(< (length lst) 2] [(<= (car lst) (cadr lst)) (sorted? (cdr lst))] [(string? lst) (string<=? (car lst) (cadr lst)) (sorted? (cdr lst))] [else #f]))
I keep getting errors about the string part, and I can't seem to figure out what I'm doing wrong. Am I getting errors because I have two different types in the same definiton? I'm just assuming that since it's a conditional statement if the arguments in the list don't fit the condition, it should be ignored. I'm new at this and I need help. Please share your knowledge if you know what I'm doing wrong and what I need to do to fix this. Thanks.
Usually you don't want to mix numerical and lexical sort, but lets imagine for a second that you can compare any value:
(define (any<? a b) (cond ((and (number? a) (number? b)) (< a b)) ((and (string? a) (string? b)) (string<? a b)) ;; You can add types here. As a default we cast it ;; to string and compare it as string ;; NB! format is Racket specific (else (string<? (format "~A" a) (format "~A" b)))))
So lets sort something:
(define unsorted '(#\a 5 "hello" 9 (a c b) 10 (a b c) "50")) ;; NB: sort is racket specific, R6RS has list-sort ;; with the arguments in reverse order. (define sorted (sort test any<?)) test2 ; ==> ((a b c) (a c b) 5 "50" 9 10 #\a "hello") ;; Using a named let with the current element ;; makes you only check null? once for each pair (define (sorted? lst <) (or (null? lst) (let loop ((e (car lst)) (lst (cdr lst))) (or (null? lst) (and (not (< (car lst) e)) (loop (car lst) (cdr lst))))))) (sorted? unsorted any<?) ; ==> #f (sorted? sorted any<?) ; ==> #t
You wouldn't use
any<? but the specific comparison procedure for that data if you know the type of the elements in the list. E.g.
(sorted? '("a" "b" "cd") string<?) ; ==> #t (sorted? '(4 7 3 5 9 3 4 6) <) ; ==> #f