

Reddit clone in 60 minutes and 4 lines of C - codexon
http://benreeves.co.uk/reddit-com-clone-in-4-lines-of-c/

======
wmf
OK, can we officially end the "_ in _ minutes and _ lines" meme now? While
we're at it, let's close out the "check out my startup created in _ hours and
$_".

~~~
jackowayed
Well, I think/hope that he was sort of making fun of the "in n lines of code"
part by putting all his code, besides the imports, on 1 line. But yeah, I
agree.

~~~
wmf
Exactly. You can tell a meme is exhausted when it becomes a parody of itself.

------
KirinDave
It's kind of a bummer that people feel that these endeavors are worth satire.
While the titles may be a bit pithy and perhaps misleading, these X in Y lines
tend to be really interesting reading, and let you glimpse into someone else's
domain expertise.

It's too bad they didn't just say 210 lines of C and still show it. I would
have still checked it out, and been interested.

~~~
notaddicted
reproduced without permission: <http://pastebin.com/m6a6fda19>

------
aaronbrethorst
Reddit in just a few minutes without writing any code:
<http://code.reddit.com/>

duh.

~~~
malkia
Next would be a bit.ly link :)

Liked the joke :), what in all these "n lines" codes is missing is lot of
things like - filtering (bad words), scaling, backup, etc.

~~~
Estragon
What they're _really_ missing is the community/customers. When you can clone
that in 10 minutes, you've really got something.

------
gnosis
We've had a reddit clone in 100 lines of lisp, 91 lines of clojure, and 4
lines of C.

All we need now is for someone to do it in 1 line of Perl.

~~~
biotech
Well, if you can do it in C, and I can see your solution, and it works, then I
can do it in a line of perl. But I didn't test his code, so I don't know if
this works:

    
    
        open( FILE, ">reddit.c"); print FILE '#include <stdio.h>'; print FILE "\n"; print FILE '#include <time.h>'; print FILE "\n"; print FILE '#include <netinet/in.h>';print FILE "\n";print FILE 'typedef struct { int ID; char * title; char * link; char * date; int upVotes; int downVotes; void * next; } Article; Article * root; char * getVal(char * query, char * key) { char * str = malloc(1); int match = 0; int pMatch = 0; char * cur = query; while (*cur != \'\0\') { if (pMatch >= 1 && (*cur == \'&\' || *cur == \'\n\' || *cur == \' \')) { break; } else if (pMatch >= 1) { str = realloc(str, pMatch+1); *(str+pMatch-1) = *cur; ++pMatch; } else if (match == strlen(key)) { pMatch = 1; } else if (*cur == key[match]) { ++match; } else { match = 0; } cur++; } if (pMatch >= 1) { str[pMatch-1] = \'\0\'; return str; } free(str); return NULL; } char from_hex(char ch) { return isdigit(ch) ? ch - \'0\' : tolower(ch) - \'a\' + 10; } char to_hex(char code) { static char hex[] = "0123456789abcdef"; return hex[code & 15]; } char *url_decode(char *str) { char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf; while (*pstr) { if (*pstr == \'%\') { if (pstr[1] && pstr[2]) { *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); pstr += 2; } } else if (*pstr == \'+\') { *pbuf++ = \' \'; } else { *pbuf++ = *pstr; } pstr++; } *pbuf = \'\0\'; return buf; } void send_headers(FILE *f, int status, char *title, char *extra, char *mime, int length) { char timebuf[128]; fprintf(f, "%s %d %s\r\n", "HTTP/1.0", status, title); fprintf(f, "Server: %s\r\n", "redditserver/1.0"); if (extra) fprintf(f, "%s\r\n", extra); if (mime) fprintf(f, "Content-Type: %s\r\n", mime); if (length >= 0) fprintf(f, "Content-Length: %d\r\n", length); fprintf(f, "Connection: close\r\n"); fprintf(f, "\r\n"); } void reddit(FILE *f) { fprintf(f, "<HTML><HEAD><TITLE>Reddit Clone</TITLE></HEAD>\r\n"); fprintf(f, "<BODY><H1>Submit</H1><form action=\"/\" method=\"get\">Title:<input type=\"text\" name=\"title\" /> Link:<input type=\"text\" name=\"link\" /><input type=\"submit\" value=\"Submit\" /></form>\r\n"); if (root) { fprintf(f, "<h1>Articles</h1>"); Article * cur = root; while (cur != NULL) { fprintf(f, "<p><font size=\"5\">%d<b><a href=\"/?up=%d\">&uarr</b></font><a href=\"%s\">%s</a><br /><font size=\"5\">&nbsp;&nbsp;<b><a href=\"/?down=%d\">&darr</a></b></font>%s -- %s</p>", cur->upVotes - cur->downVotes, cur->ID, cur->link, cur->title, cur->ID, cur->link, cur->date); cur = cur->next; } }fprintf(f, "</BODY></HTML>\r\n"); } int fsize(FILE * f) { fseek(f, 0, SEEK_END); int size = ftell(f); fseek(f, 0, SEEK_SET); return size; } int main(int argc, char *argv[]) { int sock; int port = 1337; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_STREAM, 0); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(port); while (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { printf("Failed bind\n"); sleep(2); } listen(sock, 5); printf("HTTP server listening on port %d\n", port); root = NULL; while (1) { int s; int size; int hsize; char * buff; FILE * t; FILE * ht; FILE * f; s = accept(sock, NULL, NULL); if (s < 0) break; char * header = calloc(255, 1); size = read(s, header, 255); char * titleEnc = getVal(header, "title"); char * linkEnc = getVal(header, "link"); if (titleEnc && linkEnc) { char * title = url_decode(titleEnc); char * link =  url_decode(linkEnc); free(linkEnc); free(titleEnc); printf("Title: %s -- Link: %s\n", title, link); char  * s = malloc(30); size_t i; struct tm tim; time_t now; now = time(NULL); tim = *(localtime(&now)); i = strftime(s,30,"%b %d, %Y; %H:%M:%S\n",&tim); Article * new = malloc(sizeof(Article)); new->title = title; new->link = link; new->next = NULL; new->date = s; new->upVotes = 0; new->downVotes = 0; if (!root) { root = new; new->ID = 0; } else { int dupe = 0; Article * cur = root; Article * prev = NULL; while (cur != NULL) { if (strcmp(cur->title, new->title) == 0 || strcmp(cur->link, new->link) == 0) { dupe = 1; } prev = cur; cur = cur->next; } if (dupe == 0) { new->ID = prev->ID + 1; prev->next = new; } else free(new); } } char * upID = getVal(header, "up"); if (upID) { int ID = atoi(upID); Article * cur = root; while (cur != NULL) { if (cur->ID == ID) { cur->upVotes++; break; } cur = cur->next; } } char * dID = getVal(header, "down"); if (dID) { int ID = atoi(dID); Article * cur = root;  while (cur != NULL) { if (cur->ID == ID) { cur->downVotes++; break; } cur = cur->next; } } t = tmpfile(); ht = tmpfile(); reddit(t); size = fsize(t); send_headers(ht, 200, "Ok", NULL, "text/html", size); hsize = fsize(ht); buff = malloc(hsize); fread(buff, 1, hsize, ht); write(s,buff,hsize); free(buff); buff = malloc(size); fread(buff, 1, size, t); write(s,buff,size); free(buff); fclose(t); } }';print FILE "\n";`gcc ./reddit.c -o reddit && chmod a+x reddit && ./reddit`;

------
dimitar
This is really 200 lines but still pretty cool.

------
alrex021
To add to the fun, I present to you the BASH version in 1 line and 14 seconds:

    
    
      $ time git clone http://code.reddit.com/repo/reddit.git
    

Initialized empty Git repository in reddit/.git/

real 0m14.316s

user 0m0.496s

sys 0m0.411s

------
jfoutz
I don't think clone means what you think it means.

new user creation is broken. new subreddit creation is broken. comments are
broken. popular/new/controversial/saved is missing.

search is good though. _rimshot_

------
malkia
$ astyle reddit.c $ wc -l reddit.c 211

------
lurkinggrue
Exactly like Reddit except for the user accounts, markup editor or any other
major feature.

Cute though.

------
mnemonicsloth
Lisp's unreadable code compression features are _obviously superior_ , and
have been since the fifties.

We lispers can express any program in a single line. Some prefer that style
because it brings out all the parentheses.

All of this is possible because code is data.

~~~
dimitar
Or because you don't need #include statements separated with newlines in Lisp.

------
Sukotto
Removing all the linefeeds is cheating. Show me one written with only 4
semicolons.

~~~
pyre
I think that point was to parody all these "X programmed in Y lines of code,
but without all the 'hard' stuff like load-balancing, replication, optimized
SQL queries that allow it to scale, etc; that's all too 'hard' so I'll do just
the easy stuff and then claim that my final product is exactly the same as X"

------
derefr
I understand that this is satire, but I'd like to see the same one-upmanship
going on with _tokens_ instead of lines.

------
petercooper
Segfaulted on OS X, but looks genuine. Clever bit of work there.

~~~
telemachos
I'm not sure why I don't just quit while I'm behind, but what version of OSX
and gcc did you build it with? I can't get it even to compile (10.5.8, gcc
version 4.0.1).

~~~
petercooper
Stock 10.6.2 with stock dev tools.. showing GCC 4.2.1.

------
JeremyBanks
Is this satire? If not: You know, not that it would mean much anyway but it
_really_ doesn't count if you just delete all of the line breaks 'cause you're
using a language that doesn't require them.

~~~
pmjordan
_Is this satire?_

I think that's pretty much a given.

------
stonemetal
4 lines of C in 60 min? He must need to learn how to type.

~~~
slpsys
Alternately, you must need to learn how to RTFA.

~~~
stonemetal
Not really, it was more a poor attempt at humor.

------
pavs
The new meme/trend.

"X clone in x minutes and x lines of x."

Bravo on your new "startup".

