awk-gold-collection

My best software created for POSIX AWK
git clone git://git.luxferre.top/awk-gold-collection.git
Log | Files | Refs | Submodules | README

textereo.awk (3193B)


      1 # Textereo: ASCII stereogram generator in AWK
      2 # Usage: [busybox] awk -f textereo.awk map.txt
      3 # Map format:
      4 # First line: [desired width] [maxpattern length]
      5 # Second line: alphabet (allowed characters to generate patterns from)
      6 # Next H lines: depth map, W digits from 0 to 7 without spaces
      7 # You can insert single zeros or empty lines into the map to adjust height
      8 #
      9 # Created by Luxferre in 2023, released into public domain
     10 
     11 function dchar(str, pos) { # delete a character from str at position pos
     12   if(!pos) return str
     13   else return substr(str, 1, pos - 1) substr(str, pos + 1)
     14 }
     15 
     16 function ichar(str, pos, c) { # insert a character c into str at position pos
     17   return substr(str, 1, pos - 1) c substr(str, pos)
     18 }
     19 
     20 BEGIN { # we use 95-character subset from ASCII by default
     21   srand() # init the PRNG
     22   getline # read the first line from the file to parse parameters
     23   WIDTH = int($1) # desired width of the image to generate
     24   PATLEN = int($2) # generated pattern length (must be between 8 and W/2)
     25   getline # read the full character set
     26   CHARSET = $0
     27   CHRANGE = length(CHARSET)
     28   if(WIDTH == 0) WIDTH = 78
     29   if(PATLEN < 8 || PATLEN > (WIDTH/2)) PATLEN = 10 # 10 to 15 is optimal
     30 }
     31 
     32 { # process the map itself
     33   j = 0 # set the secondary counter to store previous value
     34   FREEBUF = CHARSET # start with the full charset
     35   PATBUF = "" # start with empty pattern buffer
     36   mapline = $0 # cache the map line
     37   RWIDTH = length(mapline); # real pattern width
     38   tlen = (WIDTH - RWIDTH) / 2 # trailer AND header length
     39   for(i=0;i<tlen;i++) mapline = "0" mapline "0" # grow the line to the width
     40   if(length(mapline) > WIDTH) mapline = substr(mapline, 1, WIDTH)
     41   for(i=0;i<PATLEN;i++) { # fill in the pattern buffer
     42     do # we can repeat the characters in the pattern but not immediately
     43       pbc = substr(CHARSET, 1+int(rand()*CHRANGE), 1)
     44     while(pbc == j || !length(pbc)) # don't allow empty or repeating chars
     45     PATBUF = PATBUF pbc # concatenate the character to the pattern
     46     j = pbc # save as the previous value to j
     47     # delete this character from the unused buffer
     48     FREEBUF = dchar(FREEBUF, index(FREEBUF, pbc))
     49   }
     50   j = 0 # reset the secondary counter
     51   prevlen = PATLEN # cache the previous pattern length
     52   maplen = length(mapline)
     53   patpos = 0 # track pattern position
     54   for(i=0;++i<=maplen;) { # iterate over every character
     55     curlen = PATLEN - int(substr(mapline, i, 1)) # extract depth value and length
     56     delta = curlen - prevlen
     57     if(delta > 0) # add unused characters if decreasing depth value
     58       for(j=0;j<delta;j++) {
     59         ri = 1+int(rand()*length(FREEBUF)) # get random index
     60         rc = substr(FREEBUF, ri, 1) # retrieve the character
     61         FREEBUF = dchar(FREEBUF, ri) # delete it from the buffer
     62         PATBUF = ichar(PATBUF, 1+patpos, rc) # insert it here
     63       }
     64     else if(delta < 0) # remove characters if increasing depth value
     65       for(j=0;j<-delta;j++)
     66         PATBUF = dchar(PATBUF, 1+patpos)
     67     prevlen = curlen # update the previous length
     68     # now, output the current pattern character
     69     printf("%c", substr(PATBUF, 1 + (patpos % curlen), 1))
     70     patpos = (patpos + 1) % curlen # update pattern position
     71   }
     72   printf("\n")
     73 }