Need Scheme program to print names of numbers - lisp

For example:
(number-name 5513345)
(five million five hundred thirteen thousand three hundred forty five)
I'm not really sure how to go about this??
I tried to do it and ended up with a series of case statements. The program will successfully print out the names of integers below ten but does little else.
(define numname
(lambda (n)
(if (= n 0)
0
(cond ((= n 9) 'nine)
((= n 8) 'eight)
((= n 7) 'seven)
((= n 6) 'six)
((= n 5) 'five)
((= n 4) 'four)
((= n 3) 'three)
((= n 2) 'two)
(else 'one)))))

You're on the right track. Take your example:
5513345
This is:
5 513 345
i.e:
five million five hundred thirteen thousand three hundred forty five
Which can be written as:
five million
five hundred thirteen thousand
three hundred forty five (units)
See a pattern emerging ? Your method works well for numbers below 10 (actually, you might want to go up to 19 as numbers between 10 and 20 have special name not following the Xty Y convention).
Once you have this, it should be easy to go up to 99
Once you have this, it is trivial to go up to 999
Once you have this, it's not even work to split your numbers into billion, million, thousands... and apply it again.
Happy coding !

Related

Custom '+' (sum) function in lisp

I was reading Roots of Lisp by Paul Graham where he claims that any lisp functionality can be build with the combination of this 7 base functions: quote, atom, eq, cond, cons, car, cdr.
Question: are Lisp dialects really based solely on those functions? How can we define a 'sum' or 'plus' function using the aforementioned 7 primitive functions? e.g. Our own (+ 1 2) function
Note: I'm totally newbie to Lisp but I'm also starting to get very excited about the language. The purpose of this question is purely genuine interest
The author refers to a very famous paper written in 1960 by the Turing Award and Lisp inventor John McCarthy “Recursive Functions of Symbolic Expressions and Their Computation by Machine”, in which he defined the semantics of Lisp as a new computational formalism, equivalent in power to the Turing Machine.
In the paper (and in the Lisp 1.5 Manual) McCarthy described the interpreter for the language, that can be completely written by using only the seven primitive functions mentioned by Graham.
The language was devoted primarily to symbolic computations, and the interpreter presented in the papers concerned only those computations, without resorting to numbers or other data types different from atoms and pairs.
As Graham says in a note at page 11 of Root of Lisp, “It is possible to do arithmetic in McCarthy's 1960 Lisp by using e.g. a list of n atoms to represent the number n”, so performing a sum is simply equivalent to appending two lists.
Of course this way of doing is very inefficient: it is presented only to show the equivalence with other computational formalisms, and in the real interpreters/compilers integers are represented as usual, and have the usual operators.
as far as i remember, there was also an approach to do this using list nesting level (don't really remember, where). Starting from () as zero, (()) == 1 and so on. Then you can simply define inc as list and dec as car:
CL-USER> (defun zero? (x) (eq () x))
ZERO?
CL-USER> (zero? nil)
T
CL-USER> (zero? 1)
NIL
CL-USER> (defparameter *zero* ())
*ZERO*
CL-USER> (defun inc (x) (list x))
INC
CL-USER> (defun dec (x) (car x))
DEC
CL-USER> (defun plus (x y)
(if (zero? y) x (plus (inc x) (dec y))))
PLUS
CL-USER> (plus *zero* (inc (inc *zero*)))
((NIL))
CL-USER> (defparameter *one* (inc *zero*))
*ONE*
CL-USER> (defparameter *two* (inc *one*))
*TWO*
CL-USER> (defparameter *three* (inc *two*))
*THREE*
CL-USER> (plus *two* *three*)
(((((NIL)))))
CL-USER> (equal *two* (dec (dec (dec (plus *two* *three*)))))
T
TL; DR: No. Modern lisp systems have many more primitives than the first lisp and a new primitives are needed for each new primitive data type.
The first Lisp didn't have numbers but it was turing complete. That means it can do any computation that is possible in any other language, but it doesn't mean it would be practical to do so. Number were not hard to mimic, but calculations were slow. There are rumers today about slow arithmetic dating back pre Lisp 1.5.
When I made my first lisp interpreter I couldn't care much for numbers. It's not really an interesting aspect of an interpreter. I did however implement fibonacci as an example and this is how it looks like:
;; This is NOT Common Lisp code. It's Zozotez
(setq + (lambda (x y)
(if x (cons (car x)
(+ (cdr x) y))
y)))
(setq - (lambda (z w)
(if w (- (cdr z)
(cdr w))
z)))
(setq fibonacci
(lambda (n a1 a2)
(if n
(fibonacci (- n '(1))
a2
(+ a2 a1))
a1)))
(fibonacci '(1 1 1 1 1 1 1 1 1) () '(1))
; ==> (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
No numbers! (1 in my language is a symbol so it needs to be quoted or else it will be evaluated like a variable)
As alternative number system I have implemented a positional system, pretty much like how we write numbers with the same rules for adding/multiplying etc. Perhaps a tad faster than lits of length n but more complex to make.
If the Lisp has closures you can do church numerals. Using the same as lambda calculus you can compute anything with just closures. You only need one primitive, lambda. (Again, not the easiest to work with)

How to define a function that returns half of input, in two different ways?

I am reading a Gentle Introduction to Symbolic Computation and it asks this question. Basically, the previous content deals with making up bigger functions with small ones. (Like 2- will be made of two 1- (decrement operators for lisp))
So one of the questions is what are the two different ways to define a function HALF which returns one half of its input. I have been able to come up with the obvious one (dividing number by 2) but then get stuck. I was thinking of subtracting HALF of the number from itself to get half but then the first half also has to be calculated...(I don't think the author intended to introduce recursion so soon in the book, so I am most probably wrong).
So my question is what is the other way? And are there only two ways?
EDIT : Example HALF(5) gives 2.5
P.S - the book deals with teaching LISP of which I know nothing about but apparently has a specific bent towards using smaller blocks to build bigger ones, so please try to answer using that approach.
P.P.S - I found this so far, but it is on a completely different topic - How to define that float is half of the number?
Pdf of book available here - http://www.cs.cmu.edu/~dst/LispBook/book.pdf (ctrl+f "two different ways")
It's seems to be you are describing peano arithmetic. In practice it works the same way as doing computation with fluids using cups and buckets.
You add by taking cups from the source(s) to a target bucket until the source(s) is empty. Multiplication and division is just advanced adding and substraction. To halve you take from source to two buckets in alterations until the source is empty. Of course this will either do ceil or floor depending on what bucket you choose to use as answer.
(defun halve (x)
;; make an auxillary procedure to do the job
(labels ((loop (x even acc)
(if (zerop x)
(if even (+ acc 0.5) acc)
(loop (- x 1) (not even) (if even (+ acc 1) acc)))))
;; use the auxillary procedure
(loop x nil 0)))
Originally i provided a Scheme version (since you just tagged lisp)
(define (halve x)
(let loop ((x x) (even #f) (acc 0))
(if (zero? x)
(if even (+ acc 0.5) acc)
(loop (- x 1) (not even) (if even (+ acc 1) acc)))))
Edit: Okay, lets see if I can describe this step by step. I'll break the function into multiple lines also.
(defun half (n)
;Takes integer n, returns half of n
(+
(ash n -1) ;Line A
(if (= (mod n 2) 1) .5 0))) ;Line B
So this whole function is an addition problem. It is simply adding two numbers, but to calculate the values of those two numbers requires additional function calls within the "+" function.
Line A: This performs a bit-shift on n. The -1 tells the function to shift n to the right one bit. To explain this we'll have to look at bit strings.
Suppose we have the number 8, represented in binary. Then we shift it one to the right.
1000| --> 100|0
The vertical bar is the end of the number. When we shift one to the right, the rightmost bit pops off and is not part of the number, leaving us with 100. This is the binary for 4.
We get the same value, however if we perform the shift on nine:
1001| --> 100|1
Once, again we get the value 4. We can see from this example that bit-shifting truncates the value and we need some way to account for the lost .5 on odd numbers, which is where Line B comes in.
Line B: First this line tests to see if n is even or odd. It does this by using the modulus operation, which returns the remainder of a division problem. In our case, the function call is (mod n 2), which returns the remainder of n divided by 2. If n is even, this will return 0, if it is odd, it will return 1.
Something that might be tripping you up is the lisp "=" function. It takes a conditional as its first parameter. The next parameter is the value the "=" function returns if the conditional is true, and the final parameter is what to return if the conditional is false.
So, in this case, we test to see if (mod n 2) is equal to one, which means we are testing to see if n is odd. If it is odd, we add .5 to our value from Line A, if it is not odd, we add nothing (0) to our value from Line A.

Summing very large numbers in Racket

So I am looking to sum up the numbers between zero and one hundred million. This code works extremely well for ten million, executing on my machine in about 3 seconds. However as soon as I attempt to sum up to one hundred million, it freezes my computer along with never finishing. I have waited for this code to finish for five minutes and yet it still will not finish.
#lang racket/base
(require (only-in racket/list range))
(let ([theList (range 0 100000000)]) (time (apply + theList)))
You can use for/sum:
(for/sum ([i (in-range 100000000)])
i)
Like all of the for/xxx variations, for/sum is essentially implemented in terms of for/fold (which Chris Jester-Young explained). In other words for/sum is a convenience wrapper around for/fold.
The standard way to sum numbers in Racket, to my knowledge, is to use for/fold rather than apply, if your range is huge:
(for/fold ((n 0))
((i (in-range 100000000)))
(+ n i))
This takes half a second to run on my computer.

Problems with Nth in common lisp

I'm trying to write a function that can calculate GPA. Now I can do limited calculation(only 3 ),but I stuck on how to calculate more , without using loop or recursion (that's the requirement of subject) how to expend nth function? like: (nth n) ,if so ,is that mean i need to write a lambda expression? As an newbie, I maynot describe the question clearly, really need some help..
Glist is grade points Clist is credit hours.
GPA=( gradepoint *credithour + gradepoint *credithour) / ( the sum of credithour) like: (3*1+3*2+4*1)/(1+2+1)
here is my code:
(defun gpa (Glist Clist)
(format t "~3,2f~%"
(/
(+(nth 0 (mapcar #' * Glist Clist))
(nth 1 (mapcar #' * Glist Clist))
(nth 2 (mapcar #' * Glist Clist)))
(+ (nth 0 Clist)
(nth 1 Clist)
(nth 2 Clist))
);end "/"
);end "format"
(values) );end
EDIT
This seems like a good opportunity to emphasize some common (little c) Lisp ideas, so I fleshed out my answer to illustrate.
As mentioned in another answer, you could use a sum function that operates on lists (of numbers):
(defun sum (nums)
(reduce #'+ nums))
The dot product is the multiplicative sum of two (equal-length) vectors:
(defun dot-product (x y)
(sum (mapcar #'* x y)))
The function gpa is a simple combination of the two:
(defun gpa (grades credits)
(/ (dot-product grades credits) (sum credits)))
The example from the question results in the answer we expect (minus being formatted as a float):
(gpa '(3 3 4) '(1 2 1))
> 13/4
There are a few things worth mentioning from this example:
You should learn about map, reduce, and their variants and relatives. These functions are very important to Lisp and are very useful for operating on lists. map* functions generally map sequences to a sequence, and reduce usually transforms a sequence into to a single value (you can however use forms like (reduce #'cons '(1 2 3))).
This is a good example of the "bottom-up" approach to programming; by programming simple functions like sum that are often useful, you make it easy to write dot-product on top of it. Now the gpa function is a simple, readable function built on top of the other two. These are all one-liners, and all are easily readable to anyone who has a basic knowledge of CL. This is in contrast to the methodology usually applied to OOP.
There is no repetition of code. Sure, sum is used more than once, but only where it makes sense. You can do very little more to abstract the notion of a sum of the elements of a list. It's more natural in Scheme to write functions with functions, and that's a whole different topic. This is a simple example, but no two functions are doing the same thing.
If you're using nth to traverse a list, you're doing it wrong. In this case, you might want to write a summing function:
(defun sum (items)
(reduce #'+ items))

Conditional anaphoric collection best practices?

I trying to iterate through a sequence, conditionally perform an operation on each element and then collect it (but only if it matched the criteria). Here is a simplified example that works, I just want to know if this is proper or best practice in lisp:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n )
collect it)
yields
(2 4)
This works, it just looks funny to me and not so much of the when-when but because I feel like I am having to rig the condition to return what I want. I get that the anaphoric it works on the evaluation of the when but this just seems a little artificial to me. Am I missing something? I have only been a lisper for a few weeks.
Edit: Actually, I am somewhat confused when I tried to apply this. What I really want to do is this:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n)
collect it
do (format t "~A" it))
but the second it seems to become unbound... how do I do this?
I don't see why you need anaphor here.
(loop for n in '(1 2 3 4 5)
when (evenp n)
collect n and
do (format t "~A" n))
Delete the keyword AND if you want the FORMAT unconditionally.