{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "Jurek Wawro, (C) Galicea" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# IBAN - wyliczanie cyfr kontrolnych dla Polski" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Problem:\n", "Konto bankowe w Polsce ma format zgodny ze standardem IBAN (https://pl.wikipedia.org/wiki/Mi%C4%99dzynarodowy_numer_rachunku_bankowego).\n", "Zaczyna się od znaków PL (opcjonalnie). Potem dwie cyfry kontrolne po których następuje 24 cyfry właściwego numeru (z czego pierwsze 8 to numer banku). \n", "\n", "* [Zadanie](#Zadanie)\n", "* [Szczegóły](#Szczegóły)\n", "* [Ograniczenia](#Ograniczenia)\n", "* [Algorytm](#Algorytm)\n", "* [Kod](#Kod)\n", "* [Test](#Test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Zadanie\n", "\n", "Napisać algorytm liczenia cyfr kontrolnych dla polskich kont bankowych. \n", ". \n", "\n", "### Szczegóły\n", "\n", "W Polsce cyfry te liczymy według wzoru: 98 - konto modulo 97,\n", "gdzie konto - zamieniona na cyfry reprezentacja konta (zob. poniżej), a modulo = reszta z dzielenia.\n", "Zamiana konta na cyfry odbywa się następująco:\n", "1. Zamisń cyfry kontrolne na 00 a PL na numery liter w alfabecie łacińskim (licząc od A=10). A więc L=21 a P=25. Otrzymujemy 252100\n", "2. Przepisz powyższy ciąg na koniec konta.\n", "3. Zamiań tak otrzymany ciąg cyfr na liczbę (num) i wylicz 98- num % 97 (procent % poznacza operację modulo).\n", "4. Jeśli wynik <10 - dodaj zero z przodu.\n", "\n", "Należy napisać prosty algorytm korzystajacy z braku ograniczeń na wielkość liczby całkowitej, a później algorytm operujący na mniejszych liczbach (nie więcej niż 9 cyfr).\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ograniczenia\n", "\n", "Należy założyć, że konto otrzymujemy bez prefiksa (PLcc) i znaków rozdzielających (-)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dane testowe\n", "\n", "(konto bez cyfr kontrolnych - cyfry kontrolne)\n", "123456789012345678901234 - 04\n", "230000000123456789012345 - 63\n", "345678900000067890123456 - 15\n", "456789012345600000234567 - 60\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algorytm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Trywialny algorytm zadziała tylko wtedy, gdy język programowania obsłuży bardzo duże liczby (tak jest w Pythonie).\n", "Sposób wyliczenia reszty bez operowania na dużych liczbach można znaleźć analizując dzielenie pisemne przez liczby dwucyfrowe.\n", "Na pryzkład:\n", "Znamy pisemny sposób dzielnia. Na przykład \n", "\n", "\n", " 816345 : 12 = 6 8 02 8\n", " 72\n", " ...\n", " 96\n", " 96\n", " ...\n", " 034\n", " 24\n", " ...\n", " 105\n", " 96\n", " ...\n", " 9\n", "\n", " \n", "\n", "Jak widać za każdym razem bierzemy resztę z dzielenia i dopisujemy jedną lub \n", "dwie kolejne cyfry (gdy pierwsza jest zerem). Ale nic nie stoi na przeszkodzie,\n", "by zawsze dopisywać więcej niż jedną cyfrę:\n", "\n", "\n", "\n", " 816345 : 12 = 6 80 28\n", " 72\n", " ...\n", " 963\n", " 960\n", " ...\n", " 345\n", " 336\n", " ...\n", " 9\n", "\n", "\n", "Resztę z dzielnia całej liczby zawsze otrzymujemy w ostatnim kroku.\n", "W naszym algorytmie założymy, że dopisujemy po 8 cyfr." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Kod\n", "\n", "Najpierw kod trywialny" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Rozwiazanie(object):\n", "\n", " def algorytm(self,konto):\n", " num = int(konto+'252100')\n", " cyfry = 98 - num % 97\n", " if cyfry < 10:\n", " return '0'+str(cyfry)\n", " else:\n", " return str(cyfry)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Algorytm z mniejszymi liczbami (mozna stosować w innych niż Python językach). \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Rozwiazanie2(object):\n", "\n", " def algorytm(self,konto):\n", " n1 = int(konto[:8])\n", " c1 = n1 % 97\n", " n2 = int(str(c1)+konto[8:16])\n", " c2 = n2 % 97\n", " n3 = int(str(c2)+konto[16:])\n", " c3 = n3 % 97\n", " n4 = int(str(c3)+'252100')\n", " cyfry = 98 - n4 % 97\n", " if cyfry < 10:\n", " return '0'+str(cyfry)\n", " else:\n", " return str(cyfry)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "\n", " // przykładowa funkcja w PHP\n", " function iban_checksum($nr) {\n", " $nr1 = substr($nr,0,8);\n", " $checksum = intval($nr1) % 97;\n", " $nr1 = strval($checksum).substr($nr,8,8);\n", " $checksum = intval($nr1) % 97;\n", " $nr1 = strval($checksum).substr($nr,16,8);\n", " $checksum = intval($nr1) % 97;\n", " $nr1 = strval($checksum). \"252100\"; // PL00 => L=21, ..., P=25.\n", " $checksum = 98 - (intval($nr1) % 97);\n", " if ($checksum<10) {\n", " return '0'.$checksum;\n", " } else {\n", " return ''.$checksum;\n", " }\n", " }\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from nose.tools import assert_equal, assert_raises\n", "\n", "\n", "class Testowanie(object):\n", " parametry = [('123456789012345678901234','04'),\n", " ('230000000123456789012345','63'),\n", " ('345678900000067890123456','15'),\n", " ('456789012345600000234567','60')]\n", "\n", " def test(self, algorytm1,algorytm2):\n", " print('Testuję...')\n", " for (parametr,oczekiwany) in self.parametry:\n", " wynik = algorytm1(parametr)\n", " assert_equal(wynik, oczekiwany)\n", " wynik = algorytm2(parametr)\n", " assert_equal(wynik, oczekiwany)\n", " print('Sukces')\n", "\n", "\n", "def main():\n", " test = Testowanie()\n", " r1 = Rozwiazanie()\n", " r2 = Rozwiazanie2()\n", " \n", " try:\n", " test.test(r1.algorytm,r2.algorytm)\n", " except AttributeError as e:\n", " print e\n", " pass\n", "\n", "\n", "if __name__ == '__main__':\n", " main()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.13" } }, "nbformat": 4, "nbformat_minor": 1 }