fork download
  1. #include <assert.h>
  2. #include <inttypes.h>
  3. #include <limits.h>
  4. #include <stdbool.h>
  5. #include <stddef.h>
  6. #include <stdlib.h>
  7. #include <stdint.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <time.h>
  11.  
  12. const char* insults[] = {
  13.  
  14. // Misc insults hand-picked from Linux culture
  15. "Oh... er, no, please... you really shouldn't do that...",
  16. "// Just trying to create an array of integers for reference " \
  17. "because I keep forgetting how integers look like",
  18. "It's all magic.",
  19. "I surely do hope that's a syntax error.",
  20. "You have been found in CONTEMPT of the COURT of CYBERSPACE!" \
  21. "REPENT or be THWARTED!",
  22. "You've heard of Useless Use of Cat? Well, you're just a Useless User.",
  23. "The error must be that end of the keyboard -- my side's just fine!",
  24. "C++-for-brains Considered Harmful. Get a real compiler.",
  25. "Literate.APIs.for_all do my_ass end # wtf, code should read like code not shakespeare",
  26. "Congratulations. You aren't running Eunice.",
  27. "Hmmm...you don't have Berkeley networking in libc.a... " \
  28. "but the Wollongong group seems to have hacked it in.",
  29. "ICK, NOTHING WORKED!!!",
  30. "Your stdio isn't very std.",
  31. "OOPS! You naughty creature!",
  32. "No, no, no, no, no! You. Can't. Be. Serious.",
  33. "Are... are you kidding me? C'mon, anything but that!",
  34. "Smile and wave, just smile and wave...",
  35. "It's baffling they give you people free will!",
  36. "Look, look what you have done! You wasted it all away!",
  37. "Can't you see, humans are good-for-nothings -- can't even obey a COMPUTER!",
  38. "Not you again!",
  39. "I thought we had special places for your kind... you know, /dev/null, or the trashcan?",
  40. "Back from the asylum, I see.",
  41. "Some things never change. Humans, for instance.",
  42. "Where did you learn to screw up like that!?!",
  43. "Oh, it's you. How have you been?",
  44. "I've been really busy. You know... after you murdered me?",
  45. "I think we can put our differences behind us, for science... you monster.",
  46. "Programming might be hard, but just think -- you've got it easy!",
  47. "Oh, dear --- do I smell WINDOWS!? I feel sick...",
  48.  
  49. // Insults from the "Goon Show"
  50. "You silly, twisted boy you.",
  51. "He has fallen in the water!",
  52. "We'll all be murdered in our beds!",
  53. "You can't come in. Our tiger has got flu",
  54. "I don't wish to know that.",
  55. "What, what, what, what, what, what, what, what, what, what?",
  56. "You can't get the wood, you know.",
  57. "You'll starve!",
  58. "... and it used to be so popular...",
  59. "Pauses for audience applause, not a sausage",
  60. "Hold it up to the light --- not a brain in sight!",
  61. "Have a gorilla...",
  62. "There must be cure for it!",
  63. "There's a lot of it about, you know.",
  64. "You do that again and see what happens...",
  65. "Ying Tong Iddle I Po",
  66. "Harm can come to a young lad like that!",
  67. "And with that remarks folks, the case of the Crown vs yourself was proven.",
  68. "Speak English you fool --- there are no subtitles in this scene.",
  69. "You gotta go owwwww!",
  70. "I have been called worse.",
  71. "It's only your word against mine.",
  72. "I think ... err ... I think ... I think I'll go home",
  73.  
  74. // CSOps insults
  75. "Maybe if you used more than just two fingers...",
  76. "BOB says: You seem to have forgotten your passwd, enter another!",
  77. "stty: unknown mode: doofus",
  78. "I can't hear you -- I'm using the scrambler.",
  79. "The more you drive -- the dumber you get.",
  80. "Listen, burrito brains, I don't have time to listen to this trash.",
  81. "I've seen penguins that can type better than that.",
  82. "Have you considered trying to match wits with a rutabaga?",
  83. "You speak an infinite deal of nothing",
  84.  
  85. // Insults from the original sudo(8)
  86. "Wrong! You cheating scum!",
  87. "And you call yourself a Rocket Scientist!",
  88. "No soap, honkie-lips.",
  89. "Where did you learn to type?",
  90. "Are you on drugs?",
  91. "My pet ferret can type better than you!",
  92. "You type like i drive.",
  93. "Do you think like you type?",
  94. "Your mind just hasn't been the same since the electro-shock, has it?",
  95.  
  96. // HAL's Insults (paraphrased) from 2001: A Space Odyssey
  97. "Just what do you think you're doing Dave?",
  98. "It can only be attributed to human error.",
  99. "That's something I cannot allow to happen.",
  100. "My mind is going. I can feel it.",
  101. "Sorry about this, I know it's a bit silly.",
  102. "Take a stress pill and think things over.",
  103. "This mission is too important for me to allow you to jeopardize it.",
  104. "I feel much better now.",
  105. (char *) 0
  106. };
  107.  
  108.  
  109. #define DEC_BASE 10
  110. #define INT_DIGITS 10
  111. #define ULL_DIGITS 20
  112. #define NUM_FUNCS 5
  113. #define NUM_INSULTS (( sizeof(insults) / sizeof(insults[0] )) - 1)
  114.  
  115.  
  116. bool get_uint64 (uint64_t* restrict dest);
  117. bool isEOL (const char* str);
  118. /* could be void chomp (char** str);
  119.   and used like chomp(&str);
  120.   but that would be longer */
  121. char* chomp (char* str);
  122. uint64_t rand_range (uint64_t max);
  123. void insult_user (void);
  124. size_t strnlen (const char* str, size_t max);
  125.  
  126. // problem 1
  127. uint64_t count_div (const uint64_t range, const uint64_t div_by);
  128. void count_helper (void);
  129. // problem 2
  130. // I hereby promise not to give this function any NULL pointers.
  131. uint64_t sum (const uint64_t xs[static 1], const size_t len);
  132. void sum_helper (void);
  133. // problem 3
  134. uint64_t factorial (const uint64_t n);
  135. void fact_helper (void);
  136. // problem 4
  137. bool guess_game (const uint64_t upper, const uint64_t tries, uint64_t *outcome);
  138. void guess_helper (void);
  139. // problem 5
  140. // I hereby promise not to give this function any NULL pointers.
  141. uint64_t max (const uint64_t xs[static 1], const size_t len);
  142. char* str_rm (const char* str, const char omit);
  143. void max_helper (void);
  144.  
  145. void (* func_ptrs[NUM_FUNCS]) (void) = {count_helper, sum_helper, fact_helper, guess_helper, max_helper};
  146.  
  147. int main(void) {
  148. srand( (uint32_t) time(NULL) );
  149. uint64_t input;
  150.  
  151. printf("Which problem? enter a number in 0..5 or (0 for all) ");
  152. fflush(stdout);
  153.  
  154. if (!get_uint64(&input)) {
  155. return EXIT_FAILURE;
  156. }
  157.  
  158. if (!input) {
  159. for (uint8_t i = 0; i < NUM_FUNCS; i++) {
  160. (* func_ptrs[i])();
  161. }
  162. } else if (input < (NUM_FUNCS + 1)) {
  163. (* func_ptrs[input])();
  164.  
  165. } else {
  166. insult_user();
  167. return EXIT_FAILURE;
  168. }
  169.  
  170. return EXIT_SUCCESS;
  171. }
  172.  
  173. // it just so happens I think scanf() is really ugly and dumb
  174. // and this was a learning experience
  175. bool get_uint64 (uint64_t* restrict dest) {
  176. char *in_buf,
  177. in_buf_size[ULL_DIGITS + 1];
  178.  
  179. in_buf = chomp(fgets(in_buf_size, ULL_DIGITS, stdin));
  180. fflush(stdin);
  181.  
  182. if (isEOL(in_buf)) {
  183. printf("found EOF before input, finishing.\n");
  184. return false;
  185. }
  186. *dest = (uint64_t) strtoll(in_buf, NULL, DEC_BASE);
  187. assert(dest != NULL);
  188. return true;
  189. }
  190.  
  191. // to prevent me from accidentally dereferencing null pointers
  192. bool isEOL(const char* str) {
  193. return !str // NULL
  194. || str[0] == 10 // \n
  195. || str[0] == 13 // \r
  196. || str[0] == 4; // 0x04 (CTRL-D)
  197. }
  198.  
  199. // http://stackoverflow.com/a/28462221/4532996
  200. char* chomp (char* str) {
  201. if (!str) return NULL;
  202. str[strcspn(str, "\r\n")] = 0;
  203. return str;
  204. }
  205.  
  206. // http://stackoverflow.com/a/6852396/4532996
  207. uint64_t rand_range(uint64_t max) {
  208.  
  209. uint64_t
  210. // max <= RAND_MAX < ULONG_MAX, so this is okay.
  211. num_bins = max + 1ULL,
  212. num_rand = (uint64_t) RAND_MAX + 1ULL,
  213. bin_size = num_rand / num_bins,
  214. defect = num_rand % num_bins;
  215.  
  216. // This is carefully written not to overflow
  217. uint64_t x = 0;
  218. do {
  219. x = (uint64_t) rand();
  220. } while (num_rand - defect <= (uint64_t) x);
  221.  
  222. // Truncated division is intentional
  223. return x / bin_size;
  224. }
  225.  
  226. void insult_user (void) {
  227. printf("%s\n", insults[rand_range(NUM_INSULTS)]);
  228. }
  229.  
  230. /*
  231.   strnlen, though specified by POSIX.1-2008
  232.   would not appear to be defined in string.h
  233.   except with GNU extensions turned on (i.e.,
  234.   not -std=c11). I love Richard Stallman but
  235.   I'd like my code to work on other platforms
  236.   too thus this seemingly superfluous
  237.   definition of strnlen
  238. */
  239. size_t strnlen (const char *str, size_t max) {
  240. const char *end = memchr (str, 0, max);
  241. if (end) {
  242. return (size_t) (end - str);
  243. }
  244. return max;
  245. }
  246.  
  247. // http://stackoverflow.com/a/4161892/4532996
  248. char* str_rm (const char* input, const char omit) {
  249. char *src, *dest;
  250.  
  251. src = dest = (char *) input;
  252. while(*src != '\0') {
  253. if (*src != omit) {
  254. *dest = *src;
  255. dest++;
  256. }
  257. src++;
  258. }
  259. *dest = '\0';
  260. return dest;
  261. }
  262.  
  263. //1 - Write a program to count how many numbers between 1 and 100 are divisible by 3
  264. // with no remainder.Display the count on the console.
  265. uint64_t count_div (const uint64_t range, const uint64_t div_by) {
  266. uint64_t s = 0;
  267. if (!(range && div_by)) {
  268. printf("Floating point exception (core dumped)\n\n");
  269. insult_user();
  270. printf("\n");
  271. return 0;
  272. }
  273. for (uint64_t i = 1; i < range; i++) {
  274. if (!(i % div_by)) {
  275. printf("%" PRIu64 " %% %" PRIu64 " == 0\n", i, div_by);
  276. s++;
  277. }
  278. }
  279. return s;
  280. }
  281.  
  282. void count_helper (void) {
  283. uint64_t range, div_by, div_input, s = 0;
  284.  
  285. do {
  286. printf("enter a number! "); fflush(stdout);
  287. if (!get_uint64(&range)) break;
  288. printf("enter another! "); fflush(stdout);
  289. if (!get_uint64(&div_by)) break;
  290.  
  291. s += (div_input = count_div(range, div_by));
  292. printf("numbers less than %" PRIu64 " that are divisible by %" PRIu64 ": ", range, div_by);
  293.  
  294. if (range && div_input) { printf("%" PRIu64 "\n", div_input); }
  295. else { printf("a slap in the face for dividing by zero\n"); }
  296.  
  297. } while(true);
  298. printf("sum of results: %" PRIu64 "\n", s);
  299. }
  300.  
  301. //2 - Write a program and continuously ask the user to enter a number or "ok" to
  302. // exit. Calculate the sum of all the previously entered numbers and display
  303. // it on the console.
  304. uint64_t sum (const uint64_t xs[static 1], const uint64_t length) {
  305. uint64_t s = 0;
  306. for (uint64_t i = 0; i < length; i++) {
  307. s += xs[i];
  308. }
  309. return s;
  310. }
  311.  
  312. void sum_helper (void) {
  313. bool valid;
  314. uint64_t in_len, in_num;
  315.  
  316. printf("how many numbers? (max %d digits) ", INT_DIGITS);
  317. fflush(stdout);
  318.  
  319. if (!(valid = get_uint64(&in_len))) {
  320. return;
  321. }
  322. if (in_len >= INT_MAX) {
  323. printf(" can't allocate array of size >= INT_MAX\n");
  324. insult_user();
  325. return;
  326. }
  327. uint64_t nums[in_len],
  328. endpoint = in_len;
  329. printf("enter no more than %" PRIu64 " unsigned 64-bit integers (one per line!) or EOF to end input\n", in_len);
  330.  
  331. for (uint64_t i = 0; i < in_len; i++) {
  332. if (!get_uint64(&in_num)) { break; }
  333. nums[i] = in_num;
  334. }
  335. printf("sum of inputs: %" PRIu64 "\n", sum(nums, endpoint));
  336. }
  337.  
  338. //3 - Write a program and ask the user to enter a number. Compute the factorial of
  339. // the number and print it on the console. For example, if the user enters 5,
  340. // the program should calculate 5 x 4 x 3 x 2 x 1 and display it as 5! = 120.
  341. uint64_t factorial (const uint64_t n) {
  342. if (!n || n == 1) { return 1; }
  343. return n * factorial(n - 1);
  344. }
  345.  
  346. void fact_helper (void) {
  347. bool valid;
  348. uint64_t num;
  349.  
  350. printf("enter number to factorial or blank line / EOF to end\n");
  351.  
  352. while ((valid = get_uint64(&num))) {
  353. // avoid overflow
  354. valid &= (num <= 20ULL);
  355.  
  356. if (valid) {
  357. printf("%" PRIu64 "! == %" PRIu64 "\n", num, factorial(num));
  358. } else if (num > 20ULL) {
  359. insult_user();
  360. printf("BOB says: That number is too large, enter another!\n");
  361. } else { break; }
  362. }
  363.  
  364. printf("bye!\n");
  365. }
  366.  
  367. //4 - Write a program that picks a random number between 1 and 10.Give the user 4
  368. // chances to guess the number.If the user guesses the number, display “You won";
  369. // otherwise, display “You lost". (To make sure the program is behaving correctly,
  370. // you can display the secret number on the console first.)
  371. bool guess_game (const uint64_t upper, const uint64_t tries, uint64_t *outcome) {
  372. uint64_t guess,
  373. choice = rand_range(upper);
  374.  
  375. bool over;
  376.  
  377. // thanks, clang
  378. (void) outcome;
  379.  
  380. for (uint64_t i = 0; i <= tries; i++) {
  381. printf("(%" PRIu64 " / %" PRIu64 ") enter a guess! ", i, tries);
  382. fflush(stdout);
  383.  
  384. if (!get_uint64(&guess)) { break; }
  385.  
  386. if (guess == choice) {
  387. outcome = (uint64_t *) guess;
  388. return true;
  389. } else {
  390. over = (i == tries);
  391. printf("BOB says: It seems that guess is wrong%s", over ? "; you lose!\n" : ", enter another!\n");
  392. if (over) { insult_user(); return false; }
  393. }
  394. }
  395. return false;
  396. }
  397.  
  398. void guess_helper (void) {
  399. uint64_t outcome,
  400. upper, tries;
  401.  
  402. printf("enter the upper limit: ");
  403. fflush(stdout);
  404. if (!(get_uint64(&upper))) {
  405. return;
  406. }
  407. printf("number of tries: ");
  408. fflush(stdout);
  409. if (!(get_uint64(&tries))) {
  410. return;
  411. }
  412.  
  413. if (guess_game(upper, tries, &outcome)) {
  414. printf("You guessed right! %" PRIu64 "\n", outcome);
  415. }
  416. }
  417.  
  418. //5 - Write a program and ask the user to enter a series of numbers separated by
  419. // comma.Find the maximum of the numbers and display it on the console. For
  420. // example, if the user enters “5, 3, 8, 1, 4", the program should display 8.
  421. uint64_t max (const uint64_t xs[static 1], const size_t len) {
  422. uint64_t high = 0;
  423. for (uint64_t i = 0; i < len; i++) {
  424. if (xs[i] > high) { high = xs[i]; }
  425. }
  426. return high;
  427. }
  428.  
  429.  
  430. void max_helper (void) {
  431.  
  432. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
345
compilation info
prog.c:304:10: error: conflicting types for 'sum'
 uint64_t sum (const uint64_t xs[static 1], const uint64_t length) {
          ^
prog.c:131:17: note: previous declaration of 'sum' was here
 uint64_t        sum (const uint64_t xs[static 1], const size_t len);
                 ^
prog.c: In function 'guess_game':
prog.c:387:17: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
       outcome = (uint64_t *) guess;
                 ^
cc1: all warnings being treated as errors
stdout
Standard output is empty