# the following qsort implementation extracted from:
#
#       ftp://ftp.armory.com/pub/lib/awk/qsort
#
# Copyleft GPLv2 John DuBois
#
# @(#) qsort 1.2.1 2005-10-21
# 1990 john h. dubois iii (john@armory.com)
#
# qsortArbIndByValue(): Sort an array according to the values of its elements.
#
# Input variables:
#
# Arr[] is an array of values with arbitrary (associative) indices.
#
# Output variables:
#
# k[] is returned with numeric indices 1..n.  The values assigned to these
# indices are the indices of Arr[], ordered so that if Arr[] is stepped
# through in the order Arr[k[1]] .. Arr[k[n]], it will be stepped through in
# order of the values of its elements.
#
# Return value: The number of elements in the arrays (n).
#
# NOTES:
#
# Full example for accessing results:
#
#       foolist["second"] = 2;
#       foolist["zero"] = 0;
#       foolist["third"] = 3;
#       foolist["first"] = 1;
#
#       outlist[1] = 0;
#       n = qsortArbIndByValue(foolist, outlist)
#
#       for (i = 1; i <= n; i++) {
#               printf("item at %s has value %d\n", outlist[i], foolist[outlist[i]]);
#       }
#      delete outlist;
#
function qsortArbIndByValue(Arr, k,
                            ArrInd, ElNum)
{
        ElNum = 0;
        for (ArrInd in Arr) {
                k[++ElNum] = ArrInd;
        }
        qsortSegment(Arr, k, 1, ElNum);
        return ElNum;
}
#
# qsortSegment(): Sort a segment of an array.
#
# Input variables:
#
# Arr[] contains data with arbitrary indices.
#
# k[] has indices 1..nelem, with the indices of Arr[] as values.
#
# Output variables:
#
# k[] is modified by this function.  The elements of Arr[] that are pointed to
# by k[start..end] are sorted, with the values of elements of k[] swapped
# so that when this function returns, Arr[k[start..end]] will be in order.
#
# Return value: None.
#
function qsortSegment(Arr, k, start, end,
                      left, right, sepval, tmp, tmpe, tmps)
{
        if ((end - start) < 1) {        # 0 or 1 elements
                return;
        }
        # handle two-element case explicitly for a tiny speedup
        if ((end - start) == 1) {
                if (Arr[tmps = k[start]] > Arr[tmpe = k[end]]) {
                        k[start] = tmpe;
                        k[end] = tmps;
                }
                return;
        }
        # Make sure comparisons act on these as numbers
        left = start + 0;
        right = end + 0;
        sepval = Arr[k[int((left + right) / 2)]];
        # Make every element <= sepval be to the left of every element > sepval
        while (left < right) {
                while (Arr[k[left]] < sepval) {
                        left++;
                }
                while (Arr[k[right]] > sepval) {
                        right--;
                }
                if (left < right) {
                        tmp = k[left];
                        k[left++] = k[right];
                        k[right--] = tmp;
                }
        }
        if (left == right)
                if (Arr[k[left]] < sepval) {
                        left++;
                } else {
                        right--;
                }
        if (start < right) {
                qsortSegment(Arr, k, start, right);
        }
        if (left < end) {
                qsortSegment(Arr, k, left, end);
        }
}

implement the Quicksort algorithm to sort an array or list of elements. The algorithm works by choosing a pivot element and dividing the rest of the elements into two partitions - one with elements less than the pivot and the other with elements greater than the pivot. It then recursively sorts these partitions and joins them with the pivot to get the sorted array. The codes also include an optimized version of Quicksort that works in place by swapping elements within the array to avoid memory allocation of more arrays. The pivot selection method is not specified.


Works with: Gawk
$ awk 'BEGIN{t=systime();print strftime("%Y-%m-%d",t)"\n"strftime("%A, %B %d, %Y",t)}'
2009-05-15
Friday, May 15, 2009

display the current date in two formats: "2007-11-23" and "Friday, November 23, 2007".


cat power_set.awk
#!/usr/local/bin/gawk -f

# User defined function
function tochar(l,n,	r) {
 while (l) { n--; if (l%2 != 0) r = r sprintf(" %c ",49+n); l = int(l/2) }; return r
}

# For each input
{ for (i=0;i<=2^NF-1;i++) if (i == 0) printf("empty\n"); else printf("(%s)\n",tochar(i,NF)) }

implement a function that takes a set as input and returns its power set. The power set includes all subsets of the input set, including the empty set and the set itself. The function also demonstrates the handling of edge cases where the input set is empty or contains only the empty set.


# syntax: GAWK -f ROMAN_NUMERALS_ENCODE.AWK
BEGIN {
    leng = split("1990 2008 1666",arr," ")
    for (i=1; i<=leng; i++) {
      n = arr[i]
      printf("%s = %s\n",n,dec2roman(n))
    }
    exit(0)
}
function dec2roman(number,  v,w,x,y,roman1,roman10,roman100,roman1000) {
    number = int(number) # force to integer
    if (number < 1 || number > 3999) { # number is too small | big
      return
    }
    split("I II III IV V VI VII VIII IX",roman1," ")   # 1 2 ... 9
    split("X XX XXX XL L LX LXX LXXX XC",roman10," ")  # 10 20 ... 90
    split("C CC CCC CD D DC DCC DCCC CM",roman100," ") # 100 200 ... 900
    split("M MM MMM",roman1000," ")                    # 1000 2000 3000
    v = (number - (number % 1000)) / 1000
    number = number % 1000
    w = (number - (number % 100)) / 100
    number = number % 100
    x = (number - (number % 10)) / 10
    y = number % 10
    return(roman1000[v] roman100[w] roman10[x] roman1[y])
}

create a function that converts a positive integer into its equivalent Roman numeral representation.


BEGIN {
  # to make an array, assign elements to it
  array[1] = "first"
  array[2] = "second"
  array[3] = "third"
  alen = 3  # want the length? store in separate variable

  # or split a string
  plen = split("2 3 5 7 11 13 17 19 23 29", primes)
  clen = split("Ottawa;Washington DC;Mexico City", cities, ";")

  # retrieve an element
  print "The 6th prime number is " primes[6]

  # push an element
  cities[clen += 1] = "New York"

  dump("An array", array, alen)
  dump("Some primes", primes, plen)
  dump("A list of cities", cities, clen)
}

function dump(what, array, len,    i) {
  print what;

  # iterate an array in order
  for (i = 1; i <= len; i++) {
    print "  " i ": " array[i]
  }
}

demonstrate the basic syntax of arrays in a specific programming language. They create both fixed-length and dynamic arrays, assign values to them, and retrieve an element from them. The codes also show how to push a value into a dynamic array. In the context of AWK, every array is an associative array and the array subscripts can start at 1 or any other integer. The codes also utilize the built-in split() function to create arrays that start at 1.


BEGIN {
  while ( (getline <"input.txt") > 0 ) {
    print >"output.txt"
  }
}

demonstrate how to read contents from "input.txt" file into an intermediate variable and then write the contents of this variable into a new file called "output.txt". The codes do not handle binary files properly.


BEGIN {
  a = "alphaBETA";
  print toupper(a), tolower(a)
}

BEGIN {
  a = "alphaBETA";
  print toupper(substr(a, 1, 1)) tolower(substr(a, 2))
}

demonstrate the conversion of the string "alphaBETA" to upper-case and lower-case using the default encoding of a string literal or plain ASCII. The code also showcases additional case conversion functions such as swapping case, capitalizing the first letter, etc. available in the language's library. It also notes that in some languages, the toLower and toUpper functions may not be reversible.


provide two functions to solve the Closest Pair of Points problem in a 2D plane. The first function uses a brute force algorithm with a complexity of O(n^2) to find the two closest points. The second function uses a recursive divide and conquer approach with a complexity of O(n log n) to find the two closest points. Both functions return the minimum distance and the pair of points.


a[0]="hello"

split("one two three",a)

print a[0]

for(i in a) print i":"a[i]

create a collection in a statically-typed language, add a few values to it, and provide examples of how to access and iterate over the elements. The code also discusses the concept of collections in the context of awk, where arrays serve a similar purpose.


$ awk 'BEGIN{for(i=1;i<=10;i++){printf i;if(i<10)printf ", "};print}'

generates a comma-separated list from 1 to 10 using separate output statements for the number and the comma within the loop body.


#!/usr/bin/awk -f
{ pos=index($2,$1)
 print $2, (pos==1 ? "begins" : "does not begin" ), "with " $1
 print $2, (pos ? "contains an" : "does not contain" ), "\"" $1 "\""
 if (pos) {
	l=length($1)
	Pos=pos
	s=$2
	while (Pos){
		print " " $1 " is at index", x+Pos
		x+=Pos
		s=substr(s,Pos+l)
		Pos=index(s,$1)
	}
 }
 print $2, (substr($2,pos)==$1 ? "ends" : "does not end"), "with " $1
}

The code checks if a given string starts with, contains, or ends with a second string. It also prints the location of the match and handles multiple occurrences of the second string within the first string.


# syntax: GAWK -f 4-RINGS_OR_4-SQUARES_PUZZLE.AWK
# converted from C
BEGIN {
    cmd = "SORT /+16"
    four_squares(1,7,1,1)
    four_squares(3,9,1,1)
    four_squares(0,9,0,0)
    four_squares(0,6,1,0)
    four_squares(2,8,1,0)
    exit(0)
}
function four_squares(plo,phi,punique,pshow) {
    lo = plo
    hi = phi
    unique = punique
    show = pshow
    solutions = 0
    print("")
    if (show) {
      print("A B C D E F G  sum  A+B B+C+D D+E+F F+G")
      print("-------------  ---  -------------------")
    }
    acd()
    close(cmd)
    tmp = (unique) ? "unique" : "non-unique"
    printf("%d-%d: %d %s solutions\n",lo,hi,solutions,tmp)
}
function acd() {
    for (c=lo; c<=hi; c++) {
      for (d=lo; d<=hi; d++) {
        if (!unique || c != d) {
          a = c + d
          if (a >= lo && a <= hi && (!unique || (c != 0 && d != 0))) {
            ge()
          }
        }
      }
    }
}
function bf() {
    for (f=lo; f<=hi; f++) {
      if (!unique || (f != a && f != c && f != d && f != g && f != e)) {
        b = e + f - c
        if (b >= lo && b <= hi && (!unique || (b != a && b != c && b != d && b != g && b != e && b != f))) {
          solutions++
          if (show) {
            printf("%d %d %d %d %d %d %d %4d  ",a,b,c,d,e,f,g,a+b) | cmd
            printf("%d+%d ",a,b) | cmd
            printf("%d+%d+%d ",b,c,d) | cmd
            printf("%d+%d+%d ",d,e,f) | cmd
            printf("%d+%d\n",f,g) | cmd
          }
        }
      }
    }
}
function ge() {
    for (e=lo; e<=hi; e++) {
      if (!unique || (e != a && e != c && e != d)) {
        g = d + e
        if (g >= lo && g <= hi && (!unique || (g != a && g != c && g != d && g != e))) {
          bf()
        }
      }
    }
}

The code finds all possible solutions for a 4-squares puzzle where each square sums up to the same total. It operates under two conditions: each letter representing a unique value between 1-7 and 3-9, and each letter representing a non-unique value between 0-9. The code also counts the number of non-unique solutions.


illustrate a time-keeping device that updates every second and cycles periodically. It is designed to be simple, efficient, and not to overuse CPU resources by avoiding unnecessary system timer polling. The time displayed aligns with the system clock. Both text-based and graphical representations are supported.


# syntax: GAWK -f PYTHAGOREAN_TRIPLES.AWK
# converted from Go
BEGIN {
    printf("%5s %11s %11s %11s %s\n","limit","limit","triples","primitives","seconds")
    for (max_peri=10; max_peri<=1E9; max_peri*=10) {
      t = systime()
      prim = 0
      total = 0
      new_tri(3,4,5)
      printf("10^%-2d %11d %11d %11d %d\n",++n,max_peri,total,prim,systime()-t)
    }
    exit(0)
}
function new_tri(s0,s1,s2,  p) {
    p = s0 + s1 + s2
    if (p <= max_peri) {
      prim++
      total += int(max_peri / p)
      new_tri(+1*s0-2*s1+2*s2,+2*s0-1*s1+2*s2,+2*s0-2*s1+3*s2)
      new_tri(+1*s0+2*s1+2*s2,+2*s0+1*s1+2*s2,+2*s0+2*s1+3*s2)
      new_tri(-1*s0+2*s1+2*s2,-2*s0+1*s1+2*s2,-2*s0+2*s1+3*s2)
    }
}

The code calculates the number of Pythagorean triples (a, b, c) where a, b, and c are positive integers, a < b < c, and a^2 + b^2 = c^2, with a perimeter (a + b + c) no larger than 100. It also determines the number of these triples that are primitive, meaning a, b, and c are co-prime. The code is also optimized to handle large values up to a maximum perimeter of 100,000,000.


# usage: awk -f letters.awk HolyBible.txt

BEGIN { FS="" }
      { for(i=1;i<=NF;i++) m[$i]++}
END   { for(i in m) printf("%9d %-14s\n", m[i],i) }

Open a text file, count the frequency of each letter, and differentiate between counting all characters or only letters A to Z.


BEGIN {
    NIL = 0
    HEAD = 1
    LINK = 1
    VALUE = 2

    delete list
    initList()
}

function initList() {
    delete list
    list[HEAD] = makeNode(NIL, NIL)
}

function makeNode(link, value) {
    return link SUBSEP value
}

function getNode(part, nodePtr,    linkAndValue) {
    split(list[nodePtr], linkAndValue, SUBSEP)
    return linkAndValue[part]
}

The code defines a data structure for a singly-linked list element, capable of holding a numeric value. It uses global associative arrays with numerical indexes as node pointers. The next node pointer is separated from the value by a pre-defined SUBSEP value. A function is used to access a node's next node pointer or value given a node pointer. The first array element serves as the list head.


# syntax: GAWK -f FACTORS_OF_AN_INTEGER.AWK
BEGIN {
    print("enter a number or C/R to exit")
}
{   if ($0 == "") { exit(0) }
    if ($0 !~ /^[0-9]+$/) {
      printf("invalid: %s\n",$0)
      next
    }
    n = $0
    printf("factors of %s:",n)
    for (i=1; i<=n; i++) {
      if (n % i == 0) {
        printf(" %d",i)
      }
    }
    printf("\n")
}

compute the factors of a given positive integer, excluding zero and negative numbers. The factors are the positive integers that can divide the input number to yield a positive integer. For prime numbers, the factors are 1 and the number itself.


# syntax: GAWK -f ALIGN_COLUMNS.AWK ALIGN_COLUMNS.TXT
BEGIN {
    colsep = " " # separator between columns
    report("raw data")
}
{   printf("%s\n",$0)
    arr[NR] = $0
    n = split($0,tmp_arr,"$")
    for (j=1; j<=n; j++) {
      width = max(width,length(tmp_arr[j]))
    }
}
END {
    report("left justified")
    report("right justified")
    report("center justified")
    exit(0)
}
function report(text,  diff,i,j,l,n,r,tmp_arr) {
    printf("\nreport: %s\n",text)
    for (i=1; i<=NR; i++) {
      n = split(arr[i],tmp_arr,"$")
      if (tmp_arr[n] == "") { n-- }
      for (j=1; j<=n; j++) {
        if (text ~ /^[Ll]/) { # left
          printf("%-*s%s",width,tmp_arr[j],colsep)
        }
        else if (text ~ /^[Rr]/) { # right
          printf("%*s%s",width,tmp_arr[j],colsep)
        }
        else if (text ~ /^[Cc]/) { # center
          diff = width - length(tmp_arr[j])
          l = r = int(diff / 2)
          if (diff != l + r) { r++ }
          printf("%*s%s%*s%s",l,"",tmp_arr[j],r,"",colsep)
        }
      }
      printf("\n")
    }
}
function max(x,y) { return((x > y) ? x : y) }

report: raw data
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.

report: left justified
Given      a          text       file       of         many       lines,     where      fields     within     a          line
are        delineated by         a          single     'dollar'   character, write      a          program
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each
column     are        separated  by         at         least      one        space.
Further,   allow      for        each       word       in         a          column     to         be         either     left
justified, right      justified, or         center     justified  within     its        column.

report: right justified
     Given          a       text       file         of       many     lines,      where     fields     within          a       line
       are delineated         by          a     single   'dollar' character,      write          a    program
      that     aligns       each     column         of     fields         by   ensuring       that      words         in       each
    column        are  separated         by         at      least        one     space.
  Further,      allow        for       each       word         in          a     column         to         be     either       left
justified,      right justified,         or     center  justified     within        its    column.

report: center justified
  Given        a         text       file        of        many      lines,     where      fields     within       a         line
   are     delineated     by         a        single    'dollar'  character,   write        a       program
   that      aligns      each      column       of       fields       by      ensuring     that      words        in        each
  column      are     separated      by         at       least       one       space.
 Further,    allow       for        each       word        in         a        column       to         be       either      left
justified,   right    justified,     or       center   justified    within      its      column.

The code reads a text file, where each line contains fields separated by a dollar sign. It aligns each column of fields by ensuring at least one space between words in each column. The words in a column can be left, right, or center justified. The minimum space between columns is computed from the text, not hard-coded. No additional separating characters are added between or around columns. The output is viewed in a mono-spaced font on a plain text editor or basic terminal.


# syntax: GAWK -f DRAW_A_CUBOID.AWK [-v x=?] [-v y=?] [-v z=?]
# example: GAWK -f DRAW_A_CUBOID.AWK -v x=12 -v y=4 -v z=6
# converted from VBSCRIPT
BEGIN {
    init_sides()
    draw_cuboid(2,3,4)
    draw_cuboid(1,1,1)
    draw_cuboid(6,2,1)
    exit (errors == 0) ? 0 : 1
}
function draw_cuboid(nx,ny,nz,  esf,i,i_max,j,j_max,lx,ly,lz) {
    esf = errors # errors so far
    if (nx !~ /^[0-9]+$/ || nx <= 0) { error(nx,ny,nz,1) }
    if (ny !~ /^[0-9]+$/ || ny <= 0) { error(nx,ny,nz,2) }
    if (nz !~ /^[0-9]+$/ || nz <= 0) { error(nx,ny,nz,3) }
    if (errors > esf) { return }
    lx = x * nx
    ly = y * ny
    lz = z * nz
# define the array size
    i_max = ly + lz
    j_max = lx + ly
    delete arr
    printf("%s %s %s (%d rows x %d columns)\n",nx,ny,nz,i_max+1,j_max+1)
# draw lines
    for (i=0; i<=nz-1; i++) { draw_line(lx,0,z*i,"-") }
    for (i=0; i<=ny; i++)   { draw_line(lx,y*i,lz+y*i,"-") }
    for (i=0; i<=nx-1; i++) { draw_line(lz,x*i,0,"|") }
    for (i=0; i<=ny; i++)   { draw_line(lz,lx+y*i,y*i,"|") }
    for (i=0; i<=nz-1; i++) { draw_line(ly,lx,z*i,"/") }
    for (i=0; i<=nx; i++)   { draw_line(ly,x*i,lz,"/") }
# output the cuboid
    for (i=i_max; i>=0; i--) {
      for (j=0; j<=j_max; j++) {
        printf("%1s",arr[i,j])
      }
      printf("\n")
    }
}
function draw_line(n,x,y,c,  dx,dy,i,xi,yi) {
    if      (c == "-") { dx = 1 ; dy = 0 }
    else if (c == "|") { dx = 0 ; dy = 1 }
    else if (c == "/") { dx = 1 ; dy = 1 }
    for (i=0; i<=n; i++) {
      xi = x + i * dx
      yi = y + i * dy
      arr[yi,xi] = (arr[yi,xi] ~ /^ ?$/) ? c : "+"
    }
}
function error(x,y,z,arg) {
    printf("error: '%s,%s,%s' argument %d is invalid\n",x,y,z,arg)
    errors++
}
function init_sides() {
# to change the defaults on the command line use: -v x=? -v y=? -v z=?
    if (x+0 < 2) { x = 6 } # top
    if (y+0 < 2) { y = 2 } # right
    if (z+0 < 2) { z = 3 } # front
}

generate a graphical or ASCII art representation of a cuboid with dimensions 2x3x4, ensuring three faces are visible, and allowing for either static or rotational projection.


Works with: gawk
# usage: awk -f rot13.awk
BEGIN {
  for(i=0; i < 256; i++) {
    amap[sprintf("%c", i)] = i
  }
  for(l=amap["a"]; l <= amap["z"]; l++) {
    rot13[l] = sprintf("%c", (((l-amap["a"])+13) % 26 ) + amap["a"])
  }
  FS = ""
}
{
  o = ""
  for(i=1; i <= NF; i++) {
    if ( amap[tolower($i)] in rot13 ) {
      c = rot13[amap[tolower($i)]]
      if ( tolower($i) != $i ) c = toupper(c)
      o = o c
    } else {
      o = o $i
    }
  }
  print o
}

Input:
Hello, HAL !

implement a rot-13 function that replaces every letter of the ASCII alphabet with the letter which is "rotated" 13 characters around the 26 letter alphabet. The function should work on both upper and lower case letters, preserve case, and pass all non-alphabetic characters without alteration. Optionally, the function can be wrapped in a utility program that performs rot-13 encoding line-by-line for every line of input in each file listed on its command line or acts as a filter on its standard input.


# syntax: GAWK -f SORT_AN_ARRAY_OF_COMPOSITE_STRUCTURES.AWK
BEGIN {
# AWK lacks structures but one can be simulated using an associative array.
    arr["eight  8 "]
    arr["two    2 "]
    arr["five   5 "]
    arr["nine   9 "]
    arr["one    1 "]
    arr["three  3 "]
    arr["six    6 "]
    arr["seven  7 "]
    arr["four   4 "]
    arr["ten    10"]
    arr["zero   0 "]
    arr["twelve 12"]
    arr["minus2 -2"]
    show(1,7,"@val_str_asc","name") # use name part of name-value pair
    show(8,9,"@val_num_asc","value") # use value part of name-value pair
    exit(0)
}
function show(a,b,sequence,description,  i,x) {
    PROCINFO["sorted_in"] = "@unsorted"
    for (i in arr) {
      x = substr(i,a,b)
      sub(/ +/,"",x)
      arr[i] = x
    }
    PROCINFO["sorted_in"] = sequence
    printf("sorted by %s:",description)
    for (i in arr) {
      printf(" %s",arr[i])
    }
    printf("\n")
}

sort an array of composite structures, specifically name-value pairs, by the key name using a custom comparator.


BEGIN {
  for(i=1; i < 6; i++) {
    for(j=1; j <= i; j++ ) {
      printf "*"
    }
    print
  }
}

demonstrate how to use nested for loops to print a specific pattern. The number of iterations in the inner loop is controlled by the outer loop, resulting in a pattern of increasing asterisks.


BEGIN {
  a["red"] = 0xff0000
  a["green"] = 0x00ff00
  a["blue"] = 0x0000ff
  for (i in a) {
    printf "%8s %06x\n", i, a[i]
  }
  # deleting a key/value
  delete a["red"]
  for (i in a) {
    print i
  }
  # check if a key exists
  print ( "red" in a )   # print 0
  print ( "blue" in a )  # print 1
}

create an associative array (dictionary, map, or hash) in AWK.


function halve(x)
{
  return int(x/2)
}

function double(x)
{
  return x*2
}

function iseven(x)
{
  return x%2 == 0
}

function ethiopian(plier, plicand)
{
  r = 0
  while(plier >= 1) {
    if ( !iseven(plier) ) {
      r += plicand
    }
    plier = halve(plier)
    plicand = double(plicand)
  }
  return r
}

BEGIN {
  print ethiopian(17, 34)
}

The code defines three functions for halving an integer, doubling an integer, and checking if an integer is even. These functions are then used to implement Ethiopian multiplication, a method of multiplying integers using only addition, doubling, and halving. The multiplication process involves repeatedly halving and doubling the two input numbers, discarding rows where the halved number is even, and summing the remaining doubled numbers to get the multiplication result.


function fact_r(n)
{
  if ( n <= 1 ) return 1;
  return n*fact_r(n-1);
}

function fact(n)
{
  if ( n < 1 ) return 1;
  r = 1
  for(m = 2; m <= n; m++) {
    r *= m;
  }
  return r
}

The code calculates the factorial of a given number either iteratively or recursively. It may optionally handle errors for negative input values. The factorial is the product of all positive integers from 1 to the given number.


# Usage: GAWK -f BULLS_AND_COWS.AWK
BEGIN {
    srand()
    secret = ""
    for (i = 1; i <= 4; ) {
        digit = int(9 * rand()) + 1
        if (index(secret, digit) == 0) {
            secret = secret digit
            i++
        }
    }
    print "Welcome to 'Bulls and Cows'!"
    print "I thought of a 4-digit number."
    print "Please enter your guess."
}
iswellformed($0) {
    if (calcscore($0, secret)) {
        exit
    }
}
function iswellformed(number,    i, digit) {
    if (number !~ /[1-9][1-9][1-9][1-9]/) {
        print "Your guess should contain 4 digits, each from 1 to 9. Try again!"
        return 0
    }
    for (i = 1; i <= 3; i++) {
        digit = substr(number, 1, 1)
        number = substr(number, 2)
        if (index(number, digit) != 0) {
            print "Your guess contains a digit twice. Try again!"
            return 0
        }
    }
    return 1
}
function calcscore(guess, secret,    bulls, cows, i, idx) {
    # Bulls = correct digits at the right position
    # Cows = correct digits at the wrong position
    for (i = 1; i <= 4; i++) {
        idx = index(secret, substr(guess, i, 1))
        if (idx == i) {
            bulls++
        } else if (idx > 0) {
            cows++
        }
    }
    printf("Your score for this guess: Bulls = %d, Cows = %d.", bulls, cows)
    if (bulls < 4) {
        printf(" Try again!\n")
    } else {
        printf("\nCongratulations, you win!\n")
    }
    return bulls == 4
}

generate a unique four-digit number, accept and validate user guesses, calculate and print scores based on matching digits and their positions, and end the program when the user guess matches the generated number.


generate a collection of 1000 normally distributed pseudo-random numbers with a mean of 1.0 and a standard deviation of 0.5, using a library that may only generate uniformly distributed random numbers.


# syntax: GAWK -f DOT_PRODUCT.AWK
BEGIN {
    v1 = "1,3,-5"
    v2 = "4,-2,-1"
    if (split(v1,v1arr,",") != split(v2,v2arr,",")) {
      print("error: vectors are of unequal lengths")
      exit(1)
    }
    printf("%g\n",dot_product(v1arr,v2arr))
    exit(0)
}
function dot_product(v1,v2,  i,sum) {
    for (i in v1) {
      sum += v1[i] * v2[i]
    }
    return(sum)
}

Implement a function to calculate the dot product of two vectors of arbitrary length. The function multiplies corresponding elements from each vector and sums the products. The vectors must be of the same length. Example vectors used are [1, 3, -5] and [4, -2, -1].


"Read and print data from a text stream either word-by-word or line-by-line until the end of the stream is reached."


Works with: Gawk
$ awk 'BEGIN{print systime(),strftime()}'

the system time in a specified unit. This can be useful for debugging, network information, generating random number seeds, or measuring program performance. The system time is retrieved either through a system command or a built-in language function. The code may also be related to the task of date formatting and retrieving system time.


function ord(a)
{
  return amap[a]
}

function sedol_checksum(sed)
{
  sw[1] = 1; sw[2] = 3; sw[3] = 1
  sw[4] = 7; sw[5] = 3; sw[6] = 9
  sum = 0
  for(i=1; i <= 6; i++) {
    c = substr(toupper(sed), i, 1)
    if ( c ~ /[[:digit:]]/ ) {
      sum += c*sw[i]
    } else {
      sum += (ord(c)-ord("A")+10)*sw[i]
    }
  }
  return (10 - (sum % 10)) % 10
}

BEGIN { # prepare amap for ord
  for(_i=0;_i<256;_i++) {
    astr = sprintf("%c", _i)
    amap[astr] = _i
  }
}

/[AEIOUaeiou]/ {
  print "'" $0 "' not a valid SEDOL code"
  next
}
{
  if ( (length($0) > 7) || (length($0) < 6) ) {
    print "'" $0 "' is too long or too short to be valid SEDOL"
    next
  }
  sedol = substr($0, 1, 6)
  sedolcheck = sedol_checksum(sedol)
  if ( length($0) == 7 ) {
    if ( (sedol sedolcheck) != $0 ) {
      print sedol sedolcheck " (original " $0 " has wrong check digit"
    } else {
      print sedol sedolcheck
    }
  } else {
    print sedol sedolcheck
  }
}

The code takes a list of 6-digit SEDOL numbers as input, calculates the checksum digit for each number, and appends it to the respective number. It also validates the input to ensure it contains only valid characters allowed in a SEDOL string. The updated SEDOL codes are then outputted.


# syntax: GAWK -f DRAW_A_SPHERE.AWK
# converted from VBSCRIPT
BEGIN {
    draw_sphere(20,4,0.1)
    draw_sphere(10,2,0.4)
    exit(0)
}
function draw_sphere(radius,k,ambient, b,i,intensity,j,leng_shades,light,line,shades,vec,x,y) {
    leng_shades = split0(".:!*oe&#%@",shades,"")
    split("30,30,-50",light,",")
    normalize(light)
    for (i=int(-radius); i<=ceil(radius); i++) {
      x = i + 0.5
      line = ""
      for (j=int(-2*radius); j<=ceil(2*radius); j++) {
        y = j / 2 + 0.5
        if (x*x + y*y <= radius*radius) {
          vec[1] = x
          vec[2] = y
          vec[3] = sqrt(radius*radius - x*x - y*y)
          normalize(vec)
          b = dot(light,vec) ^ k + ambient
          intensity = int((1-b) * leng_shades)
          if (intensity < 0) {
            intensity = 0
          }
          if (intensity >= leng_shades) {
            intensity = leng_shades
          }
          line = line shades[intensity]
        }
        else {
          line = line " "
        }
      }
      printf("%s\n",line)
    }
}
function ceil(x,  tmp) {
    tmp = int(x)
    return (tmp != x) ? tmp+1 : tmp
}
function dot(x,y,  tmp) {
    tmp = x[1]*y[1] + x[2]*y[2] + x[3]*y[3]
    return (tmp < 0) ? -tmp : 0
}
function normalize(v,  tmp) {
    tmp = sqrt(v[1]*v[1] + v[2]*v[2] + v[3]*v[3])
    v[1] /= tmp
    v[2] /= tmp
    v[3] /= tmp
}
function split0(str,array,fs,  arr,i,n) { # same as split except indices start at zero
    n = split(str,arr,fs)
    for (i=1; i<=n; i++) {
      array[i-1] = arr[i]
    }
    return(n)
}

"Generates a graphical or ASCII art representation of a sphere, with either static or rotational projection."


# syntax: GAWK -f NTH.AWK
BEGIN {
    prn(0,25)
    prn(250,265)
    prn(1000,1025)
    exit(0)
}
function prn(start,stop,  i) {
    printf("%d-%d: ",start,stop)
    for (i=start; i<=stop; i++) {
      printf("%d%s ",i,nth(i))
    }
    printf("\n")
}
function nth(yearday,  nthday) {
    if (yearday ~ /1[1-3]$/) {         # 11th,12th,13th
      nthday = "th"
    }
    else if (yearday ~ /1$/) {         # 1st,21st,31st,etc.
      nthday = "st"
    }
    else if (yearday ~ /2$/) {         # 2nd,22nd,32nd,etc.
      nthday = "nd"
    }
    else if (yearday ~ /3$/) {         # 3rd,23rd,33rd,etc.
      nthday = "rd"
    }
    else if (yearday ~ /[0456789]$/) { # 4th-10th,20th,24th-30th,etc.
      nthday = "th"
    }
    return(nthday)
}

The code defines a function that takes an integer input greater than or equal to zero and returns a string representation of the number with an ordinal suffix. The function is tested with ranges 0 to 25, 250 to 265, and 1000 to 1025. The use of apostrophes in the output is optional.


#!/usr/bin/awk -f
BEGIN {
   x = "She was a soul stripper. She took my heart!";
   print x;
   gsub(/[aei]/,"",x);
   print x;
}

"Function to remove specific characters from a given string"


First, we get the parameters, and
generate a file with the list of numbers (writing directly to that file)
generate a custom awk-program for that special case (redirecting standard-output)
the custom program is run, and does the actual work to output the desired result

105
3 Fizz
5 Buzz
7 Baxx
Usage

awk  -f fizzbuzzGenerate.awk  input.txt > fizzbuzzCustom.awk
awk  -f fizzbuzzCustom.awk  numbers.txt

Program

# usage:  awk -f fizzbuzzGen.awk > fizzbuzzCustom.awk
#
function Print(s) {
    print s > "/dev/stderr"
}

BEGIN { Print( "# FizzBuzz-Generate:" )
        q2 = "\""
        fN = "numbers.txt"
       #fP = "fizzbuzzCustom.awk"
}

NF==1 { Print( "# " $1 " Numbers:" )
        for( i=1; i <= $1; i++ )
            print( i ) > fN   # (!!) write to file not allowed in sandbox at ideone.com

        Print( "# Custom program:" )
        print "BEGIN {print " q2 "# CustomFizzBuzz:" q2 "} \n"
        next
}

NF==2 { Print( "# " $1 "-->" $2 )   ##
        print "$1 %  "$1" == 0 {x = x "q2 $2 q2 "}"
        next
}

END {  print ""
       print "!x  {print $1; next}"
       print "    {print " q2 " " q2 ", x; x=" q2 q2 "} \n"

       print "END {print " q2 "# Done." q2 "}"
       Print( "# Done." )
}

The code takes a maximum number and a list of factors with corresponding words as input from the user. It then prints numbers from 1 to the maximum number, replacing multiples of the given factors with the corresponding words. If a number is a multiple of more than one factor, all corresponding words are printed in order of the factors. For example, if the maximum number is 20 and the factors are 3 (Fizz), 5 (Buzz), and 7 (Baxx), the output will replace multiples of 3 with "Fizz", multiples of 5 with "Buzz", and multiples of 7 with "Baxx". If a number is a multiple of both 3 and 5, it will print "FizzBuzz".


# syntax: GAWK -f STRING_PREPEND.AWK
BEGIN {
    s = "bar"
    s = "foo" s
    print(s)
    exit(0)
}

Creates a string variable with a specific text value, prepends another string literal to it, and displays the content of the variable. If possible, the operation is performed without referring to the variable twice in one expression.


# syntax: GAWK -f GUESS_THE_NUMBER.AWK
BEGIN {
    srand()
    n = int(rand() * 10) + 1
    print("I am thinking of a number between 1 and 10. Try to guess it.")
    while (1) {
      getline ans
      if (ans !~ /^[0-9]+$/) {
        print("Your input was not a number. Try again.")
        continue
      }
      if (n == ans) {
        print("Well done you.")
        break
      }
      print("Incorrect. Try again.")
    }
    exit(0)
}

"Implement a number guessing game where the computer selects a number between 1 and 10. The player is repeatedly prompted to guess the number until the correct number is guessed, upon which a 'Well guessed!' message is displayed and the program terminates. A conditional loop is used to facilitate repeated guessing."


Works with: gawk

# syntax: GAWK -f GENERATE_LOWER_CASE_ASCII_ALPHABET.AWK
BEGIN {
    for (i=0; i<=255; i++) {
      c = sprintf("%c",i)
      if (c ~ /[[:lower:]]/) {
        lower_chars = lower_chars c
      }
    }
    printf("%s %d: %s\n",ARGV[0],length(lower_chars),lower_chars)
    exit(0)
}

generate an array, list, or string of all lower case ASCII characters from 'a' to 'z'. The code uses a reliable coding style suitable for large programs and employs strong typing if available. It avoids manual enumeration of characters to prevent bugs. The code also tests each character code to see if it matches the POSIX character class for "lowercase", taking into account locale settings and options such as --traditional and --posix.


BEGIN {
  print tobinary(0)
  print tobinary(1)
  print tobinary(5)
  print tobinary(50)
  print tobinary(9000)
}

function tobinary(num) {
  outstr = num % 2
  while (num = int(num / 2))
    outstr = (num % 2) outstr
  return outstr
}

generate a sequence of binary digits for a given non-negative integer. The output displays only the binary digits of each number, followed by a newline, without any whitespace, radix, sign markers, or leading zeros. The conversion can be achieved using built-in radix functions or a user-defined function.


# syntax: GAWK -f MERGE_AND_AGGREGATE_DATASETS.AWK RC-PATIENTS.CSV RC-VISITS.CSV
# files may appear in any order
#
# sorting:
#   PROCINFO["sorted_in"] is used by GAWK
#   SORTTYPE is used by Thompson Automation's TAWK
#
{ # printf("%s %s\n",FILENAME,$0) # print input
    split($0,arr,",")
    if (FNR == 1) {
      file = (arr[2] == "LASTNAME") ? "patients" : "visits"
      next
    }
    patient_id_arr[key] = key = arr[1]
    if (file == "patients") {
      lastname_arr[key] = arr[2]
    }
    else if (file == "visits") {
      if (arr[2] > visit_date_arr[key]) {
        visit_date_arr[key] = arr[2]
      }
      if (arr[3] != "") {
        score_arr[key] += arr[3]
        score_count_arr[key]++
      }
    }
}
END {
    print("")
    PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
    fmt = "%-10s %-10s %-10s %9s %9s %6s\n"
    printf(fmt,"patient_id","lastname","last_visit","score_sum","score_avg","scores")
    for (i in patient_id_arr) {
      avg = (score_count_arr[i] > 0) ? score_arr[i] / score_count_arr[i] : ""
      printf(fmt,patient_id_arr[i],lastname_arr[i],visit_date_arr[i],score_arr[i],avg,score_count_arr[i]+0)
    }
    exit(0)
}

"Merge and aggregate two provided .csv datasets into a new dataset, grouping by patient id and last name, calculating the maximum visit date, and the sum and average of the scores per patient. The resulting dataset can be displayed on screen, stored in memory, or written to a file."


# syntax: GAWK -f READ_A_CONFIGURATION_FILE.AWK
BEGIN {
    fullname = favouritefruit = ""
    needspeeling = seedsremoved = "false"
    fn = "READ_A_CONFIGURATION_FILE.INI"
    while (getline rec <fn > 0) {
      tmp = tolower(rec)
      if (tmp ~ /^ *fullname/) { fullname = extract(rec) }
      else if (tmp ~ /^ *favouritefruit/) { favouritefruit = extract(rec) }
      else if (tmp ~ /^ *needspeeling/) { needspeeling = "true" }
      else if (tmp ~ /^ *seedsremoved/) { seedsremoved = "true" }
      else if (tmp ~ /^ *otherfamily/) { split(extract(rec),otherfamily,",") }
    }
    close(fn)
    printf("fullname=%s\n",fullname)
    printf("favouritefruit=%s\n",favouritefruit)
    printf("needspeeling=%s\n",needspeeling)
    printf("seedsremoved=%s\n",seedsremoved)
    for (i=1; i<=length(otherfamily); i++) {
      sub(/^ +/,"",otherfamily[i]) # remove leading spaces
      sub(/ +$/,"",otherfamily[i]) # remove trailing spaces
      printf("otherfamily(%d)=%s\n",i,otherfamily[i])
    }
    exit(0)
}
function extract(rec,  pos,str) {
    sub(/^ +/,"",rec)       # remove leading spaces before parameter name
    pos = match(rec,/[= ]/) # determine where data begins
    str = substr(rec,pos)   # extract the data
    gsub(/^[= ]+/,"",str)   # remove leading "=" and spaces
    sub(/ +$/,"",str)       # remove trailing spaces
    return(str)
}

read a configuration file and set variables based on the contents. It ignores lines starting with a hash or semicolon and blank lines. It sets variables 'fullname', 'favouritefruit', 'needspeeling', and 'seedsremoved' based on the file entries. It also stores multiple parameters from the 'otherfamily' entry into an array.


# syntax: GAWK -f HAVERSINE_FORMULA.AWK
# converted from Python
BEGIN {
    distance(36.12,-86.67,33.94,-118.40) # BNA to LAX
    exit(0)
}
function distance(lat1,lon1,lat2,lon2,  a,c,dlat,dlon) {
    dlat = radians(lat2-lat1)
    dlon = radians(lon2-lon1)
    lat1 = radians(lat1)
    lat2 = radians(lat2)
    a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
    c = 2 * atan2(sqrt(a),sqrt(1-a))
    printf("distance: %.4f km\n",6372.8 * c)
}
function radians(degree) { # degrees to radians
    return degree * (3.1415926 / 180.)
}

Implement a function to calculate the great-circle distance between two points on a sphere using the Haversine formula. The function takes the coordinates of Nashville International Airport (BNA) and Los Angeles International Airport (LAX) as input and returns the distance between them. The calculation uses the recommended earth radius of 6372.8 km or 6371 km, depending on the level of precision required.


Works with: gawk
BEGIN {
  site="en.wikipedia.org"
  path="/wiki/"
  name="Rosetta_Code"

  server = "/inet/tcp/0/" site "/80"
  print "GET " path name " HTTP/1.0" |& server
  print "Host: " site |& server
  print "\r\n\r\n" |& server

  while ( (server |& getline fish) > 0 ) {
    if ( ++scale == 1 )
      ship = fish
    else
      ship = ship "\n" fish
  }
  close(server)

  print ship
}

Print the content of a specified URL to the console using HTTP request.


The code validates credit card numbers using the Luhn test. It reverses the input number, calculates the sum of odd and even positioned digits (with even digits being doubled and if the result is greater than nine, the digits of the result are summed). If the total sum ends in zero, the number is deemed valid. The code tests this functionality on four given numbers.


# syntax: GAWK -f JOSEPHUS_PROBLEM.AWK
# converted from PL/I
BEGIN {
    main(5,2,1)
    main(41,3,1)
    main(41,3,3)
    exit(0)
}
function main(n,k,s,  dead,errors,found,i,killed,nn,p,survived) {
# n - number of prisoners
# k - kill every k'th prisoner
# s - number of survivors
    printf("\nn=%d k=%d s=%d\n",n,k,s) # show arguments
    if (s > n) { print("s>n"); errors++ }
    if (k <= 0) { print("k<=0"); errors++ }
    if (errors > 0) { return(0) }
    nn = n                             # wrap around boundary
    p = -1                             # start here
    while (n != s) {                   # until survivor count is met
      found = 0                        # start looking
      while (found != k) {             # until we have the k-th prisoner
        if (++p == nn) { p = 0 }       # wrap around
        if (dead[p] != 1) { found++ }  # if prisoner is alive increment found
      }
      dead[p] = 1                      # kill the unlucky one
      killed = killed p " "            # build killed list
      n--                              # reduce size of circle
    }
    for (i=0; i<=nn-1; i++) {
      if (dead[i] != 1) {
        survived = survived i " "      # build survivor list
      }
    }
    printf("killed: %s\n",killed)
    printf("survived: %s\n",survived)
    return(1)
}

- Determine the final survivor in the Josephus problem given any number of prisoners (n) and a step count (k).
- Calculate the position of any prisoner in the killing sequence.
- Provide an option to save a certain number of prisoners (m).
- The numbering of prisoners can start from either 0 or 1.
- The complexity of the solution is O(kn) for the complete killing sequence and O(m) for finding the m-th prisoner to die.


function repeat( str, n,    rep, i )
{
    for( ; i<n; i++ )
        rep = rep str
    return rep
}

BEGIN {
    print repeat( "ha", 5 )
}

The code takes a string or a character as input and repeats it a specified number of times. For example, if the input is "ha" and 5, the output will be "hahahahaha". Similarly, if the input is "*" and 5, the output will be "*****".


$ awk '{if($0~/[A-Z]/)print "uppercase detected"}'
abc
ABC
uppercase detected

awk '/[A-Z]/{print "uppercase detected"}'
def
DeF
uppercase detected

$ awk '{gsub(/[A-Z]/,"*");print}'
abCDefG
ab**ef*
$ awk '{gsub(/[A-Z]/,"(&)");print}'
abCDefGH
ab(C)(D)ef(G)(H)

$ awk '{gsub(/[A-Z]+/,"(&)");print}'
abCDefGH
ab(CD)ef(GH)

 print "Match not found"

The code uses AWK's support for regular expressions to match and substitute parts of a string. It includes a condition part that triggers when a match is found in an input line. The substitution function uses a regular expression as its first argument and a constant replacement string. The code also features a variant that matches one or more uppercase letters and demonstrates how to achieve regular expression negation by combining the binding operator with a logical not operator.


/^[ \t]*-?[0-9]+[ \t]+-?[0-9]+[ \t]*$/ {
	print "add:", $1 + $2
	print "sub:", $1 - $2
	print "mul:", $1 * $2
	print "div:", int($1 / $2) # truncates toward zero
	print "mod:", $1 % $2      # same sign as first operand
	print "exp:", $1 ^ $2
	exit }

take two integers as input from the user and calculate their sum, difference, product, integer quotient, remainder, and exponentiation (if applicable). The code does not include error handling. The rounding method for quotient and the sign for the remainder are specified. The code also includes an example of the integer 'divmod' operator. The behavior of division and modulus is similar to C, and the use of exponentiation operator is in accordance with the POSIX standard.


#
# countsubstring(string, pattern)
#   Returns number of occurrences of pattern in string
#   Pattern treated as a literal string (regex characters not expanded)
#
function countsubstring(str, pat,    len, i, c) {
  c = 0
  if( ! (len = length(pat) ) )
    return 0
  while(i = index(str, pat)) {
    str = substr(str, i + len)
    c++
  }
  return c
}
#
# countsubstring_regex(string, regex_pattern)
#   Returns number of occurrences of pattern in string
#   Pattern treated as regex
#
function countsubstring_regex(str, pat,    c) {
  c = 0
  c += gsub(pat, "", str)
  return c
}
BEGIN {
  print countsubstring("[do&d~run?d!run&>run&]", "run&")
  print countsubstring_regex("[do&d~run?d!run&>run&]", "run[&]")
  print countsubstring("the three truths","th")
}

The code defines a function to count the number of non-overlapping occurrences of a given substring within a larger string. The function takes two arguments: the main string and the substring to search for. It returns an integer representing the count of non-overlapping occurrences. The function prioritizes the highest number of non-overlapping matches, typically matching from left-to-right or right-to-left.


$ awk 'func hanoi(n,f,t,v){if(n>0){hanoi(n-1,f,v,t);print(f,"->",t);hanoi(n-1,v,t,f)}}
BEGIN{hanoi(4,"left","middle","right")}'

"Implement a recursive solution to solve the Towers of Hanoi problem."


# syntax: GAWK -f EVALUATE_BINOMIAL_COEFFICIENTS.AWK
BEGIN {
    main(5,3)
    main(100,2)
    main(33,17)
    exit(0)
}
function main(n,k,  i,r) {
    r = 1
    for (i=1; i<k+1; i++) {
      r *= (n - i + 1) / i
    }
    printf("%d %d = %d\n",n,k,r)
}

The code calculates any binomial coefficient using the provided formula. It is specifically designed to output the binomial coefficient of 5 choose 3, which is 10. It also includes tasks for generating combinations and permutations, both with and without replacement.


{
  line[NR] = $0
}
END { # sort it with shell sort
  increment = int(NR / 2)
  while ( increment > 0 ) {
    for(i=increment+1; i <= NR; i++) {
      j = i
      temp = line[i]
      while ( (j >= increment+1) && (line[j-increment] > temp) ) {
	line[j] = line[j-increment]
	j -= increment
      }
      line[j] = temp
    }
    if ( increment == 2 )
      increment = 1
    else
      increment = int(increment*5/11)
  }
  #print it
  for(i=1; i <= NR; i++) {
    print line[i]
  }
}

implement the Shell sort algorithm to sort an array of elements. This algorithm, invented by Donald Shell, uses a diminishing increment sort and interleaved insertion sorts based on an increment sequence. The increment size reduces after each pass until it reaches 1, turning the sort into a basic insertion sort. The data is almost sorted at this point, providing the best case for insertion sort. The increment sequence can vary but should always end in 1. Sequences with a geometric increment ratio of about 2.2 have been found to work well.


BEGIN {
  val = 0
  do {
    val++
    print val
  } while( val % 6 != 0)
}

The code initializes a value to 0, then enters a do-while loop where it increments the value by 1 and prints it, continuing as long as the value modulo 6 is not 0. The loop is guaranteed to execute at least once.


w=length("Hello, world!")      # static string example
x=length("Hello," s " world!") # dynamic string example
y=length($1)                   # input field example
z=length(s)                    # variable name example

 echo "Hello, wørld!" | awk '{print length($0)}'   # 14

#!/usr/bin/awk -f
{print"The length of this line is "length($0)}

The code calculates the character and byte length of a string, considering UTF-8 and UTF-16 encodings. It correctly handles non-BMP code points and provides the actual character counts in code points, not in code unit counts. It also has the ability to provide the string length in graphemes if the language supports it.


BEGIN {
  mystring="knights"
  print substr(mystring,2)                       # remove the first letter
  print substr(mystring,1,length(mystring)-1)    # remove the last character
  print substr(mystring,2,length(mystring)-2)    # remove both the first and last character
}

The code demonstrates how to remove the first, last, and both the first and last characters from a string. It works with any valid Unicode code point in UTF-8 or UTF-16, referencing logical characters, not code units. It doesn't necessarily support all Unicode characters for other encodings like 8-bit ASCII or EUC-JP.


"Implement a Sudoku solver that takes a partially filled 9x9 grid as input and outputs the completed Sudoku grid in a human-readable format."


# Shuffle an _array_ with indexes from 1 to _len_.
function shuffle(array, len,    i, j, t) {
	for (i = len; i > 1; i--) {
		# j = random integer from 1 to i
		j = int(i * rand()) + 1

		# swap array[i], array[j]
		t = array[i]
		array[i] = array[j]
		array[j] = t
	}
}

# Test program.
BEGIN {
	len = split("11 22 33 44 55 66 77 88 99 110", array)
	shuffle(array, len)

	for (i = 1; i < len; i++) printf "%s ", array[i]
	printf "%s\n", array[len]
}

implement the Knuth shuffle algorithm (also known as the Fisher-Yates shuffle). This algorithm randomly shuffles the elements of an input array in-place. If in-place modification is not possible, the algorithm can be adjusted to return a new shuffled array. The algorithm can also be modified to iterate from left to right for convenience. The input array can contain integers, floating-point numbers, or strings.


# syntax: GAWK -f LAST_FRIDAY_OF_EACH_MONTH.AWK year
# converted from Fortran
BEGIN {
    split("31,28,31,30,31,30,31,31,30,31,30,31",daynum_array,",") # days per month in non leap year
    year = ARGV[1]
    if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
      daynum_array[2] = 29
    }
    y = year - 1
    k = 44 + y + int(y/4) + int(6*(y/100)) + int(y/400)
    for (m=1; m<=12; m++) {
      k += daynum_array[m]
      d = daynum_array[m] - (k%7)
      printf("%04d-%02d-%02d\n",year,m,d)
    }
    exit(0)
}

The code takes a year as input and outputs the dates of the last Friday of each month for that given year.


"Display the string 'Goodbye, World!' without appending a newline at the end."


#!/usr/bin/awk -f

BEGIN {
    message = "My hovercraft is full of eels."
    key = 1

    cypher = caesarEncode(key, message)
    clear  = caesarDecode(key, cypher)

    print "message: " message
    print " cypher: " cypher
    print "  clear: " clear
    exit
}

function caesarEncode(key, message) {
    return caesarXlat(key, message, "encode")
}

function caesarDecode(key, message) {
    return caesarXlat(key, message, "decode")
}

function caesarXlat(key, message, dir,    plain, cypher, i, num, s) {
    plain = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    cypher = substr(plain, key+1) substr(plain, 1, key)

    if (toupper(substr(dir, 1, 1)) == "D") {
        s = plain
        plain = cypher
        cypher = s
    }

    s = ""
    message = toupper(message)
    for (i = 1; i <= length(message); i++) {
        num = index(plain, substr(message, i, 1))
        if (num) s = s substr(cypher, num, 1)
        else s = s substr(message, i, 1)
    }
    return s
}

implement both encoding and decoding functions of a Caesar cipher. The cipher rotates the alphabet letters based on a key ranging from 1 to 25, replacing each letter with the corresponding next letter in the alphabet. The codes also handle cases of wrapping from Z to A. The codes illustrate that Caesar cipher provides minimal security as it is vulnerable to frequency analysis and brute force attacks. The codes also demonstrate that Caesar cipher is identical to Vigenère cipher with a key length of 1 and to Rot-13 with a key of 13.


# greatest common divisor
function gcd(m, n,    t) {
	# Euclid's method
	while (n != 0) {
		t = m
		m = n
		n = t % n
	}
	return m
}

# least common multiple
function lcm(m, n,    r) {
	if (m == 0 || n == 0)
		return 0
	r = m * n / gcd(m, n)
	return r < 0 ? -r : r
}

# Read two integers from each line of input.
# Print their least common multiple.
{ print lcm($1, $2) }

Example input and output: $ awk -f lcd.awk
12 18
36
-6 14
42
35 0
0

calculate the least common multiple (LCM) of two integers m and n. The LCM is the smallest positive integer that has both m and n as factors. If either m or n is zero, the LCM is zero. The LCM can be calculated by iterating all the multiples of m until finding one that is also a multiple of n, or by using the formula lcm(m, n) = |m × n| / gcd(m, n), where gcd is the greatest common divisor. The LCM can also be found by merging the prime decompositions of both m and n.


The code validates the last digit (check digit) of a given CUSIP code, which is a nine-character alphanumeric code used to identify North American financial securities. The validation is performed according to a specific algorithm that considers the numeric value of digits, the ordinal position of letters in the alphabet, and specific values for special characters. The code also handles the doubling of values for even-positioned characters. The final check digit is calculated as (10 - (sum of calculated values mod 10)) mod 10.


Works with: Gawk

function join(array, start, end, sep,    result, i) {
        result = array[start]
        for (i = start + 1; i <= end; i++)
            result = result sep array[i]
        return result
}

function trim(str) {
        gsub(/^[[:blank:]]+|[[:blank:]\n]+$/, "", str)
        return str
}

function http2var(      site,path,server,j,output) {

        RS = ORS = "\r\n"

        site = "rosettacode.org"
        path = "/mw/api.php" \
            "?action=query" \
            "&generator=categorymembers" \
            "&gcmtitle=Category:Programming%20Languages" \
            "&gcmlimit=500" \
            (gcmcontinue "" ? "&gcmcontinue=" gcmcontinue : "") \
            "&prop=categoryinfo" \
            "&format=txt"

        server = "/inet/tcp/0/" site "/80"
        print "GET " path " HTTP/1.0" |& server
        print "Host: " site |& server
        print "" |& server
        while ((server |& getline) > 0) {
            if($0 != 0) {
                j++
                output[j] = $0
            }
        }
        close(server)
        if(length(output) == 0)
            return -1
        else
            return join(output, 1, j, "\n")
}

function parse(webpage  ,c,a,i,b,e,pages) {

       # Check for API continue code ie. a new page of results available
        match(webpage, "gcmcontinue[]] =>[^)]+[^)]", a)
        if(a[0] != "") {
            split(a[0], b, ">")
            gcmcontinue = trim(b[2])
        } else gcmcontinue = ""

        c = split(webpage, a, "[[][0-9]{1,7}[]]")

        while(i++ < c) {
            if(match(a[i], /[pages]/)) {
                match(a[i], "pages[]] =>[^[]+[^[]", b)
                split(b[0], e, ">")
                pages = trim(e[2]) + 0
            } else pages = 0
            if(match(a[i], /[title]/)) {
                match(a[i], "title[]] =>[^[]+[^[]", b)
                split(b[0], e, ":")
                e[2] = trim(e[2])
                if ( substr(e[2], length(e[2]), 1) == ")" )
                    e[2] = trim( substr(e[2], 1, length(e[2]) - 1) )
                if(length(e[2]) > 0)
                    G[e[2]] = pages
            }
        }
}

BEGIN {

        parse( http2var() )     # First 500
        while ( gcmcontinue != "" )
            parse( http2var() ) # Next 500, etc

        # https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html
        PROCINFO["sorted_in"] = "@val_type_desc"
        for ( language in G )
            print ++i ". " language " - " G[language]

}

Output from 26 May 2015:
1. Tcl - 867
2. Racket - 863
3. Python - 828
4. J - 777
5. Ruby - 769
6. Perl 6 - 755
7. C - 751
...
570. NQP - 0
571. AspectC++ - 0
572. Cilk - 0
573. PL/M - 0
574. Agda2 - 0

sorts the most popular computer programming languages based on the number of members in Rosetta Code categories. It uses either web scraping or API methods to access the data, and optionally filters incorrect results. The code also provides a complete ranked listing of all languages. The third solution in the code uses native gawk networking to connect to the API at 500 items per request.


BEGIN {
  split("Mary had a little lamb", strs, " ")
  for(el in strs) {
    print strs[el]
  }
}

BEGIN {
  n = split("Mary had a little lamb", strs, " ")
  for(i=1; i <= n; i++) {
    print strs[i]
  }
}

# This will not work
BEGIN {
  for (el in "apples","bananas","cherries") {
    print "I like " el
  }
}

iterate through each element in a collection in a specific order using a "for each" loop or an alternative loop if "for each" is not available. In AWK, the elements' indexes may not be in order, so keys are generated in the required order. The elements are filled into the array using the split function which starts indexing from 1. A normal loop is used to iterate over the array's elements in the correct order. However, in AWK, foreach loops can only be performed against an associative container and not against an explicit list.


BEGIN {
  s = "Hello,How,Are,You,Today"
  split(s, arr, ",")
  for(i=1; i < length(arr); i++) {
    printf arr[i] "."
  }
  print
}

BEGIN { FS = "," }
{
  for(i=1; i <= NF; i++) printf $i ".";
  print ""
}

"Tokenizes a string by separating it into an array using commas as delimiters, then displays the words to the user, separated by periods. It also allows for a trailing period. The code uses AWK's idiomatic way of tokenizing each line of input by using a comma as a field separator."


The code defines a function called gcd() that calculates the greatest common divisor (GCD), also known as the greatest common factor or greatest common measure, of two integers. It reads pairs of numbers from the standard input and outputs their GCD to the standard output. It is related to the task of finding the least common multiple.


$ awk 'function isnum(x){return(x==x+0)} BEGIN{print isnum("hello"),isnum("-42")}'

"Create a function that checks if a given string can be interpreted as a numeric value, including floating point and negative numbers, using the syntax rules of the language. The function uses the characteristic of AWK where non-numeric strings are treated as 0 in arithmetic operations but not in comparisons."


##
## Dense ranking in file: ranking_d.awk
##

BEGIN{ lastresult = "!"; lastrank = 0 }

function d_rank(){
    if($1==lastresult){
        print lastrank, $0
    }else{
        lastresult = $1
        print ++lastrank, $0 }
}
//{d_rank() }

##
## Fractional ranking in file: ranking_f.awk
##

BEGIN{
    last = "!"
    flen = 0 }

function f_rank(){
    item = $0
    if($1!=last){
        if(flen){
            sum = 0
            for(fl=0; fl < flen;){
                $0 = fifo[fl++]
                sum += $1 }
            mean = sum / flen
            for(fl=0; fl < flen;){
                $0 = fifo[fl++]
                $1 = ""
                printf("%3g %s\n", mean, $0) }
            flen = 0
    }}
    $0 = item
    last = $1
    fifo[flen++] = sprintf("%i %s", FNR, item)
}
//{f_rank()}

END{ if(flen){
        sum = 0
        for(fl=0; fl < flen;){
            $0 = fifo[fl++]
            sum += $1 }
        mean = sum / flen
        for(fl=0; fl < flen;){
            $0 = fifo[fl++]
            $1 = ""
            printf("%3g %s\n", mean, $0) }}}

##
## Modified competition ranking in file: ranking_mc.awk
##

BEGIN{
    lastresult = "!"
    flen = 0 }

function mc_rank(){
    if($1==lastresult){
        fifo[flen++] = $0
    }else{
        for(fl=0; fl < flen;){
            print FNR-1, fifo[fl++]}
        flen = 0
        fifo[flen++] = $0
        lastresult = $1}
}
//{mc_rank()}

END{ for(fl=0; fl < flen;){
        print FNR, fifo[fl++]} }

##
## Ordinal ranking in file: ranking_o.awk
##

function o_rank(){ print FNR, $0 }
//{o_rank() }

##
## Standard competition ranking in file: ranking_sc.awk
##

BEGIN{ lastresult = lastrank = "!" }

function sc_rank(){
    if($1==lastresult){
        print lastrank, $0
    }else{
        print FNR, $0
        lastresult = $1
        lastrank = FNR}
}
//{sc_rank()}

44 Solomon
42 Jason
42 Errol
41 Garry
41 Bernard
41 Barry
39 Stephen

The code implements five different ranking methods (Standard, Modified, Dense, Ordinal, Fractional) for competitors in a competition. It takes an ordered list of scores with scorers from a file and applies each ranking method to it, outputting the rankings for each method. In case of ties, each method handles them differently as per the task description.


tangent

arcsine

arccosine

tan

θ
=

sin

θ

cos

θ

{\displaystyle \tan \theta = \frac{\sin \theta}{\cos \theta}}

tan

(
arcsin

y
)
=

y

1
−

y
2

{\displaystyle \tan(\arcsin y) = \frac{y}{\sqrt{1 - y^2}}}

tan

(
arccos

x
)
=

1
−

x
2

x

{\displaystyle \tan(\arccos x) = \frac{\sqrt{1 - x^2}}{x}}

# tan(x) = tangent of x
function tan(x) {
	return sin(x) / cos(x)
}

# asin(y) = arcsine of y, domain [-1, 1], range [-pi/2, pi/2]
function asin(y) {
	return atan2(y, sqrt(1 - y * y))
}

# acos(x) = arccosine of x, domain [-1, 1], range [0, pi]
function acos(x) {
	return atan2(sqrt(1 - x * x), x)
}

# atan(y) = arctangent of y, range (-pi/2, pi/2)
function atan(y) {
	return atan2(y, 1)
}

BEGIN {
	pi = atan2(0, -1)
	degrees = pi / 180

	print "Using radians:"
	print "  sin(-pi / 6) =", sin(-pi / 6)
	print "  cos(3 * pi / 4) =", cos(3 * pi / 4)
	print "  tan(pi / 3) =", tan(pi / 3)
	print "  asin(-1 / 2) =", asin(-1 / 2)
	print "  acos(-sqrt(2) / 2) =", acos(-sqrt(2) / 2)
	print "  atan(sqrt(3)) =", atan(sqrt(3))

	print "Using degrees:"
	print "  sin(-30) =", sin(-30 * degrees)
	print "  cos(135) =", cos(135 * degrees)
	print "  tan(60) =", tan(60 * degrees)
	print "  asin(-1 / 2) =", asin(-1 / 2) / degrees
	print "  acos(-sqrt(2) / 2) =", acos(-sqrt(2) / 2) / degrees
	print "  atan(sqrt(3)) =", atan(sqrt(3)) / degrees
}

demonstrate the usage of trigonometric functions such as sine, cosine, tangent and their inverses in a specific programming language. The functions are applied using the same angle in both radians and degrees. For non-inverse functions, the same angle is used for both sine calls. For inverse functions, the same number is used and its result is converted to radians and degrees. In the case of languages without built-in trigonometric functions, the code provides custom functions based on known approximations or identities. In Awk, which only provides sin(), cos() and atan2(), additional functions are calculated using trigonometric identities.


increment a given numerical string while maintaining its length.


# Finds the longest common directory of paths[1], paths[2], ...,
# paths[count], where sep is a single-character directory separator.
function common_dir(paths, count, sep,    b, c, f, i, j, p) {
	if (count < 1)
		return ""

	p = ""	# Longest common prefix
	f = 0	# Final index before last sep

	# Loop for c = each character of paths[1].
	for (i = 1; i <= length(paths[1]); i++) {
		c = substr(paths[1], i, 1)

		# If c is not the same in paths[2], ..., paths[count]
		# then break both loops.
		b = 0
		for (j = 2; j <= count; j++) {
			if (c != substr(paths[j], i, 1)) {
				b = 1
				break
			}
		}
		if (b)
			break

		# Append c to prefix. Update f.
		p = p c
		if (c == sep)
			f = i - 1
	}

	# Return only f characters of prefix.
	return substr(p, 1, f)
}

BEGIN {
	a[1] = "/home/user1/tmp/coverage/test"
	a[2] = "/home/user1/tmp/covert/operator"
	a[3] = "/home/user1/tmp/coven/members"
	print common_dir(a, 3, "/")
}

"Code identifies the common directory path from a set of given directory paths using a specified directory separator character."


#!/usr/bin/awk -f

BEGIN {
    d[1] = 3.0
    d[2] = 4.0
    d[3] = 1.0
    d[4] = -8.4
    d[5] = 7.2
    d[6] = 4.0
    d[7] = 1.0
    d[8] = 1.2
    showD("Before: ")
    gnomeSortD()
    showD("Sorted: ")
    printf "Median: %f\n", medianD()
    exit
}

function medianD(     len, mid) {
    len = length(d)
    mid = int(len/2) + 1
    if (len % 2) return d[mid]
    else return (d[mid] + d[mid-1]) / 2.0
}

function gnomeSortD(    i) {
    for (i = 2; i <= length(d); i++) {
        if (d[i] < d[i-1]) gnomeSortBackD(i)
    }
}

function gnomeSortBackD(i,     t) {
    for (; i > 1 && d[i] < d[i-1]; i--) {
        t = d[i]
        d[i] = d[i-1]
        d[i-1] = t
    }
}

function showD(p,   i) {
    printf p
    for (i = 1; i <= length(d); i++) {
        printf d[i] " "
    }
    print ""
}

Before: 3 4 1 -8.4 7.2 4 1 1.2
Sorted: -8.4 1 1 1.2 3 4 4 7.2
Median: 2.100000

"Code calculates the median value of a vector of floating-point numbers, handling even number of elements by returning the average of the two middle values. It uses the selection algorithm for optimal performance. It also includes tasks for calculating various statistical measures such as mean, mode, and standard deviation. The code does not return AWK arrays, making them global."


# usage: awk  -v n=38  -f FizzBuzz.awk
#
BEGIN {
   if(!n) n=100
   print "# FizzBuzz:"

   for (ii=1; ii<=n; ii++)
       if (ii % 15 == 0)
           {print "FizzBuzz"}
       else if (ii % 3 == 0)
           {printf "Fizz "}
       else if (ii % 5 == 0)
           {printf "Buzz "}
       else
           {printf "%3d ", ii}

    print "
# Done."
}

print numbers from 1 to 100, replacing multiples of three with 'Fizz', multiples of five with 'Buzz', and multiples of both three and five with 'FizzBuzz'.


BEGIN {
  XSize=59; YSize=21;
  MinIm=-1.0; MaxIm=1.0;MinRe=-2.0; MaxRe=1.0;
  StepX=(MaxRe-MinRe)/XSize; StepY=(MaxIm-MinIm)/YSize;
  for(y=0;y<YSize;y++)
  {
    Im=MinIm+StepY*y;
    for(x=0;x<XSize;x++)
        {
      Re=MinRe+StepX*x; Zr=Re; Zi=Im;
      for(n=0;n<30;n++)
          {
        a=Zr*Zr; b=Zi*Zi;
        if(a+b>4.0) break;
        Zi=2*Zr*Zi+Im; Zr=a-b+Re;
      }
      printf "%c",62-n;
    }
    print "";
  }
  exit;
}

generate and draw the Mandelbrot set using various available algorithms and functions.


$ awk 'func sum(s){split(s,a);r=0;for(i in a)r+=a[i];return r}{print sum($0)}'
1 2 3 4 5 6 7 8 9 10
55

$ awk 'func prod(s){split(s,a);r=1;for(i in a)r*=a[i];return r}{print prod($0)}'
1 2 3 4 5 6 7 8 9 10
3628800

"Calculates the sum and product of all integers in an array, which is deserialized from a string using the split() function."


function leapyear( year )
{
    if ( year % 100 == 0 )
        return ( year % 400 == 0 )
    else
        return ( year % 4 == 0 )
}

"Determines if a specified year is a leap year in the Gregorian calendar."


# syntax: GAWK -f DEPARTMENT_NUMBERS.AWK
BEGIN {
    print(" # FD PD SD")
    for (fire=1; fire<=7; fire++) {
      for (police=1; police<=7; police++) {
        for (sanitation=1; sanitation<=7; sanitation++) {
          if (rules() ~ /^1+$/) {
            printf("%2d %2d %2d %2d\n",++count,fire,police,sanitation)
          }
        }
      }
    }
    exit(0)
}
function rules(  stmt1,stmt2,stmt3) {
    stmt1 = fire != police && fire != sanitation && police != sanitation
    stmt2 = fire + police + sanitation == 12
    stmt3 = police % 2 == 0
    return(stmt1 stmt2 stmt3)
}

all possible combinations of unique numbers between 1 and 7 (inclusive) for three different departments (police, sanitation, fire) that add up to 12, with the police department number being an even number.


BEGIN {
  a = "a string"
  b = a
  sub(/a/, "X", a) # modify a
  print b  # b is a copy, not a reference to...
}

"Implements functionality to copy a string's content and create an additional reference to an existing string where applicable."


cat mutual_recursion.awk:
#!/usr/local/bin/gawk -f

# User defined functions
function F(n)
{ return n == 0 ? 1 : n - M(F(n-1)) }

function M(n)
{ return n == 0 ? 0 : n - F(M(n-1)) }

BEGIN {
  for(i=0; i <= 20; i++) {
    printf "%3d ", F(i)
  }
  print ""
  for(i=0; i <= 20; i++) {
    printf "%3d ", M(i)
  }
  print ""
}

implement two mutually recursive functions to calculate the Hofstadter Female and Male sequences. The Female sequence is initialized with F(0)=1 and calculated using F(n)=n-M(F(n-1)) for n>0. The Male sequence is initialized with M(0)=0 and calculated using M(n)=n-F(M(n-1)) for n>0. The functions are defined in AWK.


# syntax: GAWK -f PICK_RANDOM_ELEMENT.AWK
BEGIN {
    n = split("Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",day_of_week,",")
    srand()
    x = int(n*rand()) + 1
    printf("%s\n",day_of_week[x])
    exit(0)
}

demonstrate how to select a random element from a list.


# syntax:
awk '
BEGIN {
    str = "http%3A%2F%2Ffoo%20bar%2F" # "http://foo bar/"
    printf("%s\n",str)
    len=length(str)
    for (i=1;i<=len;i++) {
      if ( substr(str,i,1) == "%") {
        L = substr(str,1,i-1) # chars to left of "%"
        M = substr(str,i+1,2) # 2 chars to right of "%"
        R = substr(str,i+3)   # chars to right of "%xx"
        str = sprintf("%s%c%s",L,hex2dec(M),R)
      }
    }
    printf("%s\n",str)
    exit(0)
}
function hex2dec(s,  num) {
    num = index("0123456789ABCDEF",toupper(substr(s,length(s)))) - 1
    sub(/.$/,"",s)
    return num + (length(s) ? 16*hex2dec(s) : 0)
} '

provide a function to convert URL-encoded strings back to their original unencoded form. The function handles various test cases including strings with special characters and percentages.


Works with: Gawk
Works with: Mawk
Works with: Nawk

function binary_search(array, value, left, right,       middle) {
    if (right < left) return 0
    middle = int((right + left) / 2)
    if (value == array[middle]) return 1
    if (value <  array[middle])
        return binary_search(array, value, left, middle - 1)
    return binary_search(array, value, middle + 1, right)
}

function binary_search(array, value, left, right,       middle) {
    while (left <= right) {
        middle = int((right + left) / 2)
        if (value == array[middle]) return 1
        if (value <  array[middle]) right = middle - 1
        else                        left  = middle + 1
    }
    return 0
}

The code implements a binary search algorithm on a sorted integer array. It takes the starting and ending points of a range, and a "secret value" as inputs. The algorithm divides the range into halves and continues to narrow down the search field until the secret value is found. The implementation can be either recursive or iterative. The code also handles multiple values equal to the given value and returns the index of the secret value if found, or the "insertion point" for it if not found. The code also includes fixes for potential overflow bugs.


#!/usr/bin/awk -f

BEGIN {
  print "There are " ARGC "command line parameters"
  for(l=1; l<ARGC; l++) {
    print "Argument " l " is " ARGV[l]
  }
}

The code retrieves and prints the list of command-line arguments provided to the program, such as 'myprogram -c "alpha beta" -h "gamma"'. It also includes functionalities for intelligent parsing of these arguments.


#!/usr/bin/awk -f
BEGIN {
        # test
	print nthroot(8,3)
	print nthroot(16,2)
	print nthroot(16,4)
	print nthroot(125,3)
	print nthroot(3,3)
	print nthroot(3,2)
}

function nthroot(y,n) {
        eps = 1e-15;   # relative accuracy
        x   = 1;
	do {
		d  = ( y / ( x^(n-1) ) - x ) / n ;
		x += d;
		e = eps*x;   # absolute accuracy
	} while ( d < -e  || d > e )

	return x
}

 2
 4
 2
 5
 1.44225
 1.73205

Implement the principal nth root computation algorithm for a positive real number A.


WARNING: the following purported solution makes an assumption about environment variables that may not be applicable in all circumstances.

$ awk 'BEGIN{print ENVIRON["HOST"]}'
E51A08ZD

"Determines and outputs the hostname of the current system where the routine is running."


# syntax: GAWK -f LEONARDO_NUMBERS.AWK
BEGIN {
    leonardo(1,1,1,"Leonardo")
    leonardo(0,1,0,"Fibonacci")
    exit(0)
}
function leonardo(L0,L1,step,text,  i,tmp) {
    printf("%s numbers (%d,%d,%d):\n",text,L0,L1,step)
    for (i=1; i<=25; i++) {
      if (i == 1) {
        printf("%d ",L0)
      }
      else if (i == 2) {
        printf("%d ",L1)
      }
      else {
        printf("%d ",L0+L1+step)
        tmp = L0
        L0 = L1
        L1 = tmp + L1 + step
      }
    }
    printf("\n")
}

generate the first 25 Leonardo numbers, starting from L(0), with the ability to specify the first two Leonardo numbers and the add number. The codes also have the functionality to generate the Fibonacci sequence by specifying 0 and 1 for L(0) and L(1), and 0 for the add number.


The code implements run-length encoding and decoding for a string of uppercase characters. It compresses repeated characters by storing the length of the run. It also provides a function to reverse the compression. The code skips lines containing numbers to avoid ambiguity.


BEGIN {
   s = "hello"
   print s " literal"
   s1 = s " literal"
   print s1
}

Creates two string variables, one with a predefined text value and the other combining the original string with an additional string literal, using AWK's concatenation operator. The content of the variables is then displayed.


BEGIN {
	for (i = 0; i <= 255; i++)
		ord[sprintf("%c", i)] = i
}

# Encode string with application/x-www-form-urlencoded escapes.
function escape(str,    c, len, res) {
	len = length(str)
	res = ""
	for (i = 1; i <= len; i++) {
		c = substr(str, i, 1);
		if (c ~ /[0-9A-Za-z]/)
		#if (c ~ /[-._*0-9A-Za-z]/)
			res = res c
		#else if (c == " ")
		#	res = res "+"
		else
			res = res "%" sprintf("%02X", ord[c])
	}
	return res
}

# Escape every line of input.
{ print escape($0) }

The code provides a function to convert a given string into URL encoding format. It changes special characters, control characters, and extended characters into a percent symbol followed by a two-digit hexadecimal code. For instance, a space character is encoded as %20. It converts all characters except 0-9, A-Z, and a-z. It also allows for variations such as lowercase escapes and different encodings for different standards like RFC 3986 and HTML 5. An optional feature is the use of an exception string that contains symbols that don't need conversion. For HTML 5 rules, it can convert " " to "+" and preserve "-._*".


# syntax: GAWK -f COMMON_SORTED_LIST.AWK
BEGIN {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    nums = "[5,1,3,8,9,4,8,7],[3,5,9,8,4],[1,3,7,9]"
    printf("%s : ",nums)
    n = split(nums,arr1,"],?") - 1
    for (i=1; i<=n; i++) {
      gsub(/[\[\]]/,"",arr1[i])
      split(arr1[i],arr2,",")
      for (j in arr2) {
        arr3[arr2[j]]++
      }
    }
    for (j in arr3) {
      printf("%s ",j)
    }
    printf("\n")
    exit(0)
}

generates a common sorted list with unique elements from multiple integer arrays.


# syntax: GAWK -f KNAPSACK_PROBLEM_CONTINUOUS.AWK
BEGIN {
#   arr["item,weight,price"]
    arr["beef,3.8,36"]
    arr["pork,5.4,43"]
    arr["ham,3.6,90"]
    arr["greaves,2.4,45"]
    arr["flitch,4.0,30"]
    arr["brawn,2.5,56"]
    arr["welt,3.7,67"]
    arr["salami,3.0,95"]
    arr["sausage,5.9,98"]
    for (i in arr) {
      split(i,tmp,",")
      arr[i] = tmp[3] / tmp[2] # $/unit
    }
    sack_size = 15 # kg
    PROCINFO["sorted_in"] = "@val_num_desc"
    print("item    weight  price $/unit")
    for (i in arr) {
      if (total_weight >= sack_size) {
        break
      }
      split(i,tmp,",")
      weight = tmp[2]
      if (total_weight + weight <= sack_size) {
        price = tmp[3]
        msg = "all"
      }
      else {
        weight = sack_size - total_weight
        price = weight * arr[i]
        msg = weight " of " tmp[2]
      }
      printf("%-7s %6.2f %6.2f %6.2f take %s\n",tmp[1],weight,tmp[3],arr[i],msg)
      total_items++
      total_price += price
      total_weight += weight
    }
    printf("%7d %6.2f %6.2f total\n",total_items,total_weight,total_price)
    exit(0)
}

determine the optimal combination of items a thief can steal from a butcher's shop without exceeding a total weight of 15 kg in his knapsack, with the possibility of cutting items proportionally to their original price, in order to maximize the total value.


# JUMBLEA.AWK - words with the most duplicate spellings
# syntax: GAWK -f JUMBLEA.AWK UNIXDICT.TXT
{   for (i=1; i<=NF; i++) {
      w = sortstr(toupper($i))
      arr[w] = arr[w] $i " "
      n = gsub(/ /,"&",arr[w])
      if (max_n < n) { max_n = n }
    }
}
END {
    for (w in arr) {
      if (gsub(/ /,"&",arr[w]) == max_n) {
        printf("%s\t%s\n",w,arr[w])
      }
    }
    exit(0)
}
function sortstr(str,  i,j,leng) {
    leng = length(str)
    for (i=2; i<=leng; i++) {
      for (j=i; j>1 && substr(str,j-1,1) > substr(str,j,1); j--) {
        str = substr(str,1,j-2) substr(str,j,1) substr(str,j-1,1) substr(str,j+1)
      }
    }
    return(str)
}

"Code identifies and lists the largest sets of anagrams from a given word list, sourced from a specified URL."


# WSC.AWK - Waclaw Sierpinski's carpet contributed by Dan Nielsen
#
# syntax: GAWK -f WSC.AWK [-v o={a|A}{b|B}] [-v X=anychar] iterations
#
#   -v o=ab default
#      a|A  loose weave | tight weave
#      b|B  don't show | show how the carpet is built
#   -v X=?  Carpet is built with X's. The character assigned to X replaces all X's.
#
#   iterations
#      The number of iterations. The default is 0 which produces one carpet.
#
# what is the difference between a loose weave and a tight weave:
#   loose                tight
#   X X X X X X X X X    XXXXXXXXX
#   X   X X   X X   X    X XX XX X
#   X X X X X X X X X    XXXXXXXXX
#   X X X       X X X    XXX   XXX
#   X   X       X   X    X X   X X
#   X X X       X X X    XXX   XXX
#   X X X X X X X X X    XXXXXXXXX
#   X   X X   X X   X    X XX XX X
#   X X X X X X X X X    XXXXXXXXX
#
# examples:
#   GAWK -f WSC.AWK 2
#   GAWK -f WSC.AWK -v o=Ab -v X=# 2
#   GAWK -f WSC.AWK -v o=Ab -v X=\xDB 2
#
BEGIN {
    optns = (o == "") ? "ab" : o
    n = ARGV[1] + 0 # iterations
    if (n !~ /^[0-9]+$/) { exit(1) }
    seed = (optns ~ /A/) ? "XXX,X X,XXX" : "X X X ,X   X ,X X X " # tight/loose weave
    leng = row = split(seed,A,",") # seed the array
    for (i=1; i<=n; i++) { # build carpet
      for (a=1; a<=3; a++) {
        row = 0
        for (b=1; b<=3; b++) {
          for (c=1; c<=leng; c++) {
            row++
            tmp = (a == 2 && b == 2) ? sprintf("%*s",length(A[c]),"") : A[c]
            B[row] = B[row] tmp
          }
          if (optns ~ /B/) { # show how the carpet is built
            if (max_row < row+0) { max_row = row }
            for (r=1; r<=max_row; r++) {
              printf("i=%d row=%02d a=%d b=%d '%s'\n",i,r,a,b,B[r])
            }
            print("")
          }
        }
      }
      leng = row
      for (j=1; j<=row; j++) { A[j] = B[j] } # re-seed the array
      for (j in B) { delete B[j] } # delete work array
    }
    for (j=1; j<=row; j++) { # print carpet
      if (X != "") { gsub(/X/,substr(X,1,1),A[j]) }
      sub(/ +$/,"",A[j])
      printf("%s\n",A[j])
    }
    exit(0)
}

Sample:
GAWK -f WSC.AWK 1

X X X X X X X X X
X   X X   X X   X
X X X X X X X X X
X X X       X X X
X   X       X   X
X X X       X X X
X X X X X X X X X
X   X X   X X   X
X X X X X X X X X

GAWK -f WSC.AWK -v o=A 1

XXXXXXXXX
X XX XX X
XXXXXXXXX
XXX   XXX
X X   X X
XXX   XXX
XXXXXXXXX
X XX XX X
XXXXXXXXX

generate a graphical or ASCII-art representation of a Sierpinski carpet of a given order N. The representation uses whitespace and non-whitespace characters, with the non-whitespace character not strictly required to be '#'. The placement of these characters follows the pattern of a Sierpinski carpet.


#!/bin/sh -f
awk '
BEGIN {
    print "Creating table..."
    dbExec("address.db", "create table address (street, city, state, zip);")
    print "Done."
    exit
}

function dbExec(db, qry,      result) {
    dbMakeQuery(db, qry) | getline result
    dbErrorCheck(result)
}

function dbMakeQuery(db, qry,      q) {
    q = dbEscapeQuery(qry) ";"
    return "echo \"" q "\" | sqlite3 " db
}

function dbEscapeQuery(qry,      q) {
    q = qry
    gsub(/"/, "\\\"", q)
    return q
}

function dbErrorCheck(res) {
    if (res ~ "SQL error") {
        print res
        exit
    }
}

'

"Create a table in a database to store US postal addresses, including fields for unique identifier, street address, city, state code, and zipcode. The code also demonstrates how to open a database connection in non-database languages using AWK pipe, 'getline' function, and sqlite3 command line program."


BEGIN {
  for(i=10; i>=0; i--) {
     print i
  }
}

The code performs a countdown from 10 to 0 using a downward for loop.


BEGIN {
  for (i= 2; i <= 8; i = i + 2) {
    print i
  }
  print "Ain't never too late!"
}

demonstrate a for-loop with a step-value greater than one.


# syntax: GAWK -f JENSENS_DEVICE.AWK
# converted from FreeBASIC
BEGIN {
    evaluation()
    exit(0)
}
function evaluation(  hi,i,lo,tmp) {
    lo = 1
    hi = 100
    for (i=lo; i<=hi; i++) {
      tmp += (1/i)
    }
    printf("%.15f\n",tmp)
}

implement Jensen's Device, a programming technique devised by Jørn Jensen. The technique is an exercise in call by name, where it computes the 100th harmonic number. The program uses a sum procedure that takes in four parameters, with the first and the last parameter being passed by name. This allows the expression passed as an actual parameter to be re-evaluated in the caller's context every time the corresponding formal parameter's value is required. The program also demonstrates the importance of passing the first parameter by name or by reference, as changes to it within the sum procedure need to be visible in the caller's context when computing each of the values to be added.


Works with: gawk

BEGIN {
    # square size
    s = 256
    # the PPM image header needs 3 lines:
    # P3
    # width height
    # max colors number (per channel)
    print("P3\n", s, s, "\n", s - 1)
    # and now we generate pixels as a RGB pair in a relaxed
    # form "R G B\n"
    for (x = 0; x < s; x++) {
        for (y = 0; y < s; y++) {
            p = xor(x, y)
            print(0, p, p)
        }
    }
}

generates a graphical pattern where each pixel's color is determined by the value of 'x xor y' using a specific color table, and produces a PPM image that can be viewed or converted with The GIMP or ImageMagick.


#!/usr/bin/awk -f

# Remember: AWK is 1-based, for better or worse.

BEGIN {
    # The maze dimensions.
    width = 20;  # Global
    height = 20; # Global
    resetMaze();

    # Some constants.
    top = 1;
    bottom = 2;
    left = 3;
    right = 4;

    # Randomize the PRNG.
    randomize();

    # Visit all the cells starting at a random point.
    visitCell(getRandX(), getRandY());

    # Show the result.
    printMaze();
}

# Wander through the maze removing walls as we go.
function visitCell(x, y,    dirList, dir, nx, ny, ndir, pi) {
    setVisited(x, y);   # This cell has been visited.

    # Visit neighbors in a random order.
    dirList = getRandDirList();
    for (dir = 1; dir <= 4; dir++) {
        # Get coordinates of a random neighbor (next in random direction list).
        ndir = substr(dirList, dir, 1);
        nx = getNextX(x, ndir);
        ny = getNextY(y, ndir);

        # Visit an unvisited neighbor, removing the separating walls.
        if (wasVisited(nx, ny) == 0) {
            rmWall(x, y, ndir);
            rmWall(nx, ny, getOppositeDir(ndir));
            visitCell(nx, ny)
        }
    }
}

# Display the text-mode maze.
function printMaze(    x, y, r, w) {
    for (y = 1; y <= height; y++) {
        for (pass = 1; pass <= 2; pass++) { # Go over each row twice: top, middle
            for (x = 1; x <= width; x++) {
                if (pass == 1) { # top
                    printf("+");
                    printf(hasWall(x, y, top) == 1 ? "---" : "   ");
                    if (x == width) printf("+");
                }
                else if (pass == 2) { # left, right
                    printf(hasWall(x, y, left) == 1 ? "|" : " ");
                    printf("   ");
                    if (x == width) printf(hasWall(x, y, right) == 1 ? "|" : " ");
                }
            }
            print;
        }
    }
    for (x = 1; x <= width; x++) printf("+---"); # bottom row
    print("+"); # bottom right corner
}

# Given a direction, get its opposite.
function getOppositeDir(d) {
    if (d == top) return bottom;
    if (d == bottom) return top;
    if (d == left) return right;
    if (d == right) return left;
}

# Build a list (string) of the four directions in random order.
function getRandDirList(    dirList, randDir, nx, ny, idx) {
    dirList = "";
    while (length(dirList) < 4) {
        randDir = getRandDir();
        if (!index(dirList, randDir)) {
            dirList = dirList randDir;
        }
    }
    return dirList;
}

# Get x coordinate of the neighbor in a given a direction.
function getNextX(x, dir) {
    if (dir == left) x = x - 1;
    if (dir == right) x = x + 1;
    if (!isGoodXY(x, 1)) return -1; # Off the edge.
    return x;
}

# Get y coordinate of the neighbor in a given a direction.
function getNextY(y, dir) {
    if (dir == top) y = y - 1;
    if (dir == bottom) y = y + 1;
    if (!isGoodXY(1, y)) return -1; # Off the edge.
    return y;
}

# Mark a cell as visited.
function setVisited(x, y,    cell) {
    cell = getCell(x, y);
    if (cell == -1) return;
    cell = substr(cell, 1, 4) "1"; # walls plus visited
    setCell(x, y, cell);
}

# Get the visited state of a cell.
function wasVisited(x, y,    cell) {
    cell = getCell(x, y);
    if (cell == -1) return 1; # Off edges already visited.
    return substr(getCell(x,y), 5, 1);
}

# Remove a cell's wall in a given direction.
function rmWall(x, y, d,    i, oldCell, newCell) {
    oldCell = getCell(x, y);
    if (oldCell == -1) return;
    newCell = "";
    for (i = 1; i <= 4; i++) { # Ugly as concat of two substrings and a constant?.
        newCell = newCell (i == d ? "0" : substr(oldCell, i, 1));
    }
    newCell = newCell wasVisited(x, y);
    setCell(x, y, newCell);
}

# Determine if a cell has a wall in a given direction.
function hasWall(x, y, d,    cell) {
    cell = getCell(x, y);
    if (cell == -1) return 1; # Cells off edge always have all walls.
    return substr(getCell(x, y), d, 1);
}

# Plunk a cell into the maze.
function setCell(x, y, cell,    idx) {
    if (!isGoodXY(x, y)) return;
    maze[x, y] = cell
}

# Get a cell from the maze.
function getCell(x, y,    idx) {
    if (!isGoodXY(x, y)) return -1; # Bad cell marker.
    return maze[x, y];
}

# Are the given coordinates in the maze?
function isGoodXY(x, y) {
    if (x < 1 || x > width) return 0;
    if (y < 1 || y > height) return 0;
    return 1;
}

# Build the empty maze.
function resetMaze(    x, y) {
    delete maze;
    for (y = 1; y <= height; y++) {
        for (x = 1; x <= width; x++) {
            maze[x, y] = "11110"; # walls (up, down, left, right) and visited state.
        }
    }
}

# Random things properly scaled.

function getRandX() {
    return 1 + int(rand() * width);
}

function getRandY() {
    return 1 +int(rand() * height);
}

function getRandDir() {
    return 1 + int(rand() * 4);
}

function randomize() {
    "echo $RANDOM" | getline t;
    srand(t);
}

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|                       |                   |                       |           |
+---+   +---+   +---+---+   +---+   +---+---+   +---+   +---+---+   +   +---+   +
|       |   |   |           |   |           |       |   |   |       |       |   |
+   +---+   +   +   +---+---+   +---+---+   +   +---+   +   +   +---+---+---+   +
|       |       |   |                   |       |       |       |               |
+   +   +   +---+   +---+   +   +---+   +---+---+   +---+---+   +---+   +---+   +
|   |   |   |   |       |   |   |       |       |   |       |           |       |
+---+   +   +   +---+   +---+   +   +---+---+   +   +   +   +---+---+---+   +---+
|       |       |       |       |               |       |   |       |       |   |
+   +   +---+---+   +---+   +---+---+---+---+   +---+---+   +---+   +   +---+   +
|   |   |       |   |           |           |   |       |       |   |   |       |
+   +---+   +   +   +---+---+   +---+   +   +   +   +   +---+   +   +   +   +   +
|   |       |       |       |       |   |   |   |   |       |   |   |       |   |
+   +   +---+---+---+   +   +---+   +   +   +   +---+---+   +   +   +---+---+   +
|   |   |               |           |   |   |               |   |               |
+   +   +---+---+---+   +---+---+---+   +   +---+---+---+   +   +---+---+   +---+
|       |               |   |           |           |       |   |       |       |
+   +---+   +---+---+---+   +   +---+---+---+---+   +   +---+   +   +   +---+   +
|   |       |           |   |   |       |       |   |   |   |       |   |       |
+   +   +   +   +---+   +   +   +   +   +   +   +   +   +   +---+---+   +   +---+
|       |   |       |   |           |   |   |   |   |   |           |   |       |
+   +---+---+---+   +   +---+---+---+   +   +   +   +   +   +---+   +   +---+   +
|   |               |           |   |       |   |           |   |   |       |   |
+---+   +---+---+---+---+---+   +   +---+   +---+---+---+---+   +   +---+   +   +
|   |   |       |           |   |       |   |           |       |       |   |   |
+   +   +   +---+   +---+   +   +---+   +   +   +---+   +---+   +---+   +   +   +
|   |   |           |       |       |       |   |           |           |   |   |
+   +   +   +---+---+   +---+---+   +   +---+   +---+---+   +---+---+   +   +---+
|   |   |   |   |       |           |       |       |   |           |   |       |
+   +   +   +   +   +---+   +---+---+---+---+---+   +   +---+---+   +   +---+   +
|       |   |   |           |                       |               |       |   |
+---+---+   +   +---+---+---+---+   +   +---+---+---+   +---+---+---+---+   +   +
|       |       |               |   |       |       |           |           |   |
+   +   +---+   +---+---+   +   +   +---+   +   +   +---+---+   +---+---+---+   +
|   |       |       |       |   |       |   |   |   |       |           |       |
+   +   +---+---+   +   +---+   +   +---+   +---+   +   +   +---+---+   +   +---+
|   |           |   |   |       |   |       |       |   |           |   |       |
+   +---+   +---+   +   +   +---+---+   +---+   +---+   +---+---+   +   +---+   +
|       |               |               |                       |               |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

generate and display a maze using the Depth-first search algorithm. It starts from a random cell, marks it as visited, and gets a list of its neighbors. For each unvisited neighbor, it removes the wall between the current cell and the neighbor, and then recursively repeats the process with the neighbor as the current cell.


# syntax: GAWK -f ORDER_TWO_NUMERICAL_LISTS.AWK
BEGIN {
    split("1,2,1,5,2",list1,",")
    split("1,2,1,5,2,2",list2,",")
    split("1,2,3,4,5",list3,",")
    split("1,2,3,4,5",list4,",")
    x = compare_array(list1,list2) ? "<" : ">=" ; printf("list1%slist2\n",x)
    x = compare_array(list2,list3) ? "<" : ">=" ; printf("list2%slist3\n",x)
    x = compare_array(list3,list4) ? "<" : ">=" ; printf("list3%slist4\n",x)
    exit(0)
}
function compare_array(arr1,arr2,  ans,i) {
    ans = 0
    for (i=1; i<=length(arr1); i++) {
      if (arr1[i] != arr2[i]) {
        ans = 1
        break
      }
    }
    if (length(arr1) != length(arr2)) {
      ans = 1
    }
    return(ans)
}

"Function to compare two numerical lists in lexicographic order and return true if the first list should be ordered before the second, false otherwise."


function ackermann(m, n)
{
  if ( m == 0 ) {
    return n+1
  }
  if ( n == 0 ) {
    return ackermann(m-1, 1)
  }
  return ackermann(m-1, ackermann(m, n-1))
}

BEGIN {
  for(n=0; n < 7; n++) {
    for(m=0; m < 4; m++) {
      print "A(" m "," n ") = " ackermann(m,n)
    }
  }
}

Implement the Ackermann function which is a recursive function that takes two non-negative arguments and returns a value based on the specified conditions. The function should ideally support arbitrary precision due to its rapid growth.


# syntax: GAWK -f GAMMA_FUNCTION.AWK
BEGIN {
    e = (1+1/100000)^100000
    pi = atan2(0,-1)

    print("X    Stirling")
    for (i=1; i<=20; i++) {
      d = i / 10
      printf("%4.2f %9.5f\n",d,gamma_stirling(d))
    }
    exit(0)
}
function gamma_stirling(x) {
    return sqrt(2*pi/x) * pow(x/e,x)
}
function pow(a,b) {
    return exp(b*log(a))
}

implement the Gamma function using either the Lanczos or Stirling's approximation. The codes also compare the results of the custom implementation with the built-in/library function if available. The Gamma function is computed through numerical integration.


#!/usr/bin/gawk -f
# Solve the Eight Queens Puzzle
#    Inspired by Raymond Hettinger [https://code.activestate.com/recipes/576647/]
#    Just the vector of row positions per column is kept,
#    and filled with all possibilities from left to right recursively,
#    then checked against the columns left from the current one:
#    - is a queen in the same row
#    - is a queen in the digonal
#    - is a queen in the reverse diagonal
BEGIN {
    dim = ARGC < 2 ? 8 : ARGV[1]
    # make vec an array
    vec[1] = 0
    # scan for a solution
    if (tryqueen(1, vec, dim))
        result(vec, dim)
    else
        print "No solution with " dim " queens."
}

# try if a queen can be set in column (col)
function tryqueen(col, vec, dim,        new)  {
    for (new = 1; new <= dim; ++new) {
        # check all previous columns
        if (noconflict(new, col, vec, dim)) {
            vec[col] = new
            if (col == dim)
                return 1
            # must try next column(s)
           if (tryqueen(col+1, vec, dim))
                return 1
        }
    }
    # all tested, failed
    return 0
}

#  check if setting the queen (new) in column (col) is ok
#  by checking the previous colums conflicts
function noconflict(new, col, vec, dim,    j) {
    for (j = 1; j < col; j++) {
        if (vec[j] == new)
            return 0    # same row
        if (vec[j] == new - col + j)
            return 0        # diagonal conflict
        if (vec[j] == new + col - j)
            return 0        # reverse diagonal conflict
    }
    # no test failed, no conflict
    return 1
}

# print matrix
function result(vec, dim,    row, col, sep, lne) {
    # print the solution vector
    for (row  = 1; row <= dim; ++row)
        printf " %d", vec[row]
    print

    # print a board matrix
    for (row = 1; row <= dim; ++row) {
        lne = "|"
        for (col = 1; col <= dim; ++col) {
            if (row == vec[col])
                lne = lne "Q|"
            else
                lne = lne "_|"
        }
        print lne
    }
}

"Code to incrementally build a vector and solve the N-queens problem, including the eight queens puzzle, inspired by Raymond Hettinger's Python solution. It also provides the number of solutions for small values of N as per OEIS: A000170."


#!/usr/bin/awk -f
BEGIN {
    split("cul-de-sac",a,"-")
    split("1-2-3",b,"-")
    concat_array(a,b,c)

    for (i in c) {
        print i,c[i]
    }
}

function concat_array(a,b,c, nc) {
    for (i in a) {
        c[++nc]=a[i]
    }
    for (i in b) {
       c[++nc]=b[i]
    }
}

demonstrate how to concatenate two arrays.


# syntax: GAWK -f KNAPSACK_PROBLEM_0-1.AWK
BEGIN {
#   arr["item,weight"] = value
    arr["map,9"] = 150
    arr["compass,13"] = 35
    arr["water,153"] = 200
    arr["sandwich,50"] = 160
    arr["glucose,15"] = 60
    arr["tin,68"] = 45
    arr["banana,27"] = 60
    arr["apple,39"] = 40
    arr["cheese,23"] = 30
    arr["beer,52"] = 10
    arr["suntan cream,11"] = 70
    arr["camera,32"] = 30
    arr["T-shirt,24"] = 15
    arr["trousers,48"] = 10
    arr["umbrella,73"] = 40
    arr["waterproof trousers,42"] = 70
    arr["waterproof overclothes,43"] = 75
    arr["note-case,22"] = 80
    arr["sunglasses,7"] = 20
    arr["towel,18"] = 12
    arr["socks,4"] = 50
    arr["book,30"] = 10
    sack_size = 400 # dag
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (i in arr) {
      if (total_weight >= sack_size) {
        break
      }
      split(i,tmp,",")
      weight = tmp[2]
      if (total_weight + weight <= sack_size) {
        printf("%s\n",tmp[1])
        total_items++
        total_value += arr[i]
        total_weight += weight
      }
    }
    printf("items=%d (out of %d) weight=%d value=%d\n",total_items,length(arr),total_weight,total_value)
    exit(0)
}

The code determines the optimal combination of items a tourist can carry in his knapsack, given a maximum weight limit of 4kg (400 dag), such that the total value of the items is maximized. The items cannot be divided or diminished.


#!/usr/bin/awk -f
BEGIN {
	print (a(1) && b(1))
	print (a(1) || b(1))
	print (a(0) && b(1))
	print (a(0) || b(1))
}

function a(x) {
	print "  x:"x
	return x
}
function b(y) {
	print "  y:"y
	return y
}

The code defines two functions, a and b, which both take and return a boolean value while printing their name when called. The code then calculates and assigns the values of two equations, x = a(i) and b(j) and y = a(i) or b(j), to variables. The calculations are done in a way that function b is only called when necessary, utilizing the concept of short-circuit evaluation in logical AND and OR operations. If the language doesn't support short-circuit evaluation, nested if statements are used to achieve the same effect.


translates a given string into Morse code and sends it as audible signals to an audio device such as a PC speaker. It ignores unknown characters or indicates them with a different pitch. Note that AWK is used for text translation into Morse code but it cannot play sounds.