From 4b37603ea55f29484069a9edca4a720fd626187d Mon Sep 17 00:00:00 2001 From: s2ks Date: Fri, 27 May 2022 21:36:03 +0200 Subject: [PATCH 1/6] Attempt to clear up some ambiguity in the descriptions of the "HammingCodes" coding contracts as well as having the "HammingCodes: Encoded Binary to Integer" coding contract generate valid Hamming codes. --- src/data/codingcontracttypes.ts | 34 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index b7fce1441..68322a80f 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -2,7 +2,7 @@ import { getRandomInt } from "../utils/helpers/getRandomInt"; import { MinHeap } from "../utils/Heap"; import { comprGenChar, comprLZGenerate, comprLZEncode, comprLZDecode } from "../utils/CompressionContracts"; -import { HammingEncode, HammingDecode } from "../utils/HammingCodeTools"; +import { HammingEncode, HammingDecode, HammingEncodeProperly } from "../utils/HammingCodeTools"; /* tslint:disable:completed-docs no-magic-numbers arrow-return-shorthand */ /* Function that generates a valid 'data' for a contract type */ @@ -1257,16 +1257,16 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ return [ "You are given the following decimal Value: \n", `${n} \n`, - "Convert it into a binary string and encode it as a 'Hamming-Code'. eg:\n ", - "Value 8 will result into binary '1000', which will be encoded", - "with the pattern 'pppdpddd', where p is a paritybit and d a databit,\n", + "Convert it to a binary representation and encode it as an 'extended Hamming code'. Eg:\n ", + "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", "or '10101' (Value 21) will result into (pppdpdddpd) '1001101011'.\n\n", - "NOTE: You need an parity Bit on Index 0 as an 'overall'-paritybit. \n", - "NOTE 2: You should watch the HammingCode-video from 3Blue1Brown, which explains the 'rule' of encoding,", - "including the first Index parity-bit mentioned on the first note.\n\n", - "Now the only one rule for this encoding:\n", - " It's not allowed to add additional leading '0's to the binary value\n", - "That means, the binary value has to be encoded as it is", + "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 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", + "Extra rule for encoding:\n", + "There should be no leading zeros in the 'data bit' section", ].join(" "); }, gen: (): number => { @@ -1284,17 +1284,21 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ return [ "You are given the following encoded binary String: \n", `'${n}' \n`, - "Treat it as a Hammingcode with 1 'possible' error on an random Index.\n", + "Treat it as an extended Hamming code with 1 'possible' error at a random index.\n", "Find the 'possible' wrong bit, fix it and extract the decimal value, which is hidden inside the string.\n\n", - "Note: The length of the binary string is dynamic, but it's encoding/decoding is following Hammings 'rule'\n", - "Note 2: Index 0 is an 'overall' parity bit. Watch the Hammingcode-video from 3Blue1Brown for more information\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 3: There's a ~55% chance for an altered Bit. So... MAYBE there is an altered Bit 😉\n", - "Extranote for automation: return the decimal value as a string", + "Note: The endianness of the \ + 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 \ + (MSB at index 0)\n", + "Extra note for automation: return the decimal value as a string", ].join(" "); }, gen: (): string => { const _alteredBit = Math.round(Math.random()); - const _buildArray: Array = HammingEncode( + const _buildArray: Array = HammingEncodeProperly( getRandomInt(Math.pow(2, 4), Math.pow(2, getRandomInt(1, 57))), ).split(""); if (_alteredBit) { From aa321e33051d465128f58a7ad4fe713827d1614f Mon Sep 17 00:00:00 2001 From: s2ks Date: Fri, 27 May 2022 21:42:39 +0200 Subject: [PATCH 2/6] re-implement HammingEncode/Decode added HammingEncodeProperly to generate valid hamming codes for "HammingCodes: Encoded Binary to Integer" --- src/utils/HammingCodeTools.ts | 243 +++++++++++++++++++++------------- 1 file changed, 151 insertions(+), 92 deletions(-) diff --git a/src/utils/HammingCodeTools.ts b/src/utils/HammingCodeTools.ts index 6fea2ee13..dd99e084c 100644 --- a/src/utils/HammingCodeTools.ts +++ b/src/utils/HammingCodeTools.ts @@ -1,97 +1,156 @@ -// by Discord: H3draut3r#6722, feel free to ask me any questions. i probably don't know the answer 🤣 -export function HammingEncode(value: number): string { - // encoding following Hammings rule - function HammingSumOfParity(_lengthOfDBits: number): number { - // will calculate the needed amount of parityBits 'without' the "overall"-Parity (that math took me 4 Days to get it working) - return _lengthOfDBits < 3 || _lengthOfDBits == 0 // oh and of course using ternary operators, it's a pretty neat function - ? _lengthOfDBits == 0 - ? 0 - : _lengthOfDBits + 1 - : // the following math will only work, if the length is greater equal 3, otherwise it's "kind of" broken :D - Math.ceil(Math.log2(_lengthOfDBits * 2)) <= - Math.ceil(Math.log2(1 + _lengthOfDBits + Math.ceil(Math.log2(_lengthOfDBits)))) - ? Math.ceil(Math.log2(_lengthOfDBits) + 1) - : Math.ceil(Math.log2(_lengthOfDBits)); - } - const _data = value.toString(2).split(""); // first, change into binary string, then create array with 1 bit per index - const _sumParity: number = HammingSumOfParity(_data.length); // get the sum of needed parity bits (for later use in encoding) - const count = (arr: Array, val: string): number => - arr.reduce((a: number, v: string) => (v === val ? a + 1 : a), 0); - // function count for specific entries in the array, for later use +export function HammingEncode(data: number): string { - const _build = ["x", "x", ..._data.splice(0, 1)]; // init the "pre-build" - for (let i = 2; i < _sumParity; i++) { - // add new paritybits and the corresponding data bits (pre-building array) - _build.push("x", ..._data.splice(0, Math.pow(2, i) - 1)); - } - // now the "calculation"... get the paritybits ('x') working - for (const index of _build.reduce(function (a: Array, e: string, i: number) { - if (e == "x") a.push(i); - return a; - }, [])) { - // that reduce will result in an array of index numbers where the "x" is placed - const _tempcount = index + 1; // set the "stepsize" for the parityBit - const _temparray = []; // temporary array to store the extracted bits - const _tempdata = [..._build]; // only work with a copy of the _build - while (_tempdata[index] !== undefined) { - // as long as there are bits on the starting index, do "cut" - const _temp: Array = _tempdata.splice(index, _tempcount * 2); // cut stepsize*2 bits, then... - _temparray.push(..._temp.splice(0, _tempcount)); // ... cut the result again and keep the first half - } - _temparray.splice(0, 1); // remove first bit, which is the parity one - _build[index] = (count(_temparray, "1") % 2).toString(); // count with remainder of 2 and"toString" to store the parityBit - } // parity done, now the "overall"-parity is set - _build.unshift((count(_build, "1") % 2).toString()); // has to be done as last element - return _build.join(""); // return the _build as string + const enc: Array = [0]; + const data_bits: Array = data.toString(2).split("").reverse(); + + data_bits.forEach((e, i, a) => { + 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; + } + } + + let parity: any = 0; + + /* Figure out the subsection parities */ + for(let i = 0; i < enc.length; i++) { + if(enc[i]) { + parity ^= i; + } + } + + parity = parity.toString(2).split("").reverse(); + parity.forEach((e: any, i: any , a: any) => { + a[i] = parseInt(e); + }); + + /* Set the parity bits accordingly */ + for(let i = 0; i < parity.length; i++) { + enc[2 ** i] = parity[i] ? 1 : 0; + } + + parity = 0; + /* Figure out the overall parity for the entire block */ + for(let i = 0; i < enc.length; i++) { + if(enc[i]) { + parity++; + } + } + + /* Finally set the overall parity bit */ + enc[0] = parity % 2 == 0 ? 0 : 1; + + return enc.join(""); } -export function HammingDecode(_data: string): number { - //check for altered bit and decode - const _build = _data.split(""); // ye, an array for working, again - const _testArray = []; //for the "truthtable". if any is false, the data has an altered bit, will check for and fix it - const _sumParity = Math.ceil(Math.log2(_data.length)); // sum of parity for later use - const count = (arr: Array, val: string): number => - arr.reduce((a: number, v: string) => (v === val ? a + 1 : a), 0); - // the count.... again ;) +export function HammingEncodeProperly(data: number): string { + /* How many bits do we need? + * n = 2^m + * k = 2^m - m - 1 + * where k is the number of data bits, m the number + * of parity bits and n the number of total bits. */ - let _overallParity = _build.splice(0, 1).join(""); // store first index, for checking in next step and fix the _build properly later on - _testArray.push(_overallParity == (count(_build, "1") % 2).toString() ? true : false); // first check with the overall parity bit - for (let i = 0; i < _sumParity; i++) { - // for the rest of the remaining parity bits we also "check" - const _tempIndex = Math.pow(2, i) - 1; // get the parityBits Index - const _tempStep = _tempIndex + 1; // set the stepsize - const _tempData = [..._build]; // get a "copy" of the build-data for working - const _tempArray = []; // init empty array for "testing" - while (_tempData[_tempIndex] != undefined) { - // extract from the copied data until the "starting" index is undefined - const _temp = [..._tempData.splice(_tempIndex, _tempStep * 2)]; // extract 2*stepsize - _tempArray.push(..._temp.splice(0, _tempStep)); // and cut again for keeping first half - } - const _tempParity = _tempArray.shift(); // and again save the first index separated for checking with the rest of the data - _testArray.push(_tempParity == (count(_tempArray, "1") % 2).toString() ? true : false); - // is the _tempParity the calculated data? push answer into the 'truthtable' - } - let _fixIndex = 0; // init the "fixing" index and start with 0 - for (let i = 1; i < _sumParity + 1; i++) { - // simple binary adding for every boolean in the _testArray, starting from 2nd index of it - _fixIndex += _testArray[i] ? 0 : Math.pow(2, i) / 2; - } - _build.unshift(_overallParity); // now we need the "overall" parity back in it's place - // try fix the actual encoded binary string if there is an error - if (_fixIndex > 0 && _testArray[0] == false) { - // if the overall is false and the sum of calculated values is greater equal 0, fix the corresponding hamming-bit - _build[_fixIndex] = _build[_fixIndex] == "0" ? "1" : "0"; - } else if (_testArray[0] == false) { - // otherwise, if the the overall_parity is the only wrong, fix that one - _overallParity = _overallParity == "0" ? "1" : "0"; - } else if (_testArray[0] == true && _testArray.some((truth) => truth == false)) { - return 0; // uhm, there's some strange going on... 2 bits are altered? How? This should not happen 👀 - } - // oof.. halfway through... we fixed an possible altered bit, now "extract" the parity-bits from the _build - for (let i = _sumParity; i >= 0; i--) { - // start from the last parity down the 2nd index one - _build.splice(Math.pow(2, i), 1); - } - _build.splice(0, 1); // remove the overall parity bit and we have our binary value - return parseInt(_build.join(""), 2); // parse the integer with redux 2 and we're done! + let m = 1; + + while((2 ** ((2 ** m) - m - 1)) < data) { + m++; + } + + const n: number = (2 ** m); + const k: number = (2 ** m) - m - 1; + + const enc: Array = [0]; + const data_bits: Array = data.toString(2).split("").reverse(); + + data_bits.forEach((e, i, a) => { + a[i] = parseInt(e); + }); + + /* Flip endianness as in the original implementation by Hedrauta + * and write the data back to front + * XXX why do we do this? */ + for(let i = 1, j = k; i < n; i++) { + if((i & (i - 1)) != 0) { + enc[i] = data_bits[--j] ? data_bits[j] : 0; + } + } + + let parity: any = 0; + + /* Figure out the subsection parities */ + for(let i = 0; i < n; i++) { + if(enc[i]) { + parity ^= i; + } + } + + parity = parity.toString(2).split("").reverse(); + parity.forEach((e: any, i: any , a: any) => { + a[i] = parseInt(e); + }); + + /* Set the parity bits accordingly */ + for(let i = 0; i < m; i++) { + enc[2 ** i] = parity[i] ? 1 : 0; + } + + parity = 0; + /* Figure out the overall parity for the entire block */ + for(let i = 0; i < n; i++) { + if(enc[i]) { + parity++; + } + } + + /* Finally set the overall parity bit */ + enc[0] = parity % 2 == 0 ? 0 : 1; + + return enc.join(""); +} + +export function HammingDecode(data: string): number { + let err = 0; + const bits: Array = []; + + /* TODO why not just work with an array of digits from the start? */ + for(const i in data.split("")) { + const bit = parseInt(data[i]); + bits[i] = bit; + + if(bit) { + err ^= +i; + } + } + + /* If err != 0 then it spells out the index of the bit that was flipped */ + if(err) { + /* Flip to correct */ + bits[err] = bits[err] ? 0 : 1; + } + + /* 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 + * a parity bit and not part of the actual message. */ + + let ans = ''; + + for(let i = 1; i < bits.length; i++) { + /* i is not a power of two so it's not a parity bit */ + if((i & (i - 1)) != 0) { + ans += bits[i]; + } + } + + /* 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? */ + return parseInt(ans, 2); } From bcc53c48a7262ea974392743b823b4c2d0f9fa93 Mon Sep 17 00:00:00 2001 From: s2ks Date: Fri, 27 May 2022 22:31:42 +0200 Subject: [PATCH 3/6] be clear about the form the answer should come in --- src/data/codingcontracttypes.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index 68322a80f..6ee30e76d 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -1260,7 +1260,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ "Convert it to a binary representation and encode it as an 'extended Hamming code'. Eg:\n ", "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", - "or '10101' (Value 21) will result into (pppdpdddpd) '1001101011'.\n\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", "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 2: You should watch the Hamming Code video from 3Blue1Brown, which explains the 'rule' of encoding,", From c88d3bcf858a9e66b7582d69b1a2c6c59df6cfc7 Mon Sep 17 00:00:00 2001 From: s2ks Date: Fri, 27 May 2022 22:37:32 +0200 Subject: [PATCH 4/6] format --- src/data/codingcontracttypes.ts | 8 +- src/utils/HammingCodeTools.ts | 235 ++++++++++++++++---------------- 2 files changed, 121 insertions(+), 122 deletions(-) diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index 6ee30e76d..f977da091 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -1261,13 +1261,13 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ "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", "or '10101' (Value 21) will result into (pppdpdddpd) '1001101011'.\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", + "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 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,", "including the first index parity bit mentioned in the previous note.\n\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(" "); }, 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 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: The endianness of the \ + "Note: The endianness of the \ 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 \ (MSB at index 0)\n", diff --git a/src/utils/HammingCodeTools.ts b/src/utils/HammingCodeTools.ts index dd99e084c..e057f3a0a 100644 --- a/src/utils/HammingCodeTools.ts +++ b/src/utils/HammingCodeTools.ts @@ -1,156 +1,155 @@ export function HammingEncode(data: number): string { + const enc: Array = [0]; + const data_bits: Array = data.toString(2).split("").reverse(); - const enc: Array = [0]; - const data_bits: Array = data.toString(2).split("").reverse(); + data_bits.forEach((e, i, a) => { + a[i] = parseInt(e); + }); - data_bits.forEach((e, i, a) => { - a[i] = parseInt(e); - }); + let k = data_bits.length; - 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 - * 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; - 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 */ - for(let i = 0; i < enc.length; i++) { - if(enc[i]) { - parity ^= i; - } - } + parity = parity.toString(2).split("").reverse(); + parity.forEach((e: any, i: any, a: any) => { + a[i] = parseInt(e); + }); - parity = parity.toString(2).split("").reverse(); - parity.forEach((e: any, i: any , a: any) => { - a[i] = parseInt(e); - }); + /* Set the parity bits accordingly */ + for (let i = 0; i < parity.length; i++) { + enc[2 ** i] = parity[i] ? 1 : 0; + } - /* Set the parity bits accordingly */ - for(let i = 0; i < parity.length; i++) { - enc[2 ** i] = parity[i] ? 1 : 0; - } + parity = 0; + /* Figure out the overall parity for the entire block */ + for (let i = 0; i < enc.length; i++) { + if (enc[i]) { + parity++; + } + } - parity = 0; - /* Figure out the overall parity for the entire block */ - for(let i = 0; i < enc.length; i++) { - if(enc[i]) { - parity++; - } - } + /* Finally set the overall parity bit */ + enc[0] = parity % 2 == 0 ? 0 : 1; - /* Finally set the overall parity bit */ - enc[0] = parity % 2 == 0 ? 0 : 1; - - return enc.join(""); + return enc.join(""); } export function HammingEncodeProperly(data: number): string { - /* How many bits do we need? - * n = 2^m - * k = 2^m - m - 1 - * where k is the number of data bits, m the number - * of parity bits and n the number of total bits. */ + /* How many bits do we need? + * n = 2^m + * k = 2^m - m - 1 + * where k is the number of data bits, m the number + * of parity bits and n the number of total bits. */ - let m = 1; + let m = 1; - while((2 ** ((2 ** m) - m - 1)) < data) { - m++; - } + while (2 ** (2 ** m - m - 1) < data) { + m++; + } - const n: number = (2 ** m); - const k: number = (2 ** m) - m - 1; + const n: number = 2 ** m; + const k: number = 2 ** m - m - 1; - const enc: Array = [0]; - const data_bits: Array = data.toString(2).split("").reverse(); + const enc: Array = [0]; + const data_bits: Array = data.toString(2).split("").reverse(); - data_bits.forEach((e, i, a) => { - a[i] = parseInt(e); - }); + data_bits.forEach((e, i, a) => { + a[i] = parseInt(e); + }); - /* Flip endianness as in the original implementation by Hedrauta - * and write the data back to front - * XXX why do we do this? */ - for(let i = 1, j = k; i < n; i++) { - if((i & (i - 1)) != 0) { - enc[i] = data_bits[--j] ? data_bits[j] : 0; - } - } + /* Flip endianness as in the original implementation by Hedrauta + * and write the data back to front + * XXX why do we do this? */ + for (let i = 1, j = k; i < n; i++) { + if ((i & (i - 1)) != 0) { + enc[i] = data_bits[--j] ? data_bits[j] : 0; + } + } - let parity: any = 0; + let parity: any = 0; - /* Figure out the subsection parities */ - for(let i = 0; i < n; i++) { - if(enc[i]) { - parity ^= i; - } - } + /* Figure out the subsection parities */ + for (let i = 0; i < n; i++) { + if (enc[i]) { + parity ^= i; + } + } - parity = parity.toString(2).split("").reverse(); - parity.forEach((e: any, i: any , a: any) => { - a[i] = parseInt(e); - }); + parity = parity.toString(2).split("").reverse(); + parity.forEach((e: any, i: any, a: any) => { + a[i] = parseInt(e); + }); - /* Set the parity bits accordingly */ - for(let i = 0; i < m; i++) { - enc[2 ** i] = parity[i] ? 1 : 0; - } + /* Set the parity bits accordingly */ + for (let i = 0; i < m; i++) { + enc[2 ** i] = parity[i] ? 1 : 0; + } - parity = 0; - /* Figure out the overall parity for the entire block */ - for(let i = 0; i < n; i++) { - if(enc[i]) { - parity++; - } - } + parity = 0; + /* Figure out the overall parity for the entire block */ + for (let i = 0; i < n; i++) { + if (enc[i]) { + parity++; + } + } - /* Finally set the overall parity bit */ - enc[0] = parity % 2 == 0 ? 0 : 1; + /* Finally set the overall parity bit */ + enc[0] = parity % 2 == 0 ? 0 : 1; - return enc.join(""); + return enc.join(""); } export function HammingDecode(data: string): number { - let err = 0; - const bits: Array = []; + let err = 0; + const bits: Array = []; - /* TODO why not just work with an array of digits from the start? */ - for(const i in data.split("")) { - const bit = parseInt(data[i]); - bits[i] = bit; + /* TODO why not just work with an array of digits from the start? */ + for (const i in data.split("")) { + const bit = parseInt(data[i]); + bits[i] = bit; - if(bit) { - err ^= +i; - } - } + if (bit) { + err ^= +i; + } + } - /* If err != 0 then it spells out the index of the bit that was flipped */ - if(err) { - /* Flip to correct */ - bits[err] = bits[err] ? 0 : 1; - } + /* If err != 0 then it spells out the index of the bit that was flipped */ + if (err) { + /* Flip to correct */ + bits[err] = bits[err] ? 0 : 1; + } - /* 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 - * a parity bit and not part of the actual message. */ + /* 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 + * a parity bit and not part of the actual message. */ - let ans = ''; + let ans = ""; - for(let i = 1; i < bits.length; i++) { - /* i is not a power of two so it's not a parity bit */ - if((i & (i - 1)) != 0) { - ans += bits[i]; - } - } + for (let i = 1; i < bits.length; i++) { + /* i is not a power of two so it's not a parity bit */ + if ((i & (i - 1)) != 0) { + ans += bits[i]; + } + } - /* 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? */ - return parseInt(ans, 2); + /* 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? */ + return parseInt(ans, 2); } From f066c0f01efb1ad3d38d5d8d255234aaa5849fd2 Mon Sep 17 00:00:00 2001 From: s2ks Date: Sat, 28 May 2022 15:27:32 +0200 Subject: [PATCH 5/6] correct size calculation --- src/utils/HammingCodeTools.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/HammingCodeTools.ts b/src/utils/HammingCodeTools.ts index e057f3a0a..11ccc31ed 100644 --- a/src/utils/HammingCodeTools.ts +++ b/src/utils/HammingCodeTools.ts @@ -60,7 +60,7 @@ export function HammingEncodeProperly(data: number): string { let m = 1; - while (2 ** (2 ** m - m - 1) < data) { + while (((2**((2**m) - m - 1)) - 1) < data) { m++; } From b27e7d00fef854bdbce2670c47b85fa01423dddd Mon Sep 17 00:00:00 2001 From: s2ks Date: Fri, 8 Jul 2022 01:37:42 +0200 Subject: [PATCH 6/6] format --- src/data/codingcontracttypes.ts | 4 ++-- src/utils/HammingCodeTools.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index e58f964bf..17a1e4662 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -1291,8 +1291,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ "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: The endianness of the 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", - "(MSB at index 0).\n", + "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", "Extra note for automation: return the decimal value as a string", ].join(" "); }, diff --git a/src/utils/HammingCodeTools.ts b/src/utils/HammingCodeTools.ts index 11ccc31ed..c75248580 100644 --- a/src/utils/HammingCodeTools.ts +++ b/src/utils/HammingCodeTools.ts @@ -60,7 +60,7 @@ export function HammingEncodeProperly(data: number): string { let m = 1; - while (((2**((2**m) - m - 1)) - 1) < data) { + while (2 ** (2 ** m - m - 1) - 1 < data) { m++; }