program

J

Joona I Palaste

Ben Pfaff said:
Joona I Palaste said:
Alexander Bartolich said:
begin followup to Joona I Palaste:
OK, I bid $300.
Cool.
So the financial damage of this piece of code is $50 per line.
OTOH I have some doubts whether the OP can compile, run, format,
present and explain it.
#include <limits.h>
#include <stdio.h>
#include <ctype.h>
int main(){int c;int n[1<<CHAR_BIT]={0};while(EOF!=(c=getchar()))
n[tolower(c)]++;printf("a=%d b=%d c=%d\n",n['a'],n['b'],n['c']);
return 0;}

Here's my version. 254 characters.

#include <stdio.h>
#include <ctype.h>
int a[3]={0};int count(void){int c=getchar();return c==EOF?0:((tolower(c)=='a'?
a[0]++:tolower(c)=='b'?a[1]++:tolower(c)=='c'?a[2]++:0),count());}int
main(void){return count(),printf("%d %d %d\n",a[0],a[1],a[2]),0;}
My entry (184 characters):
int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while
((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=%d\
,c=%d\n",*n,n[1],n[2]);}

Well, I have to say your code fits into smaller space, but you not only
use a two-statement function, one of those statements is a while loop.
My version only used one-statement functions, with no loops or if
statements. Now if I could only somehow remove the need for the local
variable c. (Don't suggest making it global...)
 
T

Tom St Denis

Ben Pfaff said:
Joona I Palaste said:
Alexander Bartolich <[email protected]> scribbled the following:
begin followup to Joona I Palaste:
OK, I bid $300.
Cool.
So the financial damage of this piece of code is $50 per line.
OTOH I have some doubts whether the OP can compile, run, format,
present and explain it.
#include <limits.h>
#include <stdio.h>
#include <ctype.h>
int main(){int c;int n[1<<CHAR_BIT]={0};while(EOF!=(c=getchar()))
n[tolower(c)]++;printf("a=%d b=%d c=%d\n",n['a'],n['b'],n['c']);
return 0;}

Here's my version. 254 characters.

#include <stdio.h>
#include <ctype.h>
int a[3]={0};int count(void){int c=getchar();return c==EOF?0:((tolower(c)=='a'?
a[0]++:tolower(c)=='b'?a[1]++:tolower(c)=='c'?a[2]++:0),count());}int
main(void){return count(),printf("%d %d %d\n",a[0],a[1],a[2]),0;}

My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=
%d\
,c=%d\n",*n,n[1],n[2]);}

You're missing a "return 0;" other than that neither splint nor the
strictest GCC warnings turned up anything useful ;-)

c=='a'?0:c=='b'?1:c=='c'?2:3

can be written as

(c<'a'||c>'c')?3:c-'a'

[saves a few chars by my count]

Tom
 
J

Joona I Palaste

Tom St Denis said:
Ben Pfaff said:
My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=
%d\
,c=%d\n",*n,n[1],n[2]);}

You're missing a "return 0;" other than that neither splint nor the
strictest GCC warnings turned up anything useful ;-)

That is true.
c=='a'?0:c=='b'?1:c=='c'?2:3
can be written as
(c<'a'||c>'c')?3:c-'a'

[saves a few chars by my count]

That is false. Very false. There is no guarantee that 'a' through 'z'
are consecutive, or even in alphabetical order.
 
T

Tom St Denis

Joona I Palaste said:
Tom St Denis said:
Ben Pfaff said:
My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while
((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=
%d\
,c=%d\n",*n,n[1],n[2]);}
You're missing a "return 0;" other than that neither splint nor the
strictest GCC warnings turned up anything useful ;-)

That is true.
c=='a'?0:c=='b'?1:c=='c'?2:3
can be written as
(c<'a'||c>'c')?3:c-'a'

[saves a few chars by my count]

That is false. Very false. There is no guarantee that 'a' through 'z'
are consecutive, or even in alphabetical order.

Um, yeah whatever and a char is eight bits...

Tom
 
B

Ben Pfaff

Tom St Denis said:
Ben Pfaff said:
Joona I Palaste said:
Alexander Bartolich <[email protected]> scribbled the following:
begin followup to Joona I Palaste:
OK, I bid $300.

Cool.
So the financial damage of this piece of code is $50 per line.
OTOH I have some doubts whether the OP can compile, run, format,
present and explain it.

#include <limits.h>
#include <stdio.h>
#include <ctype.h>
int main(){int c;int n[1<<CHAR_BIT]={0};while(EOF!=(c=getchar()))
n[tolower(c)]++;printf("a=%d b=%d c=%d\n",n['a'],n['b'],n['c']);
return 0;}

Here's my version. 254 characters.

#include <stdio.h>
#include <ctype.h>
int a[3]={0};int count(void){int c=getchar();return c==EOF?0:((tolower(c)=='a'?
a[0]++:tolower(c)=='b'?a[1]++:tolower(c)=='c'?a[2]++:0),count());}int
main(void){return count(),printf("%d %d %d\n",a[0],a[1],a[2]),0;}

My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=
%d\
,c=%d\n",*n,n[1],n[2]);}

You're missing a "return 0;" other than that neither splint nor the
strictest GCC warnings turned up anything useful ;-)

I was writing to C99. Otherwise I'd not bother with declaring
getchar() or tolower(), saving a few characters.
c=='a'?0:c=='b'?1:c=='c'?2:3

can be written as

(c<'a'||c>'c')?3:c-'a'

Not portably.
 
A

Alexander Bartolich

begin followup to Joona I Palaste:
My version only used one-statement functions, with no loops or if
statements. Now if I could only somehow remove the need for the local
variable c. (Don't suggest making it global...)

#include <stdio.h>
#include <ctype.h>
int a[4];
int f(int c){return c=='a'?1:c=='b'?2:c=='c'?3:0;}
int g(int c){return c==EOF?0:(a[f(tolower(c))]++,g(getchar()));}
int main(void){return g(getchar()),printf("%d %d %d\n",a[1],a[2],a[3]),0;}

239 characters.
 
J

Jeremy Yallop

Ben said:
Joona I Palaste said:
Alexander Bartolich said:
begin followup to Joona I Palaste:
OK, I bid $300.
Cool.
So the financial damage of this piece of code is $50 per line.
OTOH I have some doubts whether the OP can compile, run, format,
present and explain it.
#include <limits.h>
#include <stdio.h>
#include <ctype.h>
int main(){int c;int n[1<<CHAR_BIT]={0};while(EOF!=(c=getchar()))
n[tolower(c)]++;printf("a=%d b=%d c=%d\n",n['a'],n['b'],n['c']);
return 0;}

Here's my version. 254 characters.

#include <stdio.h>
#include <ctype.h>
int a[3]={0};int count(void){int c=getchar();return c==EOF?0:((tolower(c)=='a'?
a[0]++:tolower(c)=='b'?a[1]++:tolower(c)=='c'?a[2]++:0),count());}int
main(void){return count(),printf("%d %d %d\n",a[0],a[1],a[2]),0;}

My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while
((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=%d\
,c=%d\n",*n,n[1],n[2]);}

169 characters:

int getchar(),printf(const char*,...),tolower(),c,n[4];int main(){while((c=tolower(
getchar()))>=0)n[c-'a'?c-'b'?c!='c':2:3]++;printf("a=%d,b=%d,c=%d\n",n[3],n[2],*n);}

Jeremy.
 
M

Mark McIntyre

Um, yeah whatever and a char is eight bits...

Do you deny that a-z are not guaranteed to be contiguous? Do you
therefore assert that the English alphabet is the only one that
exists? Not to mention anything IBM might hae liked.
 
T

Tom St Denis

Mark McIntyre said:
Do you deny that a-z are not guaranteed to be contiguous? Do you
therefore assert that the English alphabet is the only one that
exists? Not to mention anything IBM might hae liked.

It was a joke.

They're related, in that on most platforms ASCII + the-8-bit-byte are true.

See, funny, ha ha...

Oh whatever...

Tom
 
T

Tak-Shing Chan

My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while
((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=%d\
,c=%d\n",*n,n[1],n[2]);}

My entry (12 characters; see below): int main(){}

OP> Write a program that counts the number of times the first three
OP> letters of the alphabet (a, b, c, and A, B, C) occur in a file. Do not
OP> distinguish between lowercase and uppercase letters.

The OP does not say print, so the usual as-if rule applies.

Tak-Shing
 
S

Sidney Cadot

Tak-Shing Chan said:
My entry (184 characters):

int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while
((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=%d\
,c=%d\n",*n,n[1],n[2]);}


My entry (12 characters; see below): int main(){}

That should be 13 characters; a non-empty source file must end with
newline (C99, 5.1.1.2 #2).
OP> Write a program that counts the number of times the first three
OP> letters of the alphabet (a, b, c, and A, B, C) occur in a file. Do not
OP> distinguish between lowercase and uppercase letters.

The OP does not say print, so the usual as-if rule applies.

I applaud your ingenuity; however, the 'as-if' rule does not apply, I think.

You see, I have a /dev/boobytrap file that makes my computer explode
whenever at least one character is read from it. When I run your program
on this file (using shell redirection), nothing happens.

When I run Ben Pfaff's version, again using shell redirection, I
get(*&%^#@%(^%&@

CARRIER LOST
 
M

Morris Dovey

Joona said:
Ben Pfaff said:
Joona I Palaste said:
Alexander Bartolich <[email protected]> scribbled the following:

begin followup to Joona I Palaste:

OK, I bid $300.

Cool.
So the financial damage of this piece of code is $50 per line.
OTOH I have some doubts whether the OP can compile, run, format,
present and explain it.

#include <limits.h>
#include <stdio.h>
#include <ctype.h>
int main(){int c;int n[1<<CHAR_BIT]={0};while(EOF!=(c=getchar()))
n[tolower(c)]++;printf("a=%d b=%d c=%d\n",n['a'],n['b'],n['c']);
return 0;}

Here's my version. 254 characters.

#include <stdio.h>
#include <ctype.h>
int a[3]={0};int count(void){int c=getchar();return c==EOF?0:((tolower(c)=='a'?
a[0]++:tolower(c)=='b'?a[1]++:tolower(c)=='c'?a[2]++:0),count());}int
main(void){return count(),printf("%d %d %d\n",a[0],a[1],a[2]),0;}
My entry (184 characters):
int main(){int getchar(),printf(const char*,...),tolower();int c,n[4]={0};while
((c=tolower(getchar()))>=0)n[c=='a'?0:c=='b'?1:c=='c'?2:3]++;printf("a=%d,b=%d\
,c=%d\n",*n,n[1],n[2]);}

Well, I have to say your code fits into smaller space, but you not only
use a two-statement function, one of those statements is a while loop.
My version only used one-statement functions, with no loops or if
statements. Now if I could only somehow remove the need for the local
variable c. (Don't suggest making it global...)

I won't take pride in this one, but it does shrink down to 173
characters (all on one line, despite what Netscape seems
determined to do to it):

int
getchar(),printf(),toupper(),c,n[4]={0},main(void){while(0<(c=toupper(getchar())))++n[c-'A'?c-'B'?c-'C'?3:2:1:0];printf("A=%d
B=%d C=%d\n",n[0],n[1],n[2]);return 0;}

I bid US$300*184/173 = US$319.08 (-:
 
B

Ben Pfaff

Morris Dovey said:
I won't take pride in this one, but it does shrink down to 173
characters (all on one line, despite what Netscape seems determined to
do to it):

int
getchar(),printf(),toupper(),c,n[4]={0},main(void){while(0<(c=toupper(getchar())))++n[c-'A'?c-'B'?c-'C'?3:2:1:0];printf("A=%d
B=%d C=%d\n",n[0],n[1],n[2]);return 0;}

Omitting a prototype for printf() yields undefined behavior,
because printf() is a varargs function. Adding "const char*,..."
costs 15 more characters, bringing the total to 188.
 
T

Tak-Shing Chan

That should be 13 characters; a non-empty source file must end with
newline (C99, 5.1.1.2 #2).

Thank you.
I applaud your ingenuity; however, the 'as-if' rule does not apply, I think.

No. The fopen() and the counting of alphabets can be
optimized away if the calculations are not used. This is
completely blessed by the Standard and in fact is explicitly
inscribed into the definition of the abstract machine.
You see, I have a /dev/boobytrap file that makes my computer explode
whenever at least one character is read from it.

Transformations outside the abstract machine are outside the
scope of the Standard.
When I run your program
on this file (using shell redirection), nothing happens.

Irrelevant.

Tak-Shing
 
M

Morris Dovey

Ben said:
I won't take pride in this one, but it does shrink down to 173
characters (all on one line, despite what Netscape seems determined to
do to it):

int
getchar(),printf(),toupper(),c,n[4]={0},main(void){while(0<(c=toupper(getchar())))++n[c-'A'?c-'B'?c-'C'?3:2:1:0];printf("A=%d
B=%d C=%d\n",n[0],n[1],n[2]);return 0;}


Omitting a prototype for printf() yields undefined behavior,
because printf() is a varargs function. Adding "const char*,..."
costs 15 more characters, bringing the total to 188.

Pfui! Then it becomes cheaper to add the #include and drop two
prototypes. I'll follow your lead and drop the explicit void arg
list for main() and substitute *n for n[0]:

#include <stdio.h>
int
c,n[4]={0},toupper(),main(){while(0<(c=toupper(getchar())))++n[c-'A'?c-'B'?c-'C'?3:2:1:0];printf("A=%d
B=%d C=%d\n",*n,n[1],n[2]);return 0;}

Those mods bring the character count down to 166.

Pfabulous! (-: New bid is US$300*184/166 = US$332.53
 
B

Ben Pfaff

Morris Dovey said:
Pfui! Then it becomes cheaper to add the #include and drop two
prototypes. I'll follow your lead and drop the explicit void arg list
for main() and substitute *n for n[0]:

#include <stdio.h>
int
c,n[4]={0},toupper(),main(){while(0<(c=toupper(getchar())))++n[c-'A'?c-'B'?c-'C'?3:2:1:0];printf("A=%d
B=%d C=%d\n",*n,n[1],n[2]);return 0;}

Those mods bring the character count down to 166.

Function definitions can't be combined with other declarations
that way, so you'll need to change
...toupper(),main()...
to
...toupper();int main()...
Looks good otherwise.
 
M

Morris Dovey

Ben said:
Pfui! Then it becomes cheaper to add the #include and drop two
prototypes. I'll follow your lead and drop the explicit void arg list
for main() and substitute *n for n[0]:

#include <stdio.h>
int
c,n[4]={0},toupper(),main(){while(0<(c=toupper(getchar())))++n[c-'A'?c-'B'?c-'C'?3:2:1:0];printf("A=%d
B=%d C=%d\n",*n,n[1],n[2]);return 0;}

Those mods bring the character count down to 166.


Function definitions can't be combined with other declarations
that way, so you'll need to change
...toupper(),main()...
to
...toupper();int main()...
Looks good otherwise.

Ben...

I don't seem to be able to find that one -- do you have a
normative reference I can look up? Somehow, that just doesn't
"feel" right to me.

Besides, I don't really want to lower my bid. :)

Thanks
 
B

Ben Pfaff

Morris Dovey said:
I don't seem to be able to find that one -- do you have a normative
reference I can look up? Somehow, that just doesn't "feel" right to me.

It's implicit in the syntax. Note that function-definition
below, quoted from C99, can't include more than one declarator
(at top level):

6.9 External definitions
Syntax
external-declaration:
function-definition
declaration

6.9.1 Function definitions
Syntax
1 function-definition:
declaration-specifiers declarator declaration-listopt compound-statement
 
M

Morris Dovey

Ben said:
It's implicit in the syntax. Note that function-definition
below, quoted from C99, can't include more than one declarator
(at top level):

6.9 External definitions
Syntax
external-declaration:
function-definition
declaration

6.9.1 Function definitions
Syntax
1 function-definition:
declaration-specifiers declarator declaration-listopt compound-statement

Hmm - interesting. It does strike me as pointlessly restrictive
(unlike nearly all the rest of the language); but I'll look at it
more when I've gotten a bit of sleep.

Thanks. I appreciate your alertness in catching that - as well as
the reference.
 
S

Sidney Cadot

Tak-Shing Chan said:
> [...]
I applaud your ingenuity; however, the 'as-if' rule does not apply, I think.
No. The fopen() and the counting of alphabets can be
optimized away if the calculations are not used.

As for the counting, I surely agree. However, I/O has side-effects (by
definition), so my gut feeling is that the "as-if" rule should not apply.
This is
completely blessed by the Standard and in fact is explicitly
inscribed into the definition of the abstract machine.

For this, I'd welcome a reference.
Transformations outside the abstract machine are outside the
scope of the Standard.




Irrelevant.

I am quite conviced you are not right about this, although not
absolutely certain.

Allow me to rephrase the point in contention.


Consider two programs:

/*** a.c ***/
#include <stdio.h>
int main(void)
{
fopen("somefile","rb");
return 0;
}

/*** b.c ***/
in main(void)
{
return 0;
}

Would it be legal for a compiler (through optimization), to emit the
same code for program a.c and b.c ?


I think this question is too interesting to be buried deep in a playful
thread. I will re-ask this at top level to get more exposure.

Best regards,

Sidney
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,351
Latest member
LolaD32479

Latest Threads

Top