Advertisement
Guest User

challenge-245-hard.c

a guest
Dec 18th, 2015
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.46 KB | None | 0 0
  1.    
  2.     /*
  3.         [2015-12-18] Challenge #245 [Hard] Guess Who(is)? https://redd.it/3xdmtw
  4.  
  5.         XXX --> STILL HAS BUGS
  6.    
  7.         lookup ip ranges, hopefully quickly. queries go to tightest fit or unknown.
  8.         i didn't try to optimize really so this might be slow.
  9.  
  10.         my counts aren't comming up right on the provided test case
  11.         i get 6 (instead of 8) for max and 0 (instead of 1) <unknown>
  12.         post it anyways...
  13.     */
  14.    
  15.     #include <stdio.h>  // fopen(), fclose(), fgetc(), ungetc(), scanf(), printf()
  16.     #include <stdlib.h> // qsort(), exit()
  17.     #include <stdint.h> // uint32_t, uint64_t
  18.     #include <string.h> // strcmp()
  19.     #include <ctype.h>  // isdigit()
  20.    
  21.     #define DEBUG 1
  22.    
  23.     typedef struct { uint32_t start; uint32_t end; int cnt; char *name; } rec_t;
  24.    
  25.     rec_t unknown = { 0, 0, 0, "<unknown>\n" };
  26.    
  27.     char STRBUFFER[50000000];
  28.     char *str_buff = STRBUFFER;
  29.    
  30.     rec_t records[50000000];
  31.     int N = 0;
  32.    
  33.     uint32_t ADDR;
  34.    
  35.     int read_addr(FILE *f) {
  36.         int sf, d, ch, ok;
  37.    
  38.         /* rewrite, the old read_addr() turned out to be buggy */
  39.    
  40.         sf = fscanf(f, "%d", &d); ch = fgetc(f); if(sf != 1 || d < 0 || 255 < d || ch != '.') return 0;
  41.         ADDR = d; ADDR <<= 8;
  42.         sf = fscanf(f, "%d", &d); ch = fgetc(f); if(sf != 1 || d < 0 || 255 < d || ch != '.') return 0;
  43.         ADDR |= d; ADDR <<= 8;
  44.         sf = fscanf(f, "%d", &d); ch = fgetc(f); if(sf != 1 || d < 0 || 255 < d || ch != '.') return 0;
  45.         ADDR |= d; ADDR <<= 8;
  46.         sf = fscanf(f, "%d", &d); ch = fgetc(f); if(sf != 1 || d < 0 || 255 < d || ch != ' ') return 0;
  47.         ADDR |= d;
  48.    
  49.         return 1;
  50.     }
  51.    
  52.     int read_record(FILE *f) {
  53.         rec_t tmp;
  54.         int len, ok;
  55.    
  56.         ok = read_addr(f); if(!ok) return 0; tmp.start = ADDR;
  57.         ok = read_addr(f); if(!ok) return 0; tmp.end = ADDR;
  58.    
  59.         tmp.name = str_buff;
  60.    
  61.         fgets(str_buff, 123, f);
  62.         while(*str_buff && *str_buff != '\n') str_buff++; *str_buff = '\0'; str_buff++;
  63.         records[N++] = tmp;
  64.         return 1;
  65.     }
  66.    
  67.     typedef int (*cmp_t)(const void*, const void*);
  68.    
  69.     int cmp_rec(void *A, void *B) {
  70.         rec_t *AA = A, *BB = B;
  71.         uint64_t arange, brange;
  72.    
  73.         arange = AA->start; arange <<= 32; arange += AA->end;
  74.         brange = BB->start; brange <<= 32; brange += BB->end;
  75.    
  76.         if(arange < brange) return -1;
  77.         if(arange > brange) return  1;
  78.         return 0;
  79.     }
  80.    
  81.     int cmp_cnt(void *A, void *B) {
  82.         rec_t *AA = A, *BB = B;
  83.    
  84.         if(AA->cnt < BB->cnt) return -1;
  85.         if(AA->cnt > BB->cnt) return  1;
  86.         return strcmp(AA->name, BB->name);
  87.     }
  88.    
  89.    
  90.     int search(uint32_t ip) {
  91.         int lo, hi, mid, i, n, ret;
  92.         uint32_t range, tight;
  93.    
  94.         if(ip < records[0].start || records[N-1].end < ip) return -1;
  95.         if(records[0].start <= ip && ip <= records[0].end) return 0;
  96.    
  97.         // find a record PRECEDING our range, followed by linear scan after in the ballpark
  98.    
  99.         lo = 0; hi = N-1;
  100.         while(lo < hi) {
  101.             mid = (lo + hi) / 2;
  102.             if(records[mid].start < ip) lo = mid;
  103.             if(records[mid].start >=ip) hi = mid;
  104.         }
  105.    
  106.         n = lo;
  107.         if(n >= N-1) return -1;
  108.         if(records[n+1].start > ip) return -1;
  109.         if(records[n+1].end < ip) return -1;
  110.         n++;
  111.    
  112.         tight = 0xffffffff;
  113.         for(i = n; i < N; i++) {
  114.             if(ip < records[i].start || records[i].end < ip) break;
  115.             range = records[i].end - records[i].start;
  116.             if(range < tight) { ret = i; tight = range; }
  117.         }
  118.    
  119.         return ret;
  120.     }
  121.    
  122.     typedef struct { int cnt; char *name; } report_t;
  123.    
  124.     report_t reports[100000];
  125.     int R = 0;
  126.    
  127.     int cmp_report(report_t *A, report_t *B) {
  128.         int x = ( B->cnt - A->cnt );
  129.         if(x == 0) return strcmp(A->name, B->name);
  130.         else return x;
  131.     }
  132.    
  133.     int main(int argc, char *argv[]) {
  134.         int i, n, ok, done;
  135.         FILE *f;
  136.    
  137.         char *prev = "<jrjfjfkkfk-nonsense-unique-identifier-NULL-jdjjfjmfjjfjfmjfmmf>";
  138.         int tally = 0;
  139.    
  140.         if(argc-1 != 2) {
  141.             printf("usage: ./challenge-245 <range-file> <query-file>\n\n");
  142.             exit(1);
  143.         }
  144.    
  145.         f = fopen(argv[1], "r");
  146.         do { ok = read_record(f); } while(ok);
  147.         fclose(f);
  148.    
  149.         qsort(records, N, sizeof(rec_t), (cmp_t)cmp_rec);
  150.    
  151.         f = fopen(argv[2], "r");
  152.         while(1) {
  153.             done = !read_addr(f); if(done) break;
  154.             n = search(ADDR);
  155.    
  156.             if(n < 0) unknown.cnt++;
  157.             else records[n].cnt++;
  158.         }
  159.         fclose(f);
  160.    
  161.         qsort(records, N, sizeof(rec_t), (cmp_t)cmp_cnt);
  162.    
  163.         for(i = 0; 0 < records[i].cnt; i++) {
  164.             if(strcmp(prev, records[i].name) != 0) {
  165.                 if(0 < tally) { reports[R].cnt = tally; reports[R++].name = prev; }
  166.    
  167.                 tally = records[i].cnt;
  168.                 prev = records[i].name;
  169.             }
  170.             else tally += records[i].cnt;
  171.         }
  172.    
  173.         qsort(reports, R, sizeof(report_t), (cmp_t)cmp_report);
  174.    
  175.         for(i = 0; 0 < reports[i].cnt; i++) { printf("%d - %s\n", reports[i].cnt, reports[i].name); }
  176.         printf("%d - %s\n", unknown.cnt, unknown.name);
  177.         return 0;
  178.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement