Convert a list of char into a single string - racket

If I have a list of char like (cons #\C (cons #\O (cons #\M (cons #\P (cons #\U (cons #\T (cons #\E empty))))))), how can I convert it into a string? I'm not allowed to use string-append, substring, implode, and explode. I am also on Beginning Student so I can't use string-join. I've thought about using (string char) but I can't figure out how it'd work recursively.
Or, how would I be able to convert a list of strings into a single string, given the same restrictions above?

It looks like list->string does what you want.
Edit to make the bot happy:
(define list-of-chars
(cons #\C (cons #\O (cons #\M (cons #\P (cons #\U (cons #\T (cons #\E empty))))))))
(list->string list-of-chars)
The resulting string is "COMPUTE" as desired.

Related

Alternating upcase/downcase for a string in Common Lisp

I want to write a function that will return a string formatted with alternative upcase/downcase in Common Lisp. For example, entering "stackoverflow" should return the string "StAcKoVeRfLoW". Here's my attempt, but it just returns a list of cons pairs. Am I on the right track?
(defun mockify (chars)
(let ((lst (coerce chars 'list)))
(if (equal lst nil) nil
(coerce (cons
(cons (char-upcase (car lst)) (char-downcase (cadr lst)))
(mockify (cddr lst)))
'string))))
CL-USER> (mockify "meow")
((#\M . #\e) (#\O . #\w))
Using MAP: we are creating a new string, moving over the original string and upcase/downcase based on an alternating boolean variable.
CL-USER 353 > (let ((string "stackoverflow")
(upcase t))
(map (type-of string)
(lambda (element)
(prog1 (if upcase
(char-upcase element)
(char-downcase element))
(setf upcase (not upcase))))
string))
"StAcKoVeRfLoW"
(defun mockify (chars)
(let ((lst (coerce chars 'list)))
(if (equal lst nil)
;; return nil
nil
;; return a string (coerce)
(coerce
;; a list whose elements are cons-cells, but ...
(cons (cons (char-upcase (car lst))
(char-downcase (cadr lst)))
;; ... the rest is computed by calling mockify,
;; which returns either an empty list or a string
(mockify (cddr lst)))
'string))))
The types of your expressions are confusing, and in fact your example leads to an error when using SBCL:
> (mockify "meow")
The value
(#\O . #\w)
is not of type
CHARACTER
when setting an element of (ARRAY CHARACTER)
[Condition of type TYPE-ERROR]
Also, you are going to have to handle corner cases in your code, because as is, it is possible that (cadr list), i.e. (second list), is called on a list that has only one element. Then, the result would be NIL and char-downcase would fail with an error.
Using only strings
I'd suggest writing a version of the function that does not use intermediate lists:
let R be the string-downcase of the whole string
then modify every other character of R by upcasing it
So for example, one way to do it (among others) would be:
(defun mockify (chars)
(let ((chars (string-downcase chars)))
(prog1 chars
(upcasify chars 0))))
(defun upcasify (string index)
(when (< index (length string))
(setf (char string index) (char-upcase (char string index)))
(upcasify string (+ index 2))))
Using only lists
If you prefer having a recursive function that processes lists, I'd rather define it in layers:
coerce string to list
process the list recursively
eventually, coerce the resulting list back to a string
This will avoid doing conversions from strings to lists at every step, and make the code simpler at each level.
(defun mockify (chars)
(coerce (mockify-list (coerce chars 'list)) 'string))
(defun mockify-list (chars)
...)
The list version is recursive and look like what you tried to do, but take care of corner cases.
There is more than one way to do it. Here is a loop based solution:
(let ((string "StackOverflow"))
(with-output-to-string (s)
(loop :for c :across string
:for up := t :then (not up)
:do (princ (if up
(char-upcase c)
(char-downcase c))
s))))
Fun thing - I actually wrote a similar thing some time ago.
https://github.com/phoe/string-pokemonize

How to print the elements in odd positions in a list using an iterative function in Lisp?

I have to make a recursive function in lisp which takes a list and makes another list with only the elements on odd position in the given list.
If I have (1 2 3 4 5) I have to output (1 3 5)
I have a code here:
(defun pozpar(lst) (do(
(l lst (cddr l))
(x '() (cons x (car l))))
((null l) x)))
This outputs:
(5 3 1)
I know cons adds the elements at the beginning and I tried with append or list but nothing worked.
I think this is a way easier solution:
(defun popzar (lst)
(cond ((null lst) nil)
(t (cons (car lst)
(popzar (cdr (cdr lst)))))))
It first checks if the list is empty and if not it creates a new list with the first element and the result of calling itself again with the rest of the list except for the second element.
The easiest way is to reverse the result:
(defun pozpar (lst)
(do ((l lst (cddr l))
(x '() (cons (car l) x)))
((null l)
(nreverse x))))
(pozpar '(1 2 3 4 5))
==> (1 3 5)
Notes
This returns, not outputs the value you want.
Prepending values and reverting the result is a common Lisp coding pattern.
Since append is linear in the length of its argument, using it in a loop produces quadratic code.
I formatted the code in the standard Lisp way. If you use this style, lispers will have an easier time reading your code, and, consequently, more willing to help you.
With using loop it's very easy to get the elements in the order you processed them. It is also the most effective and the only one guaranteed to work with all length arguments:
(defun pozpar1 (lst)
(loop :for e :in lst :by #'cddr
:collect e)))
If you really want recursion I would have done it with an accumulator with a linear update reverse in the end:
(defun pozpar2 (lst)
(labels ((helper (lst acc)
(if (endp lst)
(nreverse acc)
(helper (cddr lst) (cons (car lst) acc)))))
(helper lst '())))
However a classical not tail recursive version would look like this:
(defun pozpar3 (lst)
(if (endp lst)
'()
(cons (car lst) (pozpar3 (cddr lst)))))

Lisp Reverse Function using ONLY primitives [duplicate]

This question already has answers here:
How to recursively reverse a list using only basic operations?
(3 answers)
Closed 8 years ago.
I am having trouble with some lisp code. This function is just supposed to reverse a basic list.
I can only use primitives, which are defined as
" defun, cond, cons, car, cdr, null, eq, listp, atom, symbolp, +, -­‐ , <, >"
In the example of passing (1 2 3 4) I get back (((4 3) 2) 1)
(defun reverse2 (l)
(cond
((eq nil (cdr l)) (car l) )
(t (cons(reverse2 (cdr l)) (cons (car l) nil)))))
Please let me know how to improve this. This is NOT for homework, I'm just working on this as an exercise for my final tomorrow.
To implement a reverse function, you need to use an accumulator. Here is how you might implement this (in this case, tail is the accumulator):
(defun revappend (list tail)
(cond ((null list) tail)
(t (revappend (cdr list) (cons (car list) tail)))))
Then, implement reverse in terms of revappend:
(defun reverse (list)
(revappend list nil))
If you would want to use simple recursion, then you would have to append the first item to the end of the list. Note that this is not a good implementation of a list reverse operation. Why?
(defun reverse2 (l)
(cond ((endp l) l)
(t (append (reverse2 (rest l))
(list (first l))))))
REVERSE
CL-USER> (reverse2 '(a b c d))
(D C B A)
Instead of using an auxillary function you can use an optional argument:
(defun reverse (list &optional tail)
(cond ((null list) tail)
(t (reverse (cdr list)
(cons (car list) tail)))))

Converting an s expression to a list in Scheme [duplicate]

This question already has answers here:
Flatten a list using only the forms in "The Little Schemer"
(3 answers)
Closed 9 years ago.
If I have an s expression, for example '(1 2 (3) (4 (5)) 6 7), how would I convert that into a list like (1 2 3 4 5 6 7)? I basically need to extract all of the atoms from the s expression. Is there a built in function that would help me do it?
(define (convert-to-list s) ... )
My algorithm so far is, if the first element is an atom append it onto a list. If the first element is a list then get the car of that element and then call the function (convert-to-list) with that function so it catches the base case of the recursion. And append the cdr of that list being invoked on convert-to-list to car of it. I'm trying to teach myself scheme from Structure and Interpretation of Computer Programs and I'm just trying out random things. Doing this recursively is proving to be more difficult than I anticipated.
To literally answer your question, "Is there a built in function to help me do this?", in Racket yes there is. flatten does exactly this: "Flattens an arbitrary S-expression structure of pairs into a list."
Examples:
> (flatten '((a) b (c (d) . e) ()))
'(a b c d e)
> (flatten 'a)
'(a)
However it's a great exercise to think about how you would write flatten yourself.
Chris Jester-Young's comment has a link to an elegant way. If she'd posted that as an answer, instead of as a comment, I'd suggest marking her answer as accepted, not mine. :)
Your algorithm doesn't look bad, it's just missing a step or two.
(define (flatten lst) ; 'flatten' is a better name for this function IMO
(cond
((null lst) nil)
;; Don't worry that I'm calling (flatten (cdr lst)) without any checking;
;; the above case handles it
((atom (car lst)) ; The car's okay
(cons (car lst) (flatten (cdr lst))))
((cons? (car lst)) ; The car still needs flattening; note the use of
; 'append' here (the car-list may have any number of elements)
(append (flatten (car lst)) (flatten (cdr lst))))))
Between the (flatten (car lst)) calls dealing with the first element and the (flatten (cdr lst)) calls recursively dealing with the rest of the list, the input list ends up a flat list (i.e. no elements are conses).
(Warning: I'm not a Scheme guru; the above code may contain errors.)
Your cases should cover the empty list, an atom, (car s) being an atom, and (car s) being a list.
This works, though I bashed out a list append function because I didn't remember what the built-in one was. Works in Racket Advanced Student.
(define (list-glue left-list right-list)
(cond
((null? left-list) right-list)
(else (cons (car left-list) (list-glue (cdr left-list) (right-list))))))
(define (convert-to-list s)
(cond
((null? s) '())
((not (list? s)) (cons s (quote ())))
((not (list? (car s))) (cons (car s) (convert-to-list (cdr s))))
(else
(list-glue
(convert-to-list (car s))
(convert-to-list (cdr s))))))
Now, if you want a faster implementation, you don't need append at all.
The idea is to pass around what you would append onto as a parameter. I call this tail.
If you have an empty s-exp, you just return the tail, since there is nothing to add to it.
I've got the code, flat and flat2, where flat uses a match statement, things in racket, and flat2 just uses a cond, which I find a little harder to read, but I provide it in case you haven't seen match yet.
#lang racket
(define (flat s-exp tail)
(match s-exp
['() tail]
[(cons fst rst)
(let ([new-tail (flat rst tail)])
(flat fst new-tail))]
[atom
(cons atom tail)]))
(define (flat
(cond
[(empty? s-exp) tail]
[(list? s-exp)
(let* ([fst (first s-exp)]
[rst (rest s-exp)]
[new-tail (flat])
(flat fst new-tail))]
[#t
(cons s-exp tail)]))
To use them, call them like so (flat '(1 () (2 (3)) 4) '()) ===> '(1 2 3 4).
You need to supply the empty list for them to start off on.
This can be done simply by recursing on sublists and rest-lists. You can see how easily this code reads. Like such:
(define (convert-to-list list)
(if (null? list)
'()
(let ((next (car list))
(rest (cdr list)))
(if (list? next)
(append (convert-to-list next) (convert-to-list rest))
(cons next (convert-to-list rest))))))
> (convert-to-list '(a b c))
(a b c)
> (convert-to-list '((a b) (((c d) e f) g h) i j))
(a b c d e f g h i j)
>

Searching lists that contain lists or conses

Lets say that we got a list like this(with much more elements but the method should be the same):
(define l '((cons 'name 'john)
(cons 'sur 'asurname)
(cons 'name 'george)
(cons 'sur 'georgesurname)))
and we can always add more elements to the existing list. Which is the most effective way lets say to write a function that takes the name of a the user and returns the surname:
something like :
(define display-surname
(lamdba (name)
(...)))
What is the general practice in such cases? Can anyone point an example/link of a how to?
It'd be a better idea to represent each record (name,surname) in a single list, and then handle your data as a list of lists of pairs:
(define lst '(((name . a) (sur . b)) ((name . c) (sur . d))))
With the above representation, finding a name (given a surname) is as simple as this (assuming that each field in the record is always found in the same position):
(define display-surname
(lambda (lst name)
(cond ((null? lst) #f)
((eq? (cdaar lst) name) (cdadar lst))
(else (display-surname (cdr lst) name)))))
You can simplify things even further (again assuming that each field in the record is always in the same position) by representing the above data as follows, with the corresponding changes in display-surname:
(define lst '((a . b) (c . d)))
(define display-surname
(lambda (lst name)
(cond ((null? lst) #f)
((eq? (caar lst) name) (cdar lst))
(else (display-surname (cdr lst) name)))))
Either way, this works:
(display-surname lst 'a)
> 'b
(display-surname lst 'x)
> #f