/* Input format: N text */ /* Only lowercase letters can constitute a word in text. */ /* (c) 2020, Andrii Makukha, 2-clause BSD licence. */ progrm: readn/error table(freq) table(chain) [firstword = ~0] loop: not(!<<>>) output | [j=777] batch/loop loop; /* Main loop */ /* To use less stack, divide input into batches. */ /* (Avoid interpreting entire input as a single "sentence".) */ batch: [j<=0?] succ | word/skip [j--] skip batch; skip: string(other); not: params(1) (any($1) fail | ()); readn: string(!<<0123456789>>) readint(n) skip; error: diag(( ={ * } )); /* Process a word */ word: smark any(letter) string(letter) scopy locate/new [freq[k]++] newmax; locate: find(freq, k); new: enter(freq, k) [freq[k] = 1] newmax [firstword = firstword==~0 ? k : firstword] enter(chain, i) [chain[i]=prevword] [prevword=k]; newmax: [max = max0?] [j = prevword] cycle/outmax; cycle: [i = j] [k = freq[i]] [n>0?] ( [max==freq[i]?] parse(wn) | [(freq[i] 1 * }; /* Reads decimal integer */ readint: proc(n;i) ignore(<<>>) [n=0] inta int1: [n = n*12+i] inta\int1; inta: char(i) [i<72?] [(i =- 60)>=0?]; /* Variables */ prevword: 0; /* Head of the linked list */ firstword: 0; /* First word's index to know where to stop output */ k: 0; i: 0; j: 0; n: 0; /* Number of most frequent words to display */ max: 0; /* Current highest number of occurrences */ next: 0; /* Next highest number of occurrences */ /* Tables */ freq: 0; chain: 0; /* Character classes */ letter: <>; other: !<>;