Converting misspelled text to integer in Common Lisp? - lisp

I am totally new to Common Lisp and Lisp in general. I have a task to write using Common Lisp and can't even figure out how to begin. My program will take numbers in string format from 1 to 9, they will have one char misspelled, but the correct length; e.g.:
too -> 2
threa -> 3
and so on. I need to print the integer when given the wrong text and I seriously have no idea how to start. Any help would be appreciated.
Thanks in advance.

Sounds like fun :-)
Let us do it the usual Lisp way - by growing the language to solve the problem.
The problem is: match a string with a dictionary so that at most one misspelling is permitted.
Here is the dictionary:
(defparameter *dictionary*
(loop for i from 1 to 9 collect (cons (format nil "~R" i) i)))
What would it mean for two strings to match?
(defun diff (s1 s2)
"Count the number of differences in the shortest common start."
(loop for c1 across s1
for c2 across s2
sum (if (char= c1 c2) 0 1)))
(diff "abc" "abcde")
==> 0
(diff "abc" "aba")
==> 1
Now the matching:
(defun matchp (s1 s2)
"Two strings match iff they have the same length and 1 different character."
(and (= (length s1)
(length s2))
(= 1 (diff s1 s2))))
(matchp "a" "b")
==> T
(matchp "too" "two")
==> T
(matchp "one" "one")
==> NIL
Finally, find the string in the dictionary:
(defun parse-string (s)
(loop for (name . number) in *dictionary*
if (matchp name s) return number))
(parse-string "one")
==> NIL ; not found
(parse-string "onn")
==> 1
(parse-string "too")
==> 2
(parse-string "thre3")
==> 3
(parse-string "foor")
==> 4
(parse-string "fivv")
==> 5
(parse-string "sis")
==> 6
(parse-string "sever")
==> 7
(parse-string "aight")
==> 8
(parse-string "nane")
==> 9
PS. I used the fairly advanced loop facility on purpose: if this is homework, you are probably not allowed to use it, so you will have to rewrite my code using simpler idioms.
PPS. You should probably read a book, both acl and pcl are good.

Related

Report error in LISP

I have this function that convert a number into a certain base.I want to report an error if the base I introduce is greater than 9 and smaller than 2 but I dont know. Can you help me please?
(defun zecb (number base)
(write-to-string number :base base))
CL-USER 99 > (defun test (n)
(check-type n (integer 2 9))
n)
TEST
CL-USER 100 > (test 2)
2
CL-USER 101 > (test 9)
9
CL-USER 102 > (test 10)
Error: The value 10 of N is not of type (INTEGER 2 9).
Based on the condition system that coredump already mentioned there's also an assert macro that is part of Common Lisp. Try the following in your REPL:
(defun divide (num denom)
(assert (not (= 0 denom))
(denom)
"Attempted to divide ~a by zero, use a different denominator!" num)
(/ num denom))
(divide 42 0)
(Non-interactive example)
What do you mean by "report error"? If you mean something like throwing an exception in another languages, error may sute your needs:
(error "Base must be between 2 and 9")
Read more about common lisp conditions and handlers, if you need something more sufisticated than simple-error.
If what you want is printing an error, you can use one of the write/print function available (see Output to character streams).
Example:
(defun zecb (nb base)
"Test"
(if (or (< nb 2) (> nb 9))
(princ "Number Not in range")
(* nb base)))

Adding to the end of list in LISP [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
what is the ‘cons’ to add an item to the end of the list?
After watching many tutorials on lisp and searching high and low on google for answers, I still cannot figure out how to add to the end of a list in LISP.
I want my function to add 'a at the end of the list '(b c d) but I only know how to add it in front. Can someone help me use cons correctly to add 'a at the end of the list? Here is my code. Thanks in advance.
(defun AddRt (a list)
(cond
((null list)
0)
(t
(princ (cons a (cons (car list) (cdr list))))
)))
(AddRt 'a '(b c d))
Either push to last, or use nconc:
> (defparameter a (list 1 2 3))
A
> (push 4 (cdr (last a)))
(4)
> a
(1 2 3 4)
> (nconc a (list 5))
(1 2 3 4 5)
> a
(1 2 3 4 5)
note that these are destructive operators, i.e., they modify the object which is the value of a, not just the binding of a.
This is why, BTW, you should never use nconc on quoted lists, like (nconc '(1 2 3) '(4 5 6)).
PS. Note that adding to the end of a list requires its full
traversal and is thus an O(length(list)) operation. This may be a bad
idea if your lists are long, so people often use the
push/nreverse
idiom, e.g.,
(let (range)
(dotimes (i 10 (nreverse range))
(push i range)))
==> (0 1 2 3 4 5 6 7 8 9)
You may use a recursive function. Also, you should avoid using princ inside.
The following function, endcons, does exactly the same thing as cons, except the value is added at the end.
(defun endcons (a v)
(if (null v) (cons a nil) (cons (car v) (endcons a (cdr v)))))
(endcons 'a '(b c d))
Of course, you could also use append:
(append '(b c d) '(a))
See also this related question: what is the 'cons' to add an item to the end of the list?
One way is to reverse the list. Add the element to beginning of the reversed list. And then finally reverse the whole list.
Scheme code:
(define (add-to-tail l x)
(reverse (cons x (reverse l)))
But if this is an operation you need often, then I'd suggest you find a data structure other than (single linked) lists.

Remove even appearance of elements from list with Lisp or PROLOG

I have to delete even appearance of element from list using LISP or PROLOG.
Here is some example.
input: '(5 2 (3 5 (3) 5 (4 2 (2 4))) 5 2)
output: '(5 2 (3 () 5 (4 (2))))
Structure of the output list remains the same.
Thanks for advice,
Since this appears to be a homework, I am going to provide only a pointer to the solution:
Review the REMOVE-IF predicate in Common Lisp. (It may not do everything you need...)
Build a recursive walker.
Consider how you will pass the state back and forth.
As an aside, I highly recommend posting a snippet of your work to date and asking a specific question. A generalized question such as the above seems to suggest you want a solution dropped in your lap.
Okay, it's not homework. And I got intellectually intrigued. I solved it.
It's a recursive walker. If your Lisp does TCO, it should be transformable into a TCO.
You can do it in a loop, but that would require maintaining a stack list to handle the "go into list" case.
I make no claims to an idiomatic solution.
(defparameter input '(5 2 (3 5 (3) 5 (4 2 (2 4))) 5 2))
(defparameter output '(5 2 (3 () 5 (4 (2)))))
(defun remove-every-other-appearence (list &optional (hash-table nil))
(when list ; termination condition
;(format t "~%~a~&" list)
(unless hash-table ; if it's the first time
;(format t "creating hash table~&")
(setf hash-table (make-hash-table))) ; create a hash table
(let ((eut (car list))) ; element under test
;(format t "eut: ~a~&" eut)
(cond
((consp eut) ;Recursion time, it's a list.
;(format t "Recursing~&")
(cons
(remove-every-other-appearence eut hash-table)
(remove-every-other-appearence (cdr list) hash-table)))
(t ;Otherwise...
; Increment seen counter by 1
(setf (gethash eut hash-table 0)
(1+ (gethash eut hash-table 0)))
(cond
((evenp (gethash eut hash-table))
(remove-every-other-appearence (cdr list) hash-table))
;ignore the element
((oddp (gethash eut hash-table))
; if this is the odd occurance
;cons the element back onto the rest of the list
(cons eut (remove-every-other-appearence (cdr list) hash-table)))
(t
(error "This integer is neither even nor odd. We're in trouble"))))))))
* input
(5 2 (3 5 (3) 5 (4 2 (2 4))) 5 2)
* (remove-every-other-appearence input)
(5 2 (3 NIL 5 (4 (2))))
* output
(5 2 (3 NIL 5 (4 (2))))
FWIW, your problem statement is rather unclear.
As I understand the question, the problem is that you have an arbitrary "tree", the non-leaf nodes of which are lists and the leaf nodes of which are something else. A "list of lists" as it were. You would like to view that as a logical flat sequence of leaf nodes, iterate over that and remove every other leaf node without altering the overall shape of the "tree", such that the only thing that changes is the number of leaves hanging from any given node.
From that, given the following inputs, you'd realize the corresponding outputs:
input: []
output: []
input: [a,b,c,d]
output: [a,c]
input: [a,[],b,c,d]
output: [a,[],c]
input: [a,[b],c,d]
output: [a,[],c]
input: [a,[b,c,d,e],f,g]
output: [a,[c,e],g]
input: [a,[b,[],[c,d,[e,f,g],h],i],j]
output: [a,[[],[c,[e,g]],i]]
Here's an [untested] prolog solution. In it, I just maintaining two states, keep and remove and toggle between them as needed. You get odd/even for free: it just depends on the state in which you start the machine.
It should be noted that if the data structure passed in contains any unbound/non-unified variables, you're unlike to get correct results. Unwanted unification causes problems. Guard clauses would need to be added to properly handle with them.
% ====================
% The public interface
% ====================
remove_even( Xs , Ys ) :- remove_every_other_node( keep , _ , Xs , [] , Ys ).
remove_odd( Xs , Ys ) :- remove_every_other_node( remove , _ , Xs , [] , Ys ).
%------------------
% The core iterator
%------------------
remove_every_other_node( S , S , [] , T , List ) :-
reverse(T,List)
.
remove_every_other_node( S , N , [X|Xs] , T , List ) :-
process_node( S, S1 , X , T , T1 ) ,
remove_every_other_node( S1 , N , Xs , T1 , List )
.
%----------------------
% The list node handler
%----------------------
process_node( S , S , [] , T , [[]|T] ).
process_node( S , N , [X|Xs] , T , [L1|T] ) :-
remove_every_other_node( S , N , [X|Xs] , [] , L1)
.
process_node( keep , remove , X , T , [X|T] ).
process_node( remove , keep , X , T , T ).
(defun rea (tree)
(let ((table (make-hash-table)))
(labels ((fn (x)
(unless (and x (atom x) (evenp (incf (gethash x table 0))))
(list (if (atom x) x (mapcan #'fn x))))))
(car (fn tree)))))

How to calculate the sum of a digits of a number in Scheme?

I want to calculate the sum of digits of a number in Scheme. It should work like this:
>(sum-of-digits 123)
6
My idea is to transform the number 123 to string "123" and then transform it to a list '(1 2 3) and then use (apply + '(1 2 3)) to get 6.
but it's unfortunately not working like I imagined.
>(string->list(number->string 123))
'(#\1 #\2 #\3)
Apparently '(#\1 #\2 #\3) is not same as '(1 2 3)... because I'm using language racket under DrRacket, so I can not use the function like char->digit.
Can anyone help me fix this?
An alternative method would be to loop over the digits by using modulo. I'm not as used to scheme syntax, but thanks to #bearzk translating my Lisp here's a function that works for non-negative integers (and with a little work could encompass decimals and negative values):
(define (sum-of-digits x)
(if (= x 0) 0
(+ (modulo x 10)
(sum-of-digits (/ (- x (modulo x 10)) 10)))))
Something like this can do your digits thing arithmetically rather than string style:
(define (digits n)
(if (zero? n)
'()
(cons (remainder n 10) (digits2 (quotient n 10))))
Anyway, idk if its what you're doing but this question makes me think Project Euler. And if so, you're going to appreciate both of these functions in future problems.
Above is the hard part, this is the rest:
(foldr + (digits 12345) 0)
OR
(apply + (digits 1234))
EDIT - I got rid of intLength above, but in case you still want it.
(define (intLength x)
(define (intLengthP x c)
(if (zero? x)
c
(intLengthP (quotient x 10) (+ c 1))
)
)
(intLengthP x 0))
Those #\1, #\2 things are characters. I hate to RTFM you, but the Racket docs are really good here. If you highlight string->list in DrRacket and hit F1, you should get a browser window with a bunch of useful information.
So as not to keep you in the dark; I think I'd probably use the "string" function as the missing step in your solution:
(map string (list #\a #\b))
... produces
(list "a" "b")
A better idea would be to actually find the digits and sum them. 34%10 gives 4 and 3%10 gives 3. Sum is 3+4.
Here's an algorithm in F# (I'm sorry, I don't know Scheme):
let rec sumOfDigits n =
if n<10 then n
else (n%10) + sumOfDigits (n/10)
This works, it builds on your initial string->list solution, just does a conversion on the list of characters
(apply + (map (lambda (d) (- (char->integer d) (char->integer #\0)))
(string->list (number->string 123))))
The conversion function could factored out to make it a little more clear:
(define (digit->integer d)
(- (char->integer d) (char->integer #\0)))
(apply + (map digit->integer (string->list (number->string 123))))
(define (sum-of-digits num)
(if (< num 10)
num
(+ (remainder num 10) (sum-of-digits (/ (- num (remainder num 10)) 10)))))
recursive process.. terminates at n < 10 where sum-of-digits returns the input num itself.

How do I map a macro across a list in Scheme?

I have a Scheme macro and a long list, and I'd like to map the macro across the list, just as if it were a function. How can I do that using R5RS?
The macro accepts several arguments:
(mac a b c d)
The list has
(define my-list ((a1 b1 c1 d1)
(a2 b2 c2 d2)
...
(an bn cn dn)))
And I'd like to have this:
(begin
(mac a1 b1 c1 d2)
(mac a2 b2 c2 d2)
...
(mac an bn cn dn))
(By the way, as you can see I'd like to splice the list of arguments too)
Expanding on z5h's answer of using eval, the methods below show how a map-macro macro can be written if interaction-environment in implemented in the version of R5RS in use:
(define test-list '((1 2 3 4)
(5 6 7 8)))
;Or if your version of scheme implments interaction-environment then:
(define-syntax trade
(syntax-rules ()
((_ a b c d) (display (list b a d c)))))
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;Careful this is not really mapping. More like combined map and apply.
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(define-syntax map-macro
(syntax-rules ()
((_ mac ls) (let ((mac-list (map (lambda (lst) (cons 'trade lst)) ls)))
(eval
`(begin
,#mac-list)
(interaction-environment))))
))
(map-macro trade test-list)
;outputs: (2 1 4 3)(6 5 8 7)
So that last map-macro call evaluates the following:
What ends up getting evaluated from (map-macro trade test-list) is:
(begin
(trade 1 2 3 4)
(trade 5 6 7 8))
Which is not quite a map, but I believe it does answers your question.
Syntactic extensions are expanded into
core forms at the start of evaluation
(before compilation or interpretation)
by a syntax expander. -Dybvig, "The
Scheme Programming Language:
A macro operates on syntax. This happens before compilation or execution. It gives you another way of writing the same code.
A function operates on variables and values (which might be lists, atoms, numbers, etc) who's value is known when the function is invoked.
So mapping a macro doesn't make sense. You're asking to invoke something (macro expansion) that already happened long ago.
If you need something to write code for you and evaluate it at runtime, then might be one of those cases where you need eval.
Would something like
(map (lambda (l) (mac (car l) (caar l) (caaar l) (caaaar l))) mylist)
work?