mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-03-21 01:32:30 +01:00
format
This commit is contained in:
@ -1261,13 +1261,13 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
|||||||
"Value 8 is expressed in binary as '1000', which will be encoded",
|
"Value 8 is expressed in binary as '1000', which will be encoded",
|
||||||
"with the pattern 'pppdpddd', where p is a parity bit and d a data bit,\n",
|
"with the pattern 'pppdpddd', where p is a parity bit and d a data bit,\n",
|
||||||
"or '10101' (Value 21) will result into (pppdpdddpd) '1001101011'.\n",
|
"or '10101' (Value 21) will result into (pppdpdddpd) '1001101011'.\n",
|
||||||
"The answer should be given as a string containing only 1s and 0s.\n",
|
"The answer should be given as a string containing only 1s and 0s.\n",
|
||||||
"NOTE: the endianness of the data bits is reversed in relation to the endianness of the parity bits.\n",
|
"NOTE: the endianness of the data bits is reversed in relation to the endianness of the parity bits.\n",
|
||||||
"NOTE: The bit at index zero is the overall parity bit, this should be set last.\n",
|
"NOTE: The bit at index zero is the overall parity bit, this should be set last.\n",
|
||||||
"NOTE 2: You should watch the Hamming Code video from 3Blue1Brown, which explains the 'rule' of encoding,",
|
"NOTE 2: You should watch the Hamming Code video from 3Blue1Brown, which explains the 'rule' of encoding,",
|
||||||
"including the first index parity bit mentioned in the previous note.\n\n",
|
"including the first index parity bit mentioned in the previous note.\n\n",
|
||||||
"Extra rule for encoding:\n",
|
"Extra rule for encoding:\n",
|
||||||
"There should be no leading zeros in the 'data bit' section",
|
"There should be no leading zeros in the 'data bit' section",
|
||||||
].join(" ");
|
].join(" ");
|
||||||
},
|
},
|
||||||
gen: (): number => {
|
gen: (): number => {
|
||||||
@ -1290,7 +1290,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
|||||||
"Note: The length of the binary string is dynamic, but it's encoding/decoding follows Hamming's 'rule'\n",
|
"Note: The length of the binary string is dynamic, but it's encoding/decoding follows Hamming's 'rule'\n",
|
||||||
"Note 2: Index 0 is an 'overall' parity bit. Watch the Hamming code video from 3Blue1Brown for more information\n",
|
"Note 2: Index 0 is an 'overall' parity bit. Watch the Hamming code video from 3Blue1Brown for more information\n",
|
||||||
"Note 3: There's a ~55% chance for an altered Bit. So... MAYBE there is an altered Bit 😉\n",
|
"Note 3: There's a ~55% chance for an altered Bit. So... MAYBE there is an altered Bit 😉\n",
|
||||||
"Note: The endianness of the \
|
"Note: The endianness of the \
|
||||||
encoded decimal value is reversed in relation to the endianness of the Hamming code. Where \
|
encoded decimal value is reversed in relation to the endianness of the Hamming code. Where \
|
||||||
the Hamming code is expressed as little-endian (LSB at index 0), the decimal value encoded in it is expressed as big-endian \
|
the Hamming code is expressed as little-endian (LSB at index 0), the decimal value encoded in it is expressed as big-endian \
|
||||||
(MSB at index 0)\n",
|
(MSB at index 0)\n",
|
||||||
|
@ -1,156 +1,155 @@
|
|||||||
export function HammingEncode(data: number): string {
|
export function HammingEncode(data: number): string {
|
||||||
|
const enc: Array<number> = [0];
|
||||||
|
const data_bits: Array<any> = data.toString(2).split("").reverse();
|
||||||
|
|
||||||
const enc: Array<number> = [0];
|
data_bits.forEach((e, i, a) => {
|
||||||
const data_bits: Array<any> = data.toString(2).split("").reverse();
|
a[i] = parseInt(e);
|
||||||
|
});
|
||||||
|
|
||||||
data_bits.forEach((e, i, a) => {
|
let k = data_bits.length;
|
||||||
a[i] = parseInt(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
let k = data_bits.length;
|
/* NOTE: writing the data like this flips the endianness, this is what the
|
||||||
|
* original implementation by Hedrauta did so I'm keeping it like it was. */
|
||||||
|
for (let i = 1; k > 0; i++) {
|
||||||
|
if ((i & (i - 1)) != 0) {
|
||||||
|
enc[i] = data_bits[--k];
|
||||||
|
} else {
|
||||||
|
enc[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* NOTE: writing the data like this flips the endianness, this is what the
|
let parity: any = 0;
|
||||||
* original implementation by Hedrauta did so I'm keeping it like it was. */
|
|
||||||
for(let i = 1; k > 0; i++) {
|
|
||||||
if((i & (i - 1)) != 0) {
|
|
||||||
enc[i] = data_bits[--k];
|
|
||||||
} else {
|
|
||||||
enc[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let parity: any = 0;
|
/* Figure out the subsection parities */
|
||||||
|
for (let i = 0; i < enc.length; i++) {
|
||||||
|
if (enc[i]) {
|
||||||
|
parity ^= i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Figure out the subsection parities */
|
parity = parity.toString(2).split("").reverse();
|
||||||
for(let i = 0; i < enc.length; i++) {
|
parity.forEach((e: any, i: any, a: any) => {
|
||||||
if(enc[i]) {
|
a[i] = parseInt(e);
|
||||||
parity ^= i;
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parity = parity.toString(2).split("").reverse();
|
/* Set the parity bits accordingly */
|
||||||
parity.forEach((e: any, i: any , a: any) => {
|
for (let i = 0; i < parity.length; i++) {
|
||||||
a[i] = parseInt(e);
|
enc[2 ** i] = parity[i] ? 1 : 0;
|
||||||
});
|
}
|
||||||
|
|
||||||
/* Set the parity bits accordingly */
|
parity = 0;
|
||||||
for(let i = 0; i < parity.length; i++) {
|
/* Figure out the overall parity for the entire block */
|
||||||
enc[2 ** i] = parity[i] ? 1 : 0;
|
for (let i = 0; i < enc.length; i++) {
|
||||||
}
|
if (enc[i]) {
|
||||||
|
parity++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parity = 0;
|
/* Finally set the overall parity bit */
|
||||||
/* Figure out the overall parity for the entire block */
|
enc[0] = parity % 2 == 0 ? 0 : 1;
|
||||||
for(let i = 0; i < enc.length; i++) {
|
|
||||||
if(enc[i]) {
|
|
||||||
parity++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally set the overall parity bit */
|
return enc.join("");
|
||||||
enc[0] = parity % 2 == 0 ? 0 : 1;
|
|
||||||
|
|
||||||
return enc.join("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HammingEncodeProperly(data: number): string {
|
export function HammingEncodeProperly(data: number): string {
|
||||||
/* How many bits do we need?
|
/* How many bits do we need?
|
||||||
* n = 2^m
|
* n = 2^m
|
||||||
* k = 2^m - m - 1
|
* k = 2^m - m - 1
|
||||||
* where k is the number of data bits, m the number
|
* where k is the number of data bits, m the number
|
||||||
* of parity bits and n the number of total bits. */
|
* of parity bits and n the number of total bits. */
|
||||||
|
|
||||||
let m = 1;
|
let m = 1;
|
||||||
|
|
||||||
while((2 ** ((2 ** m) - m - 1)) < data) {
|
while (2 ** (2 ** m - m - 1) < data) {
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const n: number = (2 ** m);
|
const n: number = 2 ** m;
|
||||||
const k: number = (2 ** m) - m - 1;
|
const k: number = 2 ** m - m - 1;
|
||||||
|
|
||||||
const enc: Array<number> = [0];
|
const enc: Array<number> = [0];
|
||||||
const data_bits: Array<any> = data.toString(2).split("").reverse();
|
const data_bits: Array<any> = data.toString(2).split("").reverse();
|
||||||
|
|
||||||
data_bits.forEach((e, i, a) => {
|
data_bits.forEach((e, i, a) => {
|
||||||
a[i] = parseInt(e);
|
a[i] = parseInt(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Flip endianness as in the original implementation by Hedrauta
|
/* Flip endianness as in the original implementation by Hedrauta
|
||||||
* and write the data back to front
|
* and write the data back to front
|
||||||
* XXX why do we do this? */
|
* XXX why do we do this? */
|
||||||
for(let i = 1, j = k; i < n; i++) {
|
for (let i = 1, j = k; i < n; i++) {
|
||||||
if((i & (i - 1)) != 0) {
|
if ((i & (i - 1)) != 0) {
|
||||||
enc[i] = data_bits[--j] ? data_bits[j] : 0;
|
enc[i] = data_bits[--j] ? data_bits[j] : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let parity: any = 0;
|
let parity: any = 0;
|
||||||
|
|
||||||
/* Figure out the subsection parities */
|
/* Figure out the subsection parities */
|
||||||
for(let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
if(enc[i]) {
|
if (enc[i]) {
|
||||||
parity ^= i;
|
parity ^= i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parity = parity.toString(2).split("").reverse();
|
parity = parity.toString(2).split("").reverse();
|
||||||
parity.forEach((e: any, i: any , a: any) => {
|
parity.forEach((e: any, i: any, a: any) => {
|
||||||
a[i] = parseInt(e);
|
a[i] = parseInt(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Set the parity bits accordingly */
|
/* Set the parity bits accordingly */
|
||||||
for(let i = 0; i < m; i++) {
|
for (let i = 0; i < m; i++) {
|
||||||
enc[2 ** i] = parity[i] ? 1 : 0;
|
enc[2 ** i] = parity[i] ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
parity = 0;
|
parity = 0;
|
||||||
/* Figure out the overall parity for the entire block */
|
/* Figure out the overall parity for the entire block */
|
||||||
for(let i = 0; i < n; i++) {
|
for (let i = 0; i < n; i++) {
|
||||||
if(enc[i]) {
|
if (enc[i]) {
|
||||||
parity++;
|
parity++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally set the overall parity bit */
|
/* Finally set the overall parity bit */
|
||||||
enc[0] = parity % 2 == 0 ? 0 : 1;
|
enc[0] = parity % 2 == 0 ? 0 : 1;
|
||||||
|
|
||||||
return enc.join("");
|
return enc.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HammingDecode(data: string): number {
|
export function HammingDecode(data: string): number {
|
||||||
let err = 0;
|
let err = 0;
|
||||||
const bits: Array<number> = [];
|
const bits: Array<number> = [];
|
||||||
|
|
||||||
/* TODO why not just work with an array of digits from the start? */
|
/* TODO why not just work with an array of digits from the start? */
|
||||||
for(const i in data.split("")) {
|
for (const i in data.split("")) {
|
||||||
const bit = parseInt(data[i]);
|
const bit = parseInt(data[i]);
|
||||||
bits[i] = bit;
|
bits[i] = bit;
|
||||||
|
|
||||||
if(bit) {
|
if (bit) {
|
||||||
err ^= +i;
|
err ^= +i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If err != 0 then it spells out the index of the bit that was flipped */
|
/* If err != 0 then it spells out the index of the bit that was flipped */
|
||||||
if(err) {
|
if (err) {
|
||||||
/* Flip to correct */
|
/* Flip to correct */
|
||||||
bits[err] = bits[err] ? 0 : 1;
|
bits[err] = bits[err] ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we have to read the message, bit 0 is unused (it's the overall parity bit
|
/* Now we have to read the message, bit 0 is unused (it's the overall parity bit
|
||||||
* which we don't care about). Each bit at an index that is a power of 2 is
|
* which we don't care about). Each bit at an index that is a power of 2 is
|
||||||
* a parity bit and not part of the actual message. */
|
* a parity bit and not part of the actual message. */
|
||||||
|
|
||||||
let ans = '';
|
let ans = "";
|
||||||
|
|
||||||
for(let i = 1; i < bits.length; i++) {
|
for (let i = 1; i < bits.length; i++) {
|
||||||
/* i is not a power of two so it's not a parity bit */
|
/* i is not a power of two so it's not a parity bit */
|
||||||
if((i & (i - 1)) != 0) {
|
if ((i & (i - 1)) != 0) {
|
||||||
ans += bits[i];
|
ans += bits[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO to avoid ambiguity about endianness why not let the player return the extracted (and corrected)
|
/* TODO to avoid ambiguity about endianness why not let the player return the extracted (and corrected)
|
||||||
* data bits, rather than guessing at how to convert it to a decimal string? */
|
* data bits, rather than guessing at how to convert it to a decimal string? */
|
||||||
return parseInt(ans, 2);
|
return parseInt(ans, 2);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user