.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/wallets/codes/plot_02_verhoeff_check_digit.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_wallets_codes_plot_02_verhoeff_check_digit.py: Verhoeff's check digit and detecting transpositions (1969) ========================================================== Jacobus Verhoeff studied the errors Dutch clerks made when copying numbers: most were one wrong digit, and most of the rest were two neighbouring digits swapped. A check digit chosen so that the digit sum is a multiple of 10 catches every wrong digit but no swap, since addition commutes. Luhn's scheme, used on payment cards, catches every swap but 09 and 90. Verhoeff catches all of them by computing in the dihedral group D5, where :math:`a * b \ne b * a`, and permuting each digit by its position: .. math:: \sigma^{0}(a_0) * \sigma^{1}(a_1) * \cdots * \sigma^{k}(a_k) = 0 . Base58Check and Bech32 addresses do the same job, at the scale of a whole string. .. GENERATED FROM PYTHON SOURCE LINES 23-28 .. code-block:: Python import matplotlib.pyplot as plt import blockchainkit as bk from blockchainkit.wallets.visualizers import plot_detection_rates .. GENERATED FROM PYTHON SOURCE LINES 29-31 Check digits on one number -------------------------- .. GENERATED FROM PYTHON SOURCE LINES 31-40 .. code-block:: Python number = "236" for scheme in ("sum", "luhn", "verhoeff"): digit, valid = bk.wallets.CHECK_SCHEMES[scheme] word = number + digit(number) swapped = word[1] + word[0] + word[2:] print(f"{scheme:9} {word} swap {swapped} caught: {not valid(swapped)}") assert bk.wallets.verhoeff_valid("2363") and not bk.wallets.verhoeff_valid("3263") .. rst-class:: sphx-glr-script-out .. code-block:: none sum 2369 swap 3269 caught: False luhn 2360 swap 3260 caught: True verhoeff 2363 swap 3263 caught: True .. GENERATED FROM PYTHON SOURCE LINES 41-43 Luhn's blind spot ----------------- .. GENERATED FROM PYTHON SOURCE LINES 43-50 .. code-block:: Python print("Luhn digit of 09 and 90:", bk.wallets.luhn_digit("09"), bk.wallets.luhn_digit("90")) print( "Verhoeff digit of 09 and 90:", bk.wallets.verhoeff_digit("09"), bk.wallets.verhoeff_digit("90") ) assert bk.wallets.luhn_digit("09") == bk.wallets.luhn_digit("90") .. rst-class:: sphx-glr-script-out .. code-block:: none Luhn digit of 09 and 90: 1 1 Verhoeff digit of 09 and 90: 9 2 .. GENERATED FROM PYTHON SOURCE LINES 51-53 Every error on every three-digit number --------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 53-63 .. code-block:: Python rates = [bk.wallets.detection_rates(s, 3) for s in ("sum", "luhn", "verhoeff")] for r in rates: print(f"{r.scheme:9} single errors {r.single_errors:.1%}, swaps {r.transpositions:.1%}") assert rates[2].single_errors == rates[2].transpositions == 1.0 ax = plot_detection_rates(rates) ax.set_title("Only a non-commuting group catches every swap") plt.show() .. image-sg:: /api/gallery/wallets/codes/images/sphx_glr_plot_02_verhoeff_check_digit_001.png :alt: Only a non-commuting group catches every swap :srcset: /api/gallery/wallets/codes/images/sphx_glr_plot_02_verhoeff_check_digit_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none sum single errors 100.0%, swaps 0.0% luhn single errors 100.0%, swaps 97.8% verhoeff single errors 100.0%, swaps 100.0% .. GENERATED FROM PYTHON SOURCE LINES 64-68 Exercise -------- Which pairs of different digits ab can Luhn's scheme not tell from ba? A worked solution is in :doc:`/exercises/wallets`. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.186 seconds) .. _sphx_glr_download_api_gallery_wallets_codes_plot_02_verhoeff_check_digit.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/wallets/codes/plot_02_verhoeff_check_digit.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_verhoeff_check_digit.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_verhoeff_check_digit.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_verhoeff_check_digit.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_