Lisp prefix calculator - lisp

How can I write a calculator to prefix notation, when it should count this example '(+ * 3 2 - 2 1), where there are no brackets between characters? When I have the brackets, I can handle it, but in this case I am lost.

A quick search on google yielded this wikipedia page, with an implementation (in pseudocode) of prefix evaluation using a stack. It's a starting point for writing your own implementation. Also notice that a stack can be easily implemented using Lisp's linked lists, simply add/remove elements at the head.

I'm a beginner in scheme (excuse me if it is nasty code). This one is with the brackets:
(define (fce a)
(case a
(( + ) +)
(( - ) -)
(( * ) *)
(( / ) /)))
(define (analyze vyraz)
(if (list? vyraz)
(calcul vyraz)
vyraz))
(define (calcul vyraz)
(if (= (length vyraz) 3 )
((fce (car vyraz)) (analyze (cadr vyraz)) (analyze (caddr vyraz)))
(calcul (cons (calcul (list (car vyraz) (cadr vyraz) (caddr vyraz) (cadddr vyraz)))))))
this code can count for example this : (calcul '(- (* 3 2)(+ 1 2))
I wanted to repair this code to code without brackets but conditions and listing the original input stopped me. I do not know how to write the conditions so that I didn't lose the original input and also came the final calculation.
there are my conditions (but i think, there are at wrong syntax
(define (count vyraz)
(cond (list? vyraz)
(number? (car vyraz) (cons (car vyraz)))
(number? (cdr vyraz) (cons (cdr vyraz)))
(symbol? (cddr vyraz) (cons (cddr vyraz)))
(else (cdr vyraz) (count vyraz)))
(calcul vyraz))
Thank you for all your answers and tips :)

(define (polish-notation-eval expr)
(if (finished? expr)
(car expr)
(polish-notation-eval (the-once-over expr))))
;;either we are finished, or we need to make the-once-over to get closer to finished.
(define (the-once-over expr)
(cond ((null? expr) expr )
((well-formed-expr? expr)
(cons ((get-operator (car expr)) (cadr expr) (caddr expr))
(the-once-over (cdddr expr))))
(else (cons (car expr) (the-once-over (cdr expr))))))
;; just scrolls down the list looking for well-formed expressions to evaluate.
(define *the-operations*
(list (list '+ +)
(list '* *)
(list '- -)
(list '/ /)))
;; an association list with names and functions
(define (get-operator name)
(cadr (assoc name *the-operations*)))
;;returns the function that goes with the name
(define (finished? expr)
(= (length expr) 1))
;; we are finished one we get down to a length one list, otherwise not
(define (well-formed-expr? expr)
(and (assoc (car expr) *the-operations*)
(number? (cadr expr))
(number? (caddr expr))))
;;are the next three elements something we can go ahead and evaluate?

Related

How to define function in LISP that recursively return back quoted list

I have problem with macros in my lisp interpreter writtein in JavaScript. the problem is in this code:
(define log (. console "log"))
(define (alist->object alist)
"(alist->object alist)
Function convert alist pairs to JavaScript object."
(if (pair? alist)
((. alist "toObject"))))
(define (klist->alist klist)
"(klist->alist klist)
Function convert klist in form (:foo 10 :bar 20) into alist
in form ((foo . 10) (bar . 20))."
(let iter ((klist klist) (result '()))
(if (null? klist)
result
(if (and (pair? klist) (pair? (cdr klist)) (key? (car klist)))
(begin
(log ":::" (cadr klist))
(log "data" (. (cadr klist) "data"))
(iter (cddr klist) (cons (cons (key->string (car klist)) (cadr klist)) result)))))))
(define (make-empty-object)
(alist->object '()))
(define empty-object (make-empty-object))
(define klist->object (pipe klist->alist alist->object))
;; main function that give problems
(define (make-tags expr)
(log "make-tags" expr)
`(h ,(key->string (car expr))
,(klist->object (cadr expr))
,(if (not (null? (cddr expr)))
(if (and (pair? (caddr expr)) (let ((s (caaddr expr))) (and (symbol? s) (eq? s 'list))))
`(list->array (list ,#(map make-tags (cdaddr expr))))
(caddr expr)))))
(define-macro (with-tags expr)
(make-tags expr))
I call this macro using this code:
(define (view state actions)
(with-tags (:div ()
(list (:h1 () (value (cdr (assoc 'count (. state "counter")))))
(:button (:onclick (lambda () (--> actions (down 1)))) "-")
(:button (:onclick (lambda () (--> actions (up 1)))) "+")))))
which should expand to almost the same code:
(define (view state actions)
(h "div" (make-empty-object)
(list->array (list
(h "h1" (make-empty-object) (value (cdr (assoc 'count (. state "counter")))))
(h "button" (klist->object `(:onclick ,(lambda () (--> actions (down 1))))) "-")
(h "button" (klist->object `(:onclick ,(lambda () (--> actions (up 1))))) "+")))))
This function works. I have problem with expanded code using my macro that call the main function, don't know how LIPS should behave when it find:
(:onclick (lambda () (--> actions (down 1))))
inside code and you try to process it like this:
,(klist->object (cadr expr))
Right now my lisp works that lambda is marked as data (have data flag set to true this is a hack to prevent of recursive evaluation of some code from macros) and klist->object function get lambda code as list, instead of function.
How this should work in Scheme or Common Lisp? Should klist->object get function object (lambda get evaluated) or list structure with lambda as first symbol? If second then how I sould write my function and macro to evaluate lambda should I use eval (kind of hack to me).
Sorry don't know how to test this, with more bug free LISP.
EDIT:
I've tried to apply the hint from #jkiiski in guile (because in my lisp it was not working)
;; -*- sheme -*-
(define nil '())
(define (key? symbol)
"(key? symbol)
Function check if symbol is key symbol, have colon as first character."
(and (symbol? symbol) (eq? ":" (substring (symbol->string symbol) 0 1))))
(define (key->string symbol)
"(key->string symbol)
If symbol is key it convert that to string - remove colon."
(if (key? symbol)
(substring (symbol->string symbol) 1)))
(define (pair-map fn seq-list)
"(seq-map fn list)
Function call fn argument for pairs in a list and return combined list with
values returned from function fn. It work like the map but take two items from list"
(let iter ((seq-list seq-list) (result '()))
(if (null? seq-list)
result
(if (and (pair? seq-list) (pair? (cdr seq-list)))
(let* ((first (car seq-list))
(second (cadr seq-list))
(value (fn first second)))
(if (null? value)
(iter (cddr seq-list) result)
(iter (cddr seq-list) (cons value result))))))))
(define (klist->alist klist)
"(klist->alist klist)
Function convert klist in form (:foo 10 :bar 20) into alist
in form ((foo . 10) (bar . 20))."
(pair-map (lambda (first second)
(if (key? first)
(cons (key->string first) second))) klist))
(define (h props . rest)
(display props)
(display rest)
(cons (cons 'props props) (cons (cons 'rest rest) nil)))
(define (make-tags expr)
`(h ,(key->string (car expr))
(klist->alist (list ,#(cadr expr)))
,(if (not (null? (cddr expr)))
(if (and (pair? (caddr expr)) (let ((s (caaddr expr))) (and (symbol? s) (eq? s 'list))))
`(list->array (list ,#(map make-tags (cdaddr expr))))
(caddr expr)))))
(define-macro (with-tags expr)
(make-tags expr))
(define state '((count . 10)))
(define xxx (with-tags (:div ()
(list (:h1 () (cdr (assoc 'count state)))
(:button (:onclick (lambda () (display "down"))) "-")
(:button (:onclick (lambda () (display "up"))) "+")))))
but got error:
ERROR: Unbound variable: :onclick
I've found solution for my lisp, Here is code:
(define (pair-map fn seq-list)
"(seq-map fn list)
Function call fn argument for pairs in a list and return combined list with
values returned from function fn. It work like the map but take two items from list"
(let iter ((seq-list seq-list) (result '()))
(if (null? seq-list)
result
(if (and (pair? seq-list) (pair? (cdr seq-list)))
(let* ((first (car seq-list))
(second (cadr seq-list))
(value (fn first second)))
(if (null? value)
(iter (cddr seq-list) result)
(iter (cddr seq-list) (cons value result))))))))
(define (make-tags expr)
(log "make-tags" expr)
`(h ,(key->string (car expr))
(alist->object (quasiquote
;; create alist with unquote for values and keys as strings
,#(pair-map (lambda (car cdr)
(cons (cons (key->string car) (list 'unquote cdr))))
(cadr expr))))
,(if (not (null? (cddr expr)))
(if (and (pair? (caddr expr)) (let ((s (caaddr expr))) (and (symbol? s) (eq? s 'list))))
`(list->array (list ,#(map make-tags (cdaddr expr))))
(caddr expr)))))
So in my code I'm writing some kind of meta macro I'm writing quasiquote as list that will get evaluated the same as if I use in my original code:
(klist->object `(:onclick ,(lambda () (--> actions (down 1)))))
I'm using alist->object and new function pair-map, so I can unquote the value and convert key symbol to string.
is this how it should be implemented in scheme? not sure If I need to fix my lisp or macros are working correctly there.

how to iterate through a list in racket? if the character in the list is alphabetic, I want to add to a new string

Here is my code? Can anyone tell me how to iterate through a list? if the character in the list is alphabetic, I want to add to a new string
#lang racket
(define (conversion input)
(define s (string))
(let ((char (string->list input)))
(cond
[(char-alphabetic? (first (char)))
(string-append s first)]
[(char-alphabetic? (rest (char)))
(string-append s rest)]))
(display s))
Basic iteration is:
(define (copy-list lst)
(if (null? lst)
'()
(cons (car lst)
(copy-list (cdr lst))))
(copy-list '(1 2 3)) ; ==> (1 2 3)
This one actually makes a shallow copy of your list. Sometimes you iterate with keeping some variables to accumulate stuff:
(define (sum-list lst acc)
(if (null lst)
acc
(sum-list (cdr lst) (+ acc (car lst)))))
(sum-list '(1 2 3)) ; ==> 6
Looking at these you'll see a pattern emerges so we have made stuff like map, foldl, and foldr to abstract the iteration:
(define (copy-list-foldr lst)
(foldr cons '() lst)
(define (copy-list-map lst)
(map values lst))
(define (sum-list-foldl lst)
(foldl + 0 lst))
Looking at your challenge I bet you can fix it with a foldr.

Racket Nested-Lists and applying functions to them

I'm trying to teach myself Racket. I'm currently trying to write a function to help understand nested lists. The function takes a nested list and a procedure and applies the procedure to each element to produce a new list. An example:
(map-tree even? '(1 2 3 4)) => '(#f #t #f #t)
Here's what I've got so far:
(define (map-tree proc tree)
(map-tree-aux tree proc '() ))
(define (map-tree-aux tree proc lst)
(if (null? tree)
lst
(if (list? tree)
(if (null? (cdr tree))
(if (number? (car tree))
(map-tree-aux (car tree) proc (append-end (proc (car tree)) lst))
(map-tree-aux (car tree) proc lst))
(if (number? (car tree))
(map-tree-aux (cdr tree) proc (append-end (proc (car tree)) (map-tree-aux (car tree) proc lst)))
(map-tree-aux (cdr tree) proc lst)))
lst)))
(define (append-end elem lst)
(append lst (list elem)))
While this works with the original example I supplied, a more complex example comes out incorrectly:
(map-tree even? '(1 (2 (3 (4))))) should be '(#f (#t (#f (#t)))), but is currently (#f #t #f #t).
I know it's just a matter is "listing" somewhere, but I'm having an issue finding out how to do it.
My first thought was to apply the list procedure to the lst if the tree is null and (car tree) is not a number, but I get the opposite of what I want (the resultant list is nested in the opposite direction). I'd really appreciate your help.
Thanks!
When iterating over list of lists, the general idea for the cases to check is:
if list is empty (null? lst), do something ...
if the first item in list is atomic (not (pair? (car lst))), do something else ...
if the first item in list is a list itself (pair? (car lst)), else ...
Choosing the right construct is also important, ie. instead of nesting if statements, using cond or match etc. is preferred.
Also try and avoid using non-constant time procedures (such as append) in your recursive steps to improve efficiency.
With these in mind, one approach to create the function in question is by simply using cons to build a new list while preserving the structure of the old, as follows:
(define (my-map pred lst)
(cond
((null? lst) '())
((not (pair? (car lst)))
(cons (pred (car lst))
(my-map pred (cdr lst))))
(else
(cons (my-map pred (car lst))
(my-map pred (cdr lst))))))
You can write the same function using match instead of cond:
(define (my-map pred lst)
(match lst
['() '()]
[(cons (? pair?) b)
(cons (my-map pred (car lst))
(my-map pred (cdr lst)))]
[(cons a b)
(cons (pred (car lst))
(my-map pred (cdr lst)))]))
You can also build a tail-recursive function that does this:
(define (my-map pred lst)
(let loop ((lst lst)
(acc '()))
(cond
((null? lst)
(reverse acc))
((not (pair? (car lst)))
(loop (cdr lst) (cons (pred (car lst)) acc)))
(else
(loop (cdr lst) (cons (loop (car lst) '()) acc))))))
Notice that (reverse acc) is returned in the base case because the list being built in the accumulator acc is in reverse order from the original list lst. To avoid this, we can modify this function to accumulate a continuation instead:
(define (my-map pred lst)
(let loop ((lst lst)
(acc identity))
(cond
((null? lst)
(acc '()))
((not (pair? (car lst)))
(loop (cdr lst) (lambda (r)
(acc (cons (pred (car lst)) r)))))
(else
(loop (cdr lst)
(lambda (r)
(acc (cons (loop (car lst) identity) r))))))))
For all cases, you will have:
(my-map even? '(1 2 3 4 5 7))
=> '(#f #t #f #t #f #f)
(my-map even? '(1 (2 (3 (4 (5 (7)))))))
=> '(#f (#t (#f (#t (#f (#f))))))

racket postfix to prefix

I have a series of expressions to convert from postfix to prefix and I thought that I would try to write a program to do it for me in DrRacket. I am getting stuck with some of the more complex ones such as (10 (1 2 3 +) ^).
I have the very simple case down for (1 2 \*) → (\* 1 2). I have set these expressions up as a list and I know that you have to use cdr/car and recursion to do it but that is where I get stuck.
My inputs will be something along the lines of '(1 2 +).
I have for simple things such as '(1 2 +):
(define ans '())
(define (post-pre lst)
(set! ans (list (last lst) (first lst) (second lst))))
For the more complex stuff I have this (which fails to work correctly):
(define ans '())
(define (post-pre-comp lst)
(cond [(pair? (car lst)) (post-pre-comp (car lst))]
[(pair? (cdr lst)) (post-pre-comp (cdr lst))]
[else (set! ans (list (last lst) (first lst) (second lst)))]))
Obviously I am getting tripped up because (cdr lst) will return a pair most of the time. I'm guessing my structure of the else statement is wrong and I need it to be cons instead of list, but I'm not sure how to get that to work properly in this case.
Were you thinking of something like this?
(define (pp sxp)
(cond
((null? sxp) sxp)
((list? sxp) (let-values (((args op) (split-at-right sxp 1)))
(cons (car op) (map pp args))))
(else sxp)))
then
> (pp '(1 2 *))
'(* 1 2)
> (pp '(10 (1 2 3 +) ^))
'(^ 10 (+ 1 2 3))
Try something like this:
(define (postfix->prefix expr)
(cond
[(and (list? expr) (not (null? expr)))
(define op (last expr))
(define args (drop-right expr 1))
(cons op (map postfix->prefix args))]
[else expr]))
This operates on the structure recursively by using map to call itself on the arguments to each call.

Issue using cons function in Lisp?

I am learning Lisp and I had to write a function whose return value was a list containing the odd integers (if any) from the given input. In code I have this:
(defun f3 (a)
(cond
((null a) nil )
((and (numberp (car a)) (oddp (car a))) (cons (car a) (f3 (cdr a))))
(T (f3 (cdr a)))
) ; end cond
)
I originally wanted to use the append function, but I kept getting errors.
It was recommended to me to use cons function. When I did this my function started working (code is above). I originally had this:
(defun f3 (a)
(cond
((null a) ())
((and (numberp (car a)) (oddp (car a))) (append (f3 (cdr a)) (car a))))
(T (append () (f3 (cdr a))))
)
)
but kept getting errors. For example, if I called (f3 '(1 2 3)) it would say "error 3 is not type LIST". So, my questions are why does cons work here and why did append not work? How does cons work? Thanks in advance.
append wants list arguments, and (car a) is not a list. Instead of (car a) you'd need (list (car a)). In other words, (append (f3 (cdr a)) (list (car a))).
That will basically work, but you'll get the result in reverse order. So that should be (append (list (car a)) (f3 (cdr a))).
Also note that your (append () (f3 (cdr a))) is equivalent to just (f3 (cdr a)).
The resulting changes in your original would be:
(defun f3 (a)
(cond
((null a) ())
((and (numberp (car a)) (oddp (car a)))
(append (list (car a)) (f3 (cdr a)))))
(T (f3 (cdr a)))))
But, you wouldn't normally use append to prepend a single element to a list. It would more naturally be done using cons. So
(append (list (car a)) (f3 (cdr a)))
Is more appropriately done by:
(cons (car a) (f3 (cdr a)))
Which finally takes you right to the working version you showed.
While something like mbratch's answer will help you in learning about list manipulation (and so is probably a more useful answer for you at this point in your study), it's also important to learn about the standard library of the language that you're using. In this case, you're trying to filter out everything except odd numbers. Using remove-if-not, that's just:
(defun keep-odd-numbers (list)
(remove-if-not (lambda (x)
(and (numberp x) (oddp x)))
list))
CL-USER> (keep-odd-numbers '(1 a 2 b 3 c 4 d 5 e))
;=> (1 3 5)
While this isn't a fix to your actual problem, which #mbratch provided, here's the way I would implement something like this using the LOOP macro (another part of the standard library):
(defun keep-odd-numbers (list)
(loop for x in list collecting x when (and (numberp x) (oddp x))))