I practice in Scheme language. My code is below Scheme the procedure called (invert lst) that reverses the list lst (any sub-lists of lst should be reversed as well). I initially went down this path, but I'm having an inconsistent reversal (inconsistent) of the list in the last example.
My code:
`#lang scheme
(require "project3test.scm")
(define (invert lst)
(if (null? lst) '()
(if (not (list? lst)) lst (append (invert (cdr lst)) (list (car lst))))))
(test-invert invert)`
Test file "project3test.scm":
`#lang scheme
(provide test-invert)
(define test-invert
(lambda (x)
(begin
(newline)
(write "Question 5: invert")
(newline)
(write (x 'a))(newline)
(write (x '(1 2 3)))(newline)
(write (x '(1 2 (3 4) (5 (6 7 (8))) 9)))(newline)
)))`
Output:
`"Question 5: invert"
a
(3 2 1)
(9 (5 (6 7 (8))) (3 4) 2 1)`
The problem is here. The numbers are not consecutive, not fully implemented. What is my mistake?
Then I tried another way, but the following error occurs: car: contract violation expected: pair? given: a
`#lang scheme
(require "project3test.scm")
(define (inverse ls)
(cond ((null? ls) ls)
((list? (car ls)) (append (inverse (cdr ls)) (list (inverse (car ls)))))
(else (append (inverse (cdr ls)) (list (car ls))))))
(test-invert invert)`
If I run this code separately from the test file, with the output (display ....) it works and turns the sheet over correctly.
`#lang scheme
(define (inverse ls)
(cond ((null? ls) ls)
((list? (car ls)) (append (inverse (cdr ls)) (list (inverse (car ls)))))
(else (append (inverse (cdr ls)) (list (car ls))))))
(display (inverse '(1 2 (3 4) (5 (6 7 (8))) 9)))`
Output:
(9 (((8) 7 6) 5) (4 3) 2 1)
I would be grateful for any advice, any hint, and help.
CodePudding user response:
Your error is caused by one of the test cases: (write (x 'a))(newline)
. a
isn't list, so it can't be reversed.
When you rewrite this test case and use your inverse
function, everything seems to work:
#lang scheme
(define (test-invert fn)
(writeln "Question 5: invert")
(writeln (fn '(a)))
(writeln (fn '(1 2 3)))
(writeln (fn '(1 2 (3 4) (5 (6 7 (8))) 9))))
(define (inverse ls)
(cond ((null? ls) ls)
((list? (car ls)) (append (inverse (cdr ls))
(list (inverse (car ls)))))
(else (append (inverse (cdr ls))
(list (car ls))))))
(test-invert inverse)
Output:
"Question 5: invert"
(a)
(3 2 1)
(9 (((8) 7 6) 5) (4 3) 2 1)
Note that there's a function reverse
, which doesn't reverse nested lists, but can be used to write a function which does so.
(define (deep-reverse o)
(if (list? o)
(reverse (map deep-reverse o))
o))
(test-invert deep-reverse)
CodePudding user response:
There are 4 limit cases:
- null list
- car is a list
- car is not a list
- bottom in case of non-list input
Here is the code
(define inv
(lambda (l)
((lambda (s) (s s '() l))
(lambda (s a l)
(if (null? l)
a
(s s
(cons
(if (pair? (car l))
(inv (car l))
(car l))
a)
(cdr l)))))))
If you want to write the same code in a compressed form, you can do so:
(define inv
(lambda (l)
(fold-right
(lambda (a x) (cons (if (pair? a) (inv a) a) x))
'()
l)))