Add pholcode support to annna. - annna - Annna the nice friendly bot. HTML git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/annna/ DIR Log DIR Files DIR Refs DIR Tags DIR README --- DIR commit 7c69a018ae0f2c8a92922058333f86fe59d0af20 DIR parent 0da5bb56bf17635438234d4f055e53d0a831b81e HTML Author: Annna Robert-Houdin <annna@bitreich.org> Date: Sun, 6 Apr 2025 15:59:47 +0200 Add pholcode support to annna. Thanks Ben Collver! Diffstat: M annna-message-common | 5 +++++ A pohlcode.awk | 265 +++++++++++++++++++++++++++++++ 2 files changed, 270 insertions(+), 0 deletions(-) --- DIR diff --git a/annna-message-common b/annna-message-common @@ -720,6 +720,11 @@ case "${text}" in suri="$(printf "%s\n" "${word}" | ghost -e)" annna-say -s "${server}" -c "${channel}" "${suri}" ;; +"${ircuser}, please pohlish "*) + word="$(printf "%s\n" "${text}" | cut -c 23- | sed 's,\t, ,g')" + suri="$(pohlcode.awk "${word}")" + annna-say -s "${server}" -c "${channel}" "${suri}" + ;; "${ircuser}, what can I cook with "*) ingredients="$(printf "%s\n" "${text}" | cut -c 29- | sed 's,\t, ,g')" case "$ingredients" in DIR diff --git a/pohlcode.awk b/pohlcode.awk @@ -0,0 +1,265 @@ +#!/usr/bin/awk -f +# pohlcode.awk version 3 by Ben Collver +# +# Implement spoken representation of binary numbers described in +# On Binary Digits And Human Habits by Frederik Pohl, 1962. +# +# Dual license: WTFPL and Public Domain +# +# Pohl encode string from decimal number: +# awk -f pohlcode.awk 31337 +# +# Decode decimal number from Pohl encoded string: +# awk -f pohlcode.awk tee two group totter-poot totter-poot + +# initialize tables used to convert between bases and encodings + +function init( hl, hu, i) { + split("pohl poot pahtah pod too tot dye tee", second, " ") + split("ohly ooty ahtah oddy too totter dye teeter", first, " ") + split("000 001 010 011 100 101 110 111", trip, " ") + split("zero one two three four five six seven eight nine", eng, " ") + split("0 1 2 3 4 5 6 7 8 9 A B C D E F", hex, " ") + split("0000 0001 0010 0011 0100 0101 0110 0111 " \ + "1000 1001 1010 1011 1100 1101 1110 1111", bin, " ") + + # bin/dec/hex conversion tables + for (i in hex) { + hu = hex[i] + hl = tolower(hu) + h2b[hl] = h2b[hu] = bin[i] + h2d[hl] = h2d[hu] = i - 1 + b2h[bin[i]] = hu + } + + # english digit conversion tables + for (i in eng) { + d2e[i - 1] = eng[i] + e2d[eng[i]] = i - 1 + } + + # Pohl code binary triplet conversion tables + for (i in trip) { + f2p[trip[i]] = first[i] + s2p[trip[i]] = second[i] + p2f[first[i]] = trip[i] + p2s[second[i]] = trip[i] + } + + return +} + +function bin2dec(str, dec, hex) { + hex = bin2hex(str) + dec = hex2dec(hex) + return dec +} + +function bin2hex(str, chunk, n, i, hex, pad, rem) { + str = zpad4(str) + n = length(str) + for (i = 1; i <= n; i += 4) { + chunk = zpad4(substr(str, i, 4)) + hex = hex b2h[chunk] + } + return hex +} + +function bin2pohl(bin, bbuf, groups, p, parts, retval, val) { + groups = int(length(bin) / 6) + if (groups > 9) { + print "Error: groups out of bounds: " groups + exit 1 + } + p = 0 + bbuf = zpad6(bin) + if (length(bbuf) > length(bin)) { + val = substr(bbuf, 1, 6) + sub(/^000/, "", val) + bbuf = substr(bbuf, 7) + p++ + parts[p] = pohlencode(val) + } + if (groups > 0) { + p++ + parts[p] = d2e[groups] " group" + } + for (i = 1; i <= groups; i++) { + val = substr(bbuf, 1, 6) + bbuf = substr(bbuf, 7) + p++ + parts[p] = pohlencode(val) + } + retval = "" + for (i = 1; i <= p; i++) { + if (length(retval) == 0) { + retval = parts[i] + } else { + retval = retval " " parts[i] + + } + } + return retval +} + +function dec2bin(dec, hex, bin) { + hex = sprintf("%x\n", dec) + bin = hex2bin(hex) + return bin +} + +function hex2bin(hex, n, i, bin) { + n = length(hex) + for (i = 1; i <= n; i++) { + bin = bin h2b[substr(hex, i, 1)] + } + sub(/^0+/, "", bin) + if (length(bin) == 0) { + bin = "0" + } + return bin +} + +function hex2dec(val, out, i, n) { + if (val ~ /^0x/) { + val = substr(val, 3) + } + n = length(val) + for (i = 1; i <= n; i++) { + out = (out * 16) + h2d[substr(val, i, 1)] + } + #return sprintf("%.0f", out) + return out +} + +function pohl2bin(str, bbuf, eng, groups, i, prefix, result, wnum, \ + words) +{ + bbuf = "" + groups = 1 + result = match(str, /.* group /) + if (result > 0) { + prefix = substr(str, 1, RLENGTH) + str = substr(str, RLENGTH + 1) + wnum = split(prefix, words, " ") + if (wnum == 2) { + eng = words[1] + } else if (wnum == 3) { + eng = words[2] + bbuf = pohldecode(words[1]) + sub(/^0*/, "", bbuf) + } else { + print "Bad Pohl code prefix: " prefix + exit 1 + } + if (eng in e2d) { + groups = e2d[eng] + } else { + print "Invalid number of groups: " eng + exit 1 + } + } + wnum = split(str, words, " ") + if (wnum != groups) { + print "Expected " groups " group(s) but got: " wnum + exit 1 + } + for (i = 1; i <= wnum ; i++) { + bbuf = bbuf pohldecode(words[i]) + } + return bbuf +} + +# decode pohl-encoded 6-bit word + +function pohldecode(word, parts, pnum, retval) { + pnum = split(word, parts, "-") + if (pnum == 2 && parts[1] in p2f && parts[2] in p2s) { + retval = p2f[parts[1]] p2s[parts[2]] + } else if (pnum == 1 && parts[1] in p2s) { + retval = "000" p2s[parts[1]] + } else { + print "Invalid pohl code word: " word + exit 1 + } + return retval +} + +# pohl encode 6-bit word + +function pohlencode(digits, retval, triplet1, triplet2) { + if (length(digits) == 3) { + retval = s2p[digits] + } else { + triplet1 = substr(digits, 1, 3) + triplet2 = substr(digits, 4, 6) + retval = f2p[triplet1] "-" s2p[triplet2] + } + return retval +} + +# zero pad number until length is a multiple of 4 digits + +function zpad4(str, pad, rem) { + rem = length(str) % 4 + if (rem > 0) { + pad = substr("0000", 1, 4 - rem) + str = pad str + } + return str +} + +# zero pad number until length is a multiple of 6 digits + +function zpad6(str, pad, rem) { + rem = length(str) % 6 + if (rem > 0) { + pad = substr("000000", 1, 6 - rem) + str = pad str + } + return str +} + +function main( i, result, val) { + for (i = 1; i < ARGC; i++) { + if (length(val) == 0) { + val = ARGV[i] + } else { + val = val " " ARGV[i] + } + } + if (length(val) == 0) { + print "Usage: pohlcode.awk [code|number|test]" + print "" + print "[code]: Converts Pohl code to decimal." + print "[number]: Converts decimal to Pohl code." + print "test: Print test output." + exit 1 + } + sub(/\n$/, "", val) + init() + if (val == "test") { + test() + } else if (val ~ /^[0-9][0-9]*$/) { + result = bin2pohl(dec2bin(val)) + } else { + result = bin2dec(pohl2bin(val)) + } + print result + return +} + +function test( code, i, j) { + return + for (i = 0; i < 1024; i++) { + code = bin2pohl(dec2bin(i)) + j = bin2dec(pohl2bin(code)) + printf "%d\t%s\t%d\n", i, code, j + } + return +} + +BEGIN { + main() + exit 0 +}