Error Correction, Part 1

6+ hours across 72 lessons — Data Structures, Algorithms, Cryptography, Binary, Software Design, and Essential Unix Skills.
As you watch this video, note that it's not always smooth and seamless. Behind the scenes, Vimeo (my video provider) is adjusting for bandwith changes, alternating the sources based on throughput. The player is compensating for packet loss as well, correcting for errors in audio and video.
This stuff is complicated and you're about to see why.
This is part 1 of a 2-part series where we try to answer two simple questions:
- Was there an error in the transmission?
- Where is it?
This is tricky stuff! We'll tackle the theory in this video and in the next one, part 2, we'll spend the entire time writing the code necessary to fix my favorite Big Lebowski quote.
The Code
Here's the code used in the video. Note that the blurbs below are mostly for example. In the next video we'll write more useful stuff.
<span class="hljs-keyword">class</span> <span class="hljs-title class_">Encoder</span>{
<span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>){
<span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span> = {
<span class="hljs-string">"A"</span> : <span class="hljs-string">"01000000000"</span>,
<span class="hljs-string">"B"</span> : <span class="hljs-string">"10000000000"</span>,
<span class="hljs-string">"C"</span> : <span class="hljs-string">"00100000000"</span>,
<span class="hljs-string">"D"</span> : <span class="hljs-string">"00101000000"</span>,
<span class="hljs-string">"E"</span> : <span class="hljs-string">"10100000000"</span>,
<span class="hljs-string">"F"</span> : <span class="hljs-string">"10010000000"</span>,
<span class="hljs-string">"G"</span> : <span class="hljs-string">"01010000000"</span>,
<span class="hljs-string">"H"</span> : <span class="hljs-string">"11000000000"</span>,
<span class="hljs-string">"I"</span> : <span class="hljs-string">"11010000000"</span>,
<span class="hljs-string">"J"</span> : <span class="hljs-string">"01011000000"</span>,
<span class="hljs-string">"K"</span> : <span class="hljs-string">"01011001000"</span>,
<span class="hljs-string">"L"</span> : <span class="hljs-string">"10001000000"</span>,
<span class="hljs-string">"M"</span> : <span class="hljs-string">"01010100000"</span>,
<span class="hljs-string">"N"</span> : <span class="hljs-string">"01100000000"</span>,
<span class="hljs-string">"O"</span> : <span class="hljs-string">"01110000000"</span>,
<span class="hljs-string">"P"</span> : <span class="hljs-string">"10000100000"</span>,
<span class="hljs-string">"Q"</span> : <span class="hljs-string">"01011000100"</span>,
<span class="hljs-string">"R"</span> : <span class="hljs-string">"11100000000"</span>,
<span class="hljs-string">"S"</span> : <span class="hljs-string">"11110000000"</span>,
<span class="hljs-string">"T"</span> : <span class="hljs-string">"00110000000"</span>,
<span class="hljs-string">"U"</span> : <span class="hljs-string">"10011000000"</span>,
<span class="hljs-string">"V"</span> : <span class="hljs-string">"01011010000"</span>,
<span class="hljs-string">"W"</span> : <span class="hljs-string">"00100100000"</span>,
<span class="hljs-string">"X"</span> : <span class="hljs-string">"01011000110"</span>,
<span class="hljs-string">"Y"</span> : <span class="hljs-string">"01011100000"</span>,
<span class="hljs-string">"Z"</span> : <span class="hljs-string">"01011000111"</span>,
<span class="hljs-string">" "</span> : <span class="hljs-string">"00000000000"</span>
}
}
<span class="hljs-title function_">encode</span>(<span class="hljs-params">message</span>){
<span class="hljs-comment">//loop the characters in the message</span>
<span class="hljs-comment">//we'll assume for now that they won't enter anything but alpha numeric with a space for separation</span>
<span class="hljs-comment">//also ... uppercase to reduce pain</span>
<span class="hljs-keyword">const</span> words = message.<span class="hljs-title function_">toUpperCase</span>(), out = [];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> word <span class="hljs-keyword">of</span> words){
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> char <span class="hljs-keyword">of</span> word){
<span class="hljs-keyword">const</span> encoding = <span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>[char];
<span class="hljs-comment">//if the character can be encoded great. If not, ignore</span>
<span class="hljs-keyword">if</span>(encoding) out.<span class="hljs-title function_">push</span>(encoding);
}
}
<span class="hljs-keyword">return</span> out.<span class="hljs-title function_">join</span>(<span class="hljs-string">""</span>);
}
<span class="hljs-comment">//add the methods below</span>
}
<span class="hljs-title function_">evenParity</span>(<span class="hljs-params"></span>){
<span class="hljs-keyword">const</span> keys = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">keys</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>);
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> key <span class="hljs-keyword">of</span> keys){
<span class="hljs-comment">//default to even</span>
<span class="hljs-keyword">let</span> pad = <span class="hljs-string">"0"</span>;
<span class="hljs-comment">//split into a character array so we can filter</span>
<span class="hljs-keyword">const</span> chars = <span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>[key].<span class="hljs-title function_">split</span>(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> ones = chars.<span class="hljs-title function_">filter</span>(<span class="hljs-function"><span class="hljs-params">v</span> =></span> v === <span class="hljs-string">"1"</span>);
<span class="hljs-comment">//check mod 2 to see if we're odd, if so, set the pad to 1</span>
<span class="hljs-keyword">if</span>(ones.<span class="hljs-property">length</span> % <span class="hljs-number">2</span> !==<span class="hljs-number">0</span>) pad = <span class="hljs-string">"1"</span>
<span class="hljs-comment">//update the encoding with a pad at the end</span>
<span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>[key]+= pad;
}
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>);
}
<span class="hljs-title function_">checkParity</span>(<span class="hljs-params">word</span>){
<span class="hljs-comment">//make sure we have the right length</span>
<span class="hljs-keyword">if</span>(word.<span class="hljs-property">length</span> !== <span class="hljs-number">12</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
<span class="hljs-comment">//now make sure it's even</span>
<span class="hljs-keyword">return</span> word.<span class="hljs-title function_">split</span>(<span class="hljs-string">""</span>).<span class="hljs-title function_">filter</span>(<span class="hljs-function"><span class="hljs-params">char</span> =></span> char === <span class="hljs-string">"1"</span>).<span class="hljs-property">length</span> %<span class="hljs-number">2</span> === <span class="hljs-number">0</span>;
}
<span class="hljs-title function_">decode</span>(<span class="hljs-params">binaryMessage</span>){
<span class="hljs-keyword">let</span> out = [], codeWord = <span class="hljs-string">""</span>;
<span class="hljs-keyword">const</span> pad = <span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>.<span class="hljs-property">A</span>.<span class="hljs-property">length</span>;
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i < binaryMessage.<span class="hljs-property">length</span>; i+=pad){
codeWord = binaryMessage.<span class="hljs-title function_">substring</span>(i, i + pad);
<span class="hljs-keyword">const</span> noError = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">checkParity</span>(codeWord);
<span class="hljs-keyword">if</span>(noError){
<span class="hljs-keyword">const</span> key = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">getAlpha</span>(codeWord);
out.<span class="hljs-title function_">push</span>(key);
codeWord = <span class="hljs-string">""</span>;
}<span class="hljs-keyword">else</span>{
<span class="hljs-comment">//this is an error!</span>
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"Got an error with "</span>, codeWord);
<span class="hljs-keyword">const</span> fix = <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">simpleHammingErrorCorrector</span>(codeWord);
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"Fixing with best guess:"</span>, fix);
out.<span class="hljs-title function_">push</span>(fix.<span class="hljs-property">word</span>);
}
}
<span class="hljs-keyword">return</span> out.<span class="hljs-title function_">join</span>(<span class="hljs-string">""</span>);
}
<span class="hljs-title function_">simpleHammingErrorCorrector</span>(<span class="hljs-params">binaryMessage</span>){
<span class="hljs-keyword">const</span> codeWords = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">values</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">encoding</span>);
<span class="hljs-keyword">let</span> bestCandidate = {}, bestDistance = <span class="hljs-title class_">Number</span>.<span class="hljs-property">POSITIVE_INFINITY</span>;
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> codeWord <span class="hljs-keyword">of</span> codeWords){
<span class="hljs-keyword">let</span> thisDistance = <span class="hljs-number">0</span>;;
<span class="hljs-comment">//we're scanning each word for a match</span>
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i < codeWord.<span class="hljs-property">length</span>; i++){
<span class="hljs-keyword">if</span>(codeWord[i] !== binaryMessage[i]) {
thisDistance+=<span class="hljs-number">1</span>;
}
}
<span class="hljs-keyword">if</span>(thisDistance < bestDistance){
bestDistance = thisDistance;
bestCandidate = {<span class="hljs-attr">word</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">getAlpha</span>(codeWord), <span class="hljs-attr">binary</span>: codeWord, <span class="hljs-attr">distance</span>: bestDistance}
}
}
<span class="hljs-keyword">return</span> bestCandidate;
}
6+ hours across 72 lessons — Data Structures, Algorithms, Cryptography, Binary, Software Design, and Essential Unix Skills.