We'll be using signed integer values using two's complement representation.
Depending on desired granularity, we may use:
bits | range |
---|---|
2 | [ -1, +1 ] |
4 | [ -7, +7 ] |
8 | [ -127, +127 ] |
//two's complement
const decv = (v) => (v > 7) ? ~((v-2) & 0b111) : v
const encv = (v) => (v < 0) ? -~-v | 0b1000 : v
//test encoding/decoding
let dall = [0x8, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7].map(decv)
let eall = [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7].map(encv);
console.log({dall, eall});
//encode pair
const dexy = (ff) => [decv(f & 0b1111), decv(f & 0b1111 >> 4)]
const enxy = ([x,y]) => encv(x) << 4 + encv(y)
//decode string
const decodeXY = ([shape,xy])=> [shape,dexy(xy)]
const decode = (nfss)=> decodeXY(nffs.split('n'))
let shapes = [ "3n0404", "0n0000" ].map(decode);
/*
[
[3,[4,4]],
[0,[0,0]]
]
*/
f6://0n003nd4
/* example above
{"circle":[0,0], "triangle":[-4,4]} => [ '0n00', '3nd4' ] => f6://0n003nd4/ => https://physix.tech?ff=0n003nd4
*/
f6://0n003nd4@3puf2l2:0815 => https://physix.tech?sl=3puf2l2&wt=0815&ff=0n003nd4
let all = [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7].map(v=>[v,encv(v)]).map(([l,v])=>[l,'0b'+v.toString(2).padStart(4,'0'), '0x'+v.toString(16), v])
/* all possible values in 4 bit encoding
[
[-7, "0b1000", "0x8", 8],
[-6, "0b1111", "0xf", 15],
[-5, "0b1110", "0xe", 14],
[-4, "0b1101", "0xd", 13],
[-3, "0b1100", "0xc", 12],
[-2, "0b1011", "0xb", 11],
[-1, "0b1010", "0xa", 10],
[0, "0b0000", "0x0", 0],
[+1, "0b0001", "0x1", 1],
[+2, "0b0010", "0x2", 2],
[+3, "0b0011", "0x3", 3],
[+4, "0b0100", "0x4", 4],
[+5, "0b0101", "0x5", 5],
[+6, "0b0110", "0x6", 6],
[+7, "0b0111", "0x7", 7]
]
*/