main.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <ctype.h>
  4. #include <math.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <limits.h>
  8. // From https://stackoverflow.com/a/3437484
  9. #define max(a,b) \
  10. ({ __typeof__ (a) _a = (a); \
  11. __typeof__ (b) _b = (b); \
  12. _a > _b ? _a : _b; })
  13. #define min(a,b) \
  14. ({ __typeof__ (a) _a = (a); \
  15. __typeof__ (b) _b = (b); \
  16. _a < _b ? _a : _b; })
  17. typedef enum invocation_type {
  18. NTIMES,
  19. NHOURS,
  20. INVALID
  21. } invocation_type;
  22. long calculate_lambda(long s) {
  23. long lambda = 0;
  24. if(s <= 0) {
  25. lambda = floor(abs((double)s/2.0)) + 1;
  26. }
  27. return lambda;
  28. }
  29. void train_n_times(long int s, long int n) {
  30. long lambda = calculate_lambda(s);
  31. printf("%ld\n", n + (n > lambda)*(n-lambda)*(n + s + lambda - 2));
  32. }
  33. long calculate_train_n_hours(long int s, long int h) {
  34. long n = -1;
  35. if(s < 1) {
  36. long lambda = calculate_lambda(s);
  37. long h_minus = min(h, lambda);
  38. long h_plus = max(0, h - lambda);
  39. long n_minus = h_minus;
  40. long s_plus = s + 2*n_minus;
  41. long n_plus = 0;
  42. if(h_plus > 0) {
  43. n_plus = calculate_train_n_hours(s_plus, h_plus);
  44. }
  45. n = n_minus + n_plus;
  46. } else if(s == 1) {
  47. n = floor(sqrt((long double)h/s));
  48. } else { // s > 1
  49. n = floor((-1.0 + sqrt(1 + 4.0*h/(powl(s-1.0, 2.0))))*(s-1.0)/2.0);
  50. }
  51. return n;
  52. }
  53. void train_n_hours(long int s, long int h) {
  54. long n = calculate_train_n_hours(s, h);
  55. printf("%ld\n", n);
  56. }
  57. int main(int argc, char** argv) {
  58. if(argc != 4) {
  59. fprintf(stderr, "Usage: rqt <current skill percentage> <number> <times|hours>\n");
  60. exit(1);
  61. }
  62. char* arg_iter;
  63. int minus_found = 0;
  64. if(*argv[1] == '-') {
  65. minus_found = 1;
  66. }
  67. for(arg_iter = argv[1] + minus_found; *arg_iter != '\0'; ++arg_iter) {
  68. if(!isdigit(*arg_iter)) {
  69. fprintf(stderr, "Current skill percentage must be an integer.\n");
  70. exit(1);
  71. }
  72. }
  73. long s = strtol(argv[1], NULL, 10);
  74. if((errno == ERANGE && (s == LONG_MAX || s == LONG_MIN))
  75. || (errno != 0 && s == 0)) {
  76. printf("Error %d (%s) converting string '%s' to number.\n", errno, strerror(errno), argv[1]);
  77. return 1;
  78. }
  79. for(arg_iter = argv[2]; *arg_iter != '\0'; ++arg_iter) {
  80. if(!isdigit(*arg_iter)) {
  81. fprintf(stderr, "The second argument must be a non-negative integer, either number of times to train, or number of hours.\n");
  82. exit(1);
  83. }
  84. }
  85. long n = strtol(argv[2], NULL, 10);
  86. if((errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))
  87. || (errno != 0 && n == 0)) {
  88. printf("Error %d (%s) converting string '%s' to number.\n", errno, strerror(errno), argv[2]);
  89. return 1;
  90. }
  91. invocation_type t = INVALID;
  92. if(strncmp(argv[3], "times", 8) == 0) {
  93. t = NTIMES;
  94. } else if(strncmp(argv[3], "hours", 8) == 0) {
  95. t = NHOURS;
  96. }
  97. if(t == INVALID) {
  98. }
  99. switch(t) {
  100. case NTIMES:
  101. {
  102. train_n_times(s, n);
  103. }
  104. break;
  105. case NHOURS:
  106. {
  107. train_n_hours(s, n);
  108. }
  109. break;
  110. case INVALID:
  111. {
  112. fprintf(stderr, "The third argument needs to be either 'times' or 'hours'.\n");
  113. exit(1);
  114. }
  115. break;
  116. }
  117. return 0;
  118. }