From: Janos Blazi
Subject: lists and numbers
Date: 
Message-ID: <38a6d79c_6@goliath.newsfeeds.com>
I have a list consisting of integers or of rationals and I'd like to perform
the following task:

(1)
If all elements are integers, I'd like to divide all integers by the gcd of
the numbers in the list.

(2)
Otherwise I'd like to multiply all elements in the list by the lcm of the
denominators and then go to (1).

It ist not quite clear to me how I do this. Any suggestions?

Thx.

Janos Blazi





-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

From: F. Xavier Noria
Subject: Re: lists and numbers
Date: 
Message-ID: <ujtdass7spsj9355kbn4sbu6sujv373dv7@4ax.com>
On Sun, 13 Feb 2000 17:19:47 +0100, "Janos Blazi" <······@netsurf.de>
wrote:

: I have a list consisting of integers or of rationals and I'd like to perform
: the following task:
: 
: (1)
: If all elements are integers, I'd like to divide all integers by the gcd of
: the numbers in the list.
: 
: (2)
: Otherwise I'd like to multiply all elements in the list by the lcm of the
: denominators and then go to (1).

What about

(defun standarize (numbers)
  "Assumes that NUMBERS is a list of rationals."
  (cond ((loop for n in numbers always (integerp n))
	 (let ((d (apply #'gcd numbers)))
	   (mapcar (lambda (n) (/ n d)) numbers)))
	(t (let ((m (apply #'lcm (mapcar #'denominator numbers))))
	     (mapcar (lambda (n) (* n m)) numbers)))))

Note that it is not necessary to go to (1) because the numbers after
the product by the lcm are coprimes.

-- Xavier
From: Marco Antoniotti
Subject: Re: lists and numbers
Date: 
Message-ID: <lw3dqw98g1.fsf@parades.rm.cnr.it>
Well :) I have been chastised for baroque programmin style :)  Now
it's my turn to be on the giving side :)

F. Xavier Noria <···@retemail.es> writes:

	...

> What about
> 
> (defun standarize (numbers)
>   "Assumes that NUMBERS is a list of rationals."
>   (cond ((loop for n in numbers always (integerp n))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
           (every #'integerp numbers)

Cheers

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - 06 68 10 03 17, fax. +39 - 06 68 80 79 26
http://www.parades.rm.cnr.it/~marcoxa
From: F. Xavier Noria
Subject: Re: lists and numbers
Date: 
Message-ID: <vo9eascm51a9t1rm32ar15k7m9s7kmlost@4ax.com>
On 13 Feb 2000 21:03:10 +0100, Marco Antoniotti <·······@parades.rm.cnr.it>
wrote:

: Well :) I have been chastised for baroque programmin style :)  Now
: it's my turn to be on the giving side :)

<snip>

: > (defun standarize (numbers)
: >   "Assumes that NUMBERS is a list of rationals."
: >   (cond ((loop for n in numbers always (integerp n))
:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:            (every #'integerp numbers)

Great! I appreciate very much such observations. I didn't remember
EVERY and friends. Thank you Marco!

-- Xavier
From: F. Xavier Noria
Subject: Re: lists and numbers
Date: 
Message-ID: <bl0easg9gbv4s5puknt5g0rr21iljljm3d@4ax.com>
: What about
: 
: (defun standarize (numbers)
:   "Assumes that NUMBERS is a list of rationals."
:   (cond ((loop for n in numbers always (integerp n))
: 	 (let ((d (apply #'gcd numbers)))
: 	   (mapcar (lambda (n) (/ n d)) numbers)))
: 	(t (let ((m (apply #'lcm (mapcar #'denominator numbers))))
: 	     (mapcar (lambda (n) (* n m)) numbers)))))
: 
: Note that it is not necessary to go to (1) because the numbers after
: the product by the lcm are coprimes.

Too quickly I'm afraid, the last remark is wrong. I am very sorry.
I think the following function does what you asked:

(defun standarize (numbers)
  "Assumes NUMBERS is a list of rationals."
  (when (loop for n in numbers thereis (ratiop n))
    (let ((m (apply #'lcm (mapcar #'denominator numbers))))
      (setq numbers (mapcar (lambda (n) (* n m)) numbers))))
  (let ((d (apply #'gcd numbers)))
    (mapcar (lambda (n) (/ n d)) numbers)))

-- Xavier
From: F. Xavier Noria
Subject: Re: lists and numbers
Date: 
Message-ID: <ioveas0n9un506fsmhh7li7nv0abh7bddj@4ax.com>
If I may, I would like to modify the code I posted taking into
account what Marco and Gareth said:

I wrote:

: (defun standarize (numbers)
:   "Assumes NUMBERS is a list of rationals."
:   (when (loop for n in numbers thereis (ratiop n))
:     (let ((m (apply #'lcm (mapcar #'denominator numbers))))
:       (setq numbers (mapcar (lambda (n) (* n m)) numbers))))
:   (let ((d (apply #'gcd numbers)))
:     (mapcar (lambda (n) (/ n d)) numbers)))

Using Lisp more appropriately:

(defun standarize (rationals)
  (when (some #'ratiop rationals)
    (let ((m (reduce #'lcm rationals :key #'denominator)))
      (setq rationals (mapcar (lambda (q) (* q m)) rationals))))
  (let ((d (reduce #'gcd rationals)))
    (mapcar (lambda (n) (/ n d)) rationals)))

Thank you very much for the improvements!

-- Xavier
From: Gareth McCaughan
Subject: Re: lists and numbers
Date: 
Message-ID: <86itzs6gru.fsf@g.local>
Janos Blazi wrote:

> I have a list consisting of integers or of rationals and I'd like to perform
> the following task:
> 
> (1)
> If all elements are integers, I'd like to divide all integers by the gcd of
> the numbers in the list.
> 
> (2)
> Otherwise I'd like to multiply all elements in the list by the lcm of the
> denominators and then go to (1).
> 
> It ist not quite clear to me how I do this. Any suggestions?

I don't think I understand the difficulty.

You can do #2 first, whether the list consists entirely of
integers or not.

(defun multiply-by-common-denominator (list)
  (let ((lcm (reduce #'lcm list :key #'denominator)))
    (mapcar (lambda (x) (* x lcm)) list)))

And then you can do #1:

(defun make-primitive (list)
  (let ((gcd (reduce #'gcd list)))
    (mapcar (lambda (x) (/ x gcd)) list)))

Combining the two:

(defun make-integer-and-primitive (list)
  (make-primitive (multiply-by-common-denominator list)))

-- 
Gareth McCaughan  ················@pobox.com
sig under construction
From: Gareth McCaughan
Subject: Re: lists and numbers
Date: 
Message-ID: <86wvo84pta.fsf@g.local>
Gareth McCaughan wrote:

I wrote:
> (defun multiply-by-common-denominator (list)
>   (let ((lcm (reduce #'lcm list :key #'denominator)))
>     (mapcar (lambda (x) (* x lcm)) list)))
..
> (defun make-primitive (list)
>   (let ((gcd (reduce #'gcd list)))
>     (mapcar (lambda (x) (/ x gcd)) list)))
..
> (defun make-integer-and-primitive (list)
>   (make-primitive (multiply-by-common-denominator list)))

Here's another version. I think I like it better,
but I can see reasons why others might disagree.
The main advantage is that there's more potential
for re-use in this:

    (defun common-denominator (rationals)
      (reduce #'lcm rationals :key #'denominator))
    
    (defun scale-list (list factor)
      (mapcar (lambda (x) (* factor x)) list))
    
    (defun scale-to-integers (list)
      (scale-list list (common-denominator list)))
    
    (defun list-gcd (integers)
      (reduce #'gcd integers))
    
    (defun make-primitive (integers)
      (scale-list integers (/ (list-gcd integers))))
    
    (defun make-integer-and-primitive (rationals)
      (make-primitive (scale-to-integers rationals)))

Incidentally, I see that someone else used the expression

    (apply #'gcd integers)

or something of the sort. I avoided that, above, for two
reasons. Firstly, to preserve the parallel between the LCM
and GCD calculations. Secondly, because on some implementations
CALL-ARGUMENTS-LIMIT might be annoyingly small.

-- 
Gareth McCaughan  ················@pobox.com
sig under construction
From: Robert Munyer
Subject: Re: lists and numbers
Date: 
Message-ID: <8873tt$drh$1@eve.enteract.com>
In article <··········@goliath.newsfeeds.com>,
Janos Blazi <······@netsurf.de> wrote:

> It ist not quite clear to me how I do this. Any suggestions?

It's very easy; it will take about six lines of code.

Just look up the following forms and functions:

    APPLY DEFUN DENOMINATOR EVERY GCD
    IF INTEGERP LAMBDA LCM LET MAPCAR

-- Robert Munyer <······@mcs.com>