Here is my solution, but I'm sure some li5p h4x0r has a much more 1337
solution :)
(setf nums (vector 21 47
23 43
24 29
22 28
22 53
31 36
22 56
31 72))
(loop for i from 0 below (car (array-dimensions nums)) by 2
do (progn
(let ((a (aref nums i))
(b (aref nums (1+ i))))
(format t "~A * ~A = ~A~%" a b (* a b)))))
What's wrong with (length nums)?
If the array to be multi-dimensional, your 1D arefs won't work anyway.
> do (progn
The do clause already takes a list of forms; no progn required.
> (let ((a (aref nums i))
> (b (aref nums (1+ i))))
> (format t "~A * ~A = ~A~%" a b (* a b)))))
It's perhaps more useful to collect the results than print.
State machine approach:
(loop for x across nums
with acc
if (null acc) do
(setf acc x)
else
collect (* x acc) and do
(setf acc nil))
> How would you take a sequence of numbers in groups of 2 and print out
> the numbers and their product?
>
> Here is my solution, but I'm sure some li5p h4x0r has a much more 1337
> solution :)
>
> (setf nums (vector 21 47
> 23 43
> 24 29
> 22 28
> 22 53
> 31 36
> 22 56
> 31 72))
Remember that variables are introduced with DEFPARAMETER (or DEFVAR)
and not with SETF.
Also remember that all top-level variables should be by convention
written like this: *nums*
>
> (loop for i from 0 below (car (array-dimensions nums)) by 2
> do (progn
> (let ((a (aref nums i))
> (b (aref nums (1+ i))))
> (format t "~A * ~A = ~A~%" a b (* a b)))))
ARRAY-DIMENSION is not the best operation for a vector in
general, since the vector could be one with a fill-pointer.
LENGTH will give you the real used length of a vector.
This solution is basically the same as yours but a bit
differently written:
(loop with size = (length *nums*)
for i from 0 below size by 2
for j from 1 below size by 2
for a = (aref *nums* i) and b = (aref *nums* j)
do (format t "~A * ~A = ~A~%" a b (* a b)))
People might advise otherwise but I'd try and get away from the loop
construction; it delays your evolution into thinking like a functional
programmer. Think lists and recursion.
Mark
Unless there's a good reason for all the numbers to be in the same list,
something like (mapcar print-fn set-1 set-2) would be the usual way to go
about this. Print-fn would just be a lambda taking two arguments
containing the format call you used.
But he said you're given a sequence of numbers, not two sequences of
numbers. Obviously this is a homework problem, and you don't get to
change the problem to suit your esthetics.
--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
> On Dec 27, 2:34 pm, "livingcosmos.org" <metap...@gmail.com> wrote:
> > How would you take a sequence of numbers in groups of 2 and print out
> > the numbers and their product?
> >
[...]
>
> It's perhaps more useful to collect the results than print.
>
> State machine approach:
>
> (loop for x across nums
> with acc
> if (null acc) do
> (setf acc x)
> else
> collect (* x acc) and do
> (setf acc nil))
Why not just:
(loop
for x on nums by #'cddr
collect (* (first x) (second x)))
The original problem might then be:
(loop
for x on nums by #'cddr
for a = (first x) and b = (second x)
do
Pfft. We are trying to write applications, not placate some wrathful god
of one paradigm or another. The simple fact is that a loop form will
beat any other syntax hands down in terms of succinctness and clarity
for any requirement other than those where (mapcar 'xxx yyy) or maphash
requiring access to both keys and values will suffice. Lawdy loop is
verbose iterating over both key and value of hash tables -- what went
wrong at /that/ design meeting?!
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
This solution is cute but really really ugly. I wouldn't turn
it in for homework...
> In article <pan.2007.12.28....@sbcglobal.net>,
> Paul Donnelly <paul-d...@sbcglobal.net> wrote:
>
>> On Thu, 27 Dec 2007 14:34:28 -0800, livingcosmos.org wrote:
>>
>> > How would you take a sequence of numbers in groups of 2 and print out
>> > the numbers and their product?
>>
>> Unless there's a good reason for all the numbers to be in the same list,
>> something like (mapcar print-fn set-1 set-2) would be the usual way to go
>> about this. Print-fn would just be a lambda taking two arguments
>> containing the format call you used.
>
> But he said you're given a sequence of numbers, not two sequences of
> numbers. Obviously this is a homework problem, and you don't get to
> change the problem to suit your esthetics.
Sorry, I forgot we're only allowed to answer the question exactly as asked. :(
You can let loop do the destructuring:
(loop for (a b nil) on nums by #'cddr ...)
> You can let loop do the destructuring:
>
> (loop for (a b nil) on nums by #'cddr ...)
And you can omit nil in this construct.
Nicolas
> People might advise otherwise but I'd try and get away from the loop
> construction; it delays your evolution into thinking like a functional
> programmer. Think lists and recursion.
>
> Mark
Seconded! I'd rather catch up on Java and Python before delving
into that other language "loop" :-)
>
(setf nums (list 1 2 3 4 5 6 7 8))
(1 2 3 4 5 6 7 8)
>
(defun pair-printer (num-lst)
(when num-lst
(format t "~% ~a ~a ~a" (first num-lst) (second num-lst)
(* (first num-lst) (second num-lst)))
(pair-printer (rest (rest num-lst)))))
PAIR-PRINTER
>
(pair-printer nums)
1 2 2
3 4 12
5 6 30
7 8 56
NIL
You may now add all the bells and whistles to cover odd
numbers of elements etc.
agt
I actually tried this "(loop for (a b) on nums...)" but it didn't work
for me. The "by #'cddr" is what I needed. Thanks.
In a modern FPL not always and not here.
(define pp
[X Y | Z] -> (do (output "~A x ~A = ~A~%" X Y (* X Y)) (pp Z))
_ -> _)
Mark
In the same spirit, using a mapping function:
(defparameter *nums* '(21 47
23 43
24 29
22 28
22 53
31 36
22 56
31 72))
(mapc (let ((prev 0))
#'(lambda (x)
(cond ((= prev 0) (setf prev x))
(t (format t "~A * ~A = ~A~%" prev x (* x prev))
(setf prev 0)))))
*nums*)
21 * 47 = 987
23 * 43 = 989
24 * 29 = 696
22 * 28 = 616
22 * 53 = 1166
31 * 36 = 1116
22 * 56 = 1232
31 * 72 = 2232
Leandro
Ever since we returned in that ball of light I've been playing catch
up, but I don't
recognize this language. Which FPL is it?
agt
Qi written by Mark Tarver
http://www.lambdassociates.org/lC21.htm
--------------
John Thingstad
> > Ever since we returned in that ball of light I've been playing catch
> > up, but I don't
> > recognize this language. Which FPL is it?
>
> > agt
>
> Qi written by Mark Tarver
>
> http://www.lambdassociates.org/lC21.htm
I am truly impressed. I'll append Qi to my languages-to-learn list.
agt
(let loop ((pairs (vector->list nums)))
(if (null? pairs)
'()
(cons (apply * (take pairs 2)) (loop (cddr pairs)))))
I see that you have chosen the COBOL way by using LOOP.
Now what if you wanted to take the numbers 3 at a time?
You would then have to step three variables: i, j, and k.
And you would need to extract a, b, and c from *nums*.
And you would need to change the format string.
Let's write a generalized procedure that take n numbers
at a time. In Guile Scheme:
(define (tuple-products vec n)
(pair-for-each
(lambda (lst)
(if (= 0 (modulo (length lst) n))
(let ((group (take lst n)))
(format #t "~a = ~a~%"
(string-join (map number->string group) " * ")
(apply * group)))))
(vector->list vec)))
guile> (tuple-products nums 4)
21 * 47 * 23 * 43 = 976143
24 * 29 * 22 * 28 = 428736
22 * 53 * 31 * 36 = 1301256
22 * 56 * 31 * 72 = 2749824
Common Lisp:
(defun tuple-products (list n)
(mapn (lambda (group)
(format t "~%~{~D~^ * ~}" group (reduce '* group)))
list
n))
CL-USER 11 > (tuple-products '(21 47 23 43
24 29 22 28
22 53 31 36
22 56 31 72)
4)
21 * 47 * 23 * 43
24 * 29 * 22 * 28
22 * 53 * 31 * 36
(format t "~%~{~D~^ * ~} = ~a" group (reduce '* group)))
list
n))
CL-USER 21 > (tuple-products '(21 47 23 43
24 29 22 28
22 53 31 36
22 56 31 72)
4)
21 * 47 * 23 * 43 = 976143
Welcome to GNU CLISP 2.47 (2008-10-23) <http://clisp.cons.org/>
[1]> #'mapn
*** - FUNCTION: undefined function MAPN
Needs more code...
(defun mapn (f list n)
(loop for l = list then (nthcdr n l)
for l1 = (take-n l n)
while (= (length l1) n)
do (funcall f l1)))
I'm collecting a file with stupid tricks which contain this stuff.
It help's writing code like that...
helps
(defun take-n (list n)
(loop for e in list
repeat n
collect e))
I'm a bit tired of reposting all the code that has been
written the past decades. Some of that code
is already collected in public libraries. Some not.
Functions like these have been available for
decades. It is not a fault for a newbie
to know the libraries, but somebody like Mr. James,
could have looked around have found them
already.
Examples are:
http://common-lisp.net/project/alexandria/draft/alexandria.html
http://clocc.sourceforge.net/
Note to myself: 'Don't write anything in a foreign language on a
sunday morning!'
I meant:
It is not a fault for a newbie
to not know the libraries, but somebody like Mr. James,
> In article
> <403a2cc2-3f9d-4e34...@i12g2000prf.googlegroups.com>,
> "livingcosmos.org" <meta...@gmail.com> wrote:
>
> > How would you take a sequence of numbers in groups of 2 and print out
> > the numbers and their product?
> >
> > Here is my solution, but I'm sure some li5p h4x0r has a much more 1337
> > solution :)
> >
> > (setf nums (vector 21 47
> > 23 43
> > 24 29
> > 22 28
> > 22 53
> > 31 36
> > 22 56
> > 31 72))
>
> Remember that variables are introduced with DEFPARAMETER (or DEFVAR)
> and not with SETF.
>
> Also remember that all top-level variables should be by convention
> written like this: nums
>
> >
> > (loop for i from 0 below (car (array-dimensions nums)) by 2
> > do (progn
> > (let ((a (aref nums i))
> > (b (aref nums (1+ i))))
> > (format t "~A * ~A = ~A~%" a b (* a b)))))
>
> ARRAY-DIMENSION is not the best operation for a vector in
> general, since the vector could be one with a fill-pointer.
> LENGTH will give you the real used length of a vector.
>
> This solution is basically the same as yours but a bit
> differently written:
>
> (loop with size = (length nums)
> for i from 0 below size by 2
> for j from 1 below size by 2
> for a = (aref nums i) and b = (aref nums j)
> do (format t "~A * ~A = ~A~%" a b (* a b)))
Arc:
(each x (tuples nums 4)
(println (intersperse " * " x) " = " (apply * x)))
==>
>
> (each x (tuples nums 4)
> (println (intersperse " * " x) " = " (apply * x)))
That should be
(prn (intersperse " * " x) " = " (apply * x)))