Post B6t0lnJWgcs2okQFtY by ns@sacred.harpy.faith
(DIR) More posts by ns@sacred.harpy.faith
(DIR) Post #B6t0lnJWgcs2okQFtY by ns@sacred.harpy.faith
0 likes, 0 repeats
#include <u.h>#include <libc.h>#include <bio.h>char *choice[65536];voidmain (int argc, char *argv[]){int i, k, n, m;char *p, *file;Biobuf *f; k = 1; file = "/fd/0"; ARGBEGIN{ case 'k': k = atoi (EARGF (sysfatal ("Misfortune!"))); if (k <= 0) sysfatal ("reservoir size cannot < 1, you stupid fucking nigger"); break; default: print ("lol, lmao\n"); goto End; }ARGEND; if (argc > 0) file = argv[0]; if ((f = Bopen (file, OREAD)) == nil) sysfatal ("can't open %s: %r", file); srand (truerand ()); n = 0; while ((p = Brdline (f, '\n')) != nil) { p[Blinelen (f)-1] = 0; if (n < k) choice[n] = strdup (p); else { i = nrand (n + 1); if (i < k) { free ((void*)choice[i]); choice[i] = strdup (p); } } n ++; } if (n == 0) sysfatal ("no fortunes found"); m = n < k ? n : k; for (i = 0; i < m; i ++) print ("%s\n", choice[i]); End: exits (0);}
(DIR) Post #B6t0lnWzsXe7UWj0tM by Zergling_man@sacred.harpy.faith
0 likes, 0 repeats
@ns I'm reasonably certain that you don't need to allocate 64kb worth of char pointers.
(DIR) Post #B6t2XNaRk5HUseahVo by Zergling_man@sacred.harpy.faith
0 likes, 0 repeats
@HatkeshiatorTND @ns If you dump them as you find them, you don't need to store them in memory. You could store an array of ints to tell you which lines have been chosen, so that when you hit the end and haven't selected enough you can just go back round for another pass, but that seems annoying too.I guess the simplest way is like... Count the lines in the file, work out whether it's smaller to store the requested lines or non-requested lines, fill it up with (sorted) random numbers, then step through the file and print whatever is(n't) in that list. Does at most two passes over the file, max memory usage sizeof(int)*file_lines/2.Until the file has more lines than you can fit in an int, ugh.The other way is to just shuffle the whole fucking file into a temp file (insert at random position as you go through) then print the first k lines.