[comp.lang.c] Programming Challenge

c415-23@alberta.UUCP (Morris Barbara L) (03/04/89)

A friend and I tried to mimic the behaviour of the following program in
the fewest characters possible.  The best we were able to do was 98
characters (result of wc). Can anyone beat this?  Email for our solution.

main()
{
	int n;

	scanf( "%d", &n );
	if ( n < 1 || n >= 10 )
		printf( "error\n" );
	else printf( "answer is %d\n", factorial( n ) );
}

int factorial( n )
int n;
{	
	if ( n == 1 )
		return( n );
	else return( n * factorial( n - 1 ) );
}

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/05/89)

In article <2102@jasper.UUCP> c415-23@alberta.UUCP (Morris Barbara L) writes:
>The best we were able to do was 98 characters (result of wc).

The best I could do with approximately-portable C was 105 characters.
(Fully-portable C requires the addition of "#include<stdio.h>".)
There are several ways to "cheat", e.g. cc -Dp=printf, system(), etc.
What are the ground rules?

cjn@homxb.ATT.COM (C.NORTHRUP) (03/07/89)

------------------------------------------

Kevin Meier from AT&T Bell Labs completed this in approx 15 minutes using
only 96 characters.  I will submit his solution in a couple of days.
Gives others a chance....

kjell@saturn.ucsc.edu (Kjell Post) (03/07/89)

In article <3115@homxb.ATT.COM> cjn@homxb.ATT.COM (C.NORTHRUP) writes:
>
>------------------------------------------
>
>Kevin Meier from AT&T Bell Labs completed this in approx 15 minutes using
>only 96 characters.  I will submit his solution in a couple of days.
>Gives others a chance....

I have 91 now but am not sure about portability of main(n,m) and printf.

main(n,m){scanf("%d\n",&m);while(m>1&m<10)n*=m--;
printf(m-1?"error\n":"answer is %d\n",n);}

-- 
      For athletes and programmers,  ! Kjell E. Post
a woman is the end of their career.  ! CIS/CE
                                     ! University of California, Santa Cruz
              -- A.Wickberg          ! Email: kjell@saturn.ucsc.edu

jzs@bridge2.3Com.Com (Jeremy A. Siegel) (03/08/89)

I don't know what is considered portable or not, but I think my 95
character version (including two unnecessary \n's) is officially ok 
on any machine where 0 is a string of 0-bits (96 chars on others).

c415-23@alberta.UUCP (Morris Barbara L) (03/08/89)

In article <9789@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>
>The best I could do with approximately-portable C was 105 characters.
>(Fully-portable C requires the addition of "#include<stdio.h>".)
>There are several ways to "cheat", e.g. cc -Dp=printf, system(), etc.
>What are the ground rules?

There are no rules, really, but we didn't care about "fully portable" so
there is no need to #include<stdio.h>.  cc -Dp=printf is a good idea,
but why not carry it further and try doing the whole program on the
command line except for the printf strings?  Of course if you do that
the record will plummet from around 90-100 characters to around 20.

So, in case anyone is taking this seriously, I propose the following rules:
1. No command line arguments for the compiler or the program
2. Don't worry about #include <stdio.h>
3. The program must mimic the original in every way - if it takes several
   minutes to report an error for input of -1, it's not quite the same
   as the original.

- Barbara Morris

daveb@laidbak.UUCP (Dave Burton) (03/08/89)

> Can anyone beat [98 characters]?

We got down to 103 characters, "portably".
On a Sun, I got 96 characters - but this is implementation dependent.
-- 
Dave Burton		| ``/* You are not expected to understand this. */''
{spl1,sun}!laidbak!daveb|
(312) 505-9100 x325	| Disclaimer: I channel only for myself.

kjell@saturn.ucsc.edu (Kjell Post) (03/09/89)

In article <2128@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes:
>> Can anyone beat [98 characters]?
>
>We got down to 103 characters, "portably".
>On a Sun, I got 96 characters - but this is implementation dependent.
>-- 

Count this:

main(n,m){for(scanf("%d",&m);m>1&m<10;n*=m--);
printf(m-1?"error\n":"answer is %d\n",n);}
-- 
      For athletes and programmers,  ! Kjell E. Post
a woman is the end of their career.  ! CIS/CE
                                     ! University of California, Santa Cruz
              -- A.Wickberg          ! Email: kjell@saturn.ucsc.edu

bph@buengc.BU.EDU (Blair P. Houghton) (03/10/89)

In article <6639@saturn.ucsc.edu> kjell@saturn.ucsc.edu (Kjell Post) writes:
>>> Can anyone beat [98 characters]?
>
>Count this:
>
>main(n,m){for(scanf("%d",&m);m>1&m<10;n*=m--);
>printf(m-1?"error\n":"answer is %d\n",n);}

It must have been a "me and my ftp" problem again, but the manual page
for this program seems to have elided my grasp.  Could someone mail
me one?

				--Blair
				  "I.e., 'compiles fine,
				   but what does it do?'"
				   8-0 :-| |-) %-D

crossgl@ingr.com (Gordon Cross) (03/10/89)

In article <2102@jasper.UUCP> c415-23@alberta.UUCP (Morris Barbara L) writes:
%A friend and I tried to mimic the behaviour of the following program in
%the fewest characters possible.  The best we were able to do was 98
%characters (result of wc). Can anyone beat this?  Email for our solution.
%
%main()
%{
%	int n;
%
%	scanf( "%d", &n );
%	if ( n < 1 || n >= 10 )
%		printf( "error\n" );
%	else printf( "answer is %d\n", factorial( n ) );
%}
%
%int factorial( n )
%int n;
%{	
%	if ( n == 1 )
%		return( n );
%	else return( n * factorial( n - 1 ) );
%}

OK, how about 94 characters (line split here so you can see it better):

n,v;main(){scanf("%d",&n);for(v=n>0&n<10;v&&n;v*=n--);
printf(v?"answer is %d\n":"error\n",v);}
-- 

Gordon Cross             UUCP:      uunet!ingr!crossgl     "all opinions are
111 Westminister Way     INTERNET:  crossgl@ingr.com        mine and not those
Madison, AL 35758        MA BELL:   (205) 772-7842          of my employer."

crossgl@ingr.com (Gordon Cross) (03/10/89)

In article <6619@saturn.ucsc.edu> kjell@saturn.ucsc.edu (Kjell Post) writes:
>
>I have 91 now but am not sure about portability of main(n,m) and printf.
>
>main(n,m){scanf("%d\n",&m);while(m>1&m<10)n*=m--;
>printf(m-1?"error\n":"answer is %d\n",n);}

Interesting BUT:  this does NOT behave the same way as the original program
in all cases!!  Try running the original and your versions using:

silly 5
2

The original yields:  answer is 2
Yours yields:         answer is 4
-- 

Gordon Cross             UUCP:      uunet!ingr!crossgl     "all opinions are
111 Westminister Way     INTERNET:  crossgl@ingr.com        mine and not those
Madison, AL 35758        MA BELL:   (205) 772-7842          of my employer."

low@s.cs.uiuc.edu (03/10/89)

We found a solution of 94 characters here in NCSA. (Sorry Bell Lab :-)

Is that the lowest?

landauer@morocco.Sun.COM (Doug Landauer) (03/10/89)

> A friend and I tried to mimic the behaviour of the following program in
> the fewest characters possible.  The best we were able to do was 98
> characters (result of wc). Can anyone beat this?

>> [a few attempts, all in C, omitted]

C'mon, guys, where's your imagination?  Portable?  C?  She said "the
fewest characters possible"!  (Nothing in the original challenge said
it had to be in "C", which is why I've sent followups to comp.misc.)
Anyway, I haven't seen any other postings that solve this silly
challenge (to write a little factorial program) in as few characters as
does this 76-character shell/dc/sed script:
----
dc<<Q
[[error]pq]se`head -1`dsnd1>ed9<e[ln1-dsn*ln2<y]syln2<y[answer is ]Pp
----
(Those lacking the BSD "head" program can use "cat" instead (shortening
the solution to 72 chars) but you'll have to give a ^D after you input
the number.)

Can anyone improve this further?   I suspect it can be done more concisely in
APL, but I have no APL interpreter handy.

Meanwhile, I later came up with this cute 62-character near-solution,
that doesn't need anything but a shell (vanilla Bourne, I think).
However, it doesn't print "error" in all of the cases that it should:
----
read x
set 1 2 6 24 120 720 5040 40320 362880
eval echo $"$x"
----
Call this one "error" (and set your $PATH right) and it'll mimic the
original for 0 through 9!

A related (but shorter -- 54 characters) near-solution does almost as
well, but won't work on some BSD-based systems lacking "cut" (You should
replace each "^I" with an actual TAB character):
---
read x
cut -f$x<<Q
1^I2^I6^I24^I120^I720^I5040^I40320^I362880
---

(P.S. In case you care, most of these were tested on a Sun4 running 4.0).

Oh well, back to work.
--
  Doug Landauer -- Sun Microsystems, Inc.	Software Products Group
  landauer@sun.com   or   ...!sun!landauer

root@spdyne.UUCP (03/11/89)

In article <3115@homxb.ATT.COM> cjn@homxb.ATT.COM (C.NORTHRUP) writes:
>Kevin Meier from AT&T Bell Labs completed this in approx 15 minutes using
>only 96 characters.  I will submit his solution in a couple of days.
>Gives others a chance....

kjell@saturn.ucsc.edu Writes:
#> I have 91 now but am not sure about portability of main(n,m) and printf.
#> 
#> main(n,m){scanf("%d\n",&m);while(m>1&m<10)n*=m--;
                      ^^
Works better without this..  Remove this as it isn't needed,
and makes you enter something like 1<CR>2<CR> to get it to like the 1...

    And then combine the two onto a single line... This will give you
91 chars...

#> printf(m-1?"error\n":"answer is %d\n",n);}
#> 
#> -- 
#>       For athletes and programmers,  ! Kjell E. Post
#> a woman is the end of their career.  ! CIS/CE
#>                                      ! University of California, Santa Cruz
#>               -- A.Wickberg          ! Email: kjell@saturn.ucsc.edu

> Someone said something about allowing command line -D options...
  This of course allows the 1 Char answer: "M", where you use
  -DM="main......."


    Kinda spoils it,

        -Chert Pellett
         root@spdyne
I have 

pathak@s.cs.uiuc.edu (03/11/89)

In an article by kjell@saturn.ucsc.edu writes

>I have 91 now but am not sure about portability of main(n,m) and printf.
>
>main(n,m){scanf("%d\n",&m);while(m>1&m<10)n*=m--;
>printf(m-1?"error\n":"answer is %d\n",n);}

Well, the code I ran the code through wc and it came out to be 92 chars.
Still, it is a nice piece of code.  However, the following modifications make
the same code only 89 chars.



main(n,m){for(scanf("%d",&m);m>1&m<10;n*=m--);
printf(m-1?"error\n":"answer is %d\n",n);}

Of course, you need to delete the newline after the first line.  The code 
could further be optimized by getting rid of the extra "\n" after error and 
answer which would make it 85.


Heeren Pathak
s.cs.uiuc.edu
zaphod.ncsa.uiuc.edu

csm@violet.berkeley.edu (03/11/89)

How about some beautiful elegant self-documenting C contests instead of
portmanteau obfuscatory unreadable ones?

	Brad Sherman (bks@alfa.berkeley.edu)

hascall@atanasoff.cs.iastate.edu (John Hascall) (03/13/89)

In article <21499@agate.BERKELEY.EDU> csm@violet.berkeley.edu writes:
 
>How about some beautiful elegant self-documenting C contests instead of
>portmanteau obfuscatory unreadable ones?
>
>	Brad Sherman (bks@alfa.berkeley.edu)
 
    What the h*ll fun would that be?
 
    We have to do that all day at work :-)
 
John Hascall / Systems group / ISU Comp Center / Ames IA

squires@eecs.nwu.edu (Matthew Squires) (03/13/89)

/ eecs.nwu.edu:comp.lang.c / pathak@s.cs.uiuc.edu /  8:44 pm  Mar 10, 1989 /


> main(n,m){for(scanf("%d",&m);m>1&m<10;n*=m--);
> printf(m-1?"error\n":"answer is %d\n",n);}

The expression "m>1&m<10" can be optimized by one character with the
expression "m>1^m>9".

> Heeren Pathak
> s.cs.uiuc.edu
> zaphod.ncsa.uiuc.edu

charlie@vicorp.UUCP (Charlie Goldensher) (03/14/89)

In article <2102@jasper.UUCP>, c415-23@alberta.UUCP (Morris Barbara L) writes:
> A friend and I tried to mimic the behaviour of the following program in
> the fewest characters possible.  The best we were able to do was 98
> characters (result of wc). Can anyone beat this?  Email for our solution.

Some friends and I mimiced the behavior of your program in
97 characters (result of wc).  Can you beat this?
Email for *our* solution.

A colleague on this project suspects that
the lower limit is the prime number 73.
-- 
charlie@vicorp.uu.NET	--	Charlie Goldensher

charlie@vicorp.UUCP (Charlie Goldensher) (03/14/89)

If you allow the -D command line option why not simply

    cc -Dp="main(){...}"  ?

Now the program is:

    p
-- 
charlie@vicorp.uu.NET	--	Charlie Goldensher

limes@wseng.sun.com (Greg Limes) (03/16/89)

In article <4412@ingr.com> crossgl@ingr.com (Gordon Cross) writes:

   The example above fails to yield the correct answer if invoked
   with arguments on the command line whereas the original program did...

Perhaps it is time to ask, since c415-23@alberta did not specify.
	*** Can we assume no parameters? ***

My current version stands at 85 characters.
Assuming no parameters brings it down to 83.
Removing the final newline brings it down to 82.
Removing the newlines from the printf formats gets
it down to 78, but that is definitely cheating 8-)

bph@buengc.BU.EDU (Blair P. Houghton) (03/17/89)

In article <1712@vicorp.UUCP> charlie@vicorp.UUCP (Charlie Goldensher) writes:
>
>If you allow the -D command line option why not simply
>
>    cc -Dp="main(){...}"  ?
>
>Now the program is:
>
>    p

Funny.

Wouldn't you then include the "main(){..." in the character count for
the program?  I would.  It seems like _more_ work and more info to
keep track of.  You'd probably have to cobble up a Makefile for it,
to keep from having to type it in after every revision.  That really
brings up the character count.

				--Blair
				  "Better living through accounting?
				   Naaah."

mcdonald@uxe.cso.uiuc.edu (03/17/89)

>main(n,m){for(scanf("%d",&m);m>1&m<10;n*=m--);
>printf(m-1?"error\n":"answer is %d\n",n);}

May  I ask: main(n,m){
This looks a bit odd - no declarations for n and m. Doesn't that
make them "ints"? That is fine for n, BUT isn't the second argument
to main a char * something[]?  I would suspect that this example would
crash in Technicolor flames as often as not.




>How about some beautiful elegant self-documenting C contests instead of
>portmanteau obfuscatory unreadable ones?

To which I would like to add: 100% legal ANSI C (with no trigraphs :-) ).

rns@se-sd.sandiego.ncr.com (Rick Schubert) (03/21/89)

In article <LIMES.89Mar15203439@ouroborous.wseng.sun.com> limes@wseng.sun.com (Greg Limes) writes:
>In article <4412@ingr.com> crossgl@ingr.com (Gordon Cross) writes:

>   The example above fails to yield the correct answer if invoked
>   with arguments on the command line whereas the original program did...

>Perhaps it is time to ask, since c415-23@alberta did not specify.
>	*** Can we assume no parameters? ***

Please note that the first argument to `main' may have the value 0 !
(That's the integer 0, not 0 factorial).

A value of 0 indicates that the program name is not available.  This
is allowed by the soon-to-be ANSI Standard.

-- Rick Schubert (rns@se-sd.sandiego.NCR.COM)

karl@haddock.ima.isc.com (Karl Heuer) (03/24/89)

In article <1859@se-sd.sandiego.ncr.com> rns@se-sd.sandiego.NCR.COM (Rick Schubert(AEP)) writes:
>A value [for argc] of 0 indicates that the program name is not available.
>This is allowed by the soon-to-be ANSI Standard.

Actually, the sentence that includes "program name is not available" in the
pANS refers to the case argc > 0 && argv[0] == "".  It's true that the pANS
also allows argc == 0 && argv[0] == NULL, but it doesn't say what this is
intended to mean.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

rns@se-sd.sandiego.ncr.com (Rick Schubert) (03/28/89)

In article <12145@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <1859@se-sd.sandiego.ncr.com> rns@se-sd.sandiego.NCR.COM (Rick Schubert(AEP)) writes:
>>A value [for argc] of 0 indicates that the program name is not available.
>>This is allowed by the soon-to-be ANSI Standard.

>Actually, the sentence that includes "program name is not available" in the
>pANS refers to the case argc > 0 && argv[0] == "".  It's true that the pANS
>also allows argc == 0 && argv[0] == NULL, but it doesn't say what this is
>intended to mean.

I believe that
	argc == 0 && argv[0] == NULL
is intended for the case where the implementation has no access to
the command line (or there is no command line), whereas
	argc > 0 && argv[0] == ""
is intended for the case where the implementation has access to the command
line but not to the program name.

-- Rick Schubert (rns@se-sd.sandiego.NCR.COM)

bph@buengc.BU.EDU (Blair P. Houghton) (03/29/89)

In article <1866@se-sd.sandiego.ncr.com> rns@se-sd.sandiego.NCR.COM (Rick Schubert(AEP)) writes:
>
>I believe that
>	argc == 0 && argv[0] == NULL
>is intended for the case where the implementation has no access to
>the command line (or there is no command line), whereas
>	argc > 0 && argv[0] == ""
>is intended for the case where the implementation has access to the command
>line but not to the program name.

I get it.  One is a null pointer, and the other is a pointer-to-a-null...

				--Blair

rns@se-sd.sandiego.ncr.com (Rick Schubert) (03/30/89)

In article <2417@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <1866@se-sd.sandiego.ncr.com> rns@se-sd.sandiego.NCR.COM (Rick Schubert(AEP)) writes:
>>I believe that
>>	argc == 0 && argv[0] == NULL
>>is intended for the case where the implementation has no access to
>>the command line (or there is no command line), whereas
>>	argc > 0 && argv[0] == ""
>>is intended for the case where the implementation has access to the command
>>line but not to the program name.

>I get it.  One is a null pointer, and the other is a pointer-to-a-null...
>				--Blair

In the interest of trying to keep my postings brief and to the point, I
may, at times, assume too much and leave out something that maybe should
have been said.  When I wrote:

>>	argc > 0 && argv[0] == ""
>>is intended for the case where the implementation has access to the command
>>line but not to the program name.

I meant to imply that not only
	argc > 0
but that, potentially
	argc > 1

That is, since the implementation has access to the command line but not to
the program name, the program may be invoked with arguments, which are
pointed to by argv[1], argv[2], ..., argv[argc-1].  As always,
	argv[argc] == NULL
so that, if argc == 0,
	argv[0] == NULL
Also, argv[i] (for 0 <= i < argc) points to a C string (i.e. is not NULL),
so that, if argc > 0, argv[0] cannot be NULL and must point to a string.
If the program name is not available, "" is probably the most reasonable
choice.

I hope this posting strikes a good balance between conciseness and verbosity.
Also, I hope that my mixing of C expressions and C/English is not too confusing
(I can't post in multiple fonts).

-- Rick Schubert (rns@se-sd.sandiego.NCR.COM)

harold@fmrco (Harold Naparst) (12/15/90)

I am trying to write a function which will return the index
of the smallest element of an array.  I want the routine
to work for any type array.  That is, I don't want to write
a separate routine for each type of array (real or double or
integer).  How can I do this ?  I tried playing around with 
the GNU C typeof operator, but couldn't figure it out.  Any ideas ?

Harold Naparst
(uunet!fmrco!harold)
-- 
Harold Naparst                  (uunet!fmrco!harold) 
Fidelity Management Trust Co.   (617)-570-2587
82 Devonshire St., #I40F        The opinions expressed herein are not those
Boston, MA  02109               of my employer.

maguire@sun.soe.clarkson.edu (Bill Maguire) (12/18/90)

In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:

>I am trying to write a function which will return the index
>of the smallest element of an array.  I want the routine
>to work for any type array.  That is, I don't want to write
>a separate routine for each type of array (real or double or
>integer).  How can I do this ?  I tried playing around with 
>the GNU C typeof operator, but couldn't figure it out.  Any ideas ?

>Harold Naparst

Tw ways immediately pop to mind:

1) overload the function to take a real*, double* or integer*.  You'll
have to do some text editing to copy the code and replace the types
but this is where templates come in.  With templates you can write
only one of the functions and the compiler will generate the
completed function definitions as you use them.

(This isn't entirely true in GNU g++ yet, there is a SED script, I 
believe, that given a template will generate the function definitions
that you ask of it)

2) The problem with having the same "compiled code" work on an array
of real, double, or integer is that these objects are in no way
related through any hierarchy.  So any call to the function cannot
be resolved polymorphically at run time.  To correct this create a 
hierarchy of Numbers with Number as an abstract base class.  You will 
have to do a lot of work defining the operators between numbers as it 
will take two virtual calls to resolve the type of each operand.
   At this point you can create an Array of Number object.  Now write
the function to work on an Array of Number.  This will be slower than
the first example as a great deal of polymorphic calls will have to be
made, but less compiled code will be generated.  (Not really, as you 
have to add the code for your whole type hierarchy) Another "problem" 
with this solution is that the Arrays are no longer limited to one type,
you could have Integers, Reals, and Doubles in the same list.  Not
quite what you want.
   However you could do some more work and define the classes 
Array of Integer, Array of Real, and Array of Double as subclasses of
Array of Number.  These class would have to know what to do if they 
were asked to set an element to the wrong type (i.e error), 
(Actually if you were using an overload operator[] and passing back
a reference as an lvalue than this can be resolved in the Number class)
but they could be implemented much more efficiently than a straight array 
of number.
   Now you have what you want.  A lot of work though.

Bill Maguire
sun.soe.clarkson.edu  
She had so many chins, she looked like a piece of lisp code :-))))))

noren@dinl.uucp (Charles Noren) (12/19/90)

In article <MAGUIRE.90Dec17132020@sun.clarkson.edu> maguire@sun.soe.clarkson.edu (Bill Maguire) writes:
 >In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:
 >
 >>I am trying to write a function which will return the index
 >>of the smallest element of an array.  I want the routine
 >>to work for any type array.  That is, I don't want to write
 >>a separate routine for each type of array (real or double or
 >>integer).  How can I do this ?  I tried playing around with 
 >>the GNU C typeof operator, but couldn't figure it out.  Any ideas ?
 >
 >>Harold Naparst
 >
 >Two ways immediately pop to mind:

...or you could wait until AT&T implements Parameterized Types,
or use (AT YOUR OWN RISK) one of the C++ compilers that has a version
Parameterized Types (e.g., the C++ that comes with ObjectStore OODBMS
by Object Design, Inc).


-- 
Chuck Noren
NET:     dinl!noren@ncar.ucar.edu
US-MAIL: Martin Marietta I&CS, MS XL8058, P.O. Box 1260,
         Denver, CO 80201-1260
Phone:   (303) 971-7930

scs@adam.mit.edu (Steve Summit) (12/19/90)

In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:
>I am trying to write a function which will return the index
>of the smallest element of an array.  I want the routine
>to work for any type array.

[Someone may well already have suggested this; I might have
missed it because my news feed appears to be flakey.]

Since the question was crossposted to comp.lang.c, here's the
straight-C answer, which doesn't involve any mucking about with
derived or generic types.  The caller does, on the other hand,
have to provide a comparison routine appropriate for the data
type being searched.  (Come to think of it, this probably isn't
what Mr. Naparst was looking for at all.  Oh, well, the technique
is instructive, and understanding it helps avoid problems when
using qsort and bsearch.)

Given

	sometype array[SOMESIZE];

and

	int sometypecmp(void *p1, void *p2)
	{
	sometype *sp1 = (sometype *)p1;
	sometype *sp2 = (sometype *)p2;

	if(*sp1 < *sp2)
		return -1;
	else if(*sp1 == *sp2)
		return 0;
	else	return 1;
	}

(this could return *sp1 - *sp2 if overflow wasn't a problem, and
might have to use more complicated relationals for nonarithmetic
types),

we can call

	findbiggest(array, SOMESIZE, sizeof(sometype), sometypecmp);

where findbiggest is

	findbiggest(void *a, size_t n, size_t elsize, int (*cmp)(void*,void*))
	{
	void *biggest = a;
	register int i;
	char *p2;		/* not void * so can do pointer arithmetic */

	for(i = 1, p2 = (char *)a + elsize; i < n; i++, p2 += elsize)
		{
		if((*cmp)(p2, biggest) > 0)
			biggest = p2;
		}

	return ((char *)biggest - (char *)a) / elsize;
	}

(Actually, a more likely implementation, closer to bsearch, would
return a pointer to the largest element, not the index.)

                                            Steve Summit
                                            scs@adam.mit.edu

platt@ndla.UUCP (Daniel E. Platt) (12/21/90)

In article <1990Dec15.015355.15683@fmrco>, harold@fmrco (Harold Naparst) writes:
> 
> I am trying to write a function which will return the index
> of the smallest element of an array.  I want the routine
> to work for any type array.  That is, I don't want to write
> a separate routine for each type of array (real or double or
> integer).  How can I do this ?  I tried playing around with 
> the GNU C typeof operator, but couldn't figure it out.  Any ideas ?
> 

Hi,

I think that you'd need to provide some sort of comparator function that
will actually do the comparison between the various elements, and all you
need to be able to do is pass the size of the data objects so that you can
compute the comparison pointers.  Example:

int least_find(base, nel, size, compar)
char *base;
int nel, size;
int (*compar)();
{
	int i, i_least;

	for (i = i_least = 0; i < nel; i++)
		if ((*compar)(base + i * size, base + i_least * size) < 0)
			i_least = i;

	return i_least;
}

Then, all you'd need to do is pass the function in compar that would handle
the comparison between your two types, and which would yield a value > 0, = 0,
or < 0 depending on which element was larger.

/* a function that will compare two integers */
int comp(u, v)
int *u, *v;
{
	return (*v - *u);
}

/*
** a section of code that will find the smallest out of N elements of array
** ar[] of ints using comp().
*/

	least = least_find(ar, N, sizeof(int), comp);

Hope this gives you more of a feel of how this has been handled in the
past...

Dan

rfg@NCD.COM (Ron Guilmette) (12/22/90)

In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:
>
>I am trying to write a function which will return the index
>of the smallest element of an array.  I want the routine
>to work for any type array.  That is, I don't want to write
>a separate routine for each type of array (real or double or
>integer).  How can I do this ?  I tried playing around with 
>the GNU C typeof operator, but couldn't figure it out.  Any ideas ?



I see that there have been a few responses to this already, but I didn't
see anyone actually give what I consider to be a `good' answer.

The question was how to "write" a generic function to find the index of
the smallest element of an array of an arbitrary type.  The questioner
did not say anything about actually needing to compile it into executable
code with the help of any currently available C++ language processor.
:-) :-) :-)

Here is a solution:


template<class T> unsigned smallest (T array[], unsigned array_size)
    throw (Range_Error)
{
  T* smallest_value_p = &array[0];
  unsigned smallest_index = 0;

  if (array_size == 0)
    throw Range_Error (Zero_Length);

  for (unsigned i = 1; i < array_size; i++)
    if (array[i] < *smallest_value_p)
      {
	smallest_value = &array[i];
	smallest_index = i;
      }

  return i;
}

Won't life be beautiful when we can actually *use* templates & exceptions?

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

lerman@stpstn.UUCP (Ken Lerman) (12/31/90)

In article <3066@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes:
...
.Won't life be beautiful when we can actually *use* templates & exceptions?
.
.// Ron Guilmette  -  C++ Entomologist
.// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
.// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.

Maybe.  But I thought life would be beautiful when I could get another
16k of memory for my computer. :-)

Ken