pohlcode.awk - annna - Annna the nice friendly bot. | |
git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws6… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
pohlcode.awk (6389B) | |
--- | |
1 #!/usr/bin/awk -f | |
2 # pohlcode.awk version 3 by Ben Collver | |
3 # | |
4 # Implement spoken representation of binary numbers described in | |
5 # On Binary Digits And Human Habits by Frederik Pohl, 1962. | |
6 # | |
7 # Dual license: WTFPL and Public Domain | |
8 # | |
9 # Pohl encode string from decimal number: | |
10 # awk -f pohlcode.awk 31337 | |
11 # | |
12 # Decode decimal number from Pohl encoded string: | |
13 # awk -f pohlcode.awk tee two group totter-poot totter-poot | |
14 | |
15 # initialize tables used to convert between bases and encodings | |
16 | |
17 function init( hl, hu, i) { | |
18 split("pohl poot pahtah pod too tot dye tee", second, " ") | |
19 split("ohly ooty ahtah oddy too totter dye teeter", first, " ") | |
20 split("000 001 010 011 100 101 110 111", trip, " ") | |
21 split("zero one two three four five six seven eight nine", eng, " ") | |
22 split("0 1 2 3 4 5 6 7 8 9 A B C D E F", hex, " ") | |
23 split("0000 0001 0010 0011 0100 0101 0110 0111 " \ | |
24 "1000 1001 1010 1011 1100 1101 1110 1111", bin, " ") | |
25 | |
26 # bin/dec/hex conversion tables | |
27 for (i in hex) { | |
28 hu = hex[i] | |
29 hl = tolower(hu) | |
30 h2b[hl] = h2b[hu] = bin[i] | |
31 h2d[hl] = h2d[hu] = i - 1 | |
32 b2h[bin[i]] = hu | |
33 } | |
34 | |
35 # english digit conversion tables | |
36 for (i in eng) { | |
37 d2e[i - 1] = eng[i] | |
38 e2d[eng[i]] = i - 1 | |
39 } | |
40 | |
41 # Pohl code binary triplet conversion tables | |
42 for (i in trip) { | |
43 f2p[trip[i]] = first[i] | |
44 s2p[trip[i]] = second[i] | |
45 p2f[first[i]] = trip[i] | |
46 p2s[second[i]] = trip[i] | |
47 } | |
48 | |
49 return | |
50 } | |
51 | |
52 function bin2dec(str, dec, hex) { | |
53 hex = bin2hex(str) | |
54 dec = hex2dec(hex) | |
55 return dec | |
56 } | |
57 | |
58 function bin2hex(str, chunk, n, i, hex, pad, rem) { | |
59 str = zpad4(str) | |
60 n = length(str) | |
61 for (i = 1; i <= n; i += 4) { | |
62 chunk = zpad4(substr(str, i, 4)) | |
63 hex = hex b2h[chunk] | |
64 } | |
65 return hex | |
66 } | |
67 | |
68 function bin2pohl(bin, bbuf, groups, p, parts, retval, val) { | |
69 groups = int(length(bin) / 6) | |
70 if (groups > 9) { | |
71 print "Error: groups out of bounds: " groups | |
72 exit 1 | |
73 } | |
74 p = 0 | |
75 bbuf = zpad6(bin) | |
76 if (length(bbuf) > length(bin)) { | |
77 val = substr(bbuf, 1, 6) | |
78 sub(/^000/, "", val) | |
79 bbuf = substr(bbuf, 7) | |
80 p++ | |
81 parts[p] = pohlencode(val) | |
82 } | |
83 if (groups > 0) { | |
84 p++ | |
85 parts[p] = d2e[groups] " group" | |
86 } | |
87 for (i = 1; i <= groups; i++) { | |
88 val = substr(bbuf, 1, 6) | |
89 bbuf = substr(bbuf, 7) | |
90 p++ | |
91 parts[p] = pohlencode(val) | |
92 } | |
93 retval = "" | |
94 for (i = 1; i <= p; i++) { | |
95 if (length(retval) == 0) { | |
96 retval = parts[i] | |
97 } else { | |
98 retval = retval " " parts[i] | |
99 | |
100 } | |
101 } | |
102 return retval | |
103 } | |
104 | |
105 function dec2bin(dec, hex, bin) { | |
106 hex = sprintf("%x\n", dec) | |
107 bin = hex2bin(hex) | |
108 return bin | |
109 } | |
110 | |
111 function hex2bin(hex, n, i, bin) { | |
112 n = length(hex) | |
113 for (i = 1; i <= n; i++) { | |
114 bin = bin h2b[substr(hex, i, 1)] | |
115 } | |
116 sub(/^0+/, "", bin) | |
117 if (length(bin) == 0) { | |
118 bin = "0" | |
119 } | |
120 return bin | |
121 } | |
122 | |
123 function hex2dec(val, out, i, n) { | |
124 if (val ~ /^0x/) { | |
125 val = substr(val, 3) | |
126 } | |
127 n = length(val) | |
128 for (i = 1; i <= n; i++) { | |
129 out = (out * 16) + h2d[substr(val, i, 1)] | |
130 } | |
131 #return sprintf("%.0f", out) | |
132 return out | |
133 } | |
134 | |
135 function pohl2bin(str, bbuf, eng, groups, i, prefix, result, wnum, \ | |
136 words) | |
137 { | |
138 bbuf = "" | |
139 groups = 1 | |
140 result = match(str, /.* group /) | |
141 if (result > 0) { | |
142 prefix = substr(str, 1, RLENGTH) | |
143 str = substr(str, RLENGTH + 1) | |
144 wnum = split(prefix, words, " ") | |
145 if (wnum == 2) { | |
146 eng = words[1] | |
147 } else if (wnum == 3) { | |
148 eng = words[2] | |
149 bbuf = pohldecode(words[1]) | |
150 sub(/^0*/, "", bbuf) | |
151 } else { | |
152 print "Bad Pohl code prefix: " prefix | |
153 exit 1 | |
154 } | |
155 if (eng in e2d) { | |
156 groups = e2d[eng] | |
157 } else { | |
158 print "Invalid number of groups: " eng | |
159 exit 1 | |
160 } | |
161 } | |
162 wnum = split(str, words, " ") | |
163 if (wnum != groups) { | |
164 print "Expected " groups " group(s) but got: " wnum | |
165 exit 1 | |
166 } | |
167 for (i = 1; i <= wnum ; i++) { | |
168 bbuf = bbuf pohldecode(words[i]) | |
169 } | |
170 return bbuf | |
171 } | |
172 | |
173 # decode pohl-encoded 6-bit word | |
174 | |
175 function pohldecode(word, parts, pnum, retval) { | |
176 pnum = split(word, parts, "-") | |
177 if (pnum == 2 && parts[1] in p2f && parts[2] in p2s) { | |
178 retval = p2f[parts[1]] p2s[parts[2]] | |
179 } else if (pnum == 1 && parts[1] in p2s) { | |
180 retval = "000" p2s[parts[1]] | |
181 } else { | |
182 print "Invalid pohl code word: " word | |
183 exit 1 | |
184 } | |
185 return retval | |
186 } | |
187 | |
188 # pohl encode 6-bit word | |
189 | |
190 function pohlencode(digits, retval, triplet1, triplet2) { | |
191 if (length(digits) == 3) { | |
192 retval = s2p[digits] | |
193 } else { | |
194 triplet1 = substr(digits, 1, 3) | |
195 triplet2 = substr(digits, 4, 6) | |
196 retval = f2p[triplet1] "-" s2p[triplet2] | |
197 } | |
198 return retval | |
199 } | |
200 | |
201 # zero pad number until length is a multiple of 4 digits | |
202 | |
203 function zpad4(str, pad, rem) { | |
204 rem = length(str) % 4 | |
205 if (rem > 0) { | |
206 pad = substr("0000", 1, 4 - rem) | |
207 str = pad str | |
208 } | |
209 return str | |
210 } | |
211 | |
212 # zero pad number until length is a multiple of 6 digits | |
213 | |
214 function zpad6(str, pad, rem) { | |
215 rem = length(str) % 6 | |
216 if (rem > 0) { | |
217 pad = substr("000000", 1, 6 - rem) | |
218 str = pad str | |
219 } | |
220 return str | |
221 } | |
222 | |
223 function main( i, result, val) { | |
224 for (i = 1; i < ARGC; i++) { | |
225 if (length(val) == 0) { | |
226 val = ARGV[i] | |
227 } else { | |
228 val = val " " ARGV[i] | |
229 } | |
230 } | |
231 if (length(val) == 0) { | |
232 print "Usage: pohlcode.awk [code|number|test]" | |
233 print "" | |
234 print "[code]: Converts Pohl code to decimal." | |
235 print "[number]: Converts decimal to Pohl code." | |
236 print "test: Print test output." | |
237 exit 1 | |
238 } | |
239 sub(/\n$/, "", val) | |
240 init() | |
241 if (val == "test") { | |
242 test() | |
243 } else if (val ~ /^[0-9][0-9]*$/) { | |
244 result = bin2pohl(dec2bin(val)) | |
245 } else { | |
246 result = bin2dec(pohl2bin(val)) | |
247 } | |
248 print result | |
249 return | |
250 } | |
251 | |
252 function test( code, i, j) { | |
253 return | |
254 for (i = 0; i < 1024; i++) { | |
255 code = bin2pohl(dec2bin(i)) | |
256 j = bin2dec(pohl2bin(code)) | |
257 printf "%d\t%s\t%d\n", i, code, j | |
258 } | |
259 return | |
260 } | |
261 | |
262 BEGIN { | |
263 main() | |
264 exit 0 | |
265 } |