Bubble Sort Common Lisp Error - sorting

I'm trying to implement Bubble Sort in Common Lisp, and I'm having a tough time getting my bearings.[See Below] is what I've got so far, which follows the algorithm as far as I can tell, but I'm getting the error " Undefined function SORTED called with arguments ()." when I run it. I can't seem to find what's the cause of that.
(defun bubble (lis)
(let ((sorted nil) (j 0))
(do () ((not sorted))
(progn
(setf sorted t)
(do (i j (+ i 1))
(if (< (nth i lis) (nth (+ i 1) lis))
(progn
(swap1 (lis (nth i lis) (nth (+ i 1) lis)))
(setf sorted nil)
)
)
)
)
)
)
)

Each call to NTH needs to iterate over the list. If you treat a list like a vector, you probably should use vectors instead. And in the case you don't really care about being efficient, you might still want to use ELT instead of NTH, since ELT works on any kind of sequence. That way, you can pass either vectors or lists and at least one of them will work reasonably well (as far as bubble sort can be efficient).
You might end up having something like the one from Rosetta Code.
By the way, Rosetta Code has an example of an iterative Bubble sort for lists, so I won't copy it. Instead, here below is a recursive version that I adapted from a Prolog one (by Roman Barták). As such it is not necessarily better, but it uses multiple values, ETYPECASE, DESTRUCTURING-BIND, ... features that are apparently not usually taught.
(defun bubble-sort (list)
(labels
((bsort (list acc)
(etypecase list
(null acc)
(cons (destructuring-bind (head . tail) list
(multiple-value-bind (new-tail max)
(bubble head tail)
(bsort new-tail
(cons max acc)))))))
(bubble (x list)
(etypecase list
(null (values nil x))
(cons (destructuring-bind (y . tail) list
(multiple-value-bind (new-tail max)
(bubble (max x y) tail)
(values (cons (min x y) new-tail)
max)))))))
(bsort list nil)))

There are quite a few things we can do to improve this code.
And something you can do to improve your question. If you ask again please provide the test cases and the specific issue.
Indenting
Lisp has relatively little syntax, but we use indenting to help highlight the structure of the code. Most Lisp aware editors help manage that. The most obvious departure from the conventional indenting approach is closing parentheses on following lines. I've Indented the mergelist function to show a more readable function body - well, at least to me.
(defun bubble (lis)
(let ((sorted nil) (j 0))
(do () ((not sorted))
(progn
(setf sorted t)
(do (i j (+ i 1))
(if (< (nth i lis) (nth (+ i 1) lis))
(progn
(swap1 (lis (nth i lis) (nth (+ i 1) lis)))
(setf sorted nil))))))))
Loop vs DO
DO has a long pedigree in lisp, but to be honest, I always make mistakes with DO, so don't use it very often. I can never remember where to return form goes, the increment. I tend to use LOOP
But first off, we don't need to use progn. Most looping constructs have an implicit progn for the code they are iterating so
(defun bubble-1 (lis)
(let ((sorted nil) (j 0))
(do () ((not sorted))
(setf sorted t)
(do (i j (+ i 1))
(if (< (nth i lis) (nth (+ i 1) lis))
(swap1 (lis (nth i lis) (nth (+ i 1) lis)))
(setf sorted nil))))))
Slightly nicer. Looking at your code there is the call to swap1, which must be a defun supplied somewhere. THis line also has a syntax problem as 'lis' appears as a function call.
Lets try to evaluate the function and see what happens
; in: DEFUN BUBBLE-1
; (LET ((SORTED NIL) (J 0))
; (DO ()
; ((NOT SORTED))
; (SETF SORTED T)
; (DO (I
; J
; (+ I 1))
; (IF (< # #) (SWAP1 #) (SETF #)))))
;
; caught STYLE-WARNING:
; The variable J is defined but never used.
; in: DEFUN BUBBLE-1
; (DO (I
; J
; (+ I 1))
; (IF
; (< (NTH I LIS) (NTH (+ I 1) LIS))
; (SWAP1 (LIS (NTH I LIS) (NTH # LIS)))
; (SETF SORTED NIL)))
; --> BLOCK
; ==>
; (LET (I J (+ I))
; (TAGBODY
; (GO #:G3)
; #:G2
; (TAGBODY)
; (PSETQ + 1)
; #:G3
; (UNLESS IF (GO #:G2))
; (RETURN-FROM NIL (PROGN (< # #) (SWAP1 #) (SETF #)))))
;
; caught WARNING:
; undefined variable: I
; --> BLOCK LET TAGBODY UNLESS
; ==>
; (IF IF
; NIL
; (GO #:G2))
;
; caught WARNING:
; undefined variable: IF
; (LIS (NTH I LIS) (NTH (+ I 1) LIS))
;
; caught STYLE-WARNING:
; undefined function: LIS
; (SWAP1 (LIS (NTH I LIS) (NTH (+ I 1) LIS)))
;
; caught STYLE-WARNING:
; undefined function: SWAP1
;
; compilation unit finished
; Undefined functions:
; LIS SWAP1
; Undefined variables:
; I IF
; caught 2 WARNING conditions
; caught 3 STYLE-WARNING conditions`enter code here`
Wow. THis is telling us a few things
The variable J in the nested DO is not used. Remove it.
The syntax for DO in the nested loop is wrong. It needs to be of the general form
(DO ((var init step))
(termination-test result-form)
statement)
The nested do is missing its termination test. Also the variable declaration for i is missing its initialization.
The Let is kind of redundant you can move the declaration of sorted into the do
(do ((sorted nil)) ((not sorted ) ... )
The form
(SWAP1 (LIS (NTH I LIS) (NTH (+ I 1) LIS)))
has two problems. Firstly SWAP1 is undefined. Secondly the form (LIS (NTH I LIS) (NTH (+ I 1) LIS)) can't possibly be right as LIS appears in a function call position. Anything that appears at the front of a form must be a function. In this cas LIS is a parameter.
Fortunately Common Lisp has an inbuilt function that will swap to values for us - its called rotatef. So the entires form would need to look like
(rotatef (nth I lis) (nth (1+ i) lis))
Once function runs, it has no result form in the do, so the sorted array will never be returned to the caller. You will see no output. You need to think about the fact you have nested loops here.
I would think a bit about your algorithm. As Zephyr Pellerin says above, a recursive solution would be much nicer, so unless your assignment is to use an iterative solution

You should study the answer of David Hodge that details all the problems of your code. Here I offer an iterative version of Bubble Sort that uses the do special form. The only main difference from the algorithm that you tried to implement with your code is the use of a variable end which is decremented each time to reduce the number of tests:
(defun bubble (lis)
(let ((sorted nil)
(end (length lis)))
(do () (sorted lis)
(setf sorted t)
(decf end)
(do ((i 0 (1+ i)))
((>= i end))
(when (< (nth i lis) (nth (1+ i) lis))
(rotatef (nth i lis) (nth (1+ i) lis))
(setf sorted nil))))))

Related

How to change this function, "car" got problems

I want to write a function, which converts from a "normal" notation like this: "1+4*2-8" to this pre-notation: "+1-*428".
I hope you get the point here.
Important: It must be in Strings.
What I get so far:
(define (converter lst )
(let ((operand1 (car lst))
(operator (car (cdr lst)))
(operand2 (caddr lst)))
(list operator
(converter operand1)
(converter operand2)))
)
(infixLst->prefixLst '(1 + 2 * 3))
I got two problems here.
1) It's for Lists, I need it work for Strings like "1+3" and not '(1+3)
2) It doesn't work so far (even not for Lists), because it give me some errors regarding the "car", e.g: car: expects a pair, given 1
Soo starting with the List -> String change: (I know that (list is unappropriate here. As well as the other list-methods but I didnt got a better idea so far.
(define (infix->prefix str)
(let ((operand1 (car str))
(operator (cadr str))
(operand2 (caddr str)))
(list operator
(infix->prefix operand1)
(infix->prefix operand2)))
)
(infix->prefix "1 + 2")
The normal notation 1+4*2-8 is called infix notation.
If you simply need to use that notation, Racket has a ready module: (require infix), here's a link to its documentation.
If you want to practice writing your own infix parser, the shunting-yard algorithm can do that. It uses a stack to keep track of the operators in the math expression.
If you want to parse math from a string, you need to first split the string into a list of tokens (numbers and operators). Start with a math->tokens procedure that simply returns a list of the tokens without caring about their meaning. There are many ways to write it. Here is one:
(define (math->tokens s)
(let collect-tokens ((i 0) (tokens '()))
(if (= i (string-length s))
(reverse tokens)
(let ((char (string-ref s i)))
(if (not (char-numeric? char))
(let ((operator (string->symbol (string char))))
(collect-tokens (+ i 1) (cons operator tokens)))
(let collect-number ((j (+ i 1)))
(if (and (< j (string-length s))
(char-numeric? (string-ref s j)))
(collect-number (+ j 1))
(let ((number (string->number (substring s i j))))
(collect-tokens j (cons number tokens))))))))))
For example, (math->tokens "+1-*428") returns the list of tokens (+ 1 - * 428). Now you can apply the shunting-yard algorithm to that list.

Compare two lists and return false if they are not equal scheme

i would like to ask you for help to complete code below with condition which is testing if lists ws and vs are not equal. If they are not equal so return text false(#f) else process code below. I stared with fulfilling variables len1 and len2 which are counting length of both lists. When i run it i am getting this error: lambda: no expression after a sequence of internal definitions in: lambda What i am doing wrong?
(define (weighted-sum . ws)
(define (sub . vs)
(let ((len1 (length ws)) (len2 (length vs)))
(if (not (equal? (len1 len2) '#f))
(foldl
(lambda (i j res) (+ res (* i j)))
0
ws vs)))
sub)
Thanks for help.
length is almost always an anti-pattern in Scheme.
length is a O(n) operation, which is called twice, then you call another O(n) operation, foldl, resulting in a O(3n) process for weighted-sum - far from the ideal minimum O(n). foldl is a nice candidate for many linear computations, but because of the length-matching requirement, you've created a bit of a square-peg-in-a-round-hole situation.
Using a named-let and match*, we write weighted-sum as a O(n) computation -
#lang racket
(define ((weighted-sum . ws) . vs) ;; curried form syntactic sugar
(let loop ((acc 0)
(ws ws)
(vs vs))
(match* (ws vs)
;; both lists have at least one value
[((list w ws ...) (list v vs ...))
(loop (+ acc (* w v))
ws
vs)]
;; both lists are empty
[((list) (list))
acc]
;; any other case
[(_ _)
#f])))
Of course match* is a pretty fancy macro, so I'll show you how to rewrite weighted-sum using a simple cond expression. Get your logical reasoning hat ready: the order of the condition clauses is very important here -
(define ((weighted-sum . ws) . vs)
(let loop ((acc 0)
(ws ws)
(vs vs))
(cond
;; both lists are empty
[(and (null? ws)
(null? vs))
acc]
;; at least one list is empty
[(or (null? ws)
(null? vs))
#f]
;; inductive: both lists have at least one value
[else
(loop (+ acc (* (car ws)
(car vs)))
(cdr ws)
(cdr vs))])))
Both programs have the same output -
((weighted-sum 1 2 3) 1 2 3)
;; 14
((weighted-sum 1 2 3) 1 2)
;; #f
((weighted-sum 1 2) 1 2 3)
;; #f
((weighted-sum))
;; 0
Erase )) after #f . Add )) after len1 len2), and it'll work. (not quite, but close(*))
#f is self-evaluating, you don't need to quote it. Indent the (foldl ...) form which became a part of the if expression now.
Lastly, (if (not A) #f B) is the same as (if A B #f) is the same as (and A B).
You are correct in checking that the lengths of both lists, the carried (sic) and the expected, are equal. I don't see why the lists themselves should be equal, though. They shouldn't, as far I can tell.
(weighted-sum list-of-weights) creates a procedure expecting a list of numbers to calculate its weighted sum using the previously supplied weights.
(*) The corrected code, after a few more fixes, is:
(define (weighted-sum . ws)
(define (sub . vs)
(let ((len1 (length ws)) (len2 (length vs)))
(and (equal? len1 len2)
(foldl
(lambda (i j res) (+ res (* i j)))
0
ws vs))))
sub)
It is highly advisable to install e.g. Racket and use its editor to see and correct the parentheses mismatches etc.

programmatic way to stop a function after certain time and debug enclosed variables

A long-run function like infinite loop:
> (define appendInf
(lambda (lst)
(appendInf (cons 1 lst)))
In Chez Scheme, make-engine can achieve the stopping after ticks:
> (define eng
(make-engine
(lambda ()
(appendInf '()))))
While of course with the scope of lst I get error when:
> (eng 50
list
(lambda (new-eng)
(set! eng new-eng)
(length lst)))
Exception: variable lst is not bound
If I want to get the value 'lst' in appendInf when the time limit is reached, I use set!:
> (define lst '())
> (define appendInf
(lambda (ls)
(set! lst (cons 1 ls))
(appendInf lst)))
now I can get:
> (eng 50
list
(lambda (new-eng)
(set! eng new-eng)
(length lst)))
8
So for every variable within the function I want to trace, a global variable needs to be added, and one more transforming by adding (set!…).
is this a correct way to handle any enclosed variables?
if yes to 1, in Scheme is there a better way to achieve this?
is there any programming language that can more easily
implement this kind of debugging?
Well. I'm using racket and it has a pretty good debugger and does standard r6rs as well as non-standard racket.
;; macro to do the heavy work
(define-syntax recdb
(syntax-rules ()
((_ thunk fun a1 ...)
(let ((orig-fun fun)(ethunk thunk))
(fluid-let ((fun (lambda args
(if (ethunk)
(apply orig-fun args) ;; set breakpoint on this
(apply orig-fun args)))))
(fun a1 ...))))))
;; a time-thunk generator
(define (period-sec sec)
(let ((time-done (+ sec (current-seconds))))
(lambda ()
(if (< time-done (current-seconds))
(begin
(set! time-done (+ sec (current-seconds)))
#t)
#f))))
;; a round-thunk generator
(define (rounds n)
(let ((rounds-to-go n))
(lambda ()
(if (zero? rounds-to-go)
(begin
(set! rounds-to-go (- n 1))
#t)
(begin
(set! rounds-to-go (- rounds-to-go 1))
#f)))))
;; my never ending procedure
(define (always n)
(always (+ n 1)))
;; one of the ones below to implement
(recdb (rounds 10) always 0))
(recdb (period-sec 1) always 0)
;; functions with auxillary procedures need to have their gut changed for it to work
(define (fib n)
(define (fib-aux n a b)
(if (= n 0)
a
(fib-aux (- n 1) b (+ a b))))
(recdb (period-sec 2) fib-aux n 0 1))
;; trying it
(fib 200000)
Now. Just run the debugger and set breakpoint (right click expression in the macro and choose "Pause at this point") where it's indicated in the code and you have a way to examine the variables every x seconds or x times.
Happy debugging :)

How Do For Loops Work In Scheme?

I'm having some difficulty understanding how for loops work in scheme. In particular this code runs but I don't know why
(define (bubblesort alist)
;; this is straightforward
(define (swap-pass alist)
(if (eq? (length alist) 1)
alist
(let ((fst (car alist)) (scnd (cadr alist)) (rest (cddr alist)))
(if (> fst scnd)
(cons scnd (swap-pass (cons fst rest)))
(cons fst (swap-pass (cons scnd rest)))))))
; this is mysterious--what does the 'for' in the next line do?
(let for ((times (length alist))
(val alist))
(if (> times 1)
(for (- times 1) (swap-pass val))
(swap-pass val))))
I can't figure out what the (let for (( is supposed to do here, and the for expression in the second to last line is also a bit off putting--I've had the interpreter complain that for only takes a single argument, but here it appears to take two.
Any thoughts on what's going on here?
That's not a for loop, that's a named let. What it does is create a function called for, then call that; the "looping" behavior is caused by recursion in the function. Calling the function loop is more idiomatic, btw. E.g.
(let loop ((times 10))
(if (= times 0)
(display "stopped")
(begin (display "still looping...")
(loop (- times 1)))))
gets expanded to something like
(letrec ((loop (lambda (times)
(if (= times 0)
(display "stopped")
(begin (display "still looping...")
(loop (- times 1)))))))
(loop 10))
This isn't actually using a for language feature but just using a variation of let that allows you to easily write recursive functions. See this documentation on let (it's the second form on there).
What's going on is that this let form binds the name it's passed (in this case for) to a procedure with the given argument list (times and val) and calls it with the initial values. Uses of the bound name in the body are recursive calls.
Bottom line: the for isn't significant here. It's just a name. You could rename it to foo and it would still work. Racket does have actual for loops that you can read about here.

Help understanding Continuations in Scheme

I have been working alongside The Little Schemer to learn Scheme and using PLT-Scheme for my environment.
The Little Schemer has helped me tremendously with recursion (it is straightforward for me now) but I'm stuck on a portion of the book that introduces "collectors" and calls the function as a whole a continuation.
Here is the example code they have used. I understand the recursive elements but I am stuck, in particular on the lambda functions - my mind can't follow the path and how the arguments for that lambda function are set (since their only call is to call them again in recursion, there is no concrete use within the function body).
If someone could more-or-less give me a break down of the path of computation through the recursion of the function into the lambda collectors, that may help me.
;; Build a nested list of even numbers by removing the odd ones from its
;; argument and simultaneously multiply the even numbers and sum the odd
;; numbers that occur in its argument.
(define (even-only-collector l col)
(cond
((null? l)
(col (quote ()) 1 0))
((atom? (car l))
(cond
((even? (car l))
(even-only-collector (cdr l)
(lambda (newl p s)
(col (cons (car l) newl)
(* (car l) p) s))))
(else
(even-only-collector (cdr l)
(lambda (newl p s)
(col newl
p (+ (car l) s)))))))
(else
(even-only-collector (car l)
(lambda (al ap as)
(even-only-collector (cdr l)
(lambda (dl dp ds)
(col (cons al dl)
(* ap dp)
(+ as ds)))))))))
;; The collector function
(define (collector newl product sum)
(cons sum
(cons product newl)))
Thank you in advance!!
Try something simpler to see how this works. For example, here's a version of a list-sum function that receives a continuation argument (which is often called k):
(define (list-sum l k)
(if (null? l)
???
(list-sum (cdr l) ???)))
The basic pattern is there, and the missing parts are where the interesting things happen. The continuation argument is a function that expects to receive the result -- so if the list is null, it's clear that we should send it 0, since that is the sum:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) ???)))
Now, when the list is not null, we call the function recursively with the list's tail (in other words, this is an iteration), but the question is what should the continuation be. Doing this:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) k)))
is clearly wrong -- it means that k will eventually receive the the sum of (cdr l) instead of all of l. Instead, use a new function there, which will sum up the first element of l too along with the value that it receives:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (lambda (sum) (+ (car l) sum)))))
This is getting closer, but still wrong. But it's a good point to think about how things are working -- we're calling list-sum with a continuation that will itself receive the overall sum, and add the first item we see now to it. The missing part is evident in the fact that we're ignoring k. What we need is to compose k with this function -- so we do the same sum operation, then send the result to k:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (compose k (lambda (s) (+ s (car l)))))))
which is finally working. (BTW, remember that each of these lambda functions has its own "copy" of l.) You can try this with:
(list-sum '(1 2 3 4) (lambda (x) x))
And finally note that this is the same as:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (lambda (s) (k (+ s (car l)))))))
if you make the composition explicit.
(You can also use this code in the intermediate+lambda student language, and click the stepper button to see how the evaluation proceeds -- this will take a while to go over, but you'll see how the continuation functions get nested, each with it's own view of the list.)
Here's one way to help you "get a more concrete idea". Imagine if the collector were defined thus:
(define (collector l p s)
(display l)
(newline)
(display p)
(newline)
(display s)
(newline))
You can see in the base case, if you pass in an empty list, it will call your function with arguments '(), 1, and 0. Now, work with a one-element list, and see what it'll call your function with. Keep working up with longer and longer lists, until you figure out what's going on.
Good luck!

Resources