{"id":1687,"date":"2021-06-22T20:29:55","date_gmt":"2021-06-22T18:29:55","guid":{"rendered":"https:\/\/moijari.com\/?p=1687"},"modified":"2021-06-23T00:40:18","modified_gmt":"2021-06-22T22:40:18","slug":"ressu-2-1-lotto-numbers-and-others","status":"publish","type":"post","link":"https:\/\/moijari.com\/?p=1687","title":{"rendered":"Ressu 2.1 Lottonumerot ja muuta"},"content":{"rendered":"\n<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n. Edellisess\u00e4 Ressu 2.0 postissa esiteltyyn toiminnallisuuteen on tehty seuraavia muutoksia: asiallinen lottonumeroiden tulostus, tuotantoversio ressusta (ilman debukkailuja), debukkailuversio ressusta erikseen, digits merkkijonon perusteella teht\u00e4v\u00e4n tulosteen nopeutus, virheiden korjauksia, ja yleist\u00e4 luettavuuden parantamista. Koko ohjelma on kopypastattavissa postin lopussa.<\/p>\n\n\n\n<p>K\u00e4yn seuraavassa l\u00e4pi valitut osat uudesta ohjelmasta. Ensin ns tuotantoversio ressusta. Tuotantoversiossa on viel\u00e4 &#8211;stat komentoriviparametrill\u00e4 toimiva debug rivi, mutta l\u00e4hemm\u00e4ksi kuljetaan: Toisaalta tuotantoversiossa ei en\u00e4\u00e4 ole noita aloituspaikan varmistamisen debug while luuppeja, eik\u00e4 se luo en\u00e4\u00e4 tiedostoa. &#8211;debug versiosta luupit ja tiedostot viel\u00e4 l\u00f6ytyv\u00e4t.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unsigned long periods&#91;1024];\nunsigned long genbytes=0;\nunsigned long clockbytes=0;\n\n#define RESSUT_BYTES 4096\n#define RESSU_BITS_NEEDED 128\n#define RESSU_MIN_ROUNDS 2\n#define RESSU_MIN_CLOCKBYTES 16384+1024\n\nint ressu_bits_needed=RESSU_BITS_NEEDED;\nint ressut_bytes = RESSUT_BYTES;\n\nint stats=0;\n\nunsigned char ressu_clockbyte() \/* JariK 2013 *\/\n{\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  return(tv.tv_usec &amp; 0xff);\n}<\/code><\/pre>\n\n\n\n<p>Edellinen ensimm\u00e4inen rutiini ressu_clockbyte() palauttaa kellon millisekuntien alimmat bitit kutsujalle (seuraava rutiini).<\/p>\n\n\n\n<p>Seuraavaksi ressun ydin, eli yhden ressu kierroksen ajo: silt\u00e4 varalta ettet ole viel\u00e4 t\u00e4st\u00e4 lukenut, se koostuu kahdesta vaiheesta, joista ensimm\u00e4isess\u00e4 (for(d=0)) puskurin jokaisen merkin bittej\u00e4 siirret\u00e4\u00e4n ja xorataan puskurin merkki kellojonolla (edellinen ressu_clockbyte() rutiini). Toisessa vaiheessa (toinen for(d=0)) k\u00e4yd\u00e4\u00e4n uudelleen puskuri kokonaan l\u00e4pi ja vaihdetaan jokainen merkki satunnaisen merkin kanssa. N\u00e4m\u00e4 kaksi vaihetta tehd\u00e4\u00e4n kahdeksan kertaa (for(c=0)), eli jokaisella puskurin merkin bitill\u00e4. If prevbyte -iffill\u00e4 ker\u00e4t\u00e4\u00e4n tilastoa ns vaihtelusta, ja tilaston perusteella lasketaan seuraavassa vaiheessa teoreettisia satunnaisbittej\u00e4. Teoreettisten satunnaisbittien perusteella lasketaan kuinka monta kierrosta (round) tarvitaan puskurin satunnaistamiseen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void ressu_genbytes_fast(int size, unsigned char *buffer)\n{\n  int c, d, e, byte;\n  static int f = 0, prevbyte = -1, count = 0;\n\n  for(c=0; c&lt;8; c++) {\n    for(d=0; d&lt;size; d++) {\n      e = buffer&#91;d];\n      e = ((e&amp;0x80)&gt;&gt;7) | ((e&amp;0x7f)&lt;&lt;1); \/\/ rotate left 1\n      \/\/e=((e&amp;0xe0)&gt;&gt;5) | ((e&amp;0x1f)&lt;&lt;3); \/\/ rotate left 3\n      \/\/e=((e&amp;0xfe)&gt;&gt;1) | ((e&amp;0x1)&lt;&lt;7);  \/\/ rotate right 1\n      byte = ressu_clockbyte();\n      if(prevbyte==-1)\n\tprevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n\tperiods&#91;count]++;\n\tclockbytes+=count;\n\tcount=0;\n\tprevbyte=byte;\n      }\n      count++;\n    }\n    for(d=0; d&lt;size; d++) {\n      f = (f+buffer&#91;d])%size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Seuraavalla rutiinilla t\u00e4ytet\u00e4\u00e4n asiakkaan toimittama puskuri satunnaisbiteill\u00e4. Satunnaisbitit palautetaan ressut-taulusta. N\u00e4in asiakas ei saa koko satunnaisbittigeneraattorin rakennetta kyselyll\u00e4\u00e4n. Kun ressut taulu on k\u00e4ytetty if(ressut_pos) iffill\u00e4 haetaan ressut taulu uudestaan &#8220;t\u00e4yteen&#8221;. Taulun t\u00e4ytt\u00e4miseksi suoritetaan ressu_genbytes_fast() rutiinia niin monta kertaa ett\u00e4 tilastossa palautettujen &#8220;pienien&#8221; ketjujen m\u00e4\u00e4r\u00e4 ylitt\u00e4\u00e4 tarvittavan bittim\u00e4\u00e4r\u00e4n. T\u00e4ss\u00e4 tuotantoversiossa fast() rutiinia ajetaan v\u00e4hint\u00e4\u00e4n kaksi kertaa. Lis\u00e4ksi suorituskierroksia kasvattaa minimikellojonon pituus, jolla saadaan uniikkeja puskureita.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void ressu_genbytes(int size, unsigned char *buffer) \/\/ 6.5.2021 JariK\n{\n  int c,d,e;\n  static int ressut_first=1,\n    ressut_pos = 0,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_BYTES];\n  \n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n\tmemset(ressut,0,ressut_bytes);\n\tressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n\tperiods&#91;d]=0;\n      \n      int rndbits=0, rounds=0;\n      int lim, lim1, lim2;\n\n      for(d=0; rndbits&lt;ressu_bits_needed ||\n\t  d&lt;RESSU_MIN_ROUNDS ||\n\t  clockbytes &lt; RESSU_MIN_CLOCKBYTES; d++) {\n\n\tressu_genbytes_fast(ressut_bytes,ressut);\n\n\tlim=1;\n\t\n\tint ok=1, f, prevf=-1;\n\n\twhile(ok==1) {\n\t  ok=0;\n\t  f=-1;\n\t  for(e=0;e&lt;1024;e++) {\n\t    if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f)) {\n\t      f=periods&#91;e];\n\t    }\n\t  }\n\t  if(prevf==-1 || (f!=-1 &amp;&amp; f&lt;=(double)prevf*1.6)) {\n\t    lim=f;\n\t    prevf=f;\n\t    ok=1;\n\t  }\n\t} \/\/ while(ok==1)\n\n\tlim1=lim;\n\t\n\t\/\/ find next greater than lim\n\n\tf=-1;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f))\n\t    f=periods&#91;e];\n\t}\n\tlim=f;\n\tlim2=lim;\n\t\n\tint prev_rndbits=rndbits;\n\n\trndbits=0;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;0 &amp;&amp; periods&#91;e]&lt;lim) {\n\t    rndbits+=periods&#91;e];\n\t  }\n\t}\n\tif(rndbits==0 || prev_rndbits == rndbits) { \/\/ restart\n\t  clockbytes=0;\n\t  for(e=0;e&lt;1024;e++)\n\t    periods&#91;e]=0;\n\t  rndbits=0;\n\t}\n      } \/\/ for(d=0;\n      if(stats) {\n\tfprintf(stderr,\"round: %d\",d);\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;0)\n\t    fprintf(stderr,\" %d:%lu\",e,periods&#91;e]);\n\t}\n\tfprintf(stderr,\" lim:%d\",lim1);\n\tfprintf(stderr,\" lim2:%d\",lim2);\n\tfprintf(stderr,\" clockbytes:%ld\",clockbytes);\n\tfprintf(stderr,\" rndbits:%d\",rndbits);\n\tfprintf(stderr,\"\\n\");\n      }\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_bytes;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_bytes;\n  } \/\/ for(c=0; c&lt;size; c++)\n\n  genbytes+=size;\n}<\/code><\/pre>\n\n\n\n<p>Seuraavana debukkiversio jossa on nuo aloituspaikan varmentavat debug while:t ja puskurin ja tilastojen tulostus tiedostoon. N\u00e4it\u00e4 tarvitaan sen takia ett\u00e4 tuon uniikkeja puskureita tuottavan kellojonon pituus on viel\u00e4 hakusessa. Jos siihen tulisi joku ratkaisu kierrosm\u00e4\u00e4r\u00e4\u00e4 voisi ehk\u00e4 v\u00e4hent\u00e4\u00e4. Ennen debukkiversiota rivi newressu.deb tiedostosta:<\/p>\n\n\n\n<p>4db49f6a76c06d972a7588c443cfc43e16c2d9c69013e98ccc28b26b2c49a0c0, ressut_bytes: 4096, ressu_bits_needed: 128, ressu_min_rounds: 2, clockbytes: 131061, fluctuations: 1:13 2:14 3:18 4:12 5:13 6:12 7:14 8:21 9:9 10:25 11:3325 12:424 13:1275 14:5139, total: 131061, limit1: 25, limit2: 424, limit: 424, skipped: 11:3325 12:424 13:1275 14:5139, counted: 1:13 2:14 3:18 4:12 5:13 6:12 7:14 8:21 9:9 10:25, rndbits: 151, rounds: 4, small chains: 4 10 * 7 5 * 1 5 * 3 4 * 7 * 4 * 10 9 * 6 3 * 10 * 8 * 10 * 5 3 * 9 3 * 10 8 * 2 2 * 10 * 7 * 1 10 * 10 * 2 1 * 3 3 * 5 1 * 10 * 4 3 * 5 9 * 7 * 8 8 * 8 9 * 9 3 * 2 4 * 4 5 * 5 5 * 9 1 8 * 7 1 * 3 6 * 2 1 10 * 6 8 * 5 10 * 10 2 * 1 8 * 10 * 3 7 * 10 * 10 1 9 * 1 9 * 7 7 * 3 * 5 3 * 8 * 2 * 2 3 * 7 6 * 8 2 * 10 5 * 6 * 3 * 4 6 * 3 * 6 7 * 6 10 * 10 4 * 10 4 * 10 4 * 10 3 * 3 * 4 * 8 8 * 4 2 * 10 * 2 10 * 5 8 * 2 * 1 1 * 6 10 * 5 * 7 7 * 8 8 * 2 * 1 10 * 4 2 * 8 6 * 8 7 * 8 6 * 8 8 * 6 8 * 7 9 *, count: 151<\/p>\n\n\n\n<p>Ensimm\u00e4ist\u00e4 heksamerkkijonoa k\u00e4ytet\u00e4\u00e4n tuplapuskureiden etsimiseen, se on dumppi puskurin alusta. Lopun t\u00e4htimerkkijonossa listataan k\u00e4ytetyt pienet ketjut. Tuplapuskureita l\u00f6ytyy ainakin 1024 merkki\u00e4 pitk\u00e4ll\u00e4 puskurilla jos bittien m\u00e4\u00e4r\u00e4 on 1 ja minimikierrosten m\u00e4\u00e4r\u00e4 on 1. Eli ainakin bittien m\u00e4\u00e4r\u00e4n on oltava kohtuullisen iso.<\/p>\n\n\n\n<p>Ja debukkiversio (k\u00e4ytet\u00e4\u00e4n &#8211;debug kytkimell\u00e4):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define DEBUG4 2\n\n#ifdef DEBUG4\nunsigned char cc&#91;256*1048576]; \/\/ clock_chain\nunsigned char *ccp;\nint cc_bytes;\n#endif\n\nunsigned char ressu_clockbyte_debug() \/* JariK 2013 *\/\n{\n  unsigned char c;\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  c=tv.tv_usec &amp; 0xff;\n#ifdef DEBUG4\n  if(cc_bytes&lt;sizeof(cc)) {\n    *ccp++ = c;\n    cc_bytes++;\n  }\n#endif\n  return(c);\n}\n\nvoid ressu_genbytes_fast_debug(int size, unsigned char *buffer)\n{\n  int c, d, e, byte;\n  static int f = 0, prevbyte = -1, count = 0;\n\n  for(c=0; c&lt;8; c++) {\n    for(d=0; d&lt;size; d++) {\n      e = buffer&#91;d];\n      e = ((e&amp;0x80)&gt;&gt;7) | ((e&amp;0x7f)&lt;&lt;1); \/\/ rotate left 1\n      \/\/e=((e&amp;0xe0)&gt;&gt;5) | ((e&amp;0x1f)&lt;&lt;3); \/\/ rotate left 3\n      \/\/e=((e&amp;0xfe)&gt;&gt;1) | ((e&amp;0x1)&lt;&lt;7);  \/\/ rotate right 1\n      byte = ressu_clockbyte_debug();\n      if(prevbyte==-1)\n\tprevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n\tperiods&#91;count]++;\n\tclockbytes+=count;\n\tcount=0;\n\tprevbyte=byte;\n      }\n      count++;\n    }\n    for(d=0; d&lt;size; d++) {\n      f = (f+buffer&#91;d])%size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n  }\n}\n\nvoid ressu_genbytes_debug(int size, unsigned char *buffer) \/\/ 6.5.2021 JariK\n{\n  int c,d,e;\n  static int ressut_first=1,\n    ressut_pos = 0,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_BYTES];\n  \n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n\tmemset(ressut,0,ressut_bytes);\n\tressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n\tperiods&#91;d]=0;\n      \n#ifdef DEBUG4\n      ccp=cc;\n      cc_bytes=0;\n\n      while(ressu_clockbyte_debug()!=0);\n      while(ressu_clockbyte_debug()==0);\n\n      ccp=cc;\n      cc_bytes=0;\n#endif\n\n      int rndbits=0, rounds=0;\n      int lim, lim1, lim2;\n\n      for(d=0; rndbits&lt;ressu_bits_needed ||\n\t  d&lt;RESSU_MIN_ROUNDS; d++) {\n\n\trounds++;\n\t\n\tressu_genbytes_fast_debug(ressut_bytes,ressut);\n\n\tlim=1;\n\t\n\tint ok=1, f, prevf=-1;\n\n\twhile(ok==1) {\n\t  ok=0;\n\t  f=-1;\n\t  for(e=0;e&lt;1024;e++) {\n\t    if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f)) {\n\t      f=periods&#91;e];\n\t    }\n\t  }\n\t  if(prevf==-1 || (f!=-1 &amp;&amp; f&lt;=(double)prevf*1.6)) {\n\t    lim=f;\n\t    prevf=f;\n\t    ok=1;\n\t  }\n\t} \/\/ while(ok==1)\n\n\tlim1=lim;\n\n\t\/\/ find next greater than lim\n\n\tf=-1;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f))\n\t    f=periods&#91;e];\n\t}\n\tlim=f;\n\tlim2=lim;\n\t\n\tint prev_rndbits=rndbits;\n\n\trndbits=0;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;0 &amp;&amp; periods&#91;e]&lt;lim) {\n\t    rndbits+=periods&#91;e];\n\t  }\n\t}\n\n\tif(rndbits==0 || prev_rndbits == rndbits) { \/\/ restart\n\t  clockbytes=0;\n\t  for(e=0;e&lt;1024;e++)\n\t    periods&#91;e]=0;\n\t  ccp=cc;\n\t  cc_bytes=0;\n\t  rndbits=0;\n\t}\n      } \/\/ for(d=0;\n\n#ifdef DEBUG4\n      FILE *fp1;\n      if((fp1=fopen(\"newressu.deb\",\"a\"))!=NULL) {\n\n\tfor(d=0;d&lt;32;d++)\n\t  fprintf(fp1,\"%02x\",ressut&#91;d]);\n\n\tfprintf(fp1,\", ressut_bytes: %d\",ressut_bytes);\n\tfprintf(fp1,\", ressu_bits_needed: %d\",ressu_bits_needed);\n\tfprintf(fp1,\", ressu_min_rounds: %d\",RESSU_MIN_ROUNDS);\n\n\tfprintf(fp1,\", clockbytes: %ld\",clockbytes);\n\t\n\tunsigned long total=0;\t\n\tfprintf(fp1,\", fluctuations:\");\n\tfor(d=0;d&lt;1024;d++) {\n\t  if(periods&#91;d]!=0) {\n\t    fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n\t    total+=(periods&#91;d]*d);\n\t  }\n\t}\n\tfprintf(fp1,\", total: %lu\",total);\n\tfprintf(fp1,\", limit1: %d\",lim1);\n\tfprintf(fp1,\", limit2: %d\",lim2);\n\tfprintf(fp1,\", limit: %d\",lim);\n\n\tfprintf(fp1,\", skipped:\");\n\tfor(d=0;d&lt;1024;d++) {\n\t  if(periods&#91;d]&gt;=lim) {\n\t    fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n\t  }\n\t}\n\t\n\tfprintf(fp1,\", counted:\");\n\tfor(d=0;d&lt;1024;d++) {\n\t  if(periods&#91;d]&gt;0 &amp;&amp; periods&#91;d]&lt;lim) {\n\t    fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n\t  }\n\t}\t\n\tfprintf(fp1,\", rndbits: %d\",rndbits);\n\tfprintf(fp1,\", rounds: %d\",rounds);\n\n\tint prevbyte=-1, count=0, count2=0;\n\tunsigned char byte, small=-1;\n\tfprintf(fp1,\", small chains:\");\n\tfor(d=0;d&lt;cc_bytes;d++) {\n\t  byte=cc&#91;d];\n\t  if(prevbyte==-1) {\n\t    prevbyte=byte;\n\t    count=1;\n\t  }\n\t  if(prevbyte!=byte) {\n\t    if(periods&#91;count]&gt;=lim) {\n\t      if(small==1 || small==-1)\n\t\tfprintf(fp1,\" *\");\n\t      small=0;\n\t    } else small=1;\n\t    if(small) {\n\t      fprintf(fp1,\" %d\",count);\n\t      count2++;\n\t    }\n\t    count=0;\n\t    prevbyte=byte;\n\t  }\n\t  count++;\n\t}\n\tif(small) {\n\t  fprintf(fp1,\" %d\",count);\n\t  count2++;\n\t}\n\tfprintf(fp1,\", count: %d\",count2);\n\n\tfprintf(fp1,\"\\n\");\n\tfflush(fp1);\n\tfclose(fp1);\n      } \/\/ if((fp1=fopen\n#endif\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_bytes;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_bytes;\n  } \/\/ for(c=0; c&lt;size; c++)\n\n  genbytes+=size;\n}<\/code><\/pre>\n\n\n\n<p>Seuraavassa lottonumeroiden tulostukseen tai satunnaislukurivin lajitteluun liittyv\u00e4t rutiinit: clear() rutiini tyhjent\u00e4\u00e4 lajittelupuskurina k\u00e4ytetyn merkkijonon. add() lis\u00e4\u00e4 sanan (word) merkkijonoon. Lis\u00e4yksess\u00e4 varmistetaan ett\u00e4 sana on uniikki ja ett\u00e4 se lajitellaan. Seuraavalla get() rutiinilla luetaan lajitellut sanat sana kerrallaan.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void line_clear(int *len, unsigned char **buf)\n{\n  if(*len&lt;1) {\n    *len=129;\n    *buf=realloc(*buf,*len);\n  }\n  **buf='\\0';\n}\n\nint line_add_string_sort(int *len, unsigned char **buf, unsigned char *string)\n{\n  int cmp,count,add;\n  unsigned char *p;\n\n  p=*buf;\n  add=1;\n  while(*p!='\\0') {\n    cmp=strncmp(string,p,strlen(string));\n    if(cmp&gt;0) {\n      while(*p!=' ' &amp;&amp; *p!='\\0') \/\/ find next space\n\tp++;\n      while(*p==' ' &amp;&amp; *p!='\\0') \/\/ find next non space\n\tp++;\n    } else if(cmp==0) {\n      add=0;\n      break;\n    } else {\n      break;\n    }\n  }\n\n  if(add) {\n    count=strlen(*buf)+strlen(string)+1+1;\n    if(*buf==NULL || count&gt;*len) {\n      int diff=p-*buf;\n      *len = *len + 128;\n      *buf=realloc(*buf,*len);\n      p=*buf+diff;\n    }\n    memmove(p+strlen(string)+1,p,strlen(p)+1);\n    memmove(p,string,strlen(string));\n    p+=strlen(string);\n    *p=' ';\n  }\n\n  return(add);\n}\n\nint line_get_string(int len, unsigned char *buf, int n, unsigned char *string)\n{\n  int e,ok,count;\n  unsigned char *p,*q;\n\n  ok=0;\n  p=string;\n  e=0;\n\n  while(*p!='\\0') {\n    if(e==n) {\n      ok=1;\n      break;\n    }\n    while(*p!=' ' &amp;&amp; *p!='\\0') \/\/ find next space\n      p++;\n    while(*p==' ' &amp;&amp; *p!='\\0') \/\/ find next non space\n      p++;\n    e++;\n  }\n  if(ok) {\n    q=buf;\n    count=0;\n    while(*q!=' ' &amp;&amp; *q!='\\0') {\n      if(++count&lt;len)\n\t*q++=*p;\n      p++;\n    }\n    *q='\\0';\n  } else {\n    buf&#91;0]='\\0';\n  }\n}\n\nint line_dump(unsigned char *string)\n{\n  int e,n,ok,count;\n  unsigned char *p,*q;\n\n  p=string;\n  n=0;\n  while(*p!='\\0') {\n    fprintf(stdout,\" %d:\",n++);\n    while(*p!=' ' &amp;&amp; *p!='\\0') \/\/ find next space\n      putchar(*p++);\n    while(*p==' ' &amp;&amp; *p!='\\0') \/\/ find next non space\n      p++;\n    e++;\n  }\n  fprintf(stdout,\"\\n\");\n}<\/code><\/pre>\n\n\n\n<p>Seuraavaksi valittuja uudistuksia p\u00e4\u00e4ohjelmasta: &#8211;lotto &#8211;unique ja &#8211;sort kytkimet p\u00e4\u00e4ohjelmasta. Unique:ta ei ole viel\u00e4 toteutettu. &#8211;lotto ja &#8211;sort ovat samanlaisia.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      } else if(!strcmp(\"--sort\",argv&#91;c])) {\n\tsort=!sort;\n\tif(sspace==0)\n\t  sspace=1;\n\t\t\n      } else if(!strcmp(\"--unique\",argv&#91;c])) {\n\tunique=!unique;\n\tif(sspace==0)\n\t  sspace=1;\n\t\t\n      } else if(!strcmp(\"--lotto\",argv&#91;c])) {\n\tsort=!sort;\n\tif(sspace==0)\n\t  sspace=1;\n\t\/\/sort=1;\n\t\/\/unique=1;<\/code><\/pre>\n\n\n\n<p>Seuraava laskee kuinka monta sanaa (word) riville tulostetaan:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  pchars=0;\n  pwords=0;\n  int linew=0;\n\n  \/\/ in beginning of line, count printed line number\n      \n  if(!quiet &amp;&amp; slines) {\n    sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n    pchars += strlen(wordbuf2);\n    pchars++;\n  }\n\n  \/\/ count words\n  \n  while((chars&gt;0 &amp;&amp; pchars+size &lt; chars) ||\n\t(words&gt;0 &amp;&amp; pwords &lt; words)) {\n\n    linew++;\n    \n    if(sspace &amp;&amp; pchars&gt;0 &amp; !quiet) {\n      if(sspace==3 &amp;&amp; pwords%2==0)\n\tpchars++;\n      pchars++;\n    }\n\t\n    pchars+=size;\n    pwords++;\n  }\n<\/code><\/pre>\n\n\n\n<p>Seuraava laskee kuinka monta erilaista arvoa sana voi saada. T\u00e4t\u00e4 tarvitaan virheilmoituksia varten:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  unsigned long wordvalues=1;\n  for(c=0;c&lt;size;c++) {\n    if(wordvalues!=0 &amp;&amp; wordvalues*utf8len(digits)&lt;(unsigned long)65536*65536*65536) {\n      wordvalues*=utf8len(digits);\n    } else {\n      wordvalues=0;\n    }\n  }\n\n  if(limit &gt; 0) {\n    if(sort==1 &amp;&amp; limit-!zero&lt;words) {\n      fprintf(stderr,\"%s: limit is less than words (zero)\",procname);\n      fprintf(stderr,\", limit:%lu\",limit);\n      fprintf(stderr,\", words:%d\",words);\n      fprintf(stderr,\", zero:%d\",zero);\n      fprintf(stderr,\"\\n\");\n      \n      help=1;\n      lines=0;\n    }\n  } else {\n    if(sort==1 &amp;&amp; size&gt;0 &amp;&amp; wordvalues&gt;0 &amp;&amp; wordvalues&lt;linew) {\n      fprintf(stderr,\"%s:\",procname);\n      fprintf(stderr,\" digits is less than calculated words\");\n      fprintf(stderr,\", digits:%d(%lu)\",utf8len(digits),wordvalues);\n      fprintf(stderr,\", words:%d\\n\",linew);\n      help=1;\n      lines=0;\n    }\n  }<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 optimointi, joka korvaa lyhyen sanan useamman char_limit() haun yhdell\u00e4 gen_limit() toiminnolla.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/ small words as single ressu_gen_limit()\n  \n  if(limit==0 &amp;&amp; wordvalues&gt;0)\n    limit=wordvalues;<\/code><\/pre>\n\n\n\n<p>Seuraava on ei lotto versio tulostuksesta:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      pchars=0;\n      pwords=0;\n\n      while(pwords&lt;linew) {\n\tif(limit!=0) {\n\t  word=0;\n\t  \n\t  if(zero) {\n\t    word=ressu_gen_limit(limit); \/\/ include zeroes\n\t    \/\/fprintf(stdout,\"(%lo)\",word);\n\t  } else if(limit&gt;=1) {\n\t    while((word=ressu_gen_limit(limit))==0); \/\/ skip zeroes\n\t  }\n\t  \n\t  out_word(sizeof(wordbuf3),wordbuf3,digits,word);\n\t  \n\t  \/\/ fill leading zeroes\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  utf8getchar(sizeof(character),character,0,digits);\n\t  for(d=size-utf8len(wordbuf3);d&gt;0;d--) {\n\t    strcat(wordbuf,character);\n\t  }\n\t  \n\t  \/\/ rest of the number\n\t  \n\t  strcat(wordbuf,wordbuf3);\n\t  \n\t} else if(digits!=NULL) {\n\t  int digitslen;\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  digitslen=utf8len(digits);\n\t  \n\t  \/\/ fill whole word digit by digit\n\t  \n\t  for(d=0;d&lt;size;d++) {\n\t    if(digits&#91;0]=='0' &amp;&amp; !zero)\n\t      e=ressu_gen_limit(digitslen-1)+1;\n\t    else\n\t      e=ressu_gen_limit(digitslen);\n\t    utf8getchar(sizeof(wordbuf3),wordbuf3,e,digits);\n\t    \/\/fprintf(stdout,\"(%s)\",wordbuf3);\n\t    strcat(wordbuf,wordbuf3);\n\t  }\n\t}\n\n\t\/\/ in beginning of line, print line number\n\n\tif(pchars==0 &amp;&amp; !quiet &amp;&amp; slines) {\n\t  sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n\t  fprintf(stdout,\"%s\",wordbuf2);\n\t  pchars +=strlen(wordbuf2);\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ want to print spaces between \"words\"?\n\t\n\tif(sspace &amp;&amp; pchars&gt;0 &amp;&amp; !quiet) {\n\t  if(sspace==3 &amp;&amp; pwords%2==0) {\n\t    fprintf(stdout,\" \");\n\t    pchars++;\n\t  }\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ print word\n\t\n\tif(size!=0) {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%*s\",size,wordbuf);\n\t  pchars += size;\n\t  pwords++;\n\t} else {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%s\",wordbuf);\n\t  pchars += strlen(wordbuf);\n\t  pwords++;\n\t}\n      } \/\/ while(pwords&lt;linew) {\n    } else { \/\/ if(!sort)\n<\/code><\/pre>\n\n\n\n<p>Seuraavassa lotto versio tulostuksesta: erona on se, ett\u00e4 ensin ker\u00e4t\u00e4\u00e4n sanat, ja sitten toisessa vaiheessa ne tulostetaan: Edellisess\u00e4 ei lotto versiossa oli vain yksi vaihe joka teki kaiken.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>      pchars=0;\n      pwords=0;\n      \n      line_clear(&amp;linecnt,&amp;line);\n\n      \/\/ fetch and save words on this row\n      while(pwords&lt;linew) {\n\tif(limit!=0) {\n\t  word=0;\n\t  \n\t  if(zero) {\n\t    word=ressu_gen_limit(limit); \/\/ include zeroes\n\t  } else if(limit&gt;=1) {\n\t    while((word=ressu_gen_limit(limit))==0); \/\/ skip zeroes\n\t  }\n\t  \n\t  out_word(sizeof(wordbuf3),wordbuf3,digits,word);\n\t  \n\t  \/\/ fill leading zeroes\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  utf8getchar(sizeof(character),character,0,digits);\n\t  for(d=size-utf8len(wordbuf3);d&gt;0;d--) {\n\t    strcat(wordbuf,character);\n\t  }\n\t  \n\t  \/\/ rest of the number\n\t  \n\t  strcat(wordbuf,wordbuf3);\n\t  \n\t} else if(digits!=NULL) {\n\t  int digitslen;\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  digitslen=utf8len(digits);\n\t  \n\t  \/\/ fill whole word digit by digit\n\t  \n\t  for(d=0;d&lt;size;d++) {\n\t    if(digits&#91;0]=='0' &amp;&amp; !zero)\n\t      e=ressu_gen_limit(digitslen-1)+1;\n\t    else\n\t      e=ressu_gen_limit(digitslen);\n\t    utf8getchar(sizeof(wordbuf3),wordbuf3,e,digits);\n\t    strcat(wordbuf,wordbuf3);\n\t  }\n\t}\n\n\tif(line_add_string_sort(&amp;linecnt,&amp;line,wordbuf)) {\n\t  pwords++;\n\t}\n      } \/\/ while(pwords&lt;linew) {\n\n      pchars=0;\n      pwords=0;\n\n      \/\/ print words on this row\n      while(pwords&lt;linew) {\n\n\tline_get_string(sizeof(wordbuf),wordbuf,pwords,line);\n\n\t\/\/ in beginning of line, print line number\n\n\tif(pchars==0 &amp;&amp; !quiet &amp;&amp; slines) {\n\t  sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n\t  fprintf(stdout,\"%s\",wordbuf2);\n\t  pchars +=strlen(wordbuf2);\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ want to print spaces between \"words\"?\n\t\n\tif(sspace &amp;&amp; pchars&gt;0 &amp;&amp; !quiet) {\n\t  if(sspace==3 &amp;&amp; pwords%2==0) {\n\t    fprintf(stdout,\" \");\n\t    pchars++;\n\t  }\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ print word\n\t\n\tif(size!=0) {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%*s\",size,wordbuf);\n\t  pchars += size;\n\t  pwords++;\n\t} else {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%s\",wordbuf);\n\t  pchars += strlen(wordbuf);\n\t  pwords++;\n\t}\n      } \/\/ while(pwords&lt;linew) {<\/code><\/pre>\n\n\n\n<p>Viel\u00e4 esimerkki suomalaisista lottoriveist\u00e4: &#8211;sort ja &#8211;lotto toiminnat ovat samanlaisia, voit lajitella mitk\u00e4 tahansa rivit numeroj\u00e4rjestykseen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --lim41 -w7 --zero --sort\n00000  02 05 13 15 26 38 39\n00001  04 13 15 24 28 36 39\n00002  09 11 28 29 30 35 40\n00003  04 06 13 15 20 21 36\n00004  07 10 11 20 23 27 30\n00005  02 03 11 15 25 32 36\n00006  01 07 09 24 28 31 32\n00007  06 13 15 19 30 32 35\n00008  02 03 08 17 28 29 31\n00009  17 23 24 26 27 36 39<\/code><\/pre>\n\n\n\n<p>Ja lopuksi ohjelma kokonaisuudessaan:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;malloc.h&gt;\n\n#include &lt;string.h&gt;\n#include &lt;ctype.h&gt;\n#include &lt;math.h&gt;\n#include &lt;sys\/time.h&gt;\n\nunsigned char *procname;\nstatic char *programname = \"newressu version 2.1 \u00a9\";\nstatic unsigned char *copyright = \"Copyright (c) 2013-2021 Jari Kuivaniemi, Helsinki, Finland. Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n!\";\n\nunsigned long periods&#91;1024];\nunsigned long genbytes=0;\nunsigned long clockbytes=0;\n\n#define RESSUT_BYTES 4096\n#define RESSU_BITS_NEEDED 128\n#define RESSU_MIN_ROUNDS 2\n#define RESSU_MIN_CLOCKBYTES 16384+1024\n\nint ressu_bits_needed=RESSU_BITS_NEEDED;\nint ressut_bytes = RESSUT_BYTES;\n\nint stats=0;\n\nunsigned char ressu_clockbyte() \/* JariK 2013 *\/\n{\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  return(tv.tv_usec &amp; 0xff);\n}\n\nvoid ressu_genbytes_fast(int size, unsigned char *buffer)\n{\n  int c, d, e, byte;\n  static int f = 0, prevbyte = -1, count = 0;\n\n  for(c=0; c&lt;8; c++) {\n    for(d=0; d&lt;size; d++) {\n      e = buffer&#91;d];\n      e = ((e&amp;0x80)&gt;&gt;7) | ((e&amp;0x7f)&lt;&lt;1); \/\/ rotate left 1\n      \/\/e=((e&amp;0xe0)&gt;&gt;5) | ((e&amp;0x1f)&lt;&lt;3); \/\/ rotate left 3\n      \/\/e=((e&amp;0xfe)&gt;&gt;1) | ((e&amp;0x1)&lt;&lt;7);  \/\/ rotate right 1\n      byte = ressu_clockbyte();\n      if(prevbyte==-1)\n\tprevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n\tperiods&#91;count]++;\n\tclockbytes+=count;\n\tcount=0;\n\tprevbyte=byte;\n      }\n      count++;\n    }\n    for(d=0; d&lt;size; d++) {\n      f = (f+buffer&#91;d])%size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n  }\n}\n\nvoid ressu_genbytes(int size, unsigned char *buffer) \/\/ 6.5.2021 JariK\n{\n  int c,d,e;\n  static int ressut_first=1,\n    ressut_pos = 0,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_BYTES];\n  \n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n\tmemset(ressut,0,ressut_bytes);\n\tressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n\tperiods&#91;d]=0;\n      \n      int rndbits=0;\n      int lim, lim1, lim2;\n\n      for(d=0; rndbits&lt;ressu_bits_needed ||\n\t  d&lt;RESSU_MIN_ROUNDS ||\n\t  clockbytes &lt; RESSU_MIN_CLOCKBYTES; d++) {\n\n\tressu_genbytes_fast(ressut_bytes,ressut);\n\n\tlim=1;\n\t\n\tint ok=1, f, prevf=-1;\n\n\twhile(ok==1) {\n\t  ok=0;\n\t  f=-1;\n\t  for(e=0;e&lt;1024;e++) {\n\t    if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f)) {\n\t      f=periods&#91;e];\n\t    }\n\t  }\n\t  if(prevf==-1 || (f!=-1 &amp;&amp; f&lt;=(double)prevf*1.6)) {\n\t    lim=f;\n\t    prevf=f;\n\t    ok=1;\n\t  }\n\t} \/\/ while(ok==1)\n\n\tlim1=lim;\n\t\n\t\/\/ find next greater than lim\n\n\tf=-1;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f))\n\t    f=periods&#91;e];\n\t}\n\tlim=f;\n\tlim2=lim;\n\t\n\tint prev_rndbits=rndbits;\n\n\trndbits=0;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;0 &amp;&amp; periods&#91;e]&lt;lim) {\n\t    rndbits+=periods&#91;e];\n\t  }\n\t}\n\tif(rndbits==0 || prev_rndbits == rndbits) { \/\/ restart\n\t  clockbytes=0;\n\t  for(e=0;e&lt;1024;e++)\n\t    periods&#91;e]=0;\n\t  rndbits=0;\n\t}\n      } \/\/ for(d=0;\n      if(stats) {\n\tfprintf(stderr,\"round: %d\",d);\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;0)\n\t    fprintf(stderr,\" %d:%lu\",e,periods&#91;e]);\n\t}\n\tfprintf(stderr,\" lim:%d\",lim1);\n\tfprintf(stderr,\" lim2:%d\",lim2);\n\tfprintf(stderr,\" clockbytes:%ld\",clockbytes);\n\tfprintf(stderr,\" rndbits:%d\",rndbits);\n\tfprintf(stderr,\"\\n\");\n      }\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_bytes;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_bytes;\n  } \/\/ for(c=0; c&lt;size; c++)\n\n  genbytes+=size;\n}\n\n#define DEBUG4 2\n\n#ifdef DEBUG4\nunsigned char cc&#91;256*1048576]; \/\/ clock_chain\nunsigned char *ccp;\nint cc_bytes;\n#endif\n\nunsigned char ressu_clockbyte_debug() \/* JariK 2013 *\/\n{\n  unsigned char c;\n  struct timeval tv;\n  gettimeofday(&amp;tv, NULL);\n  c=tv.tv_usec &amp; 0xff;\n#ifdef DEBUG4\n  if(cc_bytes&lt;sizeof(cc)) {\n    *ccp++ = c;\n    cc_bytes++;\n  }\n#endif\n  return(c);\n}\n\nvoid ressu_genbytes_fast_debug(int size, unsigned char *buffer)\n{\n  int c, d, e, byte;\n  static int f = 0, prevbyte = -1, count = 0;\n\n  for(c=0; c&lt;8; c++) {\n    for(d=0; d&lt;size; d++) {\n      e = buffer&#91;d];\n      e = ((e&amp;0x80)&gt;&gt;7) | ((e&amp;0x7f)&lt;&lt;1); \/\/ rotate left 1\n      \/\/e=((e&amp;0xe0)&gt;&gt;5) | ((e&amp;0x1f)&lt;&lt;3); \/\/ rotate left 3\n      \/\/e=((e&amp;0xfe)&gt;&gt;1) | ((e&amp;0x1)&lt;&lt;7);  \/\/ rotate right 1\n      byte = ressu_clockbyte_debug();\n      if(prevbyte==-1)\n\tprevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n\tperiods&#91;count]++;\n\tclockbytes+=count;\n\tcount=0;\n\tprevbyte=byte;\n      }\n      count++;\n    }\n    for(d=0; d&lt;size; d++) {\n      f = (f+buffer&#91;d])%size;\n      e = buffer&#91;d];\n      buffer&#91;d] = buffer&#91;f];\n      buffer&#91;f] = e;\n    }\n  }\n}\n\nvoid ressu_genbytes_debug(int size, unsigned char *buffer) \/\/ 6.5.2021 JariK\n{\n  int c,d,e;\n  static int ressut_first=1,\n    ressut_pos = 0,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_BYTES];\n  \n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n\tmemset(ressut,0,ressut_bytes);\n\tressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n\tperiods&#91;d]=0;\n      \n#ifdef DEBUG4\n      ccp=cc;\n      cc_bytes=0;\n\n      while(ressu_clockbyte_debug()!=0);\n      while(ressu_clockbyte_debug()==0);\n\n      ccp=cc;\n      cc_bytes=0;\n#endif\n\n      int rndbits=0, rounds=0;\n      int lim, lim1, lim2;\n\n      for(d=0; rndbits&lt;ressu_bits_needed ||\n\t  d&lt;RESSU_MIN_ROUNDS; d++) {\n\n\trounds++;\n\t\n\tressu_genbytes_fast_debug(ressut_bytes,ressut);\n\n\tlim=1;\n\t\n\tint ok=1, f, prevf=-1;\n\n\twhile(ok==1) {\n\t  ok=0;\n\t  f=-1;\n\t  for(e=0;e&lt;1024;e++) {\n\t    if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f)) {\n\t      f=periods&#91;e];\n\t    }\n\t  }\n\t  if(prevf==-1 || (f!=-1 &amp;&amp; f&lt;=(double)prevf*1.6)) {\n\t    lim=f;\n\t    prevf=f;\n\t    ok=1;\n\t  }\n\t} \/\/ while(ok==1)\n\n\tlim1=lim;\n\n\t\/\/ find next greater than lim\n\n\tf=-1;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;lim &amp;&amp; (f==-1 || periods&#91;e]&lt;f))\n\t    f=periods&#91;e];\n\t}\n\tlim=f;\n\tlim2=lim;\n\t\n\tint prev_rndbits=rndbits;\n\n\trndbits=0;\n\tfor(e=0;e&lt;1024;e++) {\n\t  if(periods&#91;e]&gt;0 &amp;&amp; periods&#91;e]&lt;lim) {\n\t    rndbits+=periods&#91;e];\n\t  }\n\t}\n\n\tif(rndbits==0 || prev_rndbits == rndbits) { \/\/ restart\n\t  clockbytes=0;\n\t  for(e=0;e&lt;1024;e++)\n\t    periods&#91;e]=0;\n\t  ccp=cc;\n\t  cc_bytes=0;\n\t  rndbits=0;\n\t}\n      } \/\/ for(d=0;\n\n#ifdef DEBUG4\n      FILE *fp1;\n      if((fp1=fopen(\"newressu.deb\",\"a\"))!=NULL) {\n\n\tfor(d=0;d&lt;32;d++)\n\t  fprintf(fp1,\"%02x\",ressut&#91;d]);\n\n\tfprintf(fp1,\", ressut_bytes: %d\",ressut_bytes);\n\tfprintf(fp1,\", ressu_bits_needed: %d\",ressu_bits_needed);\n\tfprintf(fp1,\", ressu_min_rounds: %d\",RESSU_MIN_ROUNDS);\n\n\tfprintf(fp1,\", clockbytes: %ld\",clockbytes);\n\t\n\tunsigned long total=0;\t\n\tfprintf(fp1,\", fluctuations:\");\n\tfor(d=0;d&lt;1024;d++) {\n\t  if(periods&#91;d]!=0) {\n\t    fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n\t    total+=(periods&#91;d]*d);\n\t  }\n\t}\n\tfprintf(fp1,\", total: %lu\",total);\n\tfprintf(fp1,\", limit1: %d\",lim1);\n\tfprintf(fp1,\", limit2: %d\",lim2);\n\tfprintf(fp1,\", limit: %d\",lim);\n\n\tfprintf(fp1,\", skipped:\");\n\tfor(d=0;d&lt;1024;d++) {\n\t  if(periods&#91;d]&gt;=lim) {\n\t    fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n\t  }\n\t}\n\t\n\tfprintf(fp1,\", counted:\");\n\tfor(d=0;d&lt;1024;d++) {\n\t  if(periods&#91;d]&gt;0 &amp;&amp; periods&#91;d]&lt;lim) {\n\t    fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n\t  }\n\t}\t\n\tfprintf(fp1,\", rndbits: %d\",rndbits);\n\tfprintf(fp1,\", rounds: %d\",rounds);\n\n\tint prevbyte=-1, count=0, count2=0;\n\tunsigned char byte, small=-1;\n\tfprintf(fp1,\", small chains:\");\n\tfor(d=0;d&lt;cc_bytes;d++) {\n\t  byte=cc&#91;d];\n\t  if(prevbyte==-1) {\n\t    prevbyte=byte;\n\t    count=1;\n\t  }\n\t  if(prevbyte!=byte) {\n\t    if(periods&#91;count]&gt;=lim) {\n\t      if(small==1 || small==-1)\n\t\tfprintf(fp1,\" *\");\n\t      small=0;\n\t    } else small=1;\n\t    if(small) {\n\t      fprintf(fp1,\" %d\",count);\n\t      count2++;\n\t    }\n\t    count=0;\n\t    prevbyte=byte;\n\t  }\n\t  count++;\n\t}\n\tif(small) {\n\t  fprintf(fp1,\" %d\",count);\n\t  count2++;\n\t}\n\tfprintf(fp1,\", count: %d\",count2);\n\n\tfprintf(fp1,\"\\n\");\n\tfflush(fp1);\n\tfclose(fp1);\n      } \/\/ if((fp1=fopen\n#endif\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_bytes;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_bytes;\n  } \/\/ for(c=0; c&lt;size; c++)\n\n  genbytes+=size;\n}\n\nstatic void readfile_xor(int len,\n    unsigned char *buf,\n    unsigned char *filename)\n{\n  int c, n, n2;\n  unsigned char temp&#91;64];\n  FILE *fp1;\n\n  if((fp1 = fopen(filename, \"rb\"))\n      != NULL) {\n    while(len != 0) {\n      n = (len &lt; sizeof(temp)) ?\n          len : sizeof(temp);\n      n2=fread(temp, 1, n, fp1);\n      for(c = 0; c &lt; n2; c++)\n        buf&#91;c] ^= temp&#91;c];\n      len -= n2;\n      buf += n2;\n    }\n    fclose(fp1);\n  }\n}\n\nint input=0;\n\n#define GENT_SIZE 2048\n#define USE_RANDOM 2\n\n#define aDEBUG9 2\n\nchar *randomgen&#91;] = { \"ressu\", \"debug\",\"fast\",\"single\",\"4\",\"5\",\"6\",\"7\",\"urandom\",\"random\" };\n\nint ressu_genbyte()\n{\n  int c;\n  static unsigned char gent&#91;GENT_SIZE];\n  static unsigned char gent_pos=0;\n  unsigned char ch;\n\n  if(input==0) { \/\/ ressu prod\n    ressu_genbytes(sizeof(ch), &amp;ch);\n  } else if(input==1) { \/\/ ressu debug\n    ressu_genbytes_debug(sizeof(ch), &amp;ch);\n  } else {\n    if(gent_pos==0) {\n      if(input==2) { \/\/ ressu_fast\n\tclockbytes=0;\n\tfor(c=0; c&lt;2 ||\n\t  clockbytes &lt; RESSU_MIN_CLOCKBYTES;c++) {\n\t  ressu_genbytes_fast(sizeof(gent),gent);\n\t}\n      } else if(input==3) { \/\/ ressu_single\n\tressu_genbytes_fast(sizeof(gent),gent);\n      } else if(input==8) { \/\/ urandom\n\treadfile_xor(sizeof(gent),gent,\"\/dev\/urandom\");\n#ifdef USE_RANDOM\n      } else if(input==9) { \/\/ random\n\treadfile_xor(sizeof(gent),gent,\"\/dev\/random\");\n#endif\n      }\n    } \/\/ if(gent_pos==0\n    ch=gent&#91;gent_pos];\n    gent_pos=(gent_pos+1)%sizeof(gent);\n  }\n  return(ch);\n}\n\nint ressu_genbyte_limit(int limit)\n{\n  int c;\n  while((c=ressu_genbyte()) &gt;= (256\/limit)*limit);\n  return(c%limit);\n}\n\nint ressu_genshort()\n{\n  return(ressu_genbyte() | ressu_genbyte()&lt;&lt;8);\n}\n\nint ressu_genshort_limit(int limit)\n{\n  int c;\n  while((c=ressu_genshort()) &gt;= (65536\/limit)*limit);\n  return(c%limit);\n}\n\nunsigned int ressu_genint()\n{\n  return(ressu_genshort() | ressu_genshort()&lt;&lt;16);\n}\n\nunsigned int ressu_genint_limit(unsigned long limit)\n{\n  unsigned int c;\n  while((c=ressu_genint()) &gt;= (((unsigned long)65536*65536)\/limit)*limit);\n  return(c%limit);\n}\n\nunsigned long ressu_genlong()\n{\n  return(((unsigned long)ressu_genint()) | ((unsigned long)ressu_genint())&lt;&lt;32);\n}\n\nunsigned long ressu_genlong_limit(unsigned long limit)\n{\n  unsigned long c;\n  while((c=ressu_genlong()) &gt;= (((unsigned long)0xffffffffffffffff)\/limit)*limit);\n  return(c%limit);\n}\n\nunsigned long ressu_gen_limit(unsigned long limit)\n{\n  if(limit&lt;=256)\n    return(ressu_genbyte_limit(limit));\n  else if(limit&lt;=65536)\n    return(ressu_genshort_limit(limit));\n  else if(limit&lt;=(unsigned long)65536*65536)\n    return(ressu_genint_limit(limit));\n  else if(limit&lt;=(unsigned long)0xffffffffffffffff)\n    return(ressu_genlong_limit(limit));\n  else\n    return(-1);\n}\n\n#define MAIN 2\n\n#ifdef MAIN\n\nint help=0;\n\nint utf8len(unsigned char *buf)\n{\n  int len;\n  unsigned char *p;\n  \n  p=buf;\n  len=0;\n  while(*p!='\\0') {\n    if(*p&lt;0x80 || \/\/ ascii char\n       *p&gt;0xbf) \/\/ first utf8 byte\n      len++;\n    p++;\n  }\n  return(len);\n}\n\n#define aDEBUG38 2\n\nvoid utf8getchar(int size, unsigned char *buf, int n, unsigned char *string)\n{\n  int d;\n  unsigned char *p,*q;\n  \n  d=0;\n  p=string;\n  q=buf;\n\n  \/\/ find first byte of character\n  \n  while(*p!='\\0') {\n    if(*p&lt;0x80 || \/\/ ascii char\n       *p&gt;0xbf) { \/\/ first utf8 char\n      if(d==n)\n\tbreak;\n      d++;\n    }\n    p++;\n  }\n\n  \/\/ copy first byte and rest\n  \/\/ of character\n  \n  if(*p!='\\0') {\n    *q++=*p; \/\/ copy first byte\n    if(*p&gt;0xbf) { \/\/ if first is utf8 char\n      p++;\n      for(;;) {\n\tif(*p&gt;0xbf || \/\/ first utf8 char\n\t   *p&lt;0x80 || \/\/ ascii char\n\t   *p=='\\0')  \/\/ end of file\n\t  break;\n\t*q++=*p++; \/\/ copy rest of the bytes\n      }\n    }\n  }\n  *q='\\0';\n\n#ifdef DEBUG38\n  fprintf(stdout,\"%s: utf8getchar:\",procname);\n  fprintf(stdout,\" string: %s\",string);\n  fprintf(stdout,\", n: %d\",n);\n  fprintf(stdout,\", character: %s\",buf);\n  fprintf(stdout,\"\\n\");\n#endif\n}\n\n#define aDEBUG45\n\nvoid out_word(int size, unsigned char *buf, unsigned char *digits, unsigned long word2) \/\/ 8.5.2021 JariK\n{\n  int c, d, len, digitslen;\n  unsigned long word;\n  unsigned char string&#91;132], character&#91;32];\n\n  digitslen = utf8len(digits);\n  word=word2;\n  len=0;\n  string&#91;0]='\\0';\n\n  if(word==0 || digitslen&lt;2) {\n    \/\/ zero\n    utf8getchar(sizeof(character),character,0,digits);\n    if(len+strlen(character)&lt;sizeof(string)) {\n      strcat(string,character);\n      len+=strlen(character);\n    }\n  } else {\n    \/\/ non zero\n    while(word&gt;0) {\n      utf8getchar(sizeof(character),character,word%digitslen,digits);\n      if(len+strlen(character)&lt;sizeof(string)) {\n\tstrcat(string,character);\n\tlen+=strlen(character);\n      }\n      word\/=digitslen;\n    }\n  }\n\n  \/\/ reverse string\n  \n  *buf='\\0';\n  len=0;\n  d=utf8len(string);\n  for(c=d-1;c&gt;=0;c--) {\n    utf8getchar(sizeof(character),character,c,string);\n    if(len+strlen(character)&lt;size) {\n      strcat(buf,character);\n      len+=strlen(character);\n    }\n  }\n\n#ifdef DEBUG45\n  fprintf(stdout,\"]\\n%s: out_word: \",procname);\n  fprintf(stdout,\" reverse string: %s\",string);\n  fprintf(stdout,\", digits: %s\",digits);\n  fprintf(stdout,\", int: %lu\",word2);\n  fprintf(stdout,\"\\n&#91;\");\n#endif\n}\n\n#define aDEBUG58 2\n\nvoid in_word(unsigned long *word, unsigned char *digits, unsigned char *buf)\n{\n  int c,d,e,f,ok;\n  unsigned char character&#91;32], character2&#91;32];\n\n  *word=0;\n  d=utf8len(buf);\n  f=utf8len(digits);\n\n  for(c=0;c&lt;d;c++) {\n    utf8getchar(sizeof(character2),character2,c,buf);\n    ok=0;\n    for(e=0;e&lt;f;e++) {\n      utf8getchar(sizeof(character),character,e,digits);\n      if(!strcmp(character,character2)) {\n\tok=1;\n\tbreak;\n      }\n    }\n    if(ok) {\n      *word=((*word)*f)+e;\n    } else {\n      fprintf(stdout,\"%s: in_word:\",procname);\n      fprintf(stdout,\" illegal digit '%s'\\n\",character2);\n      help=1;\n    }\n  }\n#ifdef DEBUG58\n  fprintf(stdout,\"%s: in_word:\",procname);\n  fprintf(stdout,\" word: %lu\",*word);\n  fprintf(stdout,\", digits: %s\",digits);\n  fprintf(stdout,\", string: %s\",buf);\n  fprintf(stdout,\"\\n\");\n#endif\n}\n\nvoid line_clear(int *len, unsigned char **buf)\n{\n  if(*len&lt;1) {\n    *len=129;\n    *buf=realloc(*buf,*len);\n  }\n  **buf='\\0';\n}\n\nint line_add_string_sort(int *len, unsigned char **buf, unsigned char *string)\n{\n  int cmp,count,add;\n  unsigned char *p;\n\n  p=*buf;\n  add=1;\n  while(*p!='\\0') {\n    cmp=strncmp(string,p,strlen(string));\n    if(cmp&gt;0) {\n      while(*p!=' ' &amp;&amp; *p!='\\0') \/\/ find next space\n\tp++;\n      while(*p==' ' &amp;&amp; *p!='\\0') \/\/ find next non space\n\tp++;\n    } else if(cmp==0) {\n      add=0;\n      break;\n    } else {\n      break;\n    }\n  }\n\n  if(add) {\n    count=strlen(*buf)+strlen(string)+1+1;\n    if(*buf==NULL || count&gt;*len) {\n      int diff=p-*buf;\n      *len = *len + 128;\n      *buf=realloc(*buf,*len);\n      p=*buf+diff;\n    }\n    memmove(p+strlen(string)+1,p,strlen(p)+1);\n    memmove(p,string,strlen(string));\n    p+=strlen(string);\n    *p=' ';\n  }\n\n  return(add);\n}\n\nvoid line_get_string(int len, unsigned char *buf, int n, unsigned char *string)\n{\n  int e,ok,count;\n  unsigned char *p,*q;\n\n  ok=0;\n  p=string;\n  e=0;\n\n  while(*p!='\\0') {\n    if(e==n) {\n      ok=1;\n      break;\n    }\n    while(*p!=' ' &amp;&amp; *p!='\\0') \/\/ find next space\n      p++;\n    while(*p==' ' &amp;&amp; *p!='\\0') \/\/ find next non space\n      p++;\n    e++;\n  }\n  if(ok) {\n    q=buf;\n    count=0;\n    while(*q!=' ' &amp;&amp; *q!='\\0') {\n      if(++count&lt;len)\n\t*q++=*p;\n      p++;\n    }\n    *q='\\0';\n  } else {\n    buf&#91;0]='\\0';\n  }\n}\n\nvoid line_dump(unsigned char *string)\n{\n  int e,n;\n  unsigned char *p;\n\n  p=string;\n  n=0;\n  while(*p!='\\0') {\n    fprintf(stdout,\" %d:\",n++);\n    while(*p!=' ' &amp;&amp; *p!='\\0') \/\/ find next space\n      putchar(*p++);\n    while(*p==' ' &amp;&amp; *p!='\\0') \/\/ find next non space\n      p++;\n    e++;\n  }\n  fprintf(stdout,\"\\n\");\n}\n\n#define aDEBUG86 2\n#define aDEBUG87 2\n#define aDEBUG88 2\n#define aDEBUG89 2\n\nint main(int argc, char *argv&#91;])\n{\n  int c, d, e, size=5, sspace=0,\n    chars=72, pchars=0, words=0, pwords=0,\n    lines=10, plines=0, plinesdigits=5, slines=1,\n    quiet=0, zero=1, sort=0, unique=0;\n  unsigned char *digits=\"0123456789\",\n    digitstemp&#91;256], character&#91;32];\n  unsigned long limit;\n\n  procname=argv&#91;0];\n\n#ifdef KAL\n  c=0;\n  for(;;) {\n    unsigned char buffer&#91;2048];\n    ressu_genbytes(sizeof(buffer),buffer);\n  }\n#endif\n  limit=0;\n#ifdef DEBUG4\n  ccp=cc;\n  cc_bytes=0;\n#endif\n  clockbytes=0;\n  for(d=0;d&lt;1024;d++)\n    periods&#91;d]=0;\n\n  \/\/ look thru command line parameters\n  \n  for(c=1;c&lt;argc;c++) {\n    if(!strncmp(\"-\",argv&#91;c],1)) {\n      if(!strcmp(\"--lineno\",argv&#91;c])) {\n\tslines=!slines;\n\n      } else if(!strcmp(\"--quiet\",argv&#91;c])) {\n\tquiet=!quiet;\n\n      } else if(!strcmp(\"--stats\",argv&#91;c]) ||\n\t!strcmp(\"--stat\",argv&#91;c])) {\n\tstats=!stats;\n\n      } else if(!strcmp(\"--space\",argv&#91;c])) {\n\tsspace=!sspace;\n\n      } else if(!strcmp(\"--zero\",argv&#91;c])) {\n\tzero=!zero;\n\n      } else if(!strcmp(\"--sort\",argv&#91;c])) {\n\tsort=!sort;\n\tif(sspace==0)\n\t  sspace=1;\n\t\t\n      } else if(!strcmp(\"--unique\",argv&#91;c])) {\n\tunique=!unique;\n\tif(sspace==0)\n\t  sspace=1;\n\t\t\n      } else if(!strcmp(\"--lotto\",argv&#91;c])) {\n\tsort=!sort;\n\tif(sspace==0)\n\t  sspace=1;\n\t\/\/sort=1;\n\t\/\/unique=1;\n      } else if(!strcmp(\"--copyright\",argv&#91;c]) ||\n\t !strcmp(\"--version\",argv&#91;c])) {\n\tfprintf(stderr,\"%s\",programname);\n\tfprintf(stderr,\", %s\",copyright);\n\tfprintf(stderr,\"\\n\\n\");\n\thelp=1;\n\t\n      } else if(!strncmp(\"--lim\",argv&#91;c],5)) {\n\tif(*(argv&#91;c]+5)!='\\0') {\n\t  in_word(&amp;limit, digits, argv&#91;c]+5);\n\t} else if(c+1&lt;argc) {\n\t  in_word(&amp;limit, digits, argv&#91;c+1]);\n\t  c++;\n\t}\n\tsspace=1;\n\n      } else if(!strncmp(\"-s\",argv&#91;c],2)) {\n\tif(*(argv&#91;c]+2)!='\\0') {\n\t  size=atoi(argv&#91;c]+2);\n\t} else if(c+1&lt;argc) {\n\t  size=atoi(argv&#91;c+1]);\n\t  c++;\n\t}\n\tif(size==0)\n\t  size=1;\n      } else if(!strncmp(\"--bits\",argv&#91;c],6)) {\n\tif(*(argv&#91;c]+6)!='\\0') {\n\t  ressu_bits_needed=atoi(argv&#91;c]+6);\n\t} else if(c+1&lt;argc) {\n\t  ressu_bits_needed=atoi(argv&#91;c+1]);\n\t  c++;\n\t}\t\n\n      } else if(!strncmp(\"--bytes\",argv&#91;c],7)) {\n\tif(*(argv&#91;c]+7)!='\\0') {\n\t  ressut_bytes=atoi(argv&#91;c]+7);\n\t} else if(c+1&lt;argc) {\n\t  ressut_bytes=atoi(argv&#91;c+1]);\n\t  c++;\n\t}\t\n\n      } else if(!strncmp(\"-w\",argv&#91;c],2)) { \/\/ words per line\n\tif(*(argv&#91;c]+2)!='\\0') {\n\t  words=atoi(argv&#91;c]+2);\n\t} else if(c+1&lt;argc) {\n\t  words=atoi(argv&#91;c+1]);\n\t  c++;\n\t}\n\tif(words&lt;1)\n\t  words=1;\n\t\n\tchars = 0;\n\t\n      } else if(!strncmp(\"-c\",argv&#91;c],2)) {  \/\/ characters per line\n\tif(*(argv&#91;c]+2)!='\\0') {\n\t  chars=atoi(argv&#91;c]+2);\n\t} else if(c+1&lt;argc) {\n\t  chars=atoi(argv&#91;c+1]);\n\t  c++;\n\t}\n\twords=0;\n\t\n      } else if(!strncmp(\"-l\",argv&#91;c],2)) { \/\/ lines\n\tif(*(argv&#91;c]+2)!='\\0') {\n\t  lines=atoi(argv&#91;c]+2);\n\t} else if(c+1&lt;argc) {\n\t  lines=atoi(argv&#91;c+1]);\n\t  c++;\n\t}\n\tif(lines&lt;1)\n\t  lines=1;\n\n      } else if(!strcmp(\"-x\",argv&#91;c])) {\n\tdigits = \"0123456789abcdef\";\n\tsize=4;\n\n      } else if(!strcmp(\"-d\",argv&#91;c])) {\n\tdigits = \"0123456789\";\n\tsize=5;\n\n      } else if(!strcmp(\"-o\",argv&#91;c])) {\n\tdigits = \"01234567\";\n\tsize=3;\n\n      } else if(!strcmp(\"-b\",argv&#91;c])) {\n\tdigits = \"01\";\n\tsize=8;\n\n      } else if(!strcmp(\"-1\",argv&#91;c])) {\n\tdigits=\n\t  \"0123456789\" \\\n\t  \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n\t  \"abcdefghijklmnopqrstuvwxyz\";\n\tsize=8;\n\n      } else if(!strcmp(\"-2\",argv&#91;c])) {\n\tdigits=\n\t  \"0123456789\" \\\n\t  \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n\t  \"abcdefghijklmnopqrstuvwxyz\" \\\n\t  \"_-\";\n\tsize=8;\n\n      } else if(!strcmp(\"-3\",argv&#91;c])) { \/\/ 9.5.2021 JariK\n\tdigits=\n\t  \"!\\\"#$%&amp;'()*+,-.\/0123456789:;&lt;=&gt;?@\" \\\n\t  \"ABCDEFGHIJKLMNOPQRSTUVWXYZ&#91;\\\\]^_`\" \\\n\t  \"abcdefghijklmnopqrstuvwxyz{|}~\";\n\tsize=8;\n\n      } else if(!strcmp(\"-4\",argv&#91;c])) {\n\tdigits=\n\t  \"\u0410\u0411\u0412\u0413\u0414\u0415\u0401\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\" \\\n\t  \"\u0430\u0431\u0432\u0433\u0434\u0435\u0451\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\";\n\tsize=8;\n\n      } else if(!strcmp(\"--isalnum\",argv&#91;c]) || \/\/ 9.5.2021 JariK\n\t        !strcmp(\"--isalpha\",argv&#91;c]) ||\n\t        !strcmp(\"--isdigit\",argv&#91;c]) ||\n\t        !strcmp(\"--isgraph\",argv&#91;c]) ||\n\t        !strcmp(\"--islower\",argv&#91;c]) ||\n\t        !strcmp(\"--isprint\",argv&#91;c]) ||\n\t        !strcmp(\"--ispunct\",argv&#91;c]) ||\n\t        !strcmp(\"--isupper\",argv&#91;c]) ||\n\t\t!strcmp(\"--isxdigit\",argv&#91;c])) {\n\tunsigned char *p=digitstemp;\n\tfor(d=0;d&lt;256;d++) {\n\t  if((!strcmp(\"--isalnum\",argv&#91;c]) &amp;&amp; isalnum(d)) ||\n\t     (!strcmp(\"--isalpha\",argv&#91;c]) &amp;&amp; isalpha(d)) ||\n\t     (!strcmp(\"--isdigit\",argv&#91;c]) &amp;&amp; isdigit(d)) ||\n\t     (!strcmp(\"--isgraph\",argv&#91;c]) &amp;&amp; isgraph(d)) ||\n\t     (!strcmp(\"--islower\",argv&#91;c]) &amp;&amp; islower(d)) ||\n\t     (!strcmp(\"--isprint\",argv&#91;c]) &amp;&amp; isprint(d)) ||\n\t     (!strcmp(\"--ispunct\",argv&#91;c]) &amp;&amp; ispunct(d)) ||\n\t     (!strcmp(\"--isupper\",argv&#91;c]) &amp;&amp; isupper(d)) ||\n\t     (!strcmp(\"--isxdigit\",argv&#91;c]) &amp;&amp; isxdigit(d))) {\n\t    *p++=d;\n\t  }\n\t}\n\t*p='\\0';\n\tdigits=digitstemp;\n\tsize=8;\n\n      } else if(!strcmp(\"--rand\",argv&#91;c])) {\n\tdigits = \"0123456789\";\n\tsspace=3;\n\tslines=1;\n\twords=10;\n\tchars=0;\n\tlimit=100000;\n\t\/\/size=5;\n\t\/\/lines=20000;\n\t\n      } else if(!strncmp(\"-i\",argv&#91;c],2)) {\n\tdigits=NULL;\n\tif(*(argv&#91;c]+2)!='\\0') {\n\t  digits=argv&#91;c]+2;\n\t} else if(c+1 &lt; argc) {\n\t  digits=argv&#91;c+1];\n\t  c++;\n\t}\n\tif(digits==NULL || utf8len(digits)&lt;2) {\n\t  fprintf(stderr,\"%s: not enough digits \\\"%s\\\"\\n\",procname,argv&#91;c]);\n\t  help = 1;\n\t}\n\tsize=1;\n      } else if(!strcmp(\"--ressu\",argv&#91;c])) {\n\tinput=0;\n      } else if(!strcmp(\"--debug\",argv&#91;c])) {\n\tinput=1;\n      } else if(!strcmp(\"--fast\",argv&#91;c])) {\n\tinput=2;\n      } else if(!strcmp(\"--single\",argv&#91;c])) {\n\tinput=3;\n      } else if(!strcmp(\"--urandom\",argv&#91;c])) {\n\tinput=8;\n#ifdef USE_RANDOM\n      } else if(!strcmp(\"--random\",argv&#91;c])) {\n\tinput=9;\n#endif\n      } else {\n\tfprintf(stderr,\"%s: invalid option %s\\n\",procname,argv&#91;c]);\n\thelp = 1;\n      }\n    } else {\n      help = 1;\n    } \/\/ if(!strncmp\n  } \/\/ for(c=0\n\n  unsigned long word;\n  unsigned char wordbuf&#91;1024];\n  unsigned char wordbuf2&#91;1024];\n  unsigned char wordbuf3&#91;1024];\n\n  \/\/ get linenumber length in digits\n\n  out_word(sizeof(wordbuf),wordbuf,\"0123456789\",lines-1);\n  plinesdigits=strlen(wordbuf);\n  if(plinesdigits&lt;5)\n    plinesdigits=5;\n\n  \/\/ get data length in digits\n\n  if(limit!=0) {\n    unsigned char wordbuf&#91;128];\n    out_word(sizeof(wordbuf),wordbuf,digits,limit-1);\n    size=utf8len(wordbuf);\n  }\n\n  pchars=0;\n  pwords=0;\n  int linew=0;\n\n  \/\/ in beginning of line, count printed line number\n      \n  if(!quiet &amp;&amp; slines) {\n    sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n    pchars += strlen(wordbuf2);\n    pchars++;\n  }\n\n  \/\/ count words\n  \n  while((chars&gt;0 &amp;&amp; pchars+size &lt; chars) ||\n\t(words&gt;0 &amp;&amp; pwords &lt; words)) {\n\n    linew++;\n    \n    if(sspace &amp;&amp; pchars&gt;0 &amp;&amp; !quiet) {\n      if(sspace==3 &amp;&amp; pwords%2==0)\n\tpchars++;\n      pchars++;\n    }\n\t\n    pchars+=size;\n    pwords++;\n  }\n\n  unsigned long wordvalues=1;\n  for(c=0;c&lt;size;c++) {\n    if(wordvalues!=0 &amp;&amp; wordvalues*utf8len(digits)&lt;(unsigned long)65536*65536*65536) {\n      wordvalues*=utf8len(digits);\n    } else {\n      wordvalues=0;\n    }\n  }\n\n  if(limit &gt; 0) {\n    if(sort==1 &amp;&amp; limit-!zero&lt;words) {\n      fprintf(stderr,\"%s: limit is less than words (zero)\",procname);\n      fprintf(stderr,\", limit:%lu\",limit);\n      fprintf(stderr,\", words:%d\",words);\n      fprintf(stderr,\", zero:%d\",zero);\n      fprintf(stderr,\"\\n\");\n      \n      help=1;\n      lines=0;\n    }\n  } else {\n    if(sort==1 &amp;&amp; size&gt;0 &amp;&amp; wordvalues&gt;0 &amp;&amp; wordvalues&lt;linew) {\n      fprintf(stderr,\"%s:\",procname);\n      fprintf(stderr,\" digits is less than calculated words\");\n      fprintf(stderr,\", digits:%d(%lu)\",utf8len(digits),wordvalues);\n      fprintf(stderr,\", words:%d\\n\",linew);\n      help=1;\n      lines=0;\n    }\n  }\n\n  \/\/ small words as single ressu_gen_limit()\n  \n  if(limit==0 &amp;&amp; wordvalues&gt;0)\n    limit=wordvalues;\n\n  if(stats) {\n    fprintf(stdout,\"randomsource: %s\",randomgen&#91;input]);\n    fprintf(stdout,\", size: %d\",size);\n    fprintf(stdout,\", linew: %d\",linew);\n    fprintf(stdout,\", pchars: %d\",pchars);\n    fprintf(stdout,\", pwords: %d\",pwords);\n    if(wordvalues&gt;0)\n      fprintf(stdout,\", wordvalues: %lu\",wordvalues);\n    if(limit&gt;0)\n      fprintf(stdout,\", limit: %lu\",limit);\n    fprintf(stdout,\"\\n\");\n  }\n  \n  if(help) {\n    struct helpline {\n      char *command;\n      char *text;\n    } helplines&#91;] = {\n      { \"newressu -d\", \"print random decimal digits\" },\n      { \"newressu -o\", \"print octal digits\" },\n      { \"newressu -x\", \"print hexadecimal digits\" },\n      { \"newressu -b\", \"print binary digits\" },\n      { \"newressu -d --space\", \"print decimal digits, with spaces between \\\"words\\\"\" },\n      { \"newressu -b --space\", \"print binary digits, with spaces between \\\"words\\\"\" },\n      { \"newressu -d -l30\", \"print decimal digits, 30 lines\" },\n      { \"newressu -d -l30 --lineno\", \"print decimal digits, 30 lines, no linenumbers\"  },\n      { \"newressu -d -c128\", \"print decimal digits, 128 characters per line\"  },\n      { \"newressu -d --lim10\", \"print decimal numbers between 0-9\" },\n      { \"newressu -d --lim10 -x\",\"print hexadecimal numbers with decimal limit\" },\n      { \"newressu -d -s10 --space\",\"print decimal numbers with spaces and wordsize 10\" },\n      { \"newressu -d --space --zero --lim7\",\"print rollings of dice (1-6)\" },\n      { \"newressu -b -s1 --space\",\"print throws of coin (0,1)\" },\n      { \"newressu -d --lim41 -w7 --zero --lotto\",\"print lotto numbers for finnish lotto 7x(1-40)\" },\n      { \"newressu -d -s5 --sort -w16\",\"print 16 sorted decimal numbers from 0 to 99999\" },\n      { \"newressu --isalnum\", \"print alphanumeric characters\" },\n      { \"newressu --isalpha\", \"print alphabetic characters\" },\n      { \"newressu --isgraph\", \"print printables excluding space\" },\n      { \"newressu --islower\", \"print lowercase characters\" },\n      { \"newressu --ispunct\", \"print punctuation characters\" },\n      { \"newressu --isupper\", \"print uppercase characters\" },\n      { \"newressu -1\", \"print material for passwords\" },\n      { \"newressu -i\u0430\u044d\u044b\u0443\u043e\u044f\u0435\u0451\u044e\u0438\", \"print russian vowels\" },\n      { \"newressu --ressu\", \"use randomness from ressu (default)\" },\n      { \"newressu --debug\", \"use randomness from debugging ressu\" },\n      { \"newressu --fast\", \"use randomness from fast ressu\" },\n      { \"newressu --single\", \"use randomness from single round of ressu\" },\n      { \"newressu --urandom\", \"use randomness from \/dev\/urandom\" },\n#ifdef USE_RANDOM\n      { \"newressu --random\", \"use randomness from \/dev\/random\" },\n#endif\n    };\n    \n    for(c=0;c&lt;sizeof(helplines)\/sizeof(helplines&#91;0]);c++) {\n      fprintf(stderr,\"%-50s\",helplines&#91;c].text);\n      fprintf(stderr,\"%-25s\",helplines&#91;c].command);\n      fprintf(stderr,\"\\n\");\n    }\n    for(c=0;c&lt;chars;c++)\n      fprintf(stdout,\"*\");\n    fprintf(stdout,\"\\n\");\n    if(lines&gt;1)\n      lines=1; \/\/ print one line below help as a sample\n  }\n\n  if(lines==0)\n    exit(1);\n\n  int linecnt=0;\n  unsigned char *line=NULL;\n  \n  for(;;) {\n\n    if(!sort) { \/\/ also lotto\n\n      pchars=0;\n      pwords=0;\n\n      while(pwords&lt;linew) {\n\tif(limit!=0) {\n\t  word=0;\n\t  \n\t  if(zero) {\n\t    word=ressu_gen_limit(limit); \/\/ include zeroes\n\t    \/\/fprintf(stdout,\"(%lo)\",word);\n\t  } else if(limit&gt;=1) {\n\t    while((word=ressu_gen_limit(limit))==0); \/\/ skip zeroes\n\t  }\n\t  \n\t  out_word(sizeof(wordbuf3),wordbuf3,digits,word);\n\t  \n\t  \/\/ fill leading zeroes\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  utf8getchar(sizeof(character),character,0,digits);\n\t  for(d=size-utf8len(wordbuf3);d&gt;0;d--) {\n\t    strcat(wordbuf,character);\n\t  }\n\t  \n\t  \/\/ rest of the number\n\t  \n\t  strcat(wordbuf,wordbuf3);\n\t  \n\t} else if(digits!=NULL) {\n\t  int digitslen;\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  digitslen=utf8len(digits);\n\t  \n\t  \/\/ fill whole word digit by digit\n\t  \n\t  for(d=0;d&lt;size;d++) {\n\t    if(digits&#91;0]=='0' &amp;&amp; !zero)\n\t      e=ressu_gen_limit(digitslen-1)+1;\n\t    else\n\t      e=ressu_gen_limit(digitslen);\n\t    utf8getchar(sizeof(wordbuf3),wordbuf3,e,digits);\n\t    \/\/fprintf(stdout,\"(%s)\",wordbuf3);\n\t    strcat(wordbuf,wordbuf3);\n\t  }\n\t}\n\n\t\/\/ in beginning of line, print line number\n\n\tif(pchars==0 &amp;&amp; !quiet &amp;&amp; slines) {\n\t  sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n\t  fprintf(stdout,\"%s\",wordbuf2);\n\t  pchars +=strlen(wordbuf2);\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ want to print spaces between \"words\"?\n\t\n\tif(sspace &amp;&amp; pchars&gt;0 &amp;&amp; !quiet) {\n\t  if(sspace==3 &amp;&amp; pwords%2==0) {\n\t    fprintf(stdout,\" \");\n\t    pchars++;\n\t  }\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ print word\n\t\n\tif(size!=0) {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%*s\",size,wordbuf);\n\t  pchars += size;\n\t  pwords++;\n\t} else {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%s\",wordbuf);\n\t  pchars += strlen(wordbuf);\n\t  pwords++;\n\t}\n      } \/\/ while(pwords&lt;linew) {\n    } else { \/\/ if(!sort)\n\n      pchars=0;\n      pwords=0;\n      \n      line_clear(&amp;linecnt,&amp;line);\n\n      \/\/ fetch and save words on this row\n      while(pwords&lt;linew) {\n\tif(limit!=0) {\n\t  word=0;\n\t  \n\t  if(zero) {\n\t    word=ressu_gen_limit(limit); \/\/ include zeroes\n\t  } else if(limit&gt;=1) {\n\t    while((word=ressu_gen_limit(limit))==0); \/\/ skip zeroes\n\t  }\n\t  \n\t  out_word(sizeof(wordbuf3),wordbuf3,digits,word);\n\t  \n\t  \/\/ fill leading zeroes\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  utf8getchar(sizeof(character),character,0,digits);\n\t  for(d=size-utf8len(wordbuf3);d&gt;0;d--) {\n\t    strcat(wordbuf,character);\n\t  }\n\t  \n\t  \/\/ rest of the number\n\t  \n\t  strcat(wordbuf,wordbuf3);\n\t  \n\t} else if(digits!=NULL) {\n\t  int digitslen;\n\t  \n\t  wordbuf&#91;0]='\\0';\n\t  digitslen=utf8len(digits);\n\t  \n\t  \/\/ fill whole word digit by digit\n\t  \n\t  for(d=0;d&lt;size;d++) {\n\t    if(digits&#91;0]=='0' &amp;&amp; !zero)\n\t      e=ressu_gen_limit(digitslen-1)+1;\n\t    else\n\t      e=ressu_gen_limit(digitslen);\n\t    utf8getchar(sizeof(wordbuf3),wordbuf3,e,digits);\n\t    strcat(wordbuf,wordbuf3);\n\t  }\n\t}\n\n\tif(line_add_string_sort(&amp;linecnt,&amp;line,wordbuf)) {\n\t  pwords++;\n\t}\n      } \/\/ while(pwords&lt;linew) {\n\n      pchars=0;\n      pwords=0;\n\n      \/\/ print words on this row\n      while(pwords&lt;linew) {\n\n\tline_get_string(sizeof(wordbuf),wordbuf,pwords,line);\n\n\t\/\/ in beginning of line, print line number\n\n\tif(pchars==0 &amp;&amp; !quiet &amp;&amp; slines) {\n\t  sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n\t  fprintf(stdout,\"%s\",wordbuf2);\n\t  pchars +=strlen(wordbuf2);\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ want to print spaces between \"words\"?\n\t\n\tif(sspace &amp;&amp; pchars&gt;0 &amp;&amp; !quiet) {\n\t  if(sspace==3 &amp;&amp; pwords%2==0) {\n\t    fprintf(stdout,\" \");\n\t    pchars++;\n\t  }\n\t  fprintf(stdout,\" \");\n\t  pchars++;\n\t}\n\t\n\t\/\/ print word\n\t\n\tif(size!=0) {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%*s\",size,wordbuf);\n\t  pchars += size;\n\t  pwords++;\n\t} else {\n\t  if(!quiet)\n\t    fprintf(stdout,\"%s\",wordbuf);\n\t  pchars += strlen(wordbuf);\n\t  pwords++;\n\t}\n      } \/\/ while(pwords&lt;linew) {\n    } \/\/ if(!sort)\n\n    \/\/ line full?\n    \n    if(!quiet)\n      fprintf(stdout,\"\\n\");\n    plines++;\n    if(sspace==3 &amp;&amp; plines&lt;lines &amp;&amp; plines%5==0)\n      fprintf(stdout,\"\\n\");\n\n    \/\/ all needed lines printed?\n    \n    if(plines &gt;= lines)\n      break;\n\n  } \/\/ for(;;)\n  fflush(stdout);\n}\n\n#endif \/\/ MAIN<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n. Edellisess\u00e4 Ressu 2.0 postissa esiteltyyn toiminnallisuuteen on tehty seuraavia muutoksia: asiallinen lottonumeroiden tulostus, tuotantoversio ressusta (ilman debukkailuja), debukkailuversio ressusta erikseen, digits merkkijonon perusteella teht\u00e4v\u00e4n tulosteen nopeutus, virheiden korjauksia, ja yleist\u00e4 luettavuuden parantamista. Koko ohjelma on kopypastattavissa postin lopussa. K\u00e4yn seuraavassa l\u00e4pi valitut osat uudesta ohjelmasta. Ensin ns tuotantoversio ressusta. Tuotantoversiossa on viel\u00e4&hellip; <a class=\"more-link\" href=\"https:\/\/moijari.com\/?p=1687\">Continue reading <span class=\"screen-reader-text\">Ressu 2.1 Lottonumerot ja muuta<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,11],"tags":[],"_links":{"self":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1687"}],"collection":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1687"}],"version-history":[{"count":13,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1687\/revisions"}],"predecessor-version":[{"id":1701,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1687\/revisions\/1701"}],"wp:attachment":[{"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1687"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1687"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1687"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}