Path: csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c
Subject: Re: Sort of trivial code challenge - may be interesting to you anyway
Date: Wed, 11 Mar 2026 08:23:12 -0700
Organization: A noiseless patient Spider
Lines: 115
Message-ID: <86v7f28k67.fsf@linuxsc.com>
References: <10n80sc$3soe4$1@dont-email.me> <86v7feei2e.fsf@linuxsc.com> <10o53k6$1i0ef$2@dont-email.me> <86ms0peby6.fsf@linuxsc.com> <10ockdh$3qpk6$1@dont-email.me> <10ocrjn$3qpk6$2@dont-email.me> <10od64s$3qpk6$4@dont-email.me> <86ikb9bmtw.fsf@linuxsc.com> <10oem5t$n5hk$1@dont-email.me> <86o6kz9zng.fsf@linuxsc.com> <10oi72k$1rss6$1@dont-email.me> <20260308003557.00000754@yahoo.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Wed, 11 Mar 2026 15:23:16 +0000 (UTC)
Injection-Info: dont-email.me; posting-host="5f44bcdbc02769ce6998caa4a4cb2206"; logging-data="1172321"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19VV78YjrGOtbVarhdjBFPYW6kWxsahV9E="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:Ffm9a5JhKS6t+LTpCrmC5QdO9Fg= sha1:2wY4OrkvwoeNaX0p/cAoJ4+DlpQ=
Xref: csiph.com comp.lang.c:396906
Michael S writes:
> On Sat, 7 Mar 2026 16:58:48 -0500
> DFS wrote:
>
>> A nit you may have forgotten: you earlier said main() was not allowed:
>
> You misunderstood.
> Having main() is allowed and necessary. Calling main() in your code is
> forbidden.
Right.
> If calling main() recursively was allowed then possible solution could
> be just uglier than previos counter-challenge, but would not require
> any different ideas.
It may not require different ideas, but IMO it benefits from
adopting an approach similar to the posted setjmp version. Here
is a revision of the code I posted, changed so that it does not
use setjmp()/longjmp() but instead calls main() recursively. I
think using recursive calls to main to simulate having multiple
functions would make the code more difficult to understand, not
easier.
Note by the way that all calls to main() below are tail calls,
and are optimized away, so there is no stack depth penalty for
this method, unlike using recursive calls to main to simulate
having other functions available.
#include
#include
#include
typedef size_t Z;
typedef _Bool B;
static Z k, h, w, c;
static int d;
#define GO(x) return main( (x), argv )
#define NUMBERISH(p) ((p) && *(p) && (p)[ strspn((p),"0123456789") ] == 0)
enum {
START, // the initial state; must be zero
NADA = -99, // make the following values all be negative
AFU, USAGE, // give suitable message and exit
ROOT, DRAT, // find ceiling( sqrt( cutoff ) ); possible no joy exit
HWC, // display H*W values with cutoff C
FIN, // exit program
};
int
main( int argc, char *argv[] ){
switch( argc < 0 ? argc : 0 ){
case START: {
B usage = argc < 2 || argc > 4;
B g1 = argc > 1 && NUMBERISH( argv[1] );
B g2 = argc > 2 && NUMBERISH( argv[2] );
B g3 = argc > 3 && NUMBERISH( argv[3] );
Z a1 = g1 ? strtoul( argv[1], 0, 10 ) : 0;
Z a2 = g2 ? strtoul( argv[2], 0, 10 ) : 0;
Z a3 = g3 ? strtoul( argv[3], 0, 10 ) : 0;
B square = argc == 2 && g1;
B hw = argc == 3 && g1&&g2 && a1&&a2;
B hwc = argc == 4 && g1&&g2 && a1&&a2 && g3;
k = 0;
h = hw || hwc ? a1 : a1/4 + !a1; // note: initial value(h) > 0
w = hw || hwc ? a2 : h;
c = square ? a1 : !hwc ? h*w : a3 > h*w ? h*w : a3;
d = snprintf( 0, 0, "%zu", c );
GO( usage ?USAGE : square ?ROOT : (hw||hwc) && a1&&a2 ?HWC : AFU );
}
case AFU:
printf( " urk... bad arguments\n" );
GO( USAGE );
case USAGE:
printf( " usage:\n" );
printf( " %s cutoff {{for square}}\n", argv[0] );
printf( " %s rows columns [cutoff]\n", argv[0] );
GO( FIN );
case ROOT: {
h = c < 2 ? 1 : c < 5 ? 2 : (h + c/h) / 2;
h += h*h < c;
w = h;
B done = c < 2 || h*h < c+2*h && c <= h*h;
B good = c < 2 || h*h < c+h && c <= h*h;
GO( !done ?ROOT : good ?HWC : DRAT );
}
case DRAT:
printf( " square with cutoff %zu - no joy\n", c );
GO( FIN );
case HWC: {
B eol = k/h + 1 == w;
B end = k+1 + (h>c ? h-c : 0) >= h*w;
Z nextk = eol ? k - (w-1)*h + 1 : k+h;
printf( k < c ? " %*zu" : "", d, k+1 );
printf( c > 0 && eol ? "\n" : "" );
GO( end ?(printf( "------\n" ), FIN) : (k = nextk, HWC) );
}
}
}