#include <stdio.h> /* version from 2016-05-22 23:23 UTC+2 */
#define  NL  "\n"
#define  alphabet  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFG"

#ifdef  FILE_TABLE
#define  LOOKUP_TABLE  "lookup_table_4"
#else
#define  N  189
static int init_lookup_table(unsigned char table[][4])
{  // assuming datatype short has (at least) 16 bits
unsigned  i, j;
static short  tmp[N] = {
         0x0000,0x0001,0x0011,0x0100,0x1011,0x1000,0x0101,0x1010,0x1101,0x0111,
         0x1111,0x0010,0x1100,0x0110,0x1001,0x1110,0x1211,0x0211,0x0112,0x1021,
         0x1112,0x1022,0x1012,0x0212,0x1121,0x1002,0x1212,0x1221,0x1122,0x2111,
         0x2112,0x2122,0x2011,0x0012,0x0022,0x0121,0x1222,0x0122,0x0021,0x2121,
         0x2110,0x2101,0x2221,0x2222,0x0222,0x2021,0x2012,0x2211,0x2022,0x2000,
         0x0002,0x0221,0x2010,0x2212,0x2001,0x2100,0x1102,0x0102,0x2322,0x2123,
         0x1322,0x1223,0x0123,0x1123,0x2223,0x2232,0x2132,0x1132,0x2233,0x0223,
         0x1133,0x3122,0x2133,0x1232,0x2102,0x3222,0x2323,0x1233,0x3223,0x3211,
         0x2113,0x3121,0x3232,0x3132,0x3233,0x0322,0x1323,0x1213,0x2332,0x3221,
         0x3133,0x3111,0x3212,0x3112,0x3123,0x1023,0x1113,0x2213,0x1332,0x0132,
         0x2333,0x1333,0x2023,0x0232,0x3322,0x1013,0x1032,0x0133,0x2032,0x3323,
         0x0233,0x0213,0x0323,0x0332,0x2033,0x0113,0x3332,0x1033,0x3333,0x0333,
         0x2002,0x3213,0x0023,0x2013,0x3110,0x0032,0x2433,0x3433,0x2234,0x3234,
         0x2334,0x3334,0x1433,0x1003,0x1234,0x2243,0x2324,0x2134,0x3243,0x2224,
         0x2343,0x3324,0x3224,0x2434,0x3343,0x1103,0x3434,0x3134,0x1243,0x1224,
         0x3113,0x2124,0x1334,0x2443,0x1434,0x4233,0x1134,0x3143,0x3344,0x2244,
         0x3244,0x3443,0x2344,0x4234,0x4333,0x2103,0x0033,0x2143,0x3124,0x1244,
         0x1343,0x3444,0x1344,0x4433,0x2444,0x1324,0x4222,0x4334,0x4232,0x4243,
         0x1443,0x3144,0x4244,0x4322,0x4343,0x4434,0x4223,0x4323,0x4344
};
for (i=0;i<N;i++)
   for (j=0;j<4;j++,tmp[i]>>=4)
      table[i][j]= tmp[i]&15;
return  N;
}
#undef  N
#endif

static unsigned char  table[256][4];

int main(unsigned argc, char *argv[])
{  int   c;
   unsigned   h, i, j, j0, lb, m, n, len, bits, sz;
   unsigned long   k, no, next, total;
   FILE  *fp, *gp;
   if (argc <= 1)
      return  fprintf(stderr,"usage: %s datafile [first n [total number [linelength] ] ]\n",argv[0]), 1;
#ifdef  FILE_TABLE
   if (!(fp = fopen (LOOKUP_TABLE,"r")))
      return  fprintf(stderr,"can't open %s\n",LOOKUP_TABLE), 3;
   n= fread(table, 4, 256, fp);
   fclose(fp);
#else
   n=init_lookup_table(table);
#endif
   for (sz=0;alphabet[sz];sz++);
   if (!(fp = fopen (argv[1],"r")))
      return  fprintf(stderr,"can't open %s\n",argv[1]), 3;
   len=0;
   no= 1;
   total=0;
   if (argc >= 3  &&  1!=sscanf(argv[2],"%lu",&no) || !no)
      return  fprintf(stderr,"illegal first n: %s\n",argv[2]), 3;
   if (argc >= 4  &&  1!=sscanf(argv[3],"%lu",&total))
      return  fprintf(stderr,"illegal total: %s\n",argv[3]), 3;
   if (argc >= 5  &&  1!=sscanf(argv[4],"%u",&len))
      return  fprintf(stderr,"illegal linelength: %s\n",argv[4]), 3;
   if (fseek(fp, (long)((no-1)/4), SEEK_SET))
      return  fprintf(stderr,"insufficient data in %s\n",argv[1]), 3;
   gp = stdout;
   j0= (no-1)&3;
   bits= 0;
   lb= -1;
   for (k=no-1;k;k>>=1,lb++)
      bits += k&1;
   next= no+len;
   while ( EOF != (c=getc(fp)) )
   {  if (c >= n) 
         return  fprintf(stderr,"index=%u is too big for lookup-table\n",c), 3;
      for (j=j0;j<4;j++)
      {  for (k=no;!(k&1);k>>=1)
            bits--;
         for (h=0,i=bits;i;h++)
            i >>= 1;
         if (!bits++)
            lb++;
         m = lb+h + table[c][no-1&4-1];
#ifdef  DECIMAL
         fprintf(gp,"%3u", m);
#else
#ifdef  DELTA
         putc('0'+m-lb-h , gp);
#else
         if (m >= sz) 
            return  fprintf(stderr,"alphabet too small. At least %u characters needed\n",m), 3;
         putc(alphabet[m] , gp);
#endif
#endif
         no++;
         if (no == next)
         {  fputs(NL, gp);
            next += len;
         }
         if (!--total)
            goto over;
      }
      j0=0;
   }
   over:
   fclose(fp);
   return  0;
}
