{"id":1545,"date":"2021-05-22T23:08:18","date_gmt":"2021-05-22T21:08:18","guid":{"rendered":"https:\/\/moijari.com\/?p=1545"},"modified":"2021-06-01T15:12:37","modified_gmt":"2021-06-01T13:12:37","slug":"ressu-2-0","status":"publish","type":"post","link":"https:\/\/moijari.com\/?p=1545","title":{"rendered":"Ressu 2.0"},"content":{"rendered":"\n<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n. T\u00e4ss\u00e4 ressun uusimmassa versiossa on uusittu asiakaspuskurin hallintaa, l\u00f6ydetty kellojonosta l\u00f6ytyvien satunnaisbittien &#8220;laskentaan&#8221; uusi menetelm\u00e4.<\/p>\n\n\n\n<p>Asiakaspuskurin hallinnassa aiemmin asiakas toimitti puskurin satunnaisbittigeneraattorin t\u00e4ytett\u00e4v\u00e4ksi, ja satunnaislukugeneraattorilla ei ollut &#8220;omaa&#8221; muistialuetta. N\u00e4in j\u00e4\u00e4 aina mietitt\u00e4v\u00e4ksi voisiko edellisest\u00e4 puskurista laskea seuraavan tai p\u00e4\u00e4tell\u00e4 satunnaisbittigeneraattorin ensimm\u00e4isen puskurin. Uudessa versiossa ressulla on oma puskurinsa, josta ressu palauttaa satunnaisia merkkej\u00e4 asiakaspuskuriin. N\u00e4in asiakas ei saa koko puskurin rakennetta, vaan satunnaisen osan siit\u00e4.<\/p>\n\n\n\n<p>Kellojonosta l\u00f6ytyvien satunnaisbittien laskentaa on useassa aiemmassa postissa, ja nyt on t\u00e4st\u00e4 uusin versio ajattelun alla. Uusi versio perustuu fluctuations eli vaihtelut tulosteeseen. Tulosteesta poistetaan suurimmat ketjut ja j\u00e4ljelle j\u00e4\u00e4v\u00e4t lasketaan yhteen. T\u00e4st\u00e4 saadaan arvioidut satunnaisbitit.<\/p>\n\n\n\n<p>Ajatuksena on ett\u00e4 n\u00e4m\u00e4 suurimmat ketjut ovat se perusmateriaali jota kellomateriaali sis\u00e4lt\u00e4\u00e4 ja ett\u00e4 ne eiv\u00e4t sis\u00e4lt\u00e4isi paljoa satunnaisuutta. Toisaalta n\u00e4m\u00e4 pienet ketjut esiintyv\u00e4t silloin t\u00e4ll\u00f6in satunnaisessa paikassa koko kellomateriaalin alueella ja n\u00e4in niist\u00e4 voidaan aina laskea jonkin verran satunnaisuutta.<\/p>\n\n\n\n<p>Lis\u00e4ksi lopussa on kiva lelu satunnaismerkkien hakemiseen.<\/p>\n\n\n\n<p>Edit: korjailtu bugeja ja ohjelman formatointia. Nyt t\u00e4ytyy sanoa, ett\u00e4 t\u00e4m\u00e4 on mielest\u00e4ni l\u00e4himp\u00e4n\u00e4 tuotantoversiota t\u00e4h\u00e4n asti. Ei viel\u00e4k\u00e4\u00e4n ainoana generaattorina vaan lis\u00e4ttyn\u00e4 johonkin\/joihinkin muuhun generaattoriin. Jatkan tutkimista..<\/p>\n\n\n\n<p>Edit: muutettu lim lauseen sqrt cbrt:ksi. Kokeilu.<\/p>\n\n\n\n<p>T\u00e4ss\u00e4 postissa k\u00e4yn uusimman ohjelmaversion l\u00e4pi, ja kommentoin kappaleita. Vaihtelut lasketaan periods tauluun ja clockbytes on kellojonon merkkien lukum\u00e4\u00e4r\u00e4. Kuvassa oleva ressu_clockbyte() rutiini on vanha tuttu millisekuntien alimman merkin palauttava rutiini:<\/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 DEBUG8 2\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>Seuraava rutiini on ressun varsinainen generaattorip\u00e4tk\u00e4, joka hakee varsinaiset satunnaisluvut. Se lukee kellojonoa ja xor:aa kellojonon merkill\u00e4 puskurissa olevan merkin. Ensin xora:taan koko jonosta alin bitti, sitten toiseksi alin bitti, kolmanneksi alin ja niin edelleen. Aina kun koko puskurin yksitt\u00e4inen bitti on xor:attu vaihdetaan puskurissa merkkien paikkoja ja vaihdetaan alinta bitti\u00e4. Puhun muuten alimmasta bitist\u00e4, mutta todellisuudessa koko puskurin merkki xorataan. T\u00e4rke\u00e4t\u00e4 on se, ett\u00e4 kellojonon alimmalla bitill\u00e4 xorataan kaikki puskurin bitit. Alin bitti on se, jossa on eniten vaihtelua. Lis\u00e4ksi puskurin kaikki bitit kaikkia muitakin kellojonon 8 alinta bitti\u00e4.<\/p>\n\n\n\n<p>Seuraavan kappaleen ensimm\u00e4inen luuppi (for(d=0)) tekee xor:auksen yhdelle bitille (koko puskurissa). Toinen (for(d=0)) luuppi vaihtaa kaikkien merkkien paikkoja kesken\u00e4\u00e4n. N\u00e4it\u00e4 kahta suoritetaan 8 kertaa (for(c=0)), yksi jokaiselle merkkien bitille.<\/p>\n\n\n\n<p>Yhden genbytes_fast rutiinin ajon aikana yksitt\u00e4inen merkki xor:ataan kahdeksan kellojonon bitin kanssa, ja kellojonon bitti vaihtelee merkin puskuripaikan mukaan. Puskuripaikka vaihtelee satunnaisesti.<\/p>\n\n\n\n<p>Aliohjelmassa on kolme erilaista merkin py\u00f6ritysvaihtoehtoa, jotka ovat mahdollisia. N\u00e4ist\u00e4 on kuitenkin k\u00e4ytetty vain rotate left 1 vaihtoehtoa. Rotate left 3 kattaisi teoriassa nopeammin koko merkin, mutta sit\u00e4 ei ole tosiaan k\u00e4ytetty.<\/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        prevbyte=byte;\n      buffer&#91;d] = e^byte;\n      if(prevbyte!=byte) {\n        periods&#91;count]++;\n        clockbytes+=count;\n        count=0;\n        prevbyte=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<\/code><\/pre>\n\n\n\n<p>Seuraava rutiini on varsinainen asiakkaan kutsuma rutiini, kuten sanottu t\u00e4ss\u00e4 versiossa pidet\u00e4\u00e4n varsinaiset satunnaismerkit ja asiakkaan puskuri erill\u00e4\u00e4n. Asiakkaan puskuriin merkit kootaan (for(c=0)) luupilla, ja jos varsinaiset satunnaisbitit loppuvat (if ressut_pos) ehtolauseella haetaan niit\u00e4 lis\u00e4\u00e4. DEBUG9 ja DEBUG8 ovat debukkailua varten, ja ensimm\u00e4isell\u00e4 yritet\u00e4\u00e4n synkronoida kellojonot siten ett\u00e4 satunnaisbitit poimitaan samanlaisesta kellojonon kohdasta debukkailua varten, toisella taas raportoidaan debug tiedostoon &#8220;newressu.deb&#8221; juuri haettu puskuri. Tiedosto esittelee parhaiten sen miten teoreettiset satunnaisbitit lasketaan. Siit\u00e4 lis\u00e4\u00e4 kuvan j\u00e4lkeen:<\/p>\n\n\n\n<p>Lis\u00e4ksi rutiinissa on uutena asiana se ett\u00e4, miten paljon satunnaisbittej\u00e4 tuotetaan ja miten paljon &#8220;teoreettisia bittej\u00e4&#8221; tarvitaan m\u00e4\u00e4ritell\u00e4\u00e4n erikseen. Aiemmissa versioissa tuotettavat ja laskennalliset satunnaisbitit olivat sama asia. Ne m\u00e4\u00e4ritell\u00e4\u00e4n alun #defineiss\u00e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define RESSUT_SIZE 4096\n#define RESSU_BITS_NEEDED 128\n#define RESSU_MIN_ROUNDS 2\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_size = RESSUT_SIZE,\n    ressut_f = 0;\n  static unsigned char ressut&#91;RESSUT_SIZE];\n\n  for(c=0; c&lt;size; c++) {\n    if(ressut_pos == 0) {\n      if(ressut_first) {\n        memset(ressut,0,sizeof(ressut));\n        ressut_first=0;\n      }\n\n      clockbytes=0;\n      for(d=0;d&lt;1024;d++)\n        periods&#91;d]=0;\n#ifdef DEBUG9\n      while(ressu_clockbyte()!=0);\n      while(ressu_clockbyte()==0);\n#endif\n      int rndbits=0, rounds=0;\n\n      for(d=0; rndbits&lt;RESSU_BITS_NEEDED ||\n          d&lt;RESSU_MIN_ROUNDS; d++) {\n        rounds++;\n        ressu_genbytes_fast(sizeof(ressut),ressut);\n        rndbits=0;\n        for(e=0;e&lt;1024;e++) {\n          if(periods&#91;e]&gt;0 &amp;&amp; periods&#91;e]&lt;sqrt((double)clockbytes)) {\n            rndbits+=periods&#91;e];\n          }\n        }\n      }\n\n#ifdef DEBUG8\n\n      FILE *fp1;\n      if((fp1=fopen(\"newressu.deb\",\"a\"))!=NULL) {\n\n        for(d=0;d&lt;32;d++)\n          fprintf(fp1,\"%02x\",ressut&#91;d]);\n\n        fprintf(fp1,\", clockbytes: %ld\",clockbytes);\n\n        unsigned long total=0;\n        fprintf(fp1,\", fluctuations:\");\n        for(d=0;d&lt;1024;d++) {\n          if(periods&#91;d]!=0) {\n            fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n            total+=(periods&#91;d]*d);\n          }\n        }\n        fprintf(fp1,\", total: %lu\",total);\n\n        fprintf(fp1,\", limit: %lu\",(unsigned long)sqrt((double)clockbytes));\n\n        fprintf(fp1,\", skipped:\");\n        for(d=0;d&lt;1024;d++) {\n          if(periods&#91;d]&gt;=sqrt((double)clockbytes))\n            fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n        }\n\n        fprintf(fp1,\", counted:\");\n        rndbits=0;\n        for(d=0;d&lt;1024;d++) {\n          if(periods&#91;d]&gt;0 &amp;&amp; periods&#91;d]&lt;sqrt((double)clockbytes)) {\n            fprintf(fp1,\" %d:%lu\",d,periods&#91;d]);\n            rndbits+=periods&#91;d];\n          }\n        }\n        fprintf(fp1,\", rndbits: %d\",rndbits);\n        fprintf(fp1,\", rounds: %d\",rounds);\n\n        fprintf(fp1,\"\\n\");\n\n        fclose(fp1);\n      } \/\/ if((fp1=fopen\n#endif\n    } \/\/ if(ressut_pos == 0)\n    ressut_f = (ressut_f + ressut&#91;ressut_pos]) % ressut_size;\n    buffer&#91;c] ^= ressut&#91;ressut_f];\n    ressut_pos = (ressut_pos+1) % ressut_size;\n  } \/\/ for(c=0; c&lt;size; c++)\n\n  genbytes+=size;\n}<\/code><\/pre>\n\n\n\n<p>Seuraavassa kappaleessa on esimerkki newressu.deb tiedostoon ker\u00e4tyst\u00e4 tietueesta: clockbytes kertoo t\u00e4ll\u00e4 hetkell\u00e4 k\u00e4ytettyjen kellomerkkien m\u00e4\u00e4r\u00e4n, limit kentt\u00e4 lasketaan clockbytes kent\u00e4st\u00e4 (limit=sqrt(clockbytes)), fluctuations kertoo t\u00e4ss\u00e4 genbytes_fast ajossa olleet vaihtelut, skipped kertoo laskennassa ohitetut vaihtelut (&gt;=limit), counted kertoo teoreettisiin satunnaisbitteihin lasketut kellomerkit, rndbits on counted kenttien summa, suoritetut kierrokset t\u00e4ll\u00e4 ajokerralla on 8. ressu_genbytes_fast:ia ajetaan niin kauan kun teoreettisia satunnaisbittej\u00e4 on tarvittava m\u00e4\u00e4r\u00e4.<\/p>\n\n\n\n<p>9242aeaa253e187ed893374299d3c40a9ebcc4372f615269533f69fa163345b5, clockbytes: 262136, fluctuations: 1:13 2:7 3:15 4:12 5:13 6:8 7:9 8:9 9:6 10:11 11:10 12:8 13:22 14:9308 15:8720, total: 262136, limit: 511, skipped: 14:9308 15:8720, counted: 1:13 2:7 3:15 4:12 5:13 6:8 7:9 8:9 9:6 10:11 11:10 12:8 13:22, rndbits: 143, rounds: 8<\/p>\n\n\n\n<p>Seuraavassa vanhat tutut aputoiminnot, jotka k\u00e4ytt\u00e4v\u00e4t ressu_genbytes funktiota: rutiinit merkin (8 bits), shortin (16 bits), intin (32 bits) ja longin(64 bits) arpomiseksi. _limit-loppuisissa on yl\u00e4raja halutulle satunnaisnumerolle. Uutena n\u00e4iss\u00e4 on ressu_gen_limit, joka valitsee parametrina annetun limit:in mukaan sopivan talletuskoon.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int ressu_genbyte()\n{\n  unsigned char ch;\n  ressu_genbytes(sizeof(ch), &amp;ch);\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;=\n        (((unsigned long)65536*65536)\/limit)*limit);\n  return(c%limit);\n}\n\nunsigned long ressu_genlong()\n{\n  return(((unsigned long)ressu_genint()) |\n         ((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;=\n        (((unsigned long)0xffffffffffffffff)\/\n         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}<\/code><\/pre>\n\n\n\n<p>Loppuosuus postista koskee lelusovellusta, eli ensin lyhyt esittely ja sitten l\u00e4hdekielinen versio. N\u00e4iss\u00e4 esimerkeiss\u00e4 rivin pituus on 72:n sijaan 52, jotta ne mahtuvat koodi-ikkunaan.<\/p>\n\n\n\n<p>Aluksi virheellisist\u00e4 komennoista tulostetaan k\u00e4ytt\u00f6ohje:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu -?\n.\/newressu: invalid option -?\nprint random decimal digits                       newressu -d              \nprint octal digits                                newressu -o              \nprint hexadecimal digits                          newressu -x              \nprint binary digits                               newressu -b              \nprint decimal digits, with spaces between \"words\" newressu -d --space      \nprint binary digits, with spaces between \"words\"  newressu -b --space      \nprint decimal digits, 30 lines                    newressu -d -l30         \nprint decimal digits, 30 lines, no linenumbers    newressu -d -l30 --lineno\nprint decimal digits, 128 characters per line     newressu -d -c128        \nprint decimal numbers between 0-9                 newressu -d --lim10      \nprint hexadecimal numbers with decimal limit      newressu -d --lim10 -x   \nprint decimal numbers with spaces and wordsize 10 newressu -d -s10 --space \nprint alphanumeric characters                     newressu --isalnum       \nprint alphabetic characters                       newressu --isalpha       \nprint digits                                      newressu --isdigit       \nprint printables excluding space                  newressu --isgraph       \nprint lowercase characters                        newressu --islower       \nprint printable characters including space        newressu --isprint       \nprint punctuation characters                      newressu --ispunct       \nprint uppercase characters                        newressu --isupper       \nprint hexadecimal digits                          newressu --isxdigit      \nprint material for passwords                      newressu -1              \nprint random vowels                               newressu -iaeiouy\u00e5\u00e4\u00f6  \nprint russian vowels                              newressu -i\u0430\u044d\u044b\u0443\u043e\u044f\u0435\u0451\u044e\u0438\nflags                                             newressu -s -i\udbb9\udce5\udbb9\udce6\udbb9\udce7\udbb9\udce8\udbb9\udce9\udbb9\udcea\udbb9\udceb\udbb9\udcec\udbb9\udced\udbb9\udcee \nprint nice labyrinth                              newressu -i \"\/\\\"         \nprint statistics for ressu run                    newressu --stats         \nprint rand style random number table              newressu --rand -l20000  <\/code><\/pre>\n\n\n\n<p>Seuraavassa komento ilman parametreja: komento tulostaa kymmenen rivi\u00e4 desimaalisatunnaislukuja.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>jarik&gt;newressu\n00000 056552593701856488743208064053594455181555491\n00001 647836083655640471912091465183887333363812520\n00002 735962951043115775872773766654518963151341269\n00003 603704844650943255437410070844585966628674315\n00004 784156275041999237378412103711914182300000429\n00005 780768799139985291313622649468657009981882664\n00006 154427558713802757114262129440213749317145956\n00007 137569491937026029405363878424500216776474105\n00008 464074752787671526189691150232812511113631660\n00009 640527175186115479581523659194559928382662503<\/code><\/pre>\n\n\n\n<p>Seuraavassa desimaalilukuja v\u00e4lily\u00f6nneill\u00e4: sanojen oletus pituus desimaaliluvuissa on 5.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt;newressu --space\n00000  61911 65224 24982 56022 53474 17097 92678\n00001  91134 70560 25368 03967 41941 61026 68630\n00002  87228 04142 57313 98460 67128 78125 17012\n00003  59839 48032 77902 41734 64771 08145 89935\n00004  68054 22423 12768 13571 47189 03983 59352\n00005  78556 93369 17027 81312 98335 46255 01731\n00006  04806 08563 34406 64229 09668 04101 23024\n00007  55138 96983 11368 53354 74530 79906 56703\n00008  20257 80030 54596 50211 81565 96167 57735\n00009  46253 46243 60624 95624 85943 36918 62094<\/code><\/pre>\n\n\n\n<p>Seuraavassa kolmen merkin pituisia desimaalilukuja:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --space -s3\n00000  184 476 605 450 056 680 522 882 987 770 157\n00001  687 753 277 923 892 899 457 807 643 724 719\n00002  862 773 931 034 740 401 054 207 909 158 466\n00003  915 408 471 515 394 293 693 116 611 041 848\n00004  824 829 778 991 875 242 931 270 555 233 375\n00005  406 202 690 824 543 189 251 940 188 002 029\n00006  216 377 415 765 202 231 355 597 366 998 530\n00007  417 258 076 161 729 498 955 049 986 685 665\n00008  794 585 407 603 007 283 829 118 759 769 789\n00009  288 415 404 584 035 638 508 059 272 102 901\n<\/code><\/pre>\n\n\n\n<p>Seuraavassa desimaalisia satunnaislukuja v\u00e4lill\u00e4 0-11<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --lim12\n00000  00 03 02 01 05 04 06 08 09 00 08 00 05 02 06\n00001  03 01 09 08 10 00 03 10 11 04 04 01 03 11 00\n00002  11 06 07 03 02 01 06 09 05 11 09 10 11 02 01\n00003  06 04 02 10 01 04 04 04 00 08 05 05 10 08 07\n00004  01 07 04 00 05 00 03 00 06 07 06 10 06 05 08\n00005  03 04 06 05 04 01 01 00 06 06 09 02 01 01 05\n00006  10 01 10 08 05 07 07 04 05 03 04 00 00 09 07\n00007  00 07 11 04 06 00 00 02 01 07 00 11 07 09 01\n00008  00 08 05 08 11 06 11 04 06 03 10 04 01 11 01\n00009  01 00 10 10 11 04 01 08 04 05 06 06 01 03 02<\/code><\/pre>\n\n\n\n<p>Edellinen ilman nollia:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --lim12 --zero\n00000  01 02 07 05 07 11 07 05 11 07 08 11 01 11 08\n00001  07 01 06 06 06 04 09 08 10 08 06 02 03 10 03\n00002  08 10 01 10 07 06 10 01 03 08 08 08 04 07 07\n00003  04 05 02 05 04 03 04 09 06 03 09 09 02 07 03\n00004  10 01 07 05 05 07 03 07 08 01 02 02 05 10 11\n00005  07 10 09 09 09 10 02 11 01 02 04 03 08 08 02\n00006  02 11 08 08 05 01 09 04 08 04 06 09 05 09 02\n00007  03 01 10 07 06 10 07 06 07 10 02 06 02 06 06\n00008  06 04 05 03 05 05 01 04 09 03 04 05 02 05 11\n00009  04 06 05 07 04 01 03 11 10 02 04 10 06 06 05<\/code><\/pre>\n\n\n\n<p>Edellinen ilman rivinumeroita<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --lim12 --zero --lineno\n07 06 02 11 03 10 07 09 01 08 10 03 10 07 11 05 07\n05 07 04 06 01 07 02 11 07 06 06 10 11 09 07 08 09\n01 11 09 05 11 06 03 01 02 01 07 08 03 05 07 10 09\n11 02 08 06 04 07 02 04 03 07 09 06 04 02 05 11 07\n06 07 05 08 05 08 04 02 04 05 10 01 11 10 08 08 11\n01 08 06 11 03 10 06 05 02 10 09 06 04 01 04 04 08\n09 03 02 11 11 04 08 01 11 03 08 11 11 08 07 07 01\n10 06 02 10 11 08 03 01 09 03 03 02 11 03 03 09 05\n09 11 03 04 03 03 06 01 09 03 03 06 09 07 07 07 06\n08 10 08 03 03 08 06 01 10 04 09 04 08 02 10 02 07<\/code><\/pre>\n\n\n\n<p>Seuraavassa heksadesimaalilukuja, n\u00e4ihin voit tietysti k\u00e4ytt\u00e4\u00e4 my\u00f6s muita edellisi\u00e4 parametreja.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> .\/newressu -x\n00000 fbcfbd8a4a099ec66469ee09262455592c969430da55\n00001 7d1310727a2bcdf31bce90cc12b064159c09c1db6bd0\n00002 c60de6a1cc10cbcadc158ed847e7e46e5ff5f7cbc846\n00003 bd6f59d206f842f6049fe069859c16466eb06a84b911\n00004 dbad7e8ef05e7a601030396239aee557a8b73cfd1fe0\n00005 dfaf1bb7931cba2384de4b65be3813d213e0fdb737e2\n00006 f31a950b4164660af6b869ba2155e85db025d515a84a\n00007 a1d5acd029b4d59bf306c1376ea09d0dcd99677b7689\n00008 53c30e8edb0c6eba4da665a2d22c979a84304f49d243\n00009 74aa84093433e3421c25aafd55a9b2e9111ed01bff96<\/code><\/pre>\n\n\n\n<p>Tulostetaan heksalukuja vain 5 rivi\u00e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu -x -l5\n00000 cc47a24ad9e2e9b12e9c780304d860b0f2b9b81e08d6\n00001 aeeeac102c5759295cc8de62fa3470748ec4b85ffa1c\n00002 6b1aa5da4761932b02f396db5a4b0a67c82d1d973a2e\n00003 1e42d547a1e3dd475b40ec5b762531ad44f2495cca0d\n00004 efbe4cda2f3f434aa5be5bf5bfc7055ef1b3e38e39dd<\/code><\/pre>\n\n\n\n<p>Seuraavassa potentiaalisia lottonumeroita: (muista tippi jos voitat..)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --lim41 --zero\n00000  03 29 40 16 06 21 19 25 30 02 34 20 35 18 05\n00001  15 30 10 24 14 40 11 26 38 37 07 01 01 34 32\n00002  09 23 10 26 27 16 14 17 40 04 04 06 21 29 30\n00003  35 33 26 30 03 04 25 03 08 39 18 01 02 36 18\n00004  05 30 37 10 35 06 01 07 25 02 33 05 27 01 39\n00005  38 25 35 08 03 12 26 04 10 12 26 09 11 12 35\n00006  21 31 08 11 08 10 13 36 38 05 07 01 18 08 30\n00007  15 33 09 16 31 14 13 13 26 35 01 16 15 30 25\n00008  03 14 31 20 05 21 16 28 36 09 26 20 19 36 05\n00009  04 10 31 08 22 04 24 13 14 39 25 38 19 34 22<\/code><\/pre>\n\n\n\n<p>Seuraavassa viel\u00e4 tuloste rand tyylisest\u00e4 satunnaislukutaulukosta. T\u00e4m\u00e4 ei mahdu kokonaan ikkunaan, loput sarakkeet on scrollattava esiin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/newressu --rand\n00000   82577 42188  38567 42595  40111 51644  43968 18747  74456 07646\n00001   10773 43080  85405 81270  17432 97488  78817 56028  85562 72060\n00002   06644 40581  38948 13292  56989 49852  50198 22957  44732 54797\n00003   18889 86978  93590 17269  79162 84652  54330 67367  76106 75227\n00004   77478 81138  14027 44831  73289 58068  70203 63984  98229 81232\n\n00005   73099 63728  41327 51316  74366 74384  95033 42243  11485 90571\n00006   08640 61727  17171 35590  46059 81295  20169 66542  31996 07807\n00007   17946 54483  37618 77037  64233 74302  28806 68128  39779 09417\n00008   39456 17072  01615 32469  88133 14096  34895 95089  47737 25905\n00009   71238 89283  94066 61245  18258 93718  77054 79450  99920 86500<\/code><\/pre>\n\n\n\n<p>Loput rutiinit on lopun lelusovellusta varten. T\u00e4m\u00e4 ensimm\u00e4inen laskee utf8 merkkijonossa olevien merkkien m\u00e4\u00e4rin:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int 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}<\/code><\/pre>\n\n\n\n<p>Seuraavalla voidaan kopioida haluttu merkki tai utf8 merkin merkkijono string jonosta buf jonoon. Merkin numero annetaan n muuttujalla:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define aDEBUG38 2\n\nvoid utf8getchar(int size, unsigned char *buf,\n    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        break;\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        if(*p&gt;0xbf || \/\/ first utf8 char\n           *p&lt;0x80 || \/\/ ascii char\n           *p=='\\0')  \/\/ end of file\n          break;\n        *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}<\/code><\/pre>\n\n\n\n<p>Seuraava out_word rutiini tulostaa word2 muuttujan luvun buf merkkijonoon. Konversiossa k\u00e4ytet\u00e4\u00e4n digits merkkijonoa, jonka pit\u00e4isi sis\u00e4lt\u00e4\u00e4 halutun lukuj\u00e4rjestelm\u00e4n luvut 0:sta loppuun asti, esimerkiksi desimaali merkkijono on &#8220;0123456789&#8221;, heksadesimaali on &#8220;0123456789abcdef&#8221;, bin\u00e4\u00e4ri taas &#8220;01&#8221; ja oktaali &#8220;01234567&#8221;. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define aDEBUG45\n\nvoid out_word(int size, unsigned char *buf, \n    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], *p;\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        strcat(string,character);\n        len+=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}<\/code><\/pre>\n\n\n\n<p>Seuraava rutiini tekee tulostuksen toisinp\u00e4in, eli word-muuttujaan tulee buf kent\u00e4st\u00e4 saatavan merkkijonon arvo. Konversiossa k\u00e4ytet\u00e4\u00e4n taas digits merkkijonossa olevaa lukusarjan numeroiden luetteloa:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define DEBUG58 2\n\nvoid in_word(unsigned long *word, unsigned char *digits,\n    unsigned char *buf)\n{\n  int c,d,e,f,ok;\n  unsigned char character&#91;32], character2&#91;32], *p, *q;\n\n  *word=0;\n  p=buf;\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        ok=1;\n        break;\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}<\/code><\/pre>\n\n\n\n<p>Lopuksi satunnaislukulelun p\u00e4\u00e4ohjelman valittuja palasia. P\u00e4\u00e4ohjelma on postin lopussa kokonaisuudessaan. size muuttujassa on &#8220;sanan&#8221; eli numeron pituus merkkein\u00e4. Esimerkiksi 10000:n pituus on 5 merkki\u00e4. sspace kertoo tulostetaanko numeroiden v\u00e4liin v\u00e4lily\u00f6nnit. (0=ei tulosteta,1=tulostetaan). chars kertoo, kuinka monta merkki\u00e4 mahtuu riville. pchars kertoo kuinka monta merkki\u00e4 riville on t\u00e4ll\u00e4hetkell\u00e4 tulostettu. words kertoo kuinka monta sanaa mahtuu riville. pwords kertoo kuinka monta sanaa on jo tulostettu. lines on tulostettavien rivien lukum\u00e4\u00e4r\u00e4. plines on tulostettujen rivien lukum\u00e4\u00e4r\u00e4. quiet on hiljainen tulostus, zero kertoo tulostetaanko nollat vai ei. Edelliset ovat oletusarvoja, komentorivin kytkimill\u00e4 niille voidaan antaa uusia arvoja.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define aDEBUG86 2\n#define aDEBUG87 2\n#define aDEBUG88 2\n#define aDEBUG89 2\n\nvoid main(int argc, char *argv&#91;])\n{\n  int c, d, bytes=1024, size=5, sspace=0,\n    chars=72, pchars=0, words=0, pwords=0,\n    lines=10, plines=0, plinesdigits=5, slines=1,\n    stats=0, quiet=0, zero=1;\n  unsigned char *p, buffer&#91;32], *digits=\"0123456789\",\n    digitstemp&#91;256], character&#91;32];\n  unsigned long limit;\n\n  procname=argv&#91;0];<\/code><\/pre>\n\n\n\n<p>Seuraavat debukit kannattaa ehk\u00e4 j\u00e4tt\u00e4\u00e4 p\u00e4\u00e4lle (86,87,88,89). 86 debukki tulostaa merkkijonon, jota k\u00e4ytet\u00e4\u00e4n konversioissa:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifdef DEBUG86\n\n    \/\/ .\/newressu: digits string used: \"0123456789\", length: 10\n     \n    fprintf(stderr,\"%s:\", procname);\n    fprintf(stderr,\" digits string used: \\\"%s\\\"\", digits);\n    fprintf(stderr,\", length: %d\", d);\n    fprintf(stderr,\"\\n\");\n#endif<\/code><\/pre>\n\n\n\n<p>87 debukki tulostaa merkin numeron ja merkin. Merkit voivat olla ascii merkkej\u00e4 tai utf8 merkkej\u00e4, joissa sis\u00e4inen muoto koostuu kahdesta tai useammasta merkist\u00e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifdef DEBUG87\n\n    \/\/ .\/newressu: digits has characters 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 8:8 9:9\n\n    fprintf(stderr,\"%s:\", procname);\n    fprintf(stderr,\" digits has characters\");\n    for(c=0;c&lt;d;c++) {\n      utf8getchar(sizeof(character),character,c,digits);\n      fprintf(stderr,\" %d:%s\",c,character);\n    }\n    fprintf(stderr,\"\\n\");\n#endif<\/code><\/pre>\n\n\n\n<p>T\u00e4m\u00e4 88 debukki n\u00e4ytt\u00e4\u00e4 digits merkkijonon merkkien j\u00e4rjestysnumeron ja tulostusmerkkijonon heksana.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifdef DEBUG88\n\n    \/\/.\/newressu: characters have codes 0:30 1:31 2:32 3:33 4:34 5:35 6:36 7:37 8:38 9:39\n\n    fprintf(stderr,\"%s:\", procname);\n    fprintf(stderr,\" characters have codes\");\n    for(c=0;c&lt;d;c++) {\n      utf8getchar(sizeof(character),character,c,digits);\n      p=character;\n      fprintf(stderr,\" %d:%02x\",c,*p); \/\/ first character\n      p++;\n      while(*p!='\\0') {\n        if(*p&gt;0xbf || \/\/ first utf8 char\n           *p&lt;0x80 || \/\/ ascii char\n           *p=='\\0')  \/\/ end of file\n          break;\n        fprintf(stderr,\"%02x\",*p); \/\/ rest of the characters\n        p++;\n      }\n    }\n    fprintf(stderr,\"\\n\");\n#endif\n\n  } \/\/ if(digits!=NULL)\n<\/code><\/pre>\n\n\n\n<p>89 debukki tulostaa rivin vain jos merkkijonossa on utf8 merkkej\u00e4. T\u00e4m\u00e4 n\u00e4ytt\u00e4\u00e4 merkin utf8 koodin kun taas edellinen n\u00e4ytti tulostusmerkkijonon.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifdef DEBUG89\n\n    \/\/ .\/newressu: characters have utf8-codes 0:030 1:031 2:032 3:033 4:034 5:035 6:036 7:037 8:038 9:039 \n\n    \/\/ 0c0 \u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7 \u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\n    \/\/ 0d0 \u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7 \u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df\n    \/\/ 0e0 \u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7 \u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\n    \/\/ 0f0 \u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7 \u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff\n\n    int utffound=0;\n    for(c=0;c&lt;d;c++) {\n      utf8getchar(sizeof(character),character,c,digits);\n      if(strlen(character)&gt;1) {\n        utffound=1;\n        break;\n      }\n    }\n    if(utffound) {\n      fprintf(stderr,\"%s:\", procname);\n      fprintf(stderr,\" characters have utf8-codes\");\n      for(c=0;c&lt;d;c++) {\n        unsigned long code;\n        utf8getchar(sizeof(character),character,c,digits);\n        p=character;\n\n        \/\/ first byte\n\n        if(*p&gt;=0xfc) code=*p&amp;0x1;       \/\/ 1111110 x 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx 7fffffff\n        else if(*p&gt;=0xf8) code=*p&amp;0x3;  \/\/ 111110 xx 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx\n             if(*p&gt;=0xf0) code=*p&amp;0x7;  \/\/ 11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx\n             if(*p&gt;=0xe0) code=*p&amp;0xf;  \/\/ 1110 xxxx 10 xxxxxx 10 xxxxxx\n             if(*p&gt;=0xc0) code=*p&amp;0x1f; \/\/ 110 xxxxx 10 xxxxxx\n             code=*p&amp;0x7f; \/\/ ascii\n                                                                \n        while(*p!='\\0') {\n          if(*p&gt;0xbf || \/\/ first utf8 byte\n             *p&lt;0x80 || \/\/ ascii char\n             *p=='\\0')  \/\/ end of string\n            break;\n          code=code&lt;&lt;6|*p&amp;0x3f;\n          p++;\n        }\n        fprintf(stderr,\" %d:0%lx\",c,code);\n      }\n      fprintf(stderr,\"\\n\");\n    } \/\/ if(utffound) {\n#endif<\/code><\/pre>\n\n\n\n<p>Ohjelmanp\u00e4tk\u00e4 hakee rivinumeron pituuden merkkein\u00e4: Aluksi lines muuttujasta v\u00e4hennet\u00e4\u00e4n yksi, muutetaan se merkkijonoksi out_word toiminnolla. Otetaan edellisen vastauksen pituus merkkein\u00e4. Jos vastaus on lyhyempi kuin 5 merkki\u00e4 vastaus on viisi merkki\u00e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/ 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;<\/code><\/pre>\n\n\n\n<p>limit muuttujaan m\u00e4\u00e4ritet\u00e4\u00e4n arvo &#8211;lim kytkimell\u00e4. Menetelm\u00e4 on sama kun edellisess\u00e4 kappaleessa ilman viiden minimi\u00e4 ja edellisess\u00e4 tulostetaan aina desimaalilukuja.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/ 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  }<\/code><\/pre>\n\n\n\n<p>T\u00e4m\u00e4 rutiini tulostaa sanan, jos sille on m\u00e4\u00e4ritelty yl\u00e4raja (limitti). poistetaan sanojen joukosta nollat, tulostetaan ja t\u00e4ytet\u00e4\u00e4n etunollat.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if(limit!=0) {\n      word=0;\n\n      if(zero) {\n        word=ressu_gen_limit(limit); \/\/ include zeroes\n      } else if(limit&gt;=1) {\n        while((word=ressu_gen_limit(limit))==0); \/\/ skip zeroes\n      }\n\n      out_word(sizeof(wordbuf3),wordbuf3,digits,word);\n\n      \/\/ fill leading zeroes\n\n      wordbuf&#91;0]='\\0';\n      utf8getchar(sizeof(character),character,0,digits);\n      for(c=size-utf8len(wordbuf3);c&gt;0;c--) {\n        strcat(wordbuf,character);\n      }\n\n      \/\/ rest of the number\n\n      strcat(wordbuf,wordbuf3);\n  }<\/code><\/pre>\n\n\n\n<p>Tulostus jos ei ole m\u00e4\u00e4ritelty yl\u00e4rajaa. T\u00e4ll\u00f6in k\u00e4ytet\u00e4\u00e4n merkkien rajoitteena digits merkkijonoa.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  if(digits!=NULL) {\n      int digitslen;\n\n      wordbuf&#91;0]='\\0';\n      digitslen=utf8len(digits);\n\n      \/\/ fill whole word digit by digit\n\n      for(c=0;c&lt;size;c++) {\n        if(digits&#91;0]=='0' &amp;&amp; !zero)\n          d=ressu_gen_limit(digitslen-1)+1;\n        else\n          d=ressu_gen_limit(digitslen);\n        utf8getchar(sizeof(wordbuf3),wordbuf3,d,digits);\n        strcat(wordbuf,wordbuf3);\n      }\n    }<\/code><\/pre>\n\n\n\n<p>T\u00e4ss\u00e4 rutiinissa katsotaan tarvitaanko rivinvaihto ennen seuraavaa sanaa, eli jos tulostetun rivin pituus ja utf8 merkkijonon pituus ylitt\u00e4\u00e4 rivin pituuden, rivin pituus ja  ja sanan pituus ylitt\u00e4\u00e4 rivin pituuden tai tulostettujen sanojen lukum\u00e4\u00e4r\u00e4 ylitt\u00e4\u00e4 sanojen lukum\u00e4\u00e4r\u00e4n tulostetaan rivinvaihto. Lis\u00e4ksi t\u00e4ss\u00e4 on k\u00e4sittely rand tyyppisille riveille (sspace==3). Rand tyylisess\u00e4 taulussa tulostetaan viiden rivin j\u00e4lkeen ylim\u00e4\u00e4r\u00e4inen v\u00e4lily\u00f6nti, eli tulostetaan tyhj\u00e4 rivi. Tyhj\u00e4 rivi tulostetaan vain jos seuraavalla rivill\u00e4 on tulostettavaa (plines&lt;lines).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ line full?\n\n    if(((chars &gt; 0 &amp;&amp; pchars+utf8len(wordbuf)&gt;=chars) ||\n       (chars &gt; 0 &amp;&amp; pchars+size&gt;=chars) ||\n        (words &gt; 0 &amp;&amp; pwords&gt;=words))\n       &amp;&amp;pwords &gt; 0) { \/\/ atleast one word printed\n      pchars=0;\n      pwords=0;\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      fflush(stdout);\n    }<\/code><\/pre>\n\n\n\n<p>Jos tulostetun rivin numero sivuaa haluttua rivien m\u00e4\u00e4r\u00e4\u00e4 poistutaan for(;;) luupista.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ all needed lines printed?\n\n    if(plines &gt;= lines)\n      break;<\/code><\/pre>\n\n\n\n<p>Jos olemme rivin alussa (pchars == 0) ja rivinumeron tulostusta ei ole estetty tulostetaan se.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    \/\/ in beginning of line, print line number\n\n    if(pchars == 0) {\n      sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n      if(!quiet &amp;&amp; slines) {\n        fprintf(stdout,\"%s\",wordbuf2);\n        pchars +=strlen(wordbuf2);\n        fprintf(stdout,\" \");\n        pchars++;\n      }\n    }<\/code><\/pre>\n\n\n\n<p>Tulostetaanko v\u00e4lily\u00f6nti sanojen v\u00e4liin. T\u00e4ss\u00e4 my\u00f6s rand k\u00e4sittely\u00e4 (sspace==3). Rand tyylisess\u00e4 taulukossa sanojen v\u00e4liin tulostetaan v\u00e4lily\u00f6nti ja kahden sanan v\u00e4lein tulostetaan toinen v\u00e4lily\u00f6nti. Rivinumeron ja ensimm\u00e4isen sanan v\u00e4liin tulee kolme v\u00e4lily\u00f6nti\u00e4. Eli sanojen v\u00e4lily\u00f6nnit ovat 3 1 2 1 2 1 2 1 2 1.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ want to print spaces between \"words\"?\n\n    if(sspace &amp;&amp; pchars&gt;0) {\n      if(!quiet) {\n        if(sspace==3 &amp;&amp; pwords%2==0)\n          fprintf(stdout,\" \");\n        fprintf(stdout,\" \");\n      }\n      pchars++;\n    }<\/code><\/pre>\n\n\n\n<p>Ja viimeinen rutiini, varsinaisen sanan tulostus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ print word\n\n    if(size!=0) {\n      if(!quiet)\n        fprintf(stdout,\"%*s\",size,wordbuf);\n      pchars += size;\n      pwords++;\n    } else {\n      if(!quiet)\n        fprintf(stdout,\"%s\",wordbuf);\n      pchars += strlen(wordbuf);\n      pwords++;\n    }<\/code><\/pre>\n\n\n\n<p>Seuraavassa leluohjelma kokonaisuudessaan:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define aDEBUG75 2\n#define aDEBUG76 2\n\n#define aDEBUG86 2\n#define aDEBUG87 2\n#define aDEBUG88 2\n#define aDEBUG89 2\n\nstatic char *programname = \"newressu version 2.0 \u00a9\";\nstatic unsigned char *copyright = \"Copyright (c) 2013-2021 Jari Kuivaniemi, Helsinki, Finland. Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n!\";\n\nvoid main(int argc, char *argv&#91;])\n{\n  int c, d, bytes=1024, size=5, sspace=0,\n    chars=72, pchars=0, words=0, pwords=0,\n    lines=10, plines=0, plinesdigits=5, slines=1,\n    stats=0, quiet=0, zero=1;\n  unsigned char *p, buffer&#91;32], *digits=\"0123456789\",\n    digitstemp&#91;256], character&#91;32];\n  unsigned long limit;\n\n  procname=argv&#91;0];\n\n  limit=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        slines=!slines;\n\n      } else if(!strcmp(\"--quiet\",argv&#91;c])) {\n        quiet=!quiet;\n\n      } else if(!strcmp(\"--stats\",argv&#91;c]) ||\n        !strcmp(\"--stat\",argv&#91;c])) {\n        stats=!stats;\n\n      } else if(!strcmp(\"--space\",argv&#91;c])) {\n        sspace=!sspace;\n\n      } else if(!strcmp(\"--zero\",argv&#91;c])) {\n        zero=!zero;\n\n      } else if(!strcmp(\"--copyright\",argv&#91;c]) ||\n         !strcmp(\"--version\",argv&#91;c])) {\n        fprintf(stderr,\"%s\",programname);\n        fprintf(stderr,\", %s\",copyright);\n        fprintf(stderr,\"\\n\\n\");\n        help=1;\n\n      } else if(!strncmp(\"--lim\",argv&#91;c],5)) {\n        if(*(argv&#91;c]+5)!='\\0') {\n          in_word(&amp;limit, digits, argv&#91;c]+5);\n        } else if(c+1&lt;argc) {\n          in_word(&amp;limit, digits, argv&#91;c+1]);\n          c++;\n        }\n        sspace=1;\n\n      } else if(!strncmp(\"-s\",argv&#91;c],2)) {\n        if(*(argv&#91;c]+2)!='\\0') {\n          size=atoi(argv&#91;c]+2);\n        } else if(c+1&lt;argc) {\n          size=atoi(argv&#91;c+1]);\n          c++;\n        }\n      } else if(!strncmp(\"-w\",argv&#91;c],2)) { \/\/ words per line\n        if(*(argv&#91;c]+2)!='\\0') {\n          words=atoi(argv&#91;c]+2);\n        } else if(c+1&lt;argc) {\n          words=atoi(argv&#91;c+1]);\n          c++;\n        }\n        if(words&lt;1)\n          words=1;\n\n        chars = 0;\n\n      } else if(!strncmp(\"-c\",argv&#91;c],2)) {  \/\/ characters per line\n        if(*(argv&#91;c]+2)!='\\0') {\n          chars=atoi(argv&#91;c]+2);\n        } else if(c+1&lt;argc) {\n          chars=atoi(argv&#91;c+1]);\n          c++;\n        }\n        words=0;\n\n      } else if(!strncmp(\"-l\",argv&#91;c],2)) { \/\/ lines\n        if(*(argv&#91;c]+2)!='\\0') {\n          lines=atoi(argv&#91;c]+2);\n        } else if(c+1&lt;argc) {\n          lines=atoi(argv&#91;c+1]);\n          c++;\n        }\n\n      } else if(!strcmp(\"-x\",argv&#91;c])) {\n        digits = \"0123456789abcdef\";\n        size=4;\n\n      } else if(!strcmp(\"-d\",argv&#91;c])) {\n        digits = \"0123456789\";\n        size=5;\n\n      } else if(!strcmp(\"-o\",argv&#91;c])) {\n        digits = \"01234567\";\n        size=3;\n\n      } else if(!strcmp(\"-b\",argv&#91;c])) {\n        digits = \"01\";\n        size=8;\n\n      } else if(!strcmp(\"-1\",argv&#91;c])) {\n        digits=\n          \"0123456789\" \\\n          \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n          \"abcdefghijklmnopqrstuvwxyz\";\n        size=8;\n\n      } else if(!strcmp(\"-2\",argv&#91;c])) {\n        digits=\n          \"0123456789\" \\\n          \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" \\\n          \"abcdefghijklmnopqrstuvwxyz\" \\\n          \"_-\";\n        size=8;\n\n      } else if(!strcmp(\"-3\",argv&#91;c])) { \/\/ 9.5.2021 JariK\n        digits=\n          \"!\\\"#$%&amp;'()*+,-.\/0123456789:;&lt;=&gt;?@\" \\\n          \"ABCDEFGHIJKLMNOPQRSTUVWXYZ&#91;\\\\]^_`\" \\\n          \"abcdefghijklmnopqrstuvwxyz{|}~\";\n        size=8;\n\n      } else if(!strcmp(\"-4\",argv&#91;c])) {\n        digits=\n          \"\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          \"\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        size=8;\n\n      } else if(!strcmp(\"--isalnum\",argv&#91;c]) || \/\/ 9.5.2021 JariK\n                !strcmp(\"--isalpha\",argv&#91;c]) ||\n                !strcmp(\"--isdigit\",argv&#91;c]) ||\n                !strcmp(\"--isgraph\",argv&#91;c]) ||\n                !strcmp(\"--islower\",argv&#91;c]) ||\n                !strcmp(\"--isprint\",argv&#91;c]) ||\n                !strcmp(\"--ispunct\",argv&#91;c]) ||\n                !strcmp(\"--isupper\",argv&#91;c]) ||\n                !strcmp(\"--isxdigit\",argv&#91;c])) {\n        unsigned char *p=digitstemp;\n        for(d=0;d&lt;256;d++) {\n          if((!strcmp(\"--isalnum\",argv&#91;c]) &amp;&amp; isalnum(d)) ||\n             (!strcmp(\"--isalpha\",argv&#91;c]) &amp;&amp; isalpha(d)) ||\n             (!strcmp(\"--isdigit\",argv&#91;c]) &amp;&amp; isdigit(d)) ||\n             (!strcmp(\"--isgraph\",argv&#91;c]) &amp;&amp; isgraph(d)) ||\n             (!strcmp(\"--islower\",argv&#91;c]) &amp;&amp; islower(d)) ||\n             (!strcmp(\"--isprint\",argv&#91;c]) &amp;&amp; isprint(d)) ||\n             (!strcmp(\"--ispunct\",argv&#91;c]) &amp;&amp; ispunct(d)) ||\n             (!strcmp(\"--isupper\",argv&#91;c]) &amp;&amp; isupper(d)) ||\n             (!strcmp(\"--isxdigit\",argv&#91;c]) &amp;&amp; isxdigit(d))) {\n            *p++=d;\n          }\n        }\n        *p='\\0';\n        digits=digitstemp;\n        size=8;\n\n      } else if(!strcmp(\"--rand\",argv&#91;c])) {\n        digits = \"0123456789\";\n        sspace=3;\n        slines=1;\n        words=10;\n        limit=100000;\n        \/\/size=5;\n        \/\/lines=20000;\n\n      } else if(!strncmp(\"-i\",argv&#91;c],2)) {\n        digits=NULL;\n        if(*(argv&#91;c]+2)!='\\0') {\n          digits=argv&#91;c]+2;\n        } else if(c+1 &lt; argc) {\n          digits=argv&#91;c+1];\n          c++;\n        }\n        if(digits==NULL || utf8len(digits)&lt;2) {\n          fprintf(stderr,\"%s: not enough digits \\\"%s\\\"\\n\",procname,argv&#91;c]);\n          help = 1;\n        }\n        size=1;\n\n      } else {\n        fprintf(stderr,\"%s: invalid option %s\\n\",procname,argv&#91;c]);\n        help = 1;\n      }\n    } else {\n      help = 1;\n    } \/\/ if(!strncmp\n  } \/\/ for(c=0\n\n  if(digits!=NULL) {\n    d = utf8len(digits);\n\n#ifdef DEBUG86\n\n    \/\/ .\/newressu: digits string used: \"0123456789\", length: 10\n\n    fprintf(stderr,\"%s:\", procname);\n    fprintf(stderr,\" digits string used: \\\"%s\\\"\", digits);\n    fprintf(stderr,\", length: %d\", d);\n    fprintf(stderr,\"\\n\");\n#endif\n\n#ifdef DEBUG87\n\n    \/\/ .\/newressu: digits has characters 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 8:8 9:9\n\n    fprintf(stderr,\"%s:\", procname);\n    fprintf(stderr,\" digits has characters\");\n    for(c=0;c&lt;d;c++) {\n      utf8getchar(sizeof(character),character,c,digits);\n      fprintf(stderr,\" %d:%s\",c,character);\n    }\n    fprintf(stderr,\"\\n\");\n#endif\n\n#ifdef DEBUG88\n\n    \/\/.\/newressu: characters have codes 0:30 1:31 2:32 3:33 4:34 5:35 6:36 7:37 8:38 9:39\n\n    fprintf(stderr,\"%s:\", procname);\n    fprintf(stderr,\" characters have codes\");\n    for(c=0;c&lt;d;c++) {\n      utf8getchar(sizeof(character),character,c,digits);\n      p=character;\n      fprintf(stderr,\" %d:%02x\",c,*p); \/\/ first character\n      p++;\n      while(*p!='\\0') {\n        if(*p&gt;0xbf || \/\/ first utf8 char\n           *p&lt;0x80 || \/\/ ascii char\n           *p=='\\0')  \/\/ end of file\n          break;\n        fprintf(stderr,\"%02x\",*p); \/\/ rest of the characters\n        p++;\n      }\n    }\n    fprintf(stderr,\"\\n\");\n#endif\n\n#ifdef DEBUG89\n\n    \/\/ .\/newressu: characters have utf8-codes 0:030 1:031 2:032 3:033 4:034 5:035 6:036 7:037 8:038 9:039\n\n    \/\/ 0c0 \u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7 \u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf\n    \/\/ 0d0 \u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7 \u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df\n    \/\/ 0e0 \u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7 \u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef\n    \/\/ 0f0 \u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7 \u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff\n\n    int utffound=0;\n    for(c=0;c&lt;d;c++) {\n      utf8getchar(sizeof(character),character,c,digits);\n      if(strlen(character)&gt;1) {\n        utffound=1;\n        break;\n      }\n    }\n    if(utffound) {\n      fprintf(stderr,\"%s:\", procname);\n      fprintf(stderr,\" characters have utf8-codes\");\n      for(c=0;c&lt;d;c++) {\n        unsigned long code;\n        utf8getchar(sizeof(character),character,c,digits);\n        p=character;\n\n        \/\/ first byte\n\n        if(*p&gt;=0xfc) code=*p&amp;0x1;       \/\/ 1111110 x 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx 7fffffff\n        else if(*p&gt;=0xf8) code=*p&amp;0x3;  \/\/ 111110 xx 10 xxxxxx 10 xxxxxx 10 xxxxxx 10 xxxxxx\n        else if(*p&gt;=0xf0) code=*p&amp;0x7;  \/\/ 11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx\n        else if(*p&gt;=0xe0) code=*p&amp;0xf;  \/\/ 1110 xxxx 10 xxxxxx 10 xxxxxx\n        else if(*p&gt;=0xc0) code=*p&amp;0x1f; \/\/ 110 xxxxx 10 xxxxxx\n        else code=*p&amp;0x7f; \/\/ ascii\n        p++;\n        while(*p!='\\0') {\n          if(*p&gt;0xbf || \/\/ first utf8 byte\n             *p&lt;0x80 || \/\/ ascii char\n             *p=='\\0')  \/\/ end of string\n            break;\n          code=code&lt;&lt;6|*p&amp;0x3f;\n          p++;\n        }\n        fprintf(stderr,\" %d:0%lx\",c,code);\n      }\n      fprintf(stderr,\"\\n\");\n    } \/\/ if(utffound) {\n#endif\n  } \/\/ if(digits!=NULL)\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 --isalnum\", \"print alphanumeric characters\",\n      \"newressu --isalpha\", \"print alphabetic characters\",\n      \"newressu --isdigit\", \"print digits\",\n      \"newressu --isgraph\", \"print printables excluding space\",\n      \"newressu --islower\", \"print lowercase characters\",\n      \"newressu --isprint\", \"print printable characters including space\",\n      \"newressu --ispunct\", \"print punctuation characters\",\n      \"newressu --isupper\", \"print uppercase characters\",\n      \"newressu --isxdigit\", \"print hexadecimal digits\",\n      \"newressu -1\", \"print material for passwords\",\n      \"newressu -iaeiouy\u00e5\u00e4\u00f6\", \"print random vowels\",\n      \"newressu -i\u0430\u044d\u044b\u0443\u043e\u044f\u0435\u0451\u044e\u0438\", \"print russian vowels\",\n      \"newressu -s -i\udbb9\udce5\udbb9\udce6\udbb9\udce7\udbb9\udce8\udbb9\udce9\udbb9\udcea\udbb9\udceb\udbb9\udcec\udbb9\udced\udbb9\udcee \",\"flags\",\n      \"newressu -i \\\"\/\\\\\\\"\", \"print nice labyrinth\",\n      \"newressu --stats\", \"print statistics for ressu run\",\n      \"newressu --rand -l20000\", \"print rand style random number table\",\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    lines=1; \/\/ print one line below help as a sample\n  }\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  \/\/ init statistics\n\n  for(;;) {\n\n    if(limit!=0) {\n      word=0;\n\n      if(zero) {\n        word=ressu_gen_limit(limit); \/\/ include zeroes\n      } else if(limit&gt;=1) {\n        while((word=ressu_gen_limit(limit))==0); \/\/ skip zeroes\n      }\n\n      out_word(sizeof(wordbuf3),wordbuf3,digits,word);\n\n      \/\/ fill leading zeroes\n\n      wordbuf&#91;0]='\\0';\n      utf8getchar(sizeof(character),character,0,digits);\n      for(c=size-utf8len(wordbuf3);c&gt;0;c--) {\n        strcat(wordbuf,character);\n      }\n\n      \/\/ rest of the number\n\n      strcat(wordbuf,wordbuf3);\n\n    } else if(digits!=NULL) {\n      int digitslen;\n\n      wordbuf&#91;0]='\\0';\n      digitslen=utf8len(digits);\n\n      \/\/ fill whole word digit by digit\n\n      for(c=0;c&lt;size;c++) {\n        if(digits&#91;0]=='0' &amp;&amp; !zero)\n          d=ressu_gen_limit(digitslen-1)+1;\n        else\n          d=ressu_gen_limit(digitslen);\n        utf8getchar(sizeof(wordbuf3),wordbuf3,d,digits);\n        strcat(wordbuf,wordbuf3);\n      }\n    }\n\n    \/\/ line full?\n\n    if(((chars &gt; 0 &amp;&amp; pchars+utf8len(wordbuf)&gt;=chars) ||\n       (chars &gt; 0 &amp;&amp; pchars+size&gt;=chars) ||\n        (words &gt; 0 &amp;&amp; pwords&gt;=words))\n       &amp;&amp;pwords &gt; 0) { \/\/ atleast one word printed\n      pchars=0;\n      pwords=0;\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      fflush(stdout);\n    }\n\n    \/\/ all needed lines printed?\n\n    if(plines &gt;= lines)\n      break;\n\n    \/\/ all needed lines printed?\n\n    if(plines &gt;= lines)\n      break;\n\n    \/\/ in beginning of line, print line number\n\n    if(pchars == 0) {\n      sprintf(wordbuf2,\"%0*d\",plinesdigits,plines);\n      if(!quiet &amp;&amp; slines) {\n        fprintf(stdout,\"%s\",wordbuf2);\n        pchars +=strlen(wordbuf2);\n        fprintf(stdout,\" \");\n        pchars++;\n      }\n    }\n\n    \/\/ want to print spaces between \"words\"?\n\n    if(sspace &amp;&amp; pchars&gt;0) {\n      if(!quiet) {\n        if(sspace==3 &amp;&amp; pwords%2==0)\n          fprintf(stdout,\" \");\n        fprintf(stdout,\" \");\n      }\n      pchars++;\n    }\n\n    \/\/ print word\n\n    if(size!=0) {\n      if(!quiet)\n        fprintf(stdout,\"%*s\",size,wordbuf);\n      pchars += size;\n      pwords++;\n    } else {\n      if(!quiet)\n        fprintf(stdout,\"%s\",wordbuf);\n      pchars += strlen(wordbuf);\n      pwords++;\n    }\n  } \/\/ for(;;)\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Kaikki oikeudet pid\u00e4tet\u00e4\u00e4n. T\u00e4ss\u00e4 ressun uusimmassa versiossa on uusittu asiakaspuskurin hallintaa, l\u00f6ydetty kellojonosta l\u00f6ytyvien satunnaisbittien &#8220;laskentaan&#8221; uusi menetelm\u00e4. Asiakaspuskurin hallinnassa aiemmin asiakas toimitti puskurin satunnaisbittigeneraattorin t\u00e4ytett\u00e4v\u00e4ksi, ja satunnaislukugeneraattorilla ei ollut &#8220;omaa&#8221; muistialuetta. N\u00e4in j\u00e4\u00e4 aina mietitt\u00e4v\u00e4ksi voisiko edellisest\u00e4 puskurista laskea seuraavan tai p\u00e4\u00e4tell\u00e4 satunnaisbittigeneraattorin ensimm\u00e4isen puskurin. Uudessa versiossa ressulla on oma puskurinsa, josta ressu palauttaa&hellip; <a class=\"more-link\" href=\"https:\/\/moijari.com\/?p=1545\">Continue reading <span class=\"screen-reader-text\">Ressu 2.0<\/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\/1545"}],"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=1545"}],"version-history":[{"count":62,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1545\/revisions"}],"predecessor-version":[{"id":1637,"href":"https:\/\/moijari.com\/index.php?rest_route=\/wp\/v2\/posts\/1545\/revisions\/1637"}],"wp:attachment":[{"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/moijari.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}