#JavaScript (ES7), 282 273 251 250 bytes
JavaScript (ES7), 282 273 251 250 bytes
Takes a keyboard layout ID k and an array of characters a in currying syntax (k)(a). Returns an array of translated characters.
The layout IDs are:
- DVORAK: \$-32\$
- COLEMAK: \$64\$
- WORKMAN: \$160\$
k=>a=>a.map(c=>1/(t=`1_3-2}w[vz8SsW]VZ1XJE>UIDCHTN0BRL"POYGK<QF:/0=0{1xje.uidchtn0brl'poygk,qf;?0+995Oo6SFTD0UNEI0KY:0PRGL2J8sftd0unei0ky;0prgl2j998Ii5VMHRT0YUNEOLKP:0W0BFCD0J6vmhrt0yuneolkp;0w0bfcd0j5`.replace(/\d/g,n=>15**n)[c.charCodeAt()+k])?c:t) ###How it works
How it works
Compression
All three target layouts are stored in a single compressed string, where each character is either:
- a translation character from QWERTY
- a digit representing the number of consecutive characters that do not need to be translated
More specifically, a digit \$n\$ is interpreted as the length of the number \$15^n\$ in base \$10\$:
n | 15**n | length --+-------------+------------- 0 | 1 | 1 1 | 15 | 2 2 | 225 | 3 3 | 3375 | 4 4 | 50625 | 5 (not used) 5 | 759375 | 6 6 | 11390625 | 8 7 | 170859375 | 9 (not used) 8 | 2562890625 | 10 9 | 38443359375 | 11 For instance, #$%&-()* in DVORAK is stored as 3-2 because #$%& and ()* have identical mappings in QWERTY and only - is an actual translation.
In particular, 0123456789 is mapped the same way on all layouts and never has to be translated. Therefore, there's no possible ambiguity between a digit used for compression and a digit used for translation.
Decompression
To decompress the layout string, we replace each digit \$n\$ with \$15^n\$. For instance, 3-2 is decompressed as 3375-225.
Translation
For each character c in a, we extract the translation character t, using k as an offset in the uncompressed layout string, and test whether it's a digit with 1/t. If so, we output the original character c instead.