Well, someone wrote that they could write a program to do 1000! in one line of Haskell. I said that it would take less than 100 lines of C to do the same. I wrote the program, and it is less than 100 lines of C:
#include <stdio.h>
#include <string.h>
#define LENGTH 10000
int max (int a, int b) { return (a > b) ? a : b; }
int min (int a, int b) { return (b > a) ? a : b; }
int length (unsigned char * a)
{
int i;
i = LENGTH - 1;
while ((a[i] == 0) && (i >= 0)) i--;
return i + 1;
}
void add (unsigned char * a, unsigned char * b)
{
int i, c, C;
c = min(max(length(a), length(b)) + 1, LENGTH);
for (i = 0, C = 0; i < c; i++)
{
a[i] += b[i] + C;
C = a[i] > 99;
if (C) a[i] -= 100;
}
}
unsigned char x [LENGTH], y [LENGTH];
void mul (unsigned char * a, unsigned char * b)
{
int i, j, c, d, C;
memset(y, '\0', LENGTH);
c = min(length(a) + length(b) + 1, LENGTH);
d = length(b);
for (i = 0; i < d; i++)
{
memset(x, '\0', LENGTH);
for (j = 0, C = 0; (i + j) < c; j++)
{
x[i + j] = (a[j] * b[i] + C) % 100;
C = (a[j] * b[i] + C) / 100;
}
add(y, x);
}
memcpy(a, y, LENGTH);
}
void numset (unsigned char * a, unsigned long b)
{
int i;
for (i = 0; i < LENGTH; i++)
{
a[i] = b % 100;
b /= 100;
}
}
int tz (unsigned char * a)
{
int i;
for (i = 0; i < LENGTH; i++) if (a[i] != 0) return 0;
return 1;
}
unsigned char arg_res [LENGTH];
int main (void)
{
unsigned long a;
int i;
memset (minus1, 99, LENGTH);
printf("Input the number to take the factorial of: ");
scanf("%lu", &a);
numset(arg_res, a);
fact(arg_res);
i = LENGTH - 1;
while (arg_res[i] == 0) i--;
while (i >= 0)
{
printf("%02d", (int) arg_res[i]);
i--;
}
putchar('\n');
return 0;
}
here it OP, also a one-liner
printf("402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
Name:
Anonymous2011-04-03 2:11
New challenge: Write the shortest C program that outputs the factorial of 1000.
>>14
Yes it is.
; just for reference, Π is:
#;
(define (Π f n m #:threads (c (processor-count)))
(let* ((t (lambda (a)
(lambda ()
(let/ec k
(do ((x (+ n a) (+ x c))
(r 1 (* r (f x))))
((> x m) (k r)))))))
(xs (do ((x (sub1 c) (sub1 x))
(xs '() (cons (future (t x)) xs)))
((zero? x) xs)))
(x ((t 0))))
(foldr * x (map touch xs))))
>>10 doesn't seem to know the difference between C and Python.
>>11-12 seems to be confusing programming languages as well.
>>13,15 is an expert Scheme programer, but doesn't seem to know the difference between C and Scheme. I'd give it the most interesting implementation award, however.
I'm calling it right now, you guys are fucking morons, it wasn't a response to your retarded little SEE challenge, it was a response to the original post. It even runs faster than your pathetic entries, if you're writing C at least do it right.
>>20 >>1 is good enough, without using a bignum library. We'd just reimplement it over and over. I'd say this should be a ``make a fast/complete C bignum library'' challenge.
>>16
OP here. Nice. The math is problem specific, and faster for it. >>21
Also, nice. You took a language which you wrote factorial in one line, and wrote it in alot of lines, and showed that version to be superior. How the hell does it work?
You have to be smarter than the language. How many C programmers can do ad hoc bignum math that does more than addition and subtraction? How many Scheme programmers can write >>13 ?
>>25 >>21
I'm not the deluded pythonista! I'm usually respectful, and knew that >>13 is not a valid entry.
I tried to do it in C, and wanted to make the bignum part faster, smaller (using a whole uintmax) and general, but it seems I can't write C code anymore. I give up, it would be much easier in Assembly.
What I've done so far:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
void bignum_addbi(bignum *n, uintmax_t m) {
size_t i, j = n->len;
uintmax_t a;
for (a = n->val[i], i = 0; m && i < j; i++) {
a = n->val[i];
n->val[i] += m;
m = a > n->val[i];
}
if (m && i >= n->len)
bignum_realloc(n, n->len+1, 1);
}
void bignum_addbb(bignum *n, bignum *m) {
size_t i, j = max(n->len, m->len);
uintmax_t a; int c;
if (n->len < m->len)
bignum_realloc(n, m->len, 0);
for (i = 0, c = 0; i < j; i++) {
a = n->val[i];
n->val[i] += m->val[i] + c;
c = a > n->val[i];
}
if (c && i >= j++)
bignum_realloc(n, j, 1);
}
void bignum_subbi(bignum *n, uintmax_t m) {
size_t i, j = n->len;
uintmax_t a;
for (a = n->val[i], i = 0; m && i < j; i++) {
a = n->val[i];
n->val[i] -= m;
m = a < n->val[i];
}
if (--j && !n->val[j])
bignum_realloc(n, j, n->val[j]);
}
void bignum_mulbb(bignum *n, bignum *m) {
if (bignum_zerop(m)) {
bignum_dealloc(n);
n = bignum_from_uintmax(0);
}
if (bignum_equalpi(m, 1)) return;
bignum *i = bignum_copy(m);
bignum *l = bignum_copy(n);
for (; !bignum_equalpi(i, 1); bignum_subbi(i, 1))
bignum_addbb(n, l);
bignum_dealloc(i);
bignum_dealloc(l);
}
void bignum_mulbi(bignum *n, uintmax_t m) {
if (!m) {
bignum_dealloc(n);
n = bignum_from_uintmax(0);
}
if (m == 1) return;
bignum *l = bignum_copy(n);
while (--m)
bignum_addbb(n, l);
}
int bignum_zerop(bignum *n) {
return (!(!(n->len-1) && n->val[0]));
}
int bignum_equalp(bignum *n, bignum *m) {
if (n->len != m->len) return 0;
size_t i = n->len;
while (n->val[i] == m->val[i]) i--;
return !!i;
}
inline int bignum_equalpi(bignum *n, uintmax_t m) {
return (!(n->len > 1)) && (n->val[0] == m);
}
void debug_print_bn(bignum *n) {
printf("Memory Location: %#08x; %#08x\n", n, n->val);
printf("Length: %u\n", n->len);
size_t i;
for (i = 0; i < n->len; i++)
printf("Cell#%08u: %016llx\n", i, n->val[i]);
}
Name:
Anonymous2011-04-04 1:29
>>26
OVER 9000 REALLOC OPERATION
REWRITE THAT SHIT
Name:
Anonymous2011-04-04 1:39
Or the weenie can learn to write proper code using a functional programming language like Haskell.
>>26
Is it me, or does that look like GNU bc code? >>21
You can call me a fucking retard when you post a portable multithreaded FFT multiplication implementation that's one shot for a factorial program. I'm not a retard just because Scheme holds your little hand and hides the machine from you.
Name:
Anonymous2011-04-04 13:18
>>31
Shit, am I that bad? I've never seen GNU bc's code.
>>21
Scheme
I am the Schemer, that was the deluded pythonista troll. I'm aware I suck at C.
>>36
It does prime factorization, and basically is a faster version of
(define (factor x p)
(let loop ((x (quotient x p))
(r 0))
(if (< x 2) (+ x r)
(loop (quotient x p)
(+ x r)))))
I'm not exactly sure of how swing exactly works, and the rec-fact thing seems to be there to make it run in logarithmic time. The bit-count thing is a mystery too.
I'm still trying to understand it too.