{"title":"pandey.github.io","link":[{"@attributes":{"href":"https:\/\/pandey.github.io\/","rel":"alternate"}},{"@attributes":{"href":"https:\/\/pandey.github.io\/feeds\/all.atom.xml","rel":"self"}}],"id":"https:\/\/pandey.github.io\/","updated":"2017-02-02T00:00:00-06:00","entry":[{"title":"How old is a Unicode\u00a0character?","link":{"@attributes":{"href":"https:\/\/pandey.github.io\/posts\/unicode-codepoint-age.html","rel":"alternate"}},"published":"2017-02-02T00:00:00-06:00","updated":"2017-02-02T00:00:00-06:00","author":{"name":"Anshuman Pandey"},"id":"tag:pandey.github.io,2017-02-02:\/posts\/unicode-codepoint-age.html","summary":"<p>I often need to find out when a particular character was encoded in The \nUnicode Standard. The Unicode Character Database (<span class=\"caps\">UCD<\/span>) has \na file&nbsp;called <code>DerivedAge.txt<\/code> that contains such information. This <span class=\"caps\">UCD<\/span> \nfile provides&nbsp;the <code>Age<\/code> property for characters, which can be queried \nto obtain the version of Unicode \u2026<\/p>","content":"<p>I often need to find out when a particular character was encoded in The \nUnicode Standard. The Unicode Character Database (<span class=\"caps\">UCD<\/span>) has \na file&nbsp;called <code>DerivedAge.txt<\/code> that contains such information. This <span class=\"caps\">UCD<\/span> \nfile provides&nbsp;the <code>Age<\/code> property for characters, which can be queried \nto obtain the version of Unicode in which a codepoint was assigned. \nHowever, deriving the age of a character&nbsp;from <code>DerivedAge.txt<\/code> is not \nso straightforward on account of the file&#8217;s format. Here, I will \nparse that file and define a new function in order to obtain the \nnecessary data with&nbsp;ease.<\/p>\n<h2>Understand the&nbsp;data<\/h2>\n<p>I&nbsp;used <code>DerivedAge.txt<\/code> in a previous post to explore the \n<a href=\"https:\/\/pandey.github.io\/posts\/unicode-growth-UCD-python.html\">growth of Unicode<\/a> \nin terms of the number of characters added in each version. \nRecall that&nbsp;the <code>DerivedAge.txt<\/code> file has the following&nbsp;presentation:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>    # Age=V1_1\n\n    # Assigned as of Unicode 1.1.0 (June, 1993)\n    # [excluding removed Hangul Syllables]\n\n    0000..001F    ; 1.1 #  [32] &lt;control-0000&gt;..&lt;control-001F&gt;\n    0020..007E    ; 1.1 #  [95] SPACE..TILDE\n    007F..009F    ; 1.1 #  [33] &lt;control-007F&gt;..&lt;control-009F&gt;\n    00A0..00AC    ; 1.1 #  [13] NO-BREAK SPACE..NOT SIGN\n    00AD          ; 1.1 #       SOFT HYPHEN\n<\/code><\/pre><\/div>\n\n<p>In that previous post, I parsed this data and stored it into&nbsp;the \n<code>derivedage<\/code> list of lists, which has the following&nbsp;structure:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">derivedage<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">:<\/span><span class=\"mi\">5<\/span><span class=\"p\">]<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;0000..001F&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;32&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;&lt;control-0000&gt;..&lt;control-001F&gt;&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;0020..007E&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;95&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;SPACE..TILDE&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;007F..009F&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;33&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;&lt;control-007F&gt;..&lt;control-009F&gt;&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;00A0..00AC&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;13&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;NO-BREAK SPACE..NOT SIGN&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;00AD&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;SOFT HYPHEN&#39;<\/span>]]\n<\/code><\/pre><\/div>\n\n<p>Notice that the second element contains the codepoint. However, \nthere are actual two types of data masquerading as one. In some lists, \nthe second element is a single codepoint, eg. <span class=\"caps\">00AD<\/span>, while in others \nit stands for a range, eg. 00A0..<span class=\"caps\">00AC<\/span>.<\/p>\n<h2>Approach the&nbsp;problem<\/h2>\n<p>The issue becomes clear: searching for a particular codepoint will have \none of two results. If the query matches the exact value of the second \nelement, then&nbsp;the <code>Age<\/code> property is readily available. However, if there \nis no exact match, then additional processing is&nbsp;necessary.<\/p>\n<p>There are two ways to approach the&nbsp;task:<\/p>\n<ol>\n<li>Expand all code ranges to produce entries for each literal&nbsp;codepoint<\/li>\n<li>Infer codepoint&#8217;s membership within a range of&nbsp;codepoints<\/li>\n<\/ol>\n<p>The first approach would require generating new entries for each codepoint in a given&nbsp;range:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">coderange<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;00A0&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;00AC&#39;<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">hexlower<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">hexupper<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"ow\">in<\/span> <span class=\"p\">(<\/span><span class=\"nb\">range<\/span><span class=\"p\">(<\/span><span class=\"n\">hexlower<\/span><span class=\"p\">,<\/span> <span class=\"n\">hexupper<\/span> <span class=\"o\">+<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)):<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"nb\">hex<\/span><span class=\"p\">(<\/span><span class=\"n\">i<\/span><span class=\"p\">))<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"mf\">0<\/span><span class=\"n\">xa0<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa1<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa2<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa3<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa4<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa5<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa6<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa7<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa8<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xa9<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xaa<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xab<\/span>\n<span class=\"mf\">0<\/span><span class=\"n\">xac<\/span>\n<\/code><\/pre><\/div>\n\n<p>One benefit to this approach is the ability to produce a dictionary that contains every codepoint as a key and it&#8217;s age as the&nbsp;value:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>derivedage = {\n    &#39;00A0&#39; : &#39;1.1&#39;,\n    &#39;00A1&#39; : &#39;1.1&#39;,\n    ...\n    }\n<\/code><\/pre><\/div>\n\n<p>The downside is that it will significantly expand the dataset as there are more than 160k codepoints as of Unicode version&nbsp;9.0.<\/p>\n<p>The other approach is to search within a range at runtime and to return the associated&nbsp;age:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">coderange<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;00A0&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;00AC&#39;<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">hexlower<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">hexupper<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">char<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;00A3&#39;<\/span>\n\n<span class=\"n\">char<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span><span class=\"p\">,<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">if<\/span> <span class=\"n\">hexlower<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"n\">char<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"n\">hexupper<\/span><span class=\"p\">:<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s1\">&#39;found&#39;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">hex<\/span><span class=\"p\">(<\/span><span class=\"n\">char<\/span><span class=\"p\">),<\/span> <span class=\"s1\">&#39;within&#39;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">hex<\/span><span class=\"p\">(<\/span><span class=\"n\">hexlower<\/span><span class=\"p\">),<\/span> <span class=\"s1\">&#39;and&#39;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">hex<\/span><span class=\"p\">(<\/span><span class=\"n\">hexupper<\/span><span class=\"p\">))<\/span>\n<span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s1\">&#39;not found&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>found 0xa3 within 0xa0 and 0xac\n<\/code><\/pre><\/div>\n\n<h2>Define the&nbsp;function<\/h2>\n<p>The function relies upon&nbsp;the <code>derivedage<\/code> container, which is a list of \nlists with the following&nbsp;structure:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;1.1&#39;, &#39;0020..007E&#39;, &#39;95&#39;, &#39;SPACE..TILDE&#39;]\n<\/code><\/pre><\/div>\n\n<p>For our present purposes, we need to perform an operation on element #2, which is \neither a single codepoint value or a range of codepoints. If it is a range, then \nwe need to split into two to define the lower and upper&nbsp;bounds:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;0020&#39;, &#39;007E&#39;]\n<\/code><\/pre><\/div>\n\n<p>The function will take a list of 1 or more codepoints. The codepoint is expressed \nas a string, eg. &#8216;0065&#8217;. For each element in the list, the function will determine \nif the codepoint&nbsp;scan <code>derivedage<\/code>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">getDerivedAge<\/span><span class=\"p\">(<\/span><span class=\"n\">inputlist_<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"n\">resultslist<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">codepoint<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">inputlist_<\/span><span class=\"p\">:<\/span>\n\n        <span class=\"n\">scriptinfo<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">None<\/span>\n        <span class=\"n\">char<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">codepoint<\/span><span class=\"p\">,<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"k\">for<\/span> <span class=\"n\">script<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">derivedage<\/span><span class=\"p\">:<\/span>\n\n            <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"n\">script<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n            <span class=\"n\">coderange<\/span> <span class=\"o\">=<\/span> <span class=\"n\">script<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">split<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;..&#39;<\/span><span class=\"p\">)<\/span>\n\n            <span class=\"k\">if<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">coderange<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">2<\/span><span class=\"p\">:<\/span>\n\n                <span class=\"n\">hexlower<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">hexupper<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"s2\">&quot;0x&quot;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span>\n\n                <span class=\"k\">if<\/span> <span class=\"n\">hexlower<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"n\">char<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"n\">hexupper<\/span><span class=\"p\">:<\/span>\n                    <span class=\"n\">scriptinfo<\/span> <span class=\"o\">=<\/span> <span class=\"n\">version<\/span>\n\n            <span class=\"k\">elif<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">coderange<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">1<\/span><span class=\"p\">:<\/span>\n\n                <span class=\"k\">if<\/span> <span class=\"n\">codepoint<\/span> <span class=\"o\">==<\/span> <span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]:<\/span>\n                    <span class=\"n\">scriptinfo<\/span> <span class=\"o\">=<\/span> <span class=\"n\">version<\/span>\n\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n\n                <span class=\"n\">scriptinfo<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;Error&#39;<\/span>\n\n        <span class=\"n\">resultslist<\/span><span class=\"o\">.<\/span><span class=\"n\">update<\/span><span class=\"p\">({<\/span><span class=\"n\">codepoint<\/span> <span class=\"p\">:<\/span> <span class=\"n\">scriptinfo<\/span><span class=\"p\">})<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">resultslist<\/span>\n<\/code><\/pre><\/div>\n\n<h2>Test the&nbsp;function<\/h2>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">codepoints<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;0035&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;0913&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;A8F0&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;BBBB&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;11080&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;14000&#39;<\/span><span class=\"p\">]<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">getDerivedAge<\/span><span class=\"p\">(<\/span><span class=\"n\">codepoints<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>{&#39;0035&#39;: &#39;1.1&#39;,\n &#39;0913&#39;: &#39;1.1&#39;,\n &#39;11080&#39;: &#39;5.2&#39;,\n &#39;14000&#39;: None,\n &#39;A8F0&#39;: &#39;5.2&#39;,\n &#39;BBBB&#39;: &#39;2.0&#39;}\n<\/code><\/pre><\/div>\n\n<p>The function returns the versions in which each of our specified codepoints \nwas encoded. But, we&nbsp;got <code>None<\/code> for 14000&#8230; is there an error somewhere? \nPerforming a search&nbsp;through <code>DerivedAge.txt<\/code> for a single codepoint or \nwithinn a range yields nothing. A quick glance at the \nUnicode Roadmap shows that 14000 is an unencoded codepoint in a block \nthat is tentatively allocated for Egyptian Hieroglyphs. So, there is no \ncharacter in Unicode associated with this codepoint. The&nbsp;value <code>None<\/code> \nis&nbsp;accurate.<\/p>\n<h1>Assessment<\/h1>\n<p>The <code>DerivedAge.txt<\/code> file presents the &#8216;age&#8217; of a codepoint, or \nthe version of Unicode in which it was assigned in the stanard.. \nWhen this version information is aggregated with other data in the <span class=\"caps\">UCD<\/span>, \nit is possible to generate holistic metadata for codepoints in Unicode. \nIn a future post I will explore&nbsp;the <code>Blocks.txt<\/code> and <code>Scripts.txt<\/code> file \nin order to illustrate how codepoints are grouped within Unicode paradigms \nof &#8216;blocks&#8217; and&nbsp;&#8216;scripts&#8217;.<\/p>","category":{"@attributes":{"term":"articles"}}},{"title":"Visualizing the growth of Unicode using\u00a0matplotlib","link":{"@attributes":{"href":"https:\/\/pandey.github.io\/posts\/unicode-growth-matplotlib.html","rel":"alternate"}},"published":"2017-01-30T00:00:00-06:00","updated":"2017-01-30T00:00:00-06:00","author":{"name":"Anshuman Pandey"},"id":"tag:pandey.github.io,2017-01-30:\/posts\/unicode-growth-matplotlib.html","summary":"<p>In a <a href=\"posts\/unicode-growth-UCD-python.html\">previous post<\/a>, I presented \ninformation about the growth of Unicode in terms of the number of \ncodepoints assigned in each version. The data was displayed as text tables \nusing&nbsp;the <code>PrettyTable<\/code> package. As we are visual beings, I think it would be useful \nto also present that data \u2026<\/p>","content":"<p>In a <a href=\"posts\/unicode-growth-UCD-python.html\">previous post<\/a>, I presented \ninformation about the growth of Unicode in terms of the number of \ncodepoints assigned in each version. The data was displayed as text tables \nusing&nbsp;the <code>PrettyTable<\/code> package. As we are visual beings, I think it would be useful \nto also present that data using charts. Here I&nbsp;use <code>matplotlib<\/code> and the same \ndata sets to produce such&nbsp;visualizations.<\/p>\n<h2>Prerequisites<\/h2>\n<p>Recall the lists of lists we&nbsp;produced: <code>DA_codepoint_totals<\/code>, <code>DA_char_totals<\/code>,&nbsp;and <code>DA_other_totals<\/code>:<\/p>\n<p>** Growth of codepoints by version:&nbsp;**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_codepoint_totals<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[[&#39;1.1&#39;, 33979, 33979],\n [&#39;2.0&#39;, 144521, 178500],\n [&#39;2.1&#39;, 2, 178502],\n [&#39;3.0&#39;, 10307, 188809],\n [&#39;3.1&#39;, 44978, 233787],\n [&#39;3.2&#39;, 1016, 234803],\n [&#39;4.0&#39;, 1226, 236029],\n [&#39;4.1&#39;, 1273, 237302],\n [&#39;5.0&#39;, 1369, 238671],\n [&#39;5.1&#39;, 1624, 240295],\n [&#39;5.2&#39;, 6648, 246943],\n [&#39;6.0&#39;, 2088, 249031],\n [&#39;6.1&#39;, 732, 249763],\n [&#39;6.2&#39;, 1, 249764],\n [&#39;6.3&#39;, 5, 249769],\n [&#39;7.0&#39;, 2834, 252603],\n [&#39;8.0&#39;, 7716, 260319],\n [&#39;9.0&#39;, 7500, 267819]]\n<\/code><\/pre><\/div>\n\n<p>** Growth of characters per version:&nbsp;**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_char_totals<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[[&#39;1.1&#39;, 27512, 27512],\n [&#39;2.0&#39;, 11373, 38885],\n [&#39;2.1&#39;, 2, 38887],\n [&#39;3.0&#39;, 10307, 49194],\n [&#39;3.1&#39;, 44946, 94140],\n [&#39;3.2&#39;, 1016, 95156],\n [&#39;4.0&#39;, 1226, 96382],\n [&#39;4.1&#39;, 1273, 97655],\n [&#39;5.0&#39;, 1369, 99024],\n [&#39;5.1&#39;, 1624, 100648],\n [&#39;5.2&#39;, 6648, 107296],\n [&#39;6.0&#39;, 2088, 109384],\n [&#39;6.1&#39;, 732, 110116],\n [&#39;6.2&#39;, 1, 110117],\n [&#39;6.3&#39;, 5, 110122],\n [&#39;7.0&#39;, 2834, 112956],\n [&#39;8.0&#39;, 7716, 120672],\n [&#39;9.0&#39;, 7500, 128172]]\n<\/code><\/pre><\/div>\n\n<p>** Growth of noncharacters per version:&nbsp;**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_other_totals<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[[&#39;1.1&#39;, 6467, 6467],\n [&#39;2.0&#39;, 133148, 139615],\n [&#39;2.1&#39;, 0, 139615],\n [&#39;3.0&#39;, 0, 139615],\n [&#39;3.1&#39;, 32, 139647],\n [&#39;3.2&#39;, 0, 139647],\n [&#39;4.0&#39;, 0, 139647],\n [&#39;4.1&#39;, 0, 139647],\n [&#39;5.0&#39;, 0, 139647],\n [&#39;5.1&#39;, 0, 139647],\n [&#39;5.2&#39;, 0, 139647],\n [&#39;6.0&#39;, 0, 139647],\n [&#39;6.1&#39;, 0, 139647],\n [&#39;6.2&#39;, 0, 139647],\n [&#39;6.3&#39;, 0, 139647],\n [&#39;7.0&#39;, 0, 139647],\n [&#39;8.0&#39;, 0, 139647],\n [&#39;9.0&#39;, 0, 139647]]\n<\/code><\/pre><\/div>\n\n<h2>Approach<\/h2>\n<p>Import the Python modules needed for this&nbsp;task:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">numpy<\/span><span class=\"w\"> <\/span><span class=\"k\">as<\/span><span class=\"w\"> <\/span><span class=\"nn\">np<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">matplotlib.pyplot<\/span><span class=\"w\"> <\/span><span class=\"k\">as<\/span><span class=\"w\"> <\/span><span class=\"nn\">plt<\/span>\n<span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">matplotlib.ticker<\/span><span class=\"w\"> <\/span><span class=\"k\">as<\/span><span class=\"w\"> <\/span><span class=\"nn\">ticker<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">seaborn<\/span>\n<\/code><\/pre><\/div>\n\n<p>Use Jupyter magic to show plots within the&nbsp;notebook:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"o\">%<\/span><span class=\"n\">matplotlib<\/span> <span class=\"n\">inline<\/span>\n<\/code><\/pre><\/div>\n\n<h3>Plot line&nbsp;graphs<\/h3>\n<p>The <em>x<\/em> axis is&nbsp;the <code>arange<\/code> of the number of versions, not the version number itself. The <em>y<\/em> axis is the number of characters get values for <em>x<\/em> and <em>y<\/em> axes. Convert list of lists&nbsp;to <code>numpy<\/code> array, then read columms from array into lists: <em>x<\/em> values from column 0, <em>y<\/em> values from column 2.&nbsp;Use <code>numpy<\/code> slice <code>[:,0]<\/code> to read the matrix by column. Convert <em>y<\/em> values to&nbsp;type <code>int<\/code> when&nbsp;slicing.<\/p>\n<h4>Line graph: number of characters per&nbsp;version<\/h4>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">char_array<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">(<\/span><span class=\"n\">DA_char_totals<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">fig<\/span><span class=\"p\">,<\/span> <span class=\"n\">ax<\/span> <span class=\"o\">=<\/span> <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">subplots<\/span><span class=\"p\">()<\/span>\n\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">title<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;Number of characters encoded in Unicode&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">ylabel<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;Characters&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">xlabel<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;Versions&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">x_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">x_range<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">y_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">astype<\/span><span class=\"p\">(<\/span><span class=\"nb\">int<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_xticks<\/span><span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_xticklabels<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">,<\/span> <span class=\"n\">rotation<\/span><span class=\"o\">=<\/span><span class=\"mi\">45<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">plot<\/span> <span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">,<\/span> <span class=\"n\">y_values<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[&lt;matplotlib.lines.Line2D at 0x973c610&gt;]\n<\/code><\/pre><\/div>\n\n<p><img alt=\"image\" src=\"https:\/\/pandey.github.io\/images\/output_71_1.png\"><\/p>\n<p>As we will be plotting two more graphs of the same type and using the same type of container, it is practical to create a function for the above plot&nbsp;type:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">plot_line_graph<\/span><span class=\"p\">(<\/span><span class=\"n\">list_<\/span><span class=\"p\">,<\/span> <span class=\"n\">labels_<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"c1\"># process parameters<\/span>\n\n    <span class=\"n\">char_array<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">(<\/span><span class=\"n\">list_<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">plt_title<\/span><span class=\"p\">,<\/span> <span class=\"n\">plt_ylabel<\/span><span class=\"p\">,<\/span> <span class=\"n\">plt_xlabel<\/span> <span class=\"o\">=<\/span> <span class=\"n\">labels_<\/span>\n\n    <span class=\"c1\"># set up plot<\/span>\n\n    <span class=\"n\">fig<\/span><span class=\"p\">,<\/span> <span class=\"n\">ax<\/span> <span class=\"o\">=<\/span> <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">subplots<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">title<\/span><span class=\"p\">(<\/span><span class=\"n\">plt_title<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">ylabel<\/span><span class=\"p\">(<\/span><span class=\"n\">plt_ylabel<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">xlabel<\/span><span class=\"p\">(<\/span><span class=\"n\">plt_xlabel<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">x_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">x_range<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">))<\/span>\n    <span class=\"n\">y_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">astype<\/span><span class=\"p\">(<\/span><span class=\"nb\">int<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_xticks<\/span><span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_xticklabels<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">,<\/span> <span class=\"n\">rotation<\/span><span class=\"o\">=<\/span><span class=\"mi\">45<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">plot<\/span> <span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">,<\/span> <span class=\"n\">y_values<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p>Now we can pass a container and a list of labels to the function to generate additional&nbsp;plots:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">labels<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;Number of characters encoded in Unicode&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;Characters&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;Versions&#39;<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">plot_line_graph<\/span><span class=\"p\">(<\/span><span class=\"n\">DA_char_totals<\/span><span class=\"p\">,<\/span> <span class=\"n\">labels<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p><img alt=\"image\" src=\"https:\/\/pandey.github.io\/images\/output_75_0.png\"><\/p>\n<h4>Line graph: number of other entities per&nbsp;version<\/h4>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">labels<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;Number of other entities encoded in Unicode&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;Entities&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;Versions&#39;<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">plot_line_graph<\/span><span class=\"p\">(<\/span><span class=\"n\">DA_other_totals<\/span><span class=\"p\">,<\/span> <span class=\"n\">labels<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p><img alt=\"image\" src=\"https:\/\/pandey.github.io\/images\/output_77_0.png\"><\/p>\n<h4>Line graph: number of codepoints assigned per&nbsp;version<\/h4>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">labels<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;Number of codepoints encoded in Unicode&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;Noncharacters&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;Versions&#39;<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">plot_line_graph<\/span><span class=\"p\">(<\/span><span class=\"n\">DA_codepoint_totals<\/span><span class=\"p\">,<\/span> <span class=\"n\">labels<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p><img alt=\"image\" src=\"https:\/\/pandey.github.io\/images\/output_79_0.png\"><\/p>\n<h3>Plot stacked bar&nbsp;graphs<\/h3>\n<p>We can also plot the growth of number of characters using a stacked bar graph. Each bar is segmented into smaller categories in order to convey the smaller units that constitute the whole&nbsp;value. <\/p>\n<p>The <em>x<\/em> axis is&nbsp;the <code>arange<\/code> of the number of versions, not the version number itself. We will display the actual version numbers by modifying the labels of the plot. Our stacked bar requires two <em>y<\/em> values: the first (bottom) is the number of new characters per version, the second (top) is the value from the previous version, or, the difference between the total characters for a given version minus the new characters&nbsp;added.<\/p>\n<p>We&#8217;ll convert a list of lists to&nbsp;a <code>numpy<\/code> array, then read columms from the array into lists&nbsp;using <code>numpy<\/code> slice,&nbsp;eg. <code>[:,0]<\/code>.<\/p>\n<h4>Bar graph: growth of number of characters per&nbsp;version<\/h4>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">char_array<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">array<\/span><span class=\"p\">(<\/span><span class=\"n\">DA_char_totals<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p>Get the difference between the total characters and the new characters for each version. This is expressed as&nbsp;follows:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">diff_array<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">astype<\/span><span class=\"p\">(<\/span><span class=\"nb\">int<\/span><span class=\"p\">)<\/span> <span class=\"o\">-<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">astype<\/span><span class=\"p\">(<\/span><span class=\"nb\">int<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p>Set up the&nbsp;plot:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">fig<\/span><span class=\"p\">,<\/span> <span class=\"n\">ax<\/span> <span class=\"o\">=<\/span> <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">subplots<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">ax<\/span> <span class=\"o\">=<\/span> <span class=\"n\">plt<\/span><span class=\"o\">.<\/span><span class=\"n\">axes<\/span><span class=\"p\">()<\/span>\n\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_title<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;Characters per version&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_ylabel<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;Number of characters&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_xlabel<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;Versions&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">x_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n<span class=\"n\">x_range<\/span> <span class=\"o\">=<\/span> <span class=\"n\">np<\/span><span class=\"o\">.<\/span><span class=\"n\">arange<\/span><span class=\"p\">(<\/span><span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">))<\/span>\n\n<span class=\"n\">y1_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">astype<\/span><span class=\"p\">(<\/span><span class=\"nb\">int<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">y2_values<\/span> <span class=\"o\">=<\/span> <span class=\"n\">diff_array<\/span>\n\n<span class=\"n\">y_total<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char_array<\/span><span class=\"p\">[:,<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">astype<\/span><span class=\"p\">(<\/span><span class=\"nb\">int<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">xaxis<\/span><span class=\"o\">.<\/span><span class=\"n\">set_major_locator<\/span><span class=\"p\">(<\/span><span class=\"n\">ticker<\/span><span class=\"o\">.<\/span><span class=\"n\">FixedLocator<\/span><span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">xaxis<\/span><span class=\"o\">.<\/span><span class=\"n\">set_major_formatter<\/span><span class=\"p\">(<\/span><span class=\"n\">ticker<\/span><span class=\"o\">.<\/span><span class=\"n\">FixedFormatter<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">))<\/span>\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">set_xticklabels<\/span><span class=\"p\">(<\/span><span class=\"n\">x_values<\/span><span class=\"p\">,<\/span> <span class=\"n\">rotation<\/span><span class=\"o\">=<\/span><span class=\"mi\">45<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">bar<\/span><span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">,<\/span> <span class=\"n\">y1_values<\/span><span class=\"p\">,<\/span> <span class=\"n\">width<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">label<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;New chars&#39;<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">ax<\/span><span class=\"o\">.<\/span><span class=\"n\">bar<\/span><span class=\"p\">(<\/span><span class=\"n\">x_range<\/span><span class=\"p\">,<\/span> <span class=\"n\">y2_values<\/span><span class=\"p\">,<\/span> <span class=\"n\">width<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">bottom<\/span><span class=\"o\">=<\/span><span class=\"n\">y1_values<\/span><span class=\"p\">,<\/span> <span class=\"n\">label<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;Total chars&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p><img alt=\"image\" src=\"https:\/\/pandey.github.io\/images\/output_87_1.png\"><\/p>\n<h2>Commentary<\/h2>\n<p>This exercise helped us to convert our data from lists into graphs&nbsp;using <code>matplotlib<\/code>. The text tables I produced in the previous \nexercise, but the visualizations give us another perspective \ninto the growth of&nbsp;Unicode.<\/p>","category":{"@attributes":{"term":"articles"}}},{"title":"Exploring the growth of Unicode using the UCD and\u00a0Python","link":{"@attributes":{"href":"https:\/\/pandey.github.io\/posts\/unicode-growth-UCD-python.html","rel":"alternate"}},"published":"2017-01-28T00:00:00-06:00","updated":"2017-01-28T00:00:00-06:00","author":{"name":"Anshuman Pandey"},"id":"tag:pandey.github.io,2017-01-28:\/posts\/unicode-growth-UCD-python.html","summary":"<p>How many characters are in Unicode? How many new characters have been added for each version of Unicode? From a programmatic standpoint, figuring out the number of characters published in a given version of Unicode is not as straightforward as one might imagine. While it is true that Unicode contains \u2026<\/p>","content":"<p>How many characters are in Unicode? How many new characters have been added for each version of Unicode? From a programmatic standpoint, figuring out the number of characters published in a given version of Unicode is not as straightforward as one might imagine. While it is true that Unicode contains &#8216;characters&#8217; from writing systems, there are also entities that are not truly &#8216;characters&#8217; in the conventional sense. There are entities such as control characters, private-use characters, surrogates, and even noncharacters. Therefore, to get a sense of the number of entities in Unicode, it is practical to think instead in terms of &#8216;code&nbsp;points&#8217;.<\/p>\n<p>In this exercise, I process data from the Unicode Character Database (<span class=\"caps\">UCD<\/span>) in order to produce an overview of the longitudinal growth of Unicode. There are certainly other ways to solve the challenge, my goal is to do so in a programmatic fashion using available data. Specifically, I will explore a <span class=\"caps\">UCD<\/span> file&nbsp;called <code>DerivedAge.txt<\/code>, which provides all codepoints assignments for each version, from 1.1 to&nbsp;9.0.<\/p>\n<p>I will process this file to extract the number of code points in each version of Unicode, and also to distinguish at a high level between characters and other&nbsp;entities.<\/p>\n<h2>Approach<\/h2>\n<p>Import the Python modules needed for this&nbsp;task:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">re<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">requests<\/span>\n<span class=\"kn\">from<\/span><span class=\"w\"> <\/span><span class=\"nn\">prettytable<\/span><span class=\"w\"> <\/span><span class=\"kn\">import<\/span> <span class=\"n\">PrettyTable<\/span>\n<\/code><\/pre><\/div>\n\n<h3>Get the&nbsp;data<\/h3>\n<p>Fetch the plain text&nbsp;file <code>DerivedAge.txt<\/code> from the Unicode Character Database&nbsp;using <code>requests<\/code>, and get the text of&nbsp;the <code>requests<\/code> object using&nbsp;the <code>.text<\/code> method:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">url<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&quot;http:\/\/www.unicode.org\/Public\/UCD\/latest\/ucd\/DerivedAge.txt&quot;<\/span>\n<span class=\"n\">r<\/span> <span class=\"o\">=<\/span> <span class=\"n\">requests<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">url<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">text<\/span>\n<\/code><\/pre><\/div>\n\n<h3>Inspect the&nbsp;data<\/h3>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"mf\">106583<\/span>\n<\/code><\/pre><\/div>\n\n<p>Split&nbsp;the <code>requests<\/code> text by newline into a list&nbsp;named <code>filestream<\/code>, then take a slice of the list to get a sense of the&nbsp;data:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">filestream<\/span> <span class=\"o\">=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">split<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;<\/span><span class=\"se\">\\n<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">line<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">filestream<\/span><span class=\"p\">[<\/span><span class=\"mi\">51<\/span><span class=\"p\">:<\/span><span class=\"mi\">70<\/span><span class=\"p\">]:<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">line<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"c1\"># Age=V1_1<\/span>\n\n<span class=\"c1\"># Assigned as of Unicode 1.1.0 (June, 1993)<\/span>\n<span class=\"c1\"># [excluding removed Hangul Syllables]<\/span>\n\n<span class=\"mf\">0000..001<\/span><span class=\"n\">F<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [32] &lt;control-0000&gt;..&lt;control-001F&gt;<\/span>\n<span class=\"mf\">0020..007<\/span><span class=\"n\">E<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [95] SPACE..TILDE<\/span>\n<span class=\"n\">007F<\/span><span class=\"p\">.<\/span><span class=\"mf\">.009<\/span><span class=\"n\">F<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [33] &lt;control-007F&gt;..&lt;control-009F&gt;<\/span>\n<span class=\"n\">00A0<\/span><span class=\"p\">.<\/span><span class=\"mf\">.00<\/span><span class=\"n\">AC<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [13] NO-BREAK SPACE..NOT SIGN<\/span>\n<span class=\"n\">00AD<\/span><span class=\"w\">          <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#       SOFT HYPHEN<\/span>\n<span class=\"n\">00AE<\/span><span class=\"p\">.<\/span><span class=\"mf\">.01<\/span><span class=\"n\">F5<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\"># [328] REGISTERED SIGN..LATIN SMALL LETTER G WITH ACUTE<\/span>\n<span class=\"n\">01FA<\/span><span class=\"p\">.<\/span><span class=\"mf\">.0217<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [30] LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE..LATIN SMALL LETTER U WITH INVERTED BREVE<\/span>\n<span class=\"mf\">0250..02<\/span><span class=\"n\">A8<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [89] LATIN SMALL LETTER TURNED A..LATIN SMALL LETTER TC DIGRAPH WITH CURL<\/span>\n<span class=\"n\">02B0<\/span><span class=\"p\">.<\/span><span class=\"mf\">.02<\/span><span class=\"n\">DE<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [47] MODIFIER LETTER SMALL H..MODIFIER LETTER RHOTIC HOOK<\/span>\n<span class=\"mf\">02E0<\/span><span class=\"p\">.<\/span><span class=\"mf\">.02E9<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [10] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER EXTRA-LOW TONE BAR<\/span>\n<span class=\"mf\">0300..0345<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#  [70] COMBINING GRAVE ACCENT..COMBINING GREEK YPOGEGRAMMENI<\/span>\n<span class=\"mf\">0360..0361<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#   [2] COMBINING DOUBLE TILDE..COMBINING DOUBLE INVERTED BREVE<\/span>\n<span class=\"mf\">0374..0375<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#   [2] GREEK NUMERAL SIGN..GREEK LOWER NUMERAL SIGN<\/span>\n<span class=\"n\">037A<\/span><span class=\"w\">          <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"c1\">#       GREEK YPOGEGRAMMENI<\/span>\n<\/code><\/pre><\/div>\n\n<h3>Observations<\/h3>\n<p>The file lists the codepoints encoded in each version. It specifies the&nbsp;property <code>Age<\/code>, which is indicated both as a comment before each group of&nbsp;codepoints<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"gh\">#<\/span> Age=V1_1\n<\/code><\/pre><\/div>\n\n<p>and in the data for every code point or range of&nbsp;codepoints:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"mf\">037<\/span><span class=\"n\">A<\/span><span class=\"w\">          <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"w\">       <\/span><span class=\"n\">GREEK<\/span><span class=\"w\"> <\/span><span class=\"n\">YPOGEGRAMMENI<\/span>\n<\/code><\/pre><\/div>\n\n<p>The above record tells us that the character U+037A <span class=\"caps\">GREEK<\/span> <span class=\"caps\">YPOGRAMMENI<\/span>, was encoded in Unicode version&nbsp;1.1.<\/p>\n<p>The total number of code points is given as a comment after the list for each&nbsp;version:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code># Total code points: 33979\n<\/code><\/pre><\/div>\n\n<p>However, the number of <em>codepoints<\/em> does not tell us about the number of <em>characters<\/em>, or other entities. Such details are available&nbsp;in <code>DerivedAge.txt<\/code>, but we will need to obtain them programmatically from the data. First, let&#8217;s take a look at the format and contents of the&nbsp;file.<\/p>\n<h3>Description of the data&nbsp;format<\/h3>\n<p>A sample of data&nbsp;in <code>DerivedAge.txt<\/code>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"mf\">00<\/span><span class=\"n\">A0<\/span><span class=\"mf\">..00<\/span><span class=\"n\">AC<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"w\">  <\/span><span class=\"err\">[<\/span><span class=\"mf\">13<\/span><span class=\"err\">]<\/span><span class=\"w\"> <\/span><span class=\"n\">NO<\/span><span class=\"o\">-<\/span><span class=\"n\">BREAK<\/span><span class=\"w\"> <\/span><span class=\"n\">SPACE<\/span><span class=\"mf\">..<\/span><span class=\"ow\">NOT<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGN<\/span>\n<span class=\"mf\">00<\/span><span class=\"n\">AD<\/span><span class=\"w\">          <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"w\">       <\/span><span class=\"n\">SOFT<\/span><span class=\"w\"> <\/span><span class=\"n\">HYPHEN<\/span>\n<span class=\"mf\">4<\/span><span class=\"n\">E00<\/span><span class=\"mf\">..9<\/span><span class=\"n\">FA5<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"w\"> <\/span><span class=\"err\">[<\/span><span class=\"mf\">20902<\/span><span class=\"err\">]<\/span><span class=\"w\"> <\/span><span class=\"n\">CJK<\/span><span class=\"w\"> <\/span><span class=\"n\">UNIFIED<\/span><span class=\"w\"> <\/span><span class=\"n\">IDEOGRAPH<\/span><span class=\"o\">-<\/span><span class=\"mf\">4<\/span><span class=\"n\">E00<\/span><span class=\"mf\">..<\/span><span class=\"n\">CJK<\/span><span class=\"w\"> <\/span><span class=\"n\">UNIFIED<\/span><span class=\"w\"> <\/span><span class=\"n\">IDEOGRAPH<\/span><span class=\"o\">-<\/span><span class=\"mf\">9<\/span><span class=\"n\">FA5<\/span>\n<span class=\"n\">E000<\/span><span class=\"mf\">..<\/span><span class=\"n\">F8FF<\/span><span class=\"w\">    <\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"mf\">1.1<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"w\"> <\/span><span class=\"err\">[<\/span><span class=\"mf\">6400<\/span><span class=\"err\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"n\">private<\/span><span class=\"o\">-<\/span><span class=\"n\">use<\/span><span class=\"o\">-<\/span><span class=\"n\">E000<\/span><span class=\"o\">&gt;<\/span><span class=\"mf\">..<\/span><span class=\"o\">&lt;<\/span><span class=\"n\">private<\/span><span class=\"o\">-<\/span><span class=\"n\">use<\/span><span class=\"o\">-<\/span><span class=\"n\">F8FF<\/span><span class=\"o\">&gt;<\/span>\n<\/code><\/pre><\/div>\n\n<p>As&nbsp;shown <code>DerivedAge.txt<\/code> is a <span class=\"caps\">CSV<\/span>-like flat file. There are two primary fields, separated by&nbsp;a <code>;<\/code> semi-colon. The information&nbsp;after <code>#<\/code> may be considered comments, but may be separated into two&nbsp;fields:<\/p>\n<ul>\n<li>field 0: codepoint or codepoint range for a character or group of contiguous&nbsp;characters<\/li>\n<li>field 1: version of Unicode in which the character(s) was\/were&nbsp;encoded<\/li>\n<li>field 2: number of codepoints in a range, in square braces, empty if a single&nbsp;codepoint<\/li>\n<li>field 3: name or names of first and last item in a contiguous group; characters are <span class=\"caps\">UPPERCASE<\/span>, while noncharacters are lowercase&nbsp;within <code>&lt;<\/code> &#8230; <code>&gt;<\/code> delimiters<\/li>\n<\/ul>\n<p>The format is generally uniform, apart from inconsistencies in the spacing of fields&nbsp;after <code>#<\/code>. Field 3 is alloted a length of seven spaces between the # and field 4. In most cases,&nbsp;the <code>[<\/code>&#8230;<code>]<\/code> fits within the 7 columns. When the codepoint count is present, there is 1 space between&nbsp;the <code>#<\/code> and <code>[<\/code>&#8230;<code>]<\/code>, and 1 space&nbsp;between <code>[<\/code>&#8230;<code>]<\/code> and field 4. If&nbsp;the <code>[<\/code>&#8230;<code>]<\/code> takes more than four spaces, then the starting column for the character names are shifted&nbsp;right.<\/p>\n<h4>Define regex for extracting&nbsp;fields<\/h4>\n<p>The fields can be extracted using a&nbsp;regex:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>^([\\w\\.]*)\\s*\\; (.*) \\#\\s+(?:\\[(\\d*)\\])?\\s+(.*)\n\n  ^^^^^^^        ^^          ^^^^^^^^^      ^^\n     1            2              3           4\n<\/code><\/pre><\/div>\n\n<p>Four capture groups are&nbsp;defined:<\/p>\n<ul>\n<li><code>[\\w\\.]*<\/code> for the codepoint range or single code&nbsp;point<\/li>\n<li><code>(.*)<\/code> for the version&nbsp;number<\/li>\n<li><code>(?:\\[(\\d*)\\])<\/code> is a lookahead for [&#8230;] to handle single code&nbsp;point<\/li>\n<li><code>(.*)<\/code> for the character&nbsp;name(s)<\/li>\n<\/ul>\n<h3>Wrangle the&nbsp;data<\/h3>\n<p>Now wrangle the data from its native format into a more usable&nbsp;container:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">derivedage<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n<\/code><\/pre><\/div>\n\n<p><code>derivedage<\/code> will be a list of lists with a structure&nbsp;of:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>[\n  [&#39;version number&#39;, &#39;code point range&#39;, &#39;count&#39;, &#39;character names&#39;]]\n]\n<\/code><\/pre><\/div>\n\n<p>Also, let&#8217;s use a dictionary to capture&nbsp;the <code>Age<\/code> property values that have been explicitly specified. These values can be used for validating the data that we will derive from the&nbsp;file.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">derivedage_properties<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n<\/code><\/pre><\/div>\n\n<p>Now we&#8217;ll read the file line by line, and extract information from&nbsp;lines:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">for<\/span> <span class=\"n\">line<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">filestream<\/span><span class=\"p\">:<\/span>\n\n    <span class=\"c1\"># use the regex defined above:<\/span>\n\n    <span class=\"n\">m<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">search<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;^([\\w\\.]*)\\s*\\; (.*) \\#\\s+(?:\\[(\\d*)\\])?\\s+(.*)&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">line<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">m<\/span><span class=\"p\">:<\/span>\n\n        <span class=\"n\">m_coderange<\/span> <span class=\"o\">=<\/span> <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">m_version<\/span> <span class=\"o\">=<\/span> <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"c1\"># m.group(3) == None if the (?:\\[(\\d*)\\])? segment of the regex is empty<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"kc\">None<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">m_count<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;1&#39;<\/span>\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">m_count<\/span> <span class=\"o\">=<\/span> <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"n\">m_charname<\/span> <span class=\"o\">=<\/span> <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">4<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"n\">derivedage<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">([<\/span><span class=\"n\">m_version<\/span><span class=\"p\">,<\/span> <span class=\"n\">m_coderange<\/span><span class=\"p\">,<\/span> <span class=\"n\">m_count<\/span><span class=\"p\">,<\/span> <span class=\"n\">m_charname<\/span><span class=\"p\">])<\/span>\n\n\n    <span class=\"c1\"># now capture the age property details:<\/span>\n\n    <span class=\"n\">age_property_match<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">search<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;\\# Age=V(.*)&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">line<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">age_count_match<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">search<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;\\# Total code points: (.*)&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">line<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">age_property_match<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">age_property<\/span> <span class=\"o\">=<\/span> <span class=\"n\">age_property_match<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">age_property<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">sub<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;\\_&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;.&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">age_property<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">derivedage_properties<\/span><span class=\"o\">.<\/span><span class=\"n\">update<\/span><span class=\"p\">({<\/span><span class=\"n\">age_property<\/span> <span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">})<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">age_count_match<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">age_count<\/span> <span class=\"o\">=<\/span> <span class=\"n\">age_count_match<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">derivedage_properties<\/span><span class=\"p\">[<\/span><span class=\"n\">age_property<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"n\">age_count<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<p>Verify <code>derivedage<\/code>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">derivedage<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">:<\/span><span class=\"mi\">10<\/span><span class=\"p\">]<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;0000..001F&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;32&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;&lt;control-0000&gt;..&lt;control-001F&gt;&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;0020..007E&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;95&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;SPACE..TILDE&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;007F..009F&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;33&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;&lt;control-007F&gt;..&lt;control-009F&gt;&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;00A0..00AC&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;13&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;NO-BREAK SPACE..NOT SIGN&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;00AD&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;1&#39;<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">&#39;SOFT HYPHEN&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;00AE..01F5&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;328&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;REGISTERED SIGN..LATIN SMALL LETTER G WITH ACUTE&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;01FA..0217&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;30&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE..LATIN SMALL LETTER U WITH INVERTED BREVE&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;0250..02A8&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;89&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;LATIN SMALL LETTER TURNED A..LATIN SMALL LETTER TC DIGRAPH WITH CURL&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;02B0..02DE&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;47&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;MODIFIER LETTER SMALL H..MODIFIER LETTER RHOTIC HOOK&#39;<\/span>],\n<span class=\"w\"> <\/span>[<span class=\"s1\">&#39;1.1&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;02E0..02E9&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;10&#39;<\/span>,\n<span class=\"w\">  <\/span><span class=\"s1\">&#39;MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER EXTRA-LOW TONE BAR&#39;<\/span>]]\n<\/code><\/pre><\/div>\n\n<p>Verify <code>derivedage_summary<\/code>:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">derivedage_properties<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>{&#39;1.1&#39;: 33979,\n &#39;2.0&#39;: 144521,\n &#39;2.1&#39;: 2,\n &#39;3.0&#39;: 10307,\n &#39;3.1&#39;: 44978,\n &#39;3.2&#39;: 1016,\n &#39;4.0&#39;: 1226,\n &#39;4.1&#39;: 1273,\n &#39;5.0&#39;: 1369,\n &#39;5.1&#39;: 1624,\n &#39;5.2&#39;: 6648,\n &#39;6.0&#39;: 2088,\n &#39;6.1&#39;: 732,\n &#39;6.2&#39;: 1,\n &#39;6.3&#39;: 5,\n &#39;7.0&#39;: 2834,\n &#39;8.0&#39;: 7716,\n &#39;9.0&#39;: 7500}\n<\/code><\/pre><\/div>\n\n<h2>Process the&nbsp;data<\/h2>\n<p>Define dictionaries for capturing the&nbsp;data:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_codepoints<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n<span class=\"n\">DA_chars<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n<span class=\"n\">DA_other<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n\n<span class=\"n\">DA_entities<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n<\/code><\/pre><\/div>\n\n<p>Now iterate over&nbsp;the <code>derivedage<\/code> list of&nbsp;lists:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">for<\/span> <span class=\"n\">entry<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">derivedage<\/span><span class=\"p\">:<\/span>\n\n    <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"n\">entry<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">coderange<\/span> <span class=\"o\">=<\/span> <span class=\"n\">entry<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">split<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;..&#39;<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">count<\/span> <span class=\"o\">=<\/span> <span class=\"n\">entry<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">charname<\/span> <span class=\"o\">=<\/span> <span class=\"n\">entry<\/span><span class=\"p\">[<\/span><span class=\"mi\">3<\/span><span class=\"p\">]<\/span>\n\n    <span class=\"c1\"># 1. get codepoint range. if coderange ==2, get number of codepoints in <\/span>\n    <span class=\"c1\"># range by subtracting coderange[1] and coderange[0]. the values in <\/span>\n    <span class=\"c1\"># these lists are string represents of hex codes, so convert them <\/span>\n    <span class=\"c1\"># to actual hex numbers:<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">coderange<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">2<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">range_length<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span> <span class=\"o\">-<\/span> <span class=\"nb\">int<\/span><span class=\"p\">(<\/span><span class=\"n\">coderange<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"mi\">16<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"mi\">1<\/span>\n    <span class=\"k\">elif<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">coderange<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">1<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">range_length<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span>\n\n    <span class=\"c1\"># 2. store number of total codepoints per version:<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">version<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_codepoints<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">DA_codepoints<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">range_length<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">DA_codepoints<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">range_length<\/span>\n\n\n    <span class=\"c1\"># 3. store number of characters and other codepoints.<\/span>\n    <span class=\"c1\"># check for codepoint types. noncharacters are identified in <\/span>\n    <span class=\"c1\"># DerivedAge.txt using descriptions in &lt;..&gt; brackets<\/span>\n\n    <span class=\"n\">nonchar_match<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">search<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;^\\&lt;&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">charname<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># if entry is not a character:<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">nonchar_match<\/span><span class=\"p\">:<\/span>\n\n        <span class=\"c1\"># keep a record of the number of noncharacters per version:<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"n\">version<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_other<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">DA_other<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">range_length<\/span>\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">DA_other<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">range_length<\/span>\n\n    <span class=\"c1\"># if entry is a character:<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n\n        <span class=\"c1\"># keep a record of the number of characters per version:<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"n\">version<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_chars<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">DA_chars<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">range_length<\/span>\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">DA_chars<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">range_length<\/span>\n\n    <span class=\"c1\"># 4. store number of codepoint types per version:<\/span>\n\n    <span class=\"n\">nonchar_type_match<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">search<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;^\\&lt;(\\w*)\\-&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">charname<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">nonchar_type_match<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">entity_type<\/span> <span class=\"o\">=<\/span> <span class=\"n\">nonchar_type_match<\/span><span class=\"o\">.<\/span><span class=\"n\">group<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">entity_type<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;character&#39;<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">version<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_entities<\/span><span class=\"p\">:<\/span>               \n        <span class=\"k\">if<\/span> <span class=\"n\">entity_type<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_entities<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]:<\/span>\n            <span class=\"n\">DA_entities<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">][<\/span><span class=\"n\">entity_type<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">range_length<\/span>\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">DA_entities<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span><span class=\"o\">.<\/span><span class=\"n\">update<\/span><span class=\"p\">({<\/span><span class=\"n\">entity_type<\/span> <span class=\"p\">:<\/span> <span class=\"n\">range_length<\/span><span class=\"p\">})<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">DA_entities<\/span><span class=\"p\">[<\/span><span class=\"n\">version<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span><span class=\"n\">entity_type<\/span> <span class=\"p\">:<\/span> <span class=\"n\">range_length<\/span><span class=\"p\">}<\/span>            \n<\/code><\/pre><\/div>\n\n<h2>Review generated&nbsp;data<\/h2>\n<p>** Get number of codepoints by&nbsp;version:**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_codepoints<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>{&#39;1.1&#39;: 33979,\n &#39;2.0&#39;: 144521,\n &#39;2.1&#39;: 2,\n &#39;3.0&#39;: 10307,\n &#39;3.1&#39;: 44978,\n &#39;3.2&#39;: 1016,\n &#39;4.0&#39;: 1226,\n &#39;4.1&#39;: 1273,\n &#39;5.0&#39;: 1369,\n &#39;5.1&#39;: 1624,\n &#39;5.2&#39;: 6648,\n &#39;6.0&#39;: 2088,\n &#39;6.1&#39;: 732,\n &#39;6.2&#39;: 1,\n &#39;6.3&#39;: 5,\n &#39;7.0&#39;: 2834,\n &#39;8.0&#39;: 7716,\n &#39;9.0&#39;: 7500}\n<\/code><\/pre><\/div>\n\n<p>Does our codepoint count match&nbsp;the <code>Age<\/code> property values explicitly given&nbsp;in <code>DerivedAge.txt<\/code>?:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_codepoints<\/span> <span class=\"o\">==<\/span> <span class=\"n\">derivedage_properties<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>True\n<\/code><\/pre><\/div>\n\n<p>** Number of new characters per version:&nbsp;**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_chars<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>{&#39;1.1&#39;: 27512,\n &#39;2.0&#39;: 11373,\n &#39;2.1&#39;: 2,\n &#39;3.0&#39;: 10307,\n &#39;3.1&#39;: 44946,\n &#39;3.2&#39;: 1016,\n &#39;4.0&#39;: 1226,\n &#39;4.1&#39;: 1273,\n &#39;5.0&#39;: 1369,\n &#39;5.1&#39;: 1624,\n &#39;5.2&#39;: 6648,\n &#39;6.0&#39;: 2088,\n &#39;6.1&#39;: 732,\n &#39;6.2&#39;: 1,\n &#39;6.3&#39;: 5,\n &#39;7.0&#39;: 2834,\n &#39;8.0&#39;: 7716,\n &#39;9.0&#39;: 7500}\n<\/code><\/pre><\/div>\n\n<p>** Number of new noncharacters per version:&nbsp;**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_other<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>{&#39;1.1&#39;: 6467, &#39;2.0&#39;: 133148, &#39;3.1&#39;: 32}\n<\/code><\/pre><\/div>\n\n<p>** Breakdown of codepoint types by version&nbsp;**<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_entities<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>{&#39;1.1&#39;: {&#39;character&#39;: 27512,\n  &#39;control&#39;: 65,\n  &#39;noncharacter&#39;: 2,\n  &#39;private&#39;: 6400},\n &#39;2.0&#39;: {&#39;character&#39;: 11373,\n  &#39;noncharacter&#39;: 32,\n  &#39;private&#39;: 131068,\n  &#39;surrogate&#39;: 2048},\n &#39;2.1&#39;: {&#39;character&#39;: 2},\n &#39;3.0&#39;: {&#39;character&#39;: 10307},\n &#39;3.1&#39;: {&#39;character&#39;: 44946, &#39;noncharacter&#39;: 32},\n &#39;3.2&#39;: {&#39;character&#39;: 1016},\n &#39;4.0&#39;: {&#39;character&#39;: 1226},\n &#39;4.1&#39;: {&#39;character&#39;: 1273},\n &#39;5.0&#39;: {&#39;character&#39;: 1369},\n &#39;5.1&#39;: {&#39;character&#39;: 1624},\n &#39;5.2&#39;: {&#39;character&#39;: 6648},\n &#39;6.0&#39;: {&#39;character&#39;: 2088},\n &#39;6.1&#39;: {&#39;character&#39;: 732},\n &#39;6.2&#39;: {&#39;character&#39;: 1},\n &#39;6.3&#39;: {&#39;character&#39;: 5},\n &#39;7.0&#39;: {&#39;character&#39;: 2834},\n &#39;8.0&#39;: {&#39;character&#39;: 7716},\n &#39;9.0&#39;: {&#39;character&#39;: 7500}}\n<\/code><\/pre><\/div>\n\n<h2>Present the&nbsp;data<\/h2>\n<p>We will use&nbsp;the <code>PrettyTable<\/code> module to present the data using text&nbsp;tables<\/p>\n<h3>New codepoints and codepoint types by&nbsp;version<\/h3>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">x<\/span> <span class=\"o\">=<\/span> <span class=\"n\">PrettyTable<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;version&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;new codepoints&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;new chars&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;new other&#39;<\/span><span class=\"p\">])<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">v<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_codepoints<\/span><span class=\"o\">.<\/span><span class=\"n\">items<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">x<\/span><span class=\"o\">.<\/span><span class=\"n\">add_row<\/span><span class=\"p\">([<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">v<\/span><span class=\"p\">,<\/span> <span class=\"n\">DA_chars<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;-&#39;<\/span><span class=\"p\">),<\/span> <span class=\"n\">DA_other<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;-&#39;<\/span><span class=\"p\">)])<\/span>\n\n<span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>+---------+----------------+-----------+-----------+\n| version | new codepoints | new chars | new other |\n+---------+----------------+-----------+-----------+\n|   1.1   |     33979      |   27512   |    6467   |\n|   2.0   |     144521     |   11373   |   133148  |\n|   2.1   |       2        |     2     |     -     |\n|   3.0   |     10307      |   10307   |     -     |\n|   3.1   |     44978      |   44946   |     32    |\n|   3.2   |      1016      |    1016   |     -     |\n|   4.0   |      1226      |    1226   |     -     |\n|   4.1   |      1273      |    1273   |     -     |\n|   5.0   |      1369      |    1369   |     -     |\n|   5.1   |      1624      |    1624   |     -     |\n|   5.2   |      6648      |    6648   |     -     |\n|   6.0   |      2088      |    2088   |     -     |\n|   6.1   |      732       |    732    |     -     |\n|   6.2   |       1        |     1     |     -     |\n|   6.3   |       5        |     5     |     -     |\n|   7.0   |      2834      |    2834   |     -     |\n|   8.0   |      7716      |    7716   |     -     |\n|   9.0   |      7500      |    7500   |     -     |\n+---------+----------------+-----------+-----------+\n<\/code><\/pre><\/div>\n\n<h3>Growth of codepoints, characters, noncharacters by&nbsp;version<\/h3>\n<p>Declare three&nbsp;lists:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">DA_char_totals<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n<span class=\"n\">DA_other_totals<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n<span class=\"n\">DA_codepoint_totals<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">count_codepoints<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n<span class=\"n\">count_chars<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n<span class=\"n\">count_other<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n\n<span class=\"n\">z<\/span> <span class=\"o\">=<\/span> <span class=\"n\">PrettyTable<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;version&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;total codepoints&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;total chars&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;total other&#39;<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># for each version in DA_codepoints, get the corresponding values <\/span>\n<span class=\"c1\"># from DA_chars and DA_other. Produce running count of the values <\/span>\n<span class=\"c1\"># for each version.<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">v<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_codepoints<\/span><span class=\"o\">.<\/span><span class=\"n\">items<\/span><span class=\"p\">():<\/span>\n\n    <span class=\"n\">count_codepoints<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">DA_codepoints<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">count_chars<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">DA_chars<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">count_other<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">DA_other<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">DA_char_totals<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">([<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">DA_chars<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">),<\/span> <span class=\"n\">count_chars<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">DA_other_totals<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">([<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">DA_other<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">),<\/span> <span class=\"n\">count_other<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">DA_codepoint_totals<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">([<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">DA_codepoints<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"mi\">0<\/span><span class=\"p\">),<\/span> <span class=\"n\">count_codepoints<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"n\">z<\/span><span class=\"o\">.<\/span><span class=\"n\">add_row<\/span><span class=\"p\">([<\/span><span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">count_codepoints<\/span><span class=\"p\">,<\/span> <span class=\"n\">count_chars<\/span><span class=\"p\">,<\/span> <span class=\"n\">count_other<\/span><span class=\"p\">])<\/span>\n\n<span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>+---------+------------------+-------------+-------------+\n| version | total codepoints | total chars | total other |\n+---------+------------------+-------------+-------------+\n|   1.1   |      33979       |    27512    |     6467    |\n|   2.0   |      178500      |    38885    |    139615   |\n|   2.1   |      178502      |    38887    |    139615   |\n|   3.0   |      188809      |    49194    |    139615   |\n|   3.1   |      233787      |    94140    |    139647   |\n|   3.2   |      234803      |    95156    |    139647   |\n|   4.0   |      236029      |    96382    |    139647   |\n|   4.1   |      237302      |    97655    |    139647   |\n|   5.0   |      238671      |    99024    |    139647   |\n|   5.1   |      240295      |    100648   |    139647   |\n|   5.2   |      246943      |    107296   |    139647   |\n|   6.0   |      249031      |    109384   |    139647   |\n|   6.1   |      249763      |    110116   |    139647   |\n|   6.2   |      249764      |    110117   |    139647   |\n|   6.3   |      249769      |    110122   |    139647   |\n|   7.0   |      252603      |    112956   |    139647   |\n|   8.0   |      260319      |    120672   |    139647   |\n|   9.0   |      267819      |    128172   |    139647   |\n+---------+------------------+-------------+-------------+\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">z<\/span> <span class=\"o\">=<\/span> <span class=\"n\">PrettyTable<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;version&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;new codepoints&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;total codepoints&#39;<\/span><span class=\"p\">])<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">e<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_codepoint_totals<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">z<\/span><span class=\"o\">.<\/span><span class=\"n\">add_row<\/span><span class=\"p\">([<\/span><span class=\"n\">x<\/span> <span class=\"k\">for<\/span> <span class=\"n\">x<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">e<\/span><span class=\"p\">])<\/span>\n\n<span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>+---------+----------------+------------------+\n| version | new codepoints | total codepoints |\n+---------+----------------+------------------+\n|   1.1   |     33979      |      33979       |\n|   2.0   |     144521     |      178500      |\n|   2.1   |       2        |      178502      |\n|   3.0   |     10307      |      188809      |\n|   3.1   |     44978      |      233787      |\n|   3.2   |      1016      |      234803      |\n|   4.0   |      1226      |      236029      |\n|   4.1   |      1273      |      237302      |\n|   5.0   |      1369      |      238671      |\n|   5.1   |      1624      |      240295      |\n|   5.2   |      6648      |      246943      |\n|   6.0   |      2088      |      249031      |\n|   6.1   |      732       |      249763      |\n|   6.2   |       1        |      249764      |\n|   6.3   |       5        |      249769      |\n|   7.0   |      2834      |      252603      |\n|   8.0   |      7716      |      260319      |\n|   9.0   |      7500      |      267819      |\n+---------+----------------+------------------+\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">z<\/span> <span class=\"o\">=<\/span> <span class=\"n\">PrettyTable<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;version&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;new chars&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;total chars&#39;<\/span><span class=\"p\">])<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">e<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_char_totals<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">z<\/span><span class=\"o\">.<\/span><span class=\"n\">add_row<\/span><span class=\"p\">([<\/span><span class=\"n\">x<\/span> <span class=\"k\">for<\/span> <span class=\"n\">x<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">e<\/span><span class=\"p\">])<\/span>\n\n<span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>+---------+-----------+-------------+\n| version | new chars | total chars |\n+---------+-----------+-------------+\n|   1.1   |   27512   |    27512    |\n|   2.0   |   11373   |    38885    |\n|   2.1   |     2     |    38887    |\n|   3.0   |   10307   |    49194    |\n|   3.1   |   44946   |    94140    |\n|   3.2   |    1016   |    95156    |\n|   4.0   |    1226   |    96382    |\n|   4.1   |    1273   |    97655    |\n|   5.0   |    1369   |    99024    |\n|   5.1   |    1624   |    100648   |\n|   5.2   |    6648   |    107296   |\n|   6.0   |    2088   |    109384   |\n|   6.1   |    732    |    110116   |\n|   6.2   |     1     |    110117   |\n|   6.3   |     5     |    110122   |\n|   7.0   |    2834   |    112956   |\n|   8.0   |    7716   |    120672   |\n|   9.0   |    7500   |    128172   |\n+---------+-----------+-------------+\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">z<\/span> <span class=\"o\">=<\/span> <span class=\"n\">PrettyTable<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;version&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;new other&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;total other&#39;<\/span><span class=\"p\">])<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">e<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">DA_other_totals<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">z<\/span><span class=\"o\">.<\/span><span class=\"n\">add_row<\/span><span class=\"p\">([<\/span><span class=\"n\">x<\/span> <span class=\"k\">for<\/span> <span class=\"n\">x<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">e<\/span><span class=\"p\">])<\/span>\n\n<span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">z<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>+---------+-----------+-------------+\n| version | new other | total other |\n+---------+-----------+-------------+\n|   1.1   |    6467   |     6467    |\n|   2.0   |   133148  |    139615   |\n|   2.1   |     0     |    139615   |\n|   3.0   |     0     |    139615   |\n|   3.1   |     32    |    139647   |\n|   3.2   |     0     |    139647   |\n|   4.0   |     0     |    139647   |\n|   4.1   |     0     |    139647   |\n|   5.0   |     0     |    139647   |\n|   5.1   |     0     |    139647   |\n|   5.2   |     0     |    139647   |\n|   6.0   |     0     |    139647   |\n|   6.1   |     0     |    139647   |\n|   6.2   |     0     |    139647   |\n|   6.3   |     0     |    139647   |\n|   7.0   |     0     |    139647   |\n|   8.0   |     0     |    139647   |\n|   9.0   |     0     |    139647   |\n+---------+-----------+-------------+\n<\/code><\/pre><\/div>\n\n<h2>Commentary<\/h2>\n<p>This exercise helped us to analyze the number of codepoints added to Unicode over time&nbsp;using \n<code>DerivedAge.txt<\/code>. The data provides a high-level overview of the number and types of \ncodepoints that have been assigned. The <span class=\"caps\">UCD<\/span> contains other data that provide more details on \nthe characters, noncharacters, and other entities in the standard. I will explore these files \nin subsequent posts in order to expand our understanding of Unicode data through the \nUnicode Character&nbsp;Database.<\/p>","category":{"@attributes":{"term":"articles"}}},{"title":"Python function to transliterate\u00a0Devanagari","link":{"@attributes":{"href":"https:\/\/pandey.github.io\/posts\/transliterate-devanagari-to-latin.html","rel":"alternate"}},"published":"2016-09-15T00:00:00-05:00","updated":"2016-09-15T00:00:00-05:00","author":{"name":"Anshuman Pandey"},"id":"tag:pandey.github.io,2016-09-15:\/posts\/transliterate-devanagari-to-latin.html","summary":"<p>Transliteration between complex scripts and Latin often requires \nmore than a one-to-one mapping table. The underlying difficulty \narises from the typology of complex scripts, such as those of the \nIndic family, which are alpha-syllabic. One issue with transliterating \nIndic scripts to Latin is handling the inherent <em>a<\/em> of consonant letters \u2026<\/p>","content":"<p>Transliteration between complex scripts and Latin often requires \nmore than a one-to-one mapping table. The underlying difficulty \narises from the typology of complex scripts, such as those of the \nIndic family, which are alpha-syllabic. One issue with transliterating \nIndic scripts to Latin is handling the inherent <em>a<\/em> of consonant letters. \nIn some contexts, a consonant letter should be transliterated using only \nthe bare consonant, ie. <em>k<\/em>, <em>kh<\/em>, <em>g<\/em>, <em>gh<\/em>, <em>\u1e45<\/em>, while in others \nthe inherent <em>a<\/em> is required, ie. <em>ka<\/em>, <em>kha<\/em>, <em>ga<\/em>, <em>gha<\/em>, <em>\u1e45a<\/em>.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">re<\/span>\n<\/code><\/pre><\/div>\n\n<h2>Define conversion&nbsp;maps<\/h2>\n<p>Define mapping table as&nbsp;dictionary:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">conversiontable<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"s1\">&#39;\u0950&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;o\u1e41&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0900&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e41&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0901&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e43&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0902&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e43&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0903&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e25&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0905&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;a&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0906&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u0101&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0907&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;i&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0908&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u012b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0909&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;u&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u090a&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u016b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u090b&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;r\u0325&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0960&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39; r\u0325\u0304&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u090c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;l\u0325&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0961&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39; l\u0325\u0304&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u090d&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u00ea&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u090e&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;e&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u090f&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;e&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0910&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;ai&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0911&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u00f4&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0912&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;o&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0913&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;o&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0914&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;au&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u093e&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u0101&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u093f&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;i&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0940&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u012b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0941&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;u&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0942&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u016b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0943&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;r\u0325&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0944&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39; r\u0325\u0304&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0962&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;l\u0325&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0963&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39; l\u0325\u0304&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0945&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u00ea&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0947&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;e&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0948&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;ai&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0949&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u00f4&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u094b&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;o&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u094c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;au&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0915\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;q&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0915&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;k&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0916\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;x&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0916&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;kh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0917\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u0121&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0917&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;g&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u097b&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;g&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0918&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;gh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0919&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e45&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091a&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;c&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091b&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;ch&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091c\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;z&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;j&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u097c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;j&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091d&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;jh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091e&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u00f1&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u091f&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e6d&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0920&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e6dh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0921\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e5b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0921&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e0d&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0978&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e0d&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u097e&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;d&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0922\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e5bh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0922&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e0dh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0923&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e47&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0924&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;t&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0925&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;th&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0926&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;d&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0927&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;dh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0928&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;n&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092a&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;p&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092b\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;f&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092b&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;ph&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u097f&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092d&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;bh&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092e&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;m&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u092f&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;y&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0930&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;r&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0932&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;l&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0933&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e37&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0935&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;v&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0936&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u015b&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0937&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e63&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0938&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;s&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0939&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;h&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u093d&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\&#39;<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u094d&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u093c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0966&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;0&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0967&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;1&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0968&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;2&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0969&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;3&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u096a&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;4&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u096b&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;5&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u096c&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;6&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u096d&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;7&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u096e&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;8&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u096f&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;9&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\ua8f3&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;\u1e41&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0964&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;.&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39;\u0965&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39;..&#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"s1\">&#39; &#39;<\/span> <span class=\"p\">:<\/span> <span class=\"s1\">&#39; &#39;<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">}<\/span>\n<\/code><\/pre><\/div>\n\n<p>Define character&nbsp;classes:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">consonants<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0915<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0939\\u0958<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u095F\\u0978<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u097C\\u097E<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u097F<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">vowelsigns<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u093E<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u094C\\u093A<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u093B\\u094E<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u094F\\u0955<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0957<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">nukta<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u093C<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">virama<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u094D<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">devanagarichars<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0900<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u097F\\u1CD0<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CFF\\uA8E0<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\uA8FF<\/span><span class=\"s1\">&#39;<\/span>\n<\/code><\/pre><\/div>\n\n<h2>Define&nbsp;functions<\/h2>\n<h3>deva_to_latn()<\/h3>\n<p>Primary transliteration function. Performs the following general&nbsp;operations:<\/p>\n<ol>\n<li>Loops over each character in a&nbsp;word<\/li>\n<li>If character is a Devanagari character, then continue processing, otherwise go to next&nbsp;character<\/li>\n<li>Most characters can be transliterated by mapping to Latin characters in&nbsp;the <code>conversationtable<\/code> dictionary. Consonants need additional&nbsp;attention.<\/li>\n<li>Perform lookahead check to determine if an&nbsp;&#8216;<code>a<\/code><span class=\"quo\">&#8216;<\/span> needs to be appended after a&nbsp;consonant.<\/li>\n<\/ol>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">deva_to_latn<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"n\">word<\/span> <span class=\"o\">=<\/span> <span class=\"n\">text<\/span><span class=\"o\">.<\/span><span class=\"n\">strip<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c1\"># define a buffer to store the transliteration<\/span>\n    <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">index<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">enumerate<\/span><span class=\"p\">(<\/span><span class=\"n\">word<\/span><span class=\"p\">):<\/span>\n\n        <span class=\"c1\"># check if char is a Devanagari character. if true then continue processing.<\/span>\n        <span class=\"c1\"># otherwise, output char to curr<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">devanagarichars<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n\n            <span class=\"c1\"># if char = consonant, then its transliteration is dependent upon various<\/span>\n            <span class=\"c1\"># factors. need to check if next char = nukta, virama, vowel sign.<\/span>\n\n            <span class=\"k\">if<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">consonants<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n\n                <span class=\"c1\"># check next char<\/span>\n                <span class=\"n\">nextchar<\/span> <span class=\"o\">=<\/span> <span class=\"n\">word<\/span><span class=\"p\">[(<\/span><span class=\"n\">index<\/span> <span class=\"o\">+<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"o\">%<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">word<\/span><span class=\"p\">)]<\/span>\n\n                <span class=\"k\">if<\/span> <span class=\"n\">nextchar<\/span><span class=\"p\">:<\/span>\n\n                    <span class=\"c1\"># if next char = nukta, then add present char and nukta <\/span>\n                    <span class=\"c1\"># to &#39;cons&#39;. else just add present char. set variable<\/span>\n                    <span class=\"c1\"># to test for nukta when processing next char<\/span>\n\n                    <span class=\"k\">if<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">nukta<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">nextchar<\/span><span class=\"p\">):<\/span>\n                        <span class=\"n\">cons<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char<\/span> <span class=\"o\">+<\/span> <span class=\"n\">nextchar<\/span>\n                        <span class=\"n\">nukta_present<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span>\n                    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                        <span class=\"n\">cons<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char<\/span>\n                        <span class=\"n\">nukta_present<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n\n                    <span class=\"c1\"># if present char is nukta, then check next char<\/span>\n\n                    <span class=\"k\">if<\/span> <span class=\"n\">nukta_present<\/span><span class=\"p\">:<\/span>\n                        <span class=\"n\">nextchar<\/span> <span class=\"o\">=<\/span> <span class=\"n\">word<\/span><span class=\"p\">[(<\/span><span class=\"n\">index<\/span> <span class=\"o\">+<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"o\">%<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">word<\/span><span class=\"p\">)]<\/span>\n\n                    <span class=\"c1\"># if next char = combining sign or virama, convert consonant <\/span>\n                    <span class=\"c1\"># without &quot;a&quot;. else if next char != combining sign or virama, <\/span>\n                    <span class=\"c1\"># add &quot;a&quot; to consonant<\/span>\n\n                    <span class=\"k\">if<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">vowelsigns<\/span> <span class=\"o\">+<\/span> <span class=\"n\">virama<\/span> <span class=\"o\">+<\/span><span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">nextchar<\/span><span class=\"p\">):<\/span>\n                        <span class=\"n\">trans<\/span> <span class=\"o\">=<\/span> <span class=\"n\">conversiontable<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">cons<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">)<\/span>\n                        <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">trans<\/span>\n                    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                        <span class=\"n\">trans<\/span> <span class=\"o\">=<\/span> <span class=\"n\">conversiontable<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">cons<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">)<\/span>\n                        <span class=\"n\">trans<\/span> <span class=\"o\">=<\/span> <span class=\"n\">trans<\/span> <span class=\"o\">+<\/span> <span class=\"s2\">&quot;a&quot;<\/span>\n                        <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">trans<\/span>\n\n            <span class=\"c1\"># transliterate all other chars<\/span>\n\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">trans<\/span> <span class=\"o\">=<\/span> <span class=\"n\">conversiontable<\/span><span class=\"o\">.<\/span><span class=\"n\">get<\/span><span class=\"p\">(<\/span><span class=\"n\">char<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">trans<\/span>\n\n        <span class=\"c1\"># char is not Devanagari. output char to curr<\/span>\n\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n             <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">curr<\/span>\n<\/code><\/pre><\/div>\n\n<h3>getLatin()<\/h3>\n<p>Function that preprocesses Devanagari input and passes it&nbsp;to <code>deva_to_latn()<\/code><\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">getLatin<\/span><span class=\"p\">(<\/span><span class=\"n\">inputtext<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"n\">word_syllables<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"n\">all_words<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">word<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">inputtext<\/span><span class=\"o\">.<\/span><span class=\"n\">split<\/span><span class=\"p\">():<\/span>\n\n        <span class=\"n\">latin_output<\/span> <span class=\"o\">=<\/span> <span class=\"n\">deva_to_latn<\/span><span class=\"p\">(<\/span><span class=\"n\">word<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">all_words<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">latin_output<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">joined_all_words<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39; &#39;<\/span><span class=\"o\">.<\/span><span class=\"n\">join<\/span><span class=\"p\">(<\/span><span class=\"n\">all_words<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">joined_all_words<\/span>\n<\/code><\/pre><\/div>\n\n<h2>Test transliteration&nbsp;routines<\/h2>\n<p>Test some Sanskrit text in Devanagari with Vedic &#8216;accents&#8217;. Accents are ignored at&nbsp;present. <\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">text<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&quot;\u0905\u0952\u0917\u094d\u0928\u093f\u092e\u0940\u0951\u0933\u0947 \u092a\u0941\u0952\u0930\u094b\u0939\u093f\u0951\u0924\u0902 \u092f\u0952\u091c\u094d\u091e\u0938\u094d\u092f\u0951 \u0926\u0947\u0952\u0935\u092e\u0943\u0952\u0924\u094d\u0935\u093f\u091c\u0951\u092e\u094d\u0964 \u0939\u094b\u0924\u093e\u0951\u0930\u0902 \u0930\u0924\u094d\u0928\u0952\u0927\u093e\u0924\u0951\u092e\u092e\u094d\u0965&quot;<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">getLatin<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>&#39;agnim\u012b\u1e37e purohita\u1e43 yaj\u00f1asya devamr\u0325tvijam. hot\u0101ra\u1e43 ratnadh\u0101tamam..&#39;\n<\/code><\/pre><\/div>\n\n<p>Test some Hindi text. Word-final inherent&nbsp;&#8216;<code>a<\/code><span class=\"quo\">&#8216;<\/span> is generally not transliterated in modern&nbsp;Hindi.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">text<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&quot;\u0909\u0928\u094d\u0939\u0947\u0902 \u092c\u0941\u0926\u094d\u0927\u093f \u0914\u0930 \u0905\u0928\u094d\u0924\u0930\u093e\u0924\u094d\u092e\u093e \u0915\u0940 \u0926\u0947\u0928 \u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0939\u0948 \u0914\u0930 \u092a\u0930\u0938\u094d\u092a\u0930 \u0909\u0928\u094d\u0939\u0947\u0902 \u092d\u093e\u0908\u091a\u093e\u0930\u0947 \u0915\u0947 \u092d\u093e\u0935 \u0938\u0947 \u092c\u0930\u094d\u0924\u093e\u0935 \u0915\u0930\u0928\u093e \u091a\u093e\u0939\u093f\u090f&quot;<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">getLatin<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>&#39;unhe\u1e43 buddhi aura antar\u0101tm\u0101 k\u012b dena pr\u0101pta hai aura paraspara unhe\u1e43 bh\u0101\u012bc\u0101re ke bh\u0101va se bart\u0101va karan\u0101 c\u0101hie&#39;\n<\/code><\/pre><\/div>\n\n<p>Test some mixed script&nbsp;text.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">text<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&quot;This is in the \u0926\u0947\u0935\u0928\u093e\u0917\u0930\u0940 script&quot;<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">getLatin<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>&#39;This is in the devan\u0101gar\u012b script&#39;\n<\/code><\/pre><\/div>\n\n<h1>Next&nbsp;steps<\/h1>\n<p>The <code>deva_to_latn()<\/code> function can be adapted for transliterating other Indic&nbsp;scripts.<\/p>","category":{"@attributes":{"term":"articles"}}},{"title":"Tokenizing Indic strings by syllables in\u00a0Python","link":{"@attributes":{"href":"https:\/\/pandey.github.io\/posts\/tokenize-indic-syllables-python.html","rel":"alternate"}},"published":"2016-09-05T00:00:00-05:00","updated":"2016-09-05T00:00:00-05:00","author":{"name":"Anshuman Pandey"},"id":"tag:pandey.github.io,2016-09-05:\/posts\/tokenize-indic-syllables-python.html","summary":"<p>Processing text in non-Latin scripts in Python has become much easier on account \nof the native support for Unicode in version 3. There are still some challenges, \nbut these are issues related more to individual writing systems than to Python. \nOne such issue is the manner in which strings of \u2026<\/p>","content":"<p>Processing text in non-Latin scripts in Python has become much easier on account \nof the native support for Unicode in version 3. There are still some challenges, \nbut these are issues related more to individual writing systems than to Python. \nOne such issue is the manner in which strings of various script typologies are \nhandled. While handling strings in <em>alphabetic<\/em> systems, such as the Latin \nscript in which this post is written, is relatively straightforward, scripts \nthat have an <em>alpha-syllabic<\/em> structure often require additional&nbsp;processing. <\/p>\n<p>For instance, the string &#8220;English&#8221; has the following number of&nbsp;characters:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;English&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"mf\">7<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"nb\">list<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;English&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;E&#39;, &#39;n&#39;, &#39;g&#39;, &#39;l&#39;, &#39;i&#39;, &#39;s&#39;, &#39;h&#39;]\n<\/code><\/pre><\/div>\n\n<p>Now consider the string &#8216;\u0926\u0947\u0935\u0928\u093e\u0917\u0930\u0940&#8217;, which contains characters from the Devanagari script, \nwhich is part of the large &#8216;Indic&#8217; family of writing&nbsp;systems:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;\u0926\u0947\u0935\u0928\u093e\u0917\u0930\u0940&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"mf\">8<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"nb\">list<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;\u0926\u0947\u0935\u0928\u093e\u0917\u0930\u0940&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;\u0926&#39;, &#39;\u0947&#39;, &#39;\u0935&#39;, &#39;\u0928&#39;, &#39;\u093e&#39;, &#39;\u0917&#39;, &#39;\u0930&#39;, &#39;\u0940&#39;]\n<\/code><\/pre><\/div>\n\n<p>Seems reasonable, doesn&#8217;t it? At some level: yes. For practical purposes:&nbsp;no.<\/p>\n<p>For Indic scripts, parsing a string by its characters is not as meaningful as it is in Latin. The reason is that Indic scripts are alphasyllabic \nwriting systems, while Latin is an alphabetic system. For alphasyllabic types, \ninstead of individual characters, the basic orthographic unit that carries meaning \nis the syllable. For effective text processing, the Devanagari string should be analyzed&nbsp;as:<\/p>\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;\u0926\u0947&#39;, &#39;\u0935&#39;, &#39;\u0928\u093e&#39;, &#39;\u0917&#39;, &#39;\u0930\u0940&#39;]\n<\/code><\/pre><\/div>\n\n<p>Let&#8217;s find an approach to tokenize Indic strings by syllables in&nbsp;Python.<\/p>\n<h2>Approach<\/h2>\n<p>Import&nbsp;the <code>re<\/code> module for processing regular&nbsp;expressions.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">re<\/span>\n<\/code><\/pre><\/div>\n\n<h3>Define character&nbsp;classes<\/h3>\n<p>An orthographic syllable may be defined in terms of character classes. Each syllable has a base, which is either an independent vowel letter or consonant letter. One or more combining signs may attach to a base. Analyze the Unicode Devanagari charts and classify&nbsp;characters.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">vowels<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0904<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0914\\u0960<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0961\\u0972<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0977<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">consonants<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0915<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0939\\u0958<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u095F\\u0978<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u097C\\u097E<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u097F<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">glottal<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u097D<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">vowel_signs<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u093E<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u094C\\u093A<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u093B\\u094E<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u094F\\u0955<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0957\\u1CF8<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CF9<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">nasals<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0900<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0902\\u1CF2<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CF6<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">visarga<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0903<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">nukta<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u093C<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">avagraha<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u093D<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">virama<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u094D<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">vedic_signs<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0951<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0952\\u1CD0<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CE1\\u1CED<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">visarga_modifiers<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u1CE2<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CE8<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">combining<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\uA8E0<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\uA8F1<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">om<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0950<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">accents<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0953<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0954<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">dandas<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0964<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u0965<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">digits<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0966<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u096F<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">abbreviation<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0970<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">spacing<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0971<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">vedic_nasals<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\uA8F2<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\uA8F7\\u1CE9<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CEC\\u1CEE<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u1CF1<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">fillers<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\uA8F8<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\uA8F9<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">caret<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\uA8FA<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">headstroke<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\uA8FB<\/span><span class=\"s1\">&#39;<\/span>\n\n<span class=\"n\">space<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u0020<\/span><span class=\"s1\">&#39;<\/span>\n<span class=\"n\">joiners<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u200C<\/span><span class=\"s1\">-<\/span><span class=\"se\">\\u200D<\/span><span class=\"s1\">&#39;<\/span>\n<\/code><\/pre><\/div>\n\n<h3>Define&nbsp;functions<\/h3>\n<p><strong>syllabify()<\/strong> : the basic syllable tokenization&nbsp;function.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">syllabify<\/span><span class=\"p\">(<\/span><span class=\"n\">inputtext<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"n\">syllables<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n\n    <span class=\"c1\"># iterate over each character in the input. if a char belongs to a <\/span>\n    <span class=\"c1\"># class that can be part of a syllable, then add it to the curr <\/span>\n    <span class=\"c1\"># buffer. otherwise, output it to syllables[] right away.<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">char<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">inputtext<\/span><span class=\"p\">:<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">vowels<\/span> <span class=\"o\">+<\/span> <span class=\"n\">avagraha<\/span> <span class=\"o\">+<\/span> <span class=\"n\">glottal<\/span> <span class=\"o\">+<\/span> <span class=\"n\">om<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n\n            <span class=\"c1\"># need to handle non-initial independent vowel letters,<\/span>\n            <span class=\"c1\"># avagraha, and om<\/span>\n\n            <span class=\"k\">if<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">!=<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char<\/span>\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">consonants<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n\n            <span class=\"c1\"># if last in curr is not virama, output curr as syllable<\/span>\n            <span class=\"c1\"># else add present consonant to curr<\/span>\n\n            <span class=\"k\">if<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">curr<\/span><span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">virama<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">char<\/span>\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">vowel_signs<\/span> <span class=\"o\">+<\/span> <span class=\"n\">visarga<\/span> <span class=\"o\">+<\/span> <span class=\"n\">vedic_signs<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n            <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">visarga_modifiers<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n\n            <span class=\"k\">if<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">curr<\/span><span class=\"p\">[<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"n\">visarga<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n                <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">nasals<\/span> <span class=\"o\">+<\/span> <span class=\"n\">vedic_nasals<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n\n            <span class=\"c1\"># if last in curr is a vowel sign, output curr as syllable<\/span>\n            <span class=\"c1\"># else add present vowel modifier to curr and output as syllable<\/span>\n\n            <span class=\"n\">vowelsign<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">vowel_signs<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]$&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n            <span class=\"k\">if<\/span> <span class=\"n\">vowelsign<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n                <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n                <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">nukta<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n            <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">virama<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n            <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">digits<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n            <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">fillers<\/span> <span class=\"o\">+<\/span> <span class=\"n\">headstroke<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n            <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">char<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"k\">elif<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">match<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[&#39;<\/span> <span class=\"o\">+<\/span> <span class=\"n\">joiners<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">char<\/span><span class=\"p\">):<\/span>\n            <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">+<\/span> <span class=\"n\">char<\/span>\n\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"k\">pass<\/span>\n            <span class=\"c1\">#print (&quot;unhandled: &quot; + char + &quot; &quot;, char.encode(&#39;unicode_escape&#39;))<\/span>\n\n    <span class=\"c1\"># handle remaining curr<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">curr<\/span> <span class=\"o\">!=<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">syllables<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">curr<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">curr<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n\n    <span class=\"c1\"># return each syllable as item in a list<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">syllables<\/span>\n<\/code><\/pre><\/div>\n\n<p><strong>getSyllables()<\/strong> : splits input string into words and passes them to&nbsp;syllabify().<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">getSyllables<\/span><span class=\"p\">(<\/span><span class=\"n\">inputtext<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"n\">word_syllables<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"n\">all_words<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">word<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">inputtext<\/span><span class=\"o\">.<\/span><span class=\"n\">split<\/span><span class=\"p\">():<\/span>\n\n        <span class=\"n\">word<\/span> <span class=\"o\">=<\/span> <span class=\"n\">word<\/span><span class=\"o\">.<\/span><span class=\"n\">strip<\/span><span class=\"p\">()<\/span>\n        <span class=\"n\">word<\/span> <span class=\"o\">=<\/span> <span class=\"n\">re<\/span><span class=\"o\">.<\/span><span class=\"n\">sub<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;[\\s<\/span><span class=\"se\">\\n\\u0964\\u0965<\/span><span class=\"s1\">\\.]&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;&#39;<\/span><span class=\"p\">,<\/span> <span class=\"n\">word<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"n\">word_syllables<\/span> <span class=\"o\">=<\/span> <span class=\"n\">syllabify<\/span><span class=\"p\">(<\/span><span class=\"n\">word<\/span><span class=\"p\">)<\/span>\n        <span class=\"c1\">#number_syllables = len(word_syllables)<\/span>\n\n        <span class=\"c1\">#joined_syllables = &#39;\\u00B7&#39;.join(word_syllables)<\/span>\n        <span class=\"n\">joined_syllables<\/span> <span class=\"o\">=<\/span> <span class=\"n\">word_syllables<\/span>\n\n        <span class=\"c1\"># make list of lists containing each word<\/span>\n        <span class=\"c1\">#all_words.append([word, joined_syllables, number_syllables])<\/span>\n        <span class=\"n\">all_words<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">([<\/span><span class=\"n\">word<\/span><span class=\"p\">,<\/span> <span class=\"n\">joined_syllables<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">all_words<\/span>\n<\/code><\/pre><\/div>\n\n<p><strong>getSyllableStats()<\/strong> : get number of unique words and syllables in input&nbsp;text.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">getSyllableStats<\/span><span class=\"p\">(<\/span><span class=\"n\">inputtext<\/span><span class=\"p\">):<\/span>\n\n    <span class=\"n\">syllcount<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n    <span class=\"n\">wordcount<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n    <span class=\"n\">word<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n    <span class=\"n\">syllable<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n    <span class=\"n\">count<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;&#39;<\/span>\n    <span class=\"n\">syllablestatus<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{}<\/span>\n\n    <span class=\"n\">words<\/span> <span class=\"o\">=<\/span> <span class=\"n\">getSyllables<\/span><span class=\"p\">(<\/span><span class=\"n\">inputtext<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">entry<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">words<\/span><span class=\"p\">:<\/span>\n\n        <span class=\"n\">word<\/span> <span class=\"o\">=<\/span> <span class=\"n\">entry<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n        <span class=\"n\">syllables<\/span> <span class=\"o\">=<\/span> <span class=\"n\">entry<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n        <span class=\"c1\">#count = entry[2]<\/span>\n\n        <span class=\"c1\">#word_syllables = syllables.split(&#39;\\u00B7&#39;)<\/span>\n        <span class=\"n\">word_syllables<\/span> <span class=\"o\">=<\/span> <span class=\"n\">syllables<\/span>\n\n        <span class=\"c1\"># count all words in input<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">word<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">wordcount<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">wordcount<\/span><span class=\"p\">[<\/span><span class=\"n\">word<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"mi\">1<\/span>\n        <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n            <span class=\"n\">wordcount<\/span><span class=\"p\">[<\/span><span class=\"n\">word<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span>\n\n        <span class=\"c1\"># count all syllables in input<\/span>\n        <span class=\"k\">for<\/span> <span class=\"n\">syll<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">word_syllables<\/span><span class=\"p\">:<\/span>\n            <span class=\"k\">if<\/span> <span class=\"n\">syll<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">syllcount<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">syllcount<\/span><span class=\"p\">[<\/span><span class=\"n\">syll<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"mi\">1<\/span>\n            <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n                <span class=\"n\">syllcount<\/span><span class=\"p\">[<\/span><span class=\"n\">syll<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span>\n\n    <span class=\"n\">syllablestatus<\/span><span class=\"o\">.<\/span><span class=\"n\">update<\/span><span class=\"p\">({<\/span><span class=\"s1\">&#39;words&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"n\">wordcount<\/span><span class=\"p\">})<\/span>\n    <span class=\"n\">syllablestatus<\/span><span class=\"o\">.<\/span><span class=\"n\">update<\/span><span class=\"p\">({<\/span><span class=\"s1\">&#39;syllables&#39;<\/span> <span class=\"p\">:<\/span> <span class=\"n\">syllcount<\/span><span class=\"p\">})<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"p\">(<\/span><span class=\"n\">syllablestatus<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<h2>Test the&nbsp;functions<\/h2>\n<p>Some text in&nbsp;Sanskrit<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">text<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&quot;\u0905\u0952\u0917\u094d\u0928\u093f\u092e\u0940\u0951\u0933\u0947 \u092a\u0941\u0952\u0930\u094b\u0939\u093f\u0951\u0924\u0902 \u092f\u0952\u091c\u094d\u091e\u0938\u094d\u092f\u0951 \u0926\u0947\u0952\u0935\u092e\u0943\u0952\u0924\u094d\u0935\u093f\u091c\u0951\u092e\u094d\u0964 \u0939\u094b\u0924\u093e\u0951\u0930\u0902 \u0930\u0924\u094d\u0928\u0952\u0927\u093e\u0924\u0951\u092e\u092e\u094d\u0965&quot;<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">syllabify<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;\u0905\u0952&#39;,\n &#39;\u0917\u094d\u0928\u093f&#39;,\n &#39;\u092e\u0940\u0951&#39;,\n &#39;\u0933\u0947&#39;,\n &#39;\u092a\u0941\u0952&#39;,\n &#39;\u0930\u094b&#39;,\n &#39;\u0939\u093f\u0951&#39;,\n &#39;\u0924\u0902&#39;,\n &#39;\u092f\u0952&#39;,\n &#39;\u091c\u094d\u091e&#39;,\n &#39;\u0938\u094d\u092f\u0951&#39;,\n &#39;\u0926\u0947\u0952&#39;,\n &#39;\u0935&#39;,\n &#39;\u092e\u0943\u0952&#39;,\n &#39;\u0924\u094d\u0935\u093f&#39;,\n &#39;\u091c\u0951&#39;,\n &#39;\u092e\u094d\u0939\u094b&#39;,\n &#39;\u0924\u093e\u0951&#39;,\n &#39;\u0930\u0902&#39;,\n &#39;\u0930&#39;,\n &#39;\u0924\u094d\u0928\u0952&#39;,\n &#39;\u0927\u093e&#39;,\n &#39;\u0924\u0951&#39;,\n &#39;\u092e&#39;,\n &#39;\u092e\u094d&#39;]\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">results<\/span> <span class=\"o\">=<\/span> <span class=\"n\">getSyllables<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">x<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">results<\/span><span class=\"p\">:<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"s2\">&quot;:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u00B7<\/span><span class=\"s1\">&#39;<\/span><span class=\"o\">.<\/span><span class=\"n\">join<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]),<\/span> <span class=\"s2\">&quot;:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]))<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>\u0905\u0952\u0917\u094d\u0928\u093f\u092e\u0940\u0951\u0933\u0947 : \u0905\u0952\u00b7\u0917\u094d\u0928\u093f\u00b7\u092e\u0940\u0951\u00b7\u0933\u0947 : 4\n\u092a\u0941\u0952\u0930\u094b\u0939\u093f\u0951\u0924\u0902 : \u092a\u0941\u0952\u00b7\u0930\u094b\u00b7\u0939\u093f\u0951\u00b7\u0924\u0902 : 4\n\u092f\u0952\u091c\u094d\u091e\u0938\u094d\u092f\u0951 : \u092f\u0952\u00b7\u091c\u094d\u091e\u00b7\u0938\u094d\u092f\u0951 : 3\n\u0926\u0947\u0952\u0935\u092e\u0943\u0952\u0924\u094d\u0935\u093f\u091c\u0951\u092e\u094d : \u0926\u0947\u0952\u00b7\u0935\u00b7\u092e\u0943\u0952\u00b7\u0924\u094d\u0935\u093f\u00b7\u091c\u0951\u00b7\u092e\u094d : 6\n\u0939\u094b\u0924\u093e\u0951\u0930\u0902 : \u0939\u094b\u00b7\u0924\u093e\u0951\u00b7\u0930\u0902 : 3\n\u0930\u0924\u094d\u0928\u0952\u0927\u093e\u0924\u0951\u092e\u092e\u094d : \u0930\u00b7\u0924\u094d\u0928\u0952\u00b7\u0927\u093e\u00b7\u0924\u0951\u00b7\u092e\u00b7\u092e\u094d : 6\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"kn\">from<\/span><span class=\"w\"> <\/span><span class=\"nn\">IPython.display<\/span><span class=\"w\"> <\/span><span class=\"kn\">import<\/span> <span class=\"n\">HTML<\/span><span class=\"p\">,<\/span> <span class=\"n\">display<\/span>\n<span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">tabulate<\/span>\n<span class=\"n\">display<\/span><span class=\"p\">(<\/span><span class=\"n\">HTML<\/span><span class=\"p\">(<\/span><span class=\"n\">tabulate<\/span><span class=\"o\">.<\/span><span class=\"n\">tabulate<\/span><span class=\"p\">(<\/span><span class=\"n\">results<\/span><span class=\"p\">,<\/span> <span class=\"n\">tablefmt<\/span><span class=\"o\">=<\/span><span class=\"s1\">&#39;html&#39;<\/span><span class=\"p\">)))<\/span>\n<\/code><\/pre><\/div>\n\n<table>\n<tbody>\n<tr><td>\u0905\u0952\u0917\u094d\u0928\u093f\u092e\u0940\u0951\u0933\u0947 <\/td><td>[&#8216;\u0905\u0952&#8217;, &#8216;\u0917\u094d\u0928\u093f&#8217;, &#8216;\u092e\u0940\u0951&#8217;, &#8216;\u0933\u0947&#8217;]         <\/td><\/tr>\n<tr><td>\u092a\u0941\u0952\u0930\u094b\u0939\u093f\u0951\u0924\u0902  <\/td><td>[&#8216;\u092a\u0941\u0952&#8217;, &#8216;\u0930\u094b&#8217;, &#8216;\u0939\u093f\u0951&#8217;, &#8216;\u0924\u0902&#8217;]          <\/td><\/tr>\n<tr><td>\u092f\u0952\u091c\u094d\u091e\u0938\u094d\u092f\u0951   <\/td><td>[&#8216;\u092f\u0952&#8217;, &#8216;\u091c\u094d\u091e&#8217;, &#8216;\u0938\u094d\u092f\u0951&#8217;]               <\/td><\/tr>\n<tr><td>\u0926\u0947\u0952\u0935\u092e\u0943\u0952\u0924\u094d\u0935\u093f\u091c\u0951\u092e\u094d<\/td><td>[&#8216;\u0926\u0947\u0952&#8217;, &#8216;\u0935&#8217;, &#8216;\u092e\u0943\u0952&#8217;, &#8216;\u0924\u094d\u0935\u093f&#8217;, &#8216;\u091c\u0951&#8217;, &#8216;\u092e\u094d&#8217;]<\/td><\/tr>\n<tr><td>\u0939\u094b\u0924\u093e\u0951\u0930\u0902   <\/td><td>[&#8216;\u0939\u094b&#8217;, &#8216;\u0924\u093e\u0951&#8217;, &#8216;\u0930\u0902&#8217;]               <\/td><\/tr>\n<tr><td>\u0930\u0924\u094d\u0928\u0952\u0927\u093e\u0924\u0951\u092e\u092e\u094d<\/td><td>[&#8216;\u0930&#8217;, &#8216;\u0924\u094d\u0928\u0952&#8217;, &#8216;\u0927\u093e&#8217;, &#8216;\u0924\u0951&#8217;, &#8216;\u092e&#8217;, &#8216;\u092e\u094d&#8217;]<\/td><\/tr>\n<\/tbody>\n<\/table>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">stats<\/span> <span class=\"o\">=<\/span> <span class=\"n\">getSyllableStats<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">for<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">v<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">stats<\/span><span class=\"o\">.<\/span><span class=\"n\">items<\/span><span class=\"p\">():<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">x<\/span><span class=\"p\">,<\/span> <span class=\"n\">y<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">v<\/span><span class=\"o\">.<\/span><span class=\"n\">items<\/span><span class=\"p\">():<\/span>\n        <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s2\">&quot;<\/span><span class=\"se\">\\t<\/span><span class=\"s2\">&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">x<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">y<\/span><span class=\"p\">)<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s2\">&quot;total&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;=&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">v<\/span><span class=\"o\">.<\/span><span class=\"n\">values<\/span><span class=\"p\">()))<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s2\">&quot;unique&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;=&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">v<\/span><span class=\"p\">),<\/span> <span class=\"n\">end<\/span><span class=\"o\">=<\/span><span class=\"s1\">&#39;<\/span><span class=\"se\">\\n\\n<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>words\n     \u0905\u0952\u0917\u094d\u0928\u093f\u092e\u0940\u0951\u0933\u0947 : 1\n     \u092a\u0941\u0952\u0930\u094b\u0939\u093f\u0951\u0924\u0902 : 1\n     \u092f\u0952\u091c\u094d\u091e\u0938\u094d\u092f\u0951 : 1\n     \u0926\u0947\u0952\u0935\u092e\u0943\u0952\u0924\u094d\u0935\u093f\u091c\u0951\u092e\u094d : 1\n     \u0939\u094b\u0924\u093e\u0951\u0930\u0902 : 1\n     \u0930\u0924\u094d\u0928\u0952\u0927\u093e\u0924\u0951\u092e\u092e\u094d : 1\ntotal words = 6\nunique words = 6\n\nsyllables\n     \u0905\u0952 : 1\n     \u0917\u094d\u0928\u093f : 1\n     \u092e\u0940\u0951 : 1\n     \u0933\u0947 : 1\n     \u092a\u0941\u0952 : 1\n     \u0930\u094b : 1\n     \u0939\u093f\u0951 : 1\n     \u0924\u0902 : 1\n     \u092f\u0952 : 1\n     \u091c\u094d\u091e : 1\n     \u0938\u094d\u092f\u0951 : 1\n     \u0926\u0947\u0952 : 1\n     \u0935 : 1\n     \u092e\u0943\u0952 : 1\n     \u0924\u094d\u0935\u093f : 1\n     \u091c\u0951 : 1\n     \u092e\u094d : 2\n     \u0939\u094b : 1\n     \u0924\u093e\u0951 : 1\n     \u0930\u0902 : 1\n     \u0930 : 1\n     \u0924\u094d\u0928\u0952 : 1\n     \u0927\u093e : 1\n     \u0924\u0951 : 1\n     \u092e : 1\ntotal syllables = 26\nunique syllables = 25\n<\/code><\/pre><\/div>\n\n<p>Some text in&nbsp;Hindi<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">text<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&quot;\u0909\u0928\u094d\u0939\u0947\u0902 \u092c\u0941\u0926\u094d\u0927\u093f \u0914\u0930 \u0905\u0928\u094d\u0924\u0930\u093e\u0924\u094d\u092e\u093e \u0915\u0940 \u0926\u0947\u0928 \u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0939\u0948 \u0914\u0930 \u092a\u0930\u0938\u094d\u092a\u0930 \u0909\u0928\u094d\u0939\u0947\u0902 \u092d\u093e\u0908\u091a\u093e\u0930\u0947 \u0915\u0947 \u092d\u093e\u0935 \u0938\u0947 \u092c\u0930\u094d\u0924\u093e\u0935 \u0915\u0930\u0928\u093e \u091a\u093e\u0939\u093f\u090f&quot;<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">results<\/span> <span class=\"o\">=<\/span> <span class=\"n\">getSyllables<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">for<\/span> <span class=\"n\">x<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">results<\/span><span class=\"p\">:<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">],<\/span> <span class=\"s2\">&quot;:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;<\/span><span class=\"se\">\\u00B7<\/span><span class=\"s1\">&#39;<\/span><span class=\"o\">.<\/span><span class=\"n\">join<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]),<\/span> <span class=\"s2\">&quot;:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]))<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>\u0909\u0928\u094d\u0939\u0947\u0902 : \u0909\u00b7\u0928\u094d\u0939\u0947\u0902 : 2\n\u092c\u0941\u0926\u094d\u0927\u093f : \u092c\u0941\u00b7\u0926\u094d\u0927\u093f : 2\n\u0914\u0930 : \u0914\u00b7\u0930 : 2\n\u0905\u0928\u094d\u0924\u0930\u093e\u0924\u094d\u092e\u093e : \u0905\u00b7\u0928\u094d\u0924\u00b7\u0930\u093e\u00b7\u0924\u094d\u092e\u093e : 4\n\u0915\u0940 : \u0915\u0940 : 1\n\u0926\u0947\u0928 : \u0926\u0947\u00b7\u0928 : 2\n\u092a\u094d\u0930\u093e\u092a\u094d\u0924 : \u092a\u094d\u0930\u093e\u00b7\u092a\u094d\u0924 : 2\n\u0939\u0948 : \u0939\u0948 : 1\n\u0914\u0930 : \u0914\u00b7\u0930 : 2\n\u092a\u0930\u0938\u094d\u092a\u0930 : \u092a\u00b7\u0930\u00b7\u0938\u094d\u092a\u00b7\u0930 : 4\n\u0909\u0928\u094d\u0939\u0947\u0902 : \u0909\u00b7\u0928\u094d\u0939\u0947\u0902 : 2\n\u092d\u093e\u0908\u091a\u093e\u0930\u0947 : \u092d\u093e\u00b7\u0908\u00b7\u091a\u093e\u00b7\u0930\u0947 : 4\n\u0915\u0947 : \u0915\u0947 : 1\n\u092d\u093e\u0935 : \u092d\u093e\u00b7\u0935 : 2\n\u0938\u0947 : \u0938\u0947 : 1\n\u092c\u0930\u094d\u0924\u093e\u0935 : \u092c\u00b7\u0930\u094d\u0924\u093e\u00b7\u0935 : 3\n\u0915\u0930\u0928\u093e : \u0915\u00b7\u0930\u00b7\u0928\u093e : 3\n\u091a\u093e\u0939\u093f\u090f : \u091a\u093e\u00b7\u0939\u093f\u00b7\u090f : 3\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">stats<\/span> <span class=\"o\">=<\/span> <span class=\"n\">getSyllableStats<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">for<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"n\">v<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">stats<\/span><span class=\"o\">.<\/span><span class=\"n\">items<\/span><span class=\"p\">():<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"n\">k<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">x<\/span><span class=\"p\">,<\/span> <span class=\"n\">y<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">v<\/span><span class=\"o\">.<\/span><span class=\"n\">items<\/span><span class=\"p\">():<\/span>\n        <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s2\">&quot;<\/span><span class=\"se\">\\t<\/span><span class=\"s2\">&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">x<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;:&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">y<\/span><span class=\"p\">)<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s2\">&quot;total&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;=&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">sum<\/span><span class=\"p\">(<\/span><span class=\"n\">v<\/span><span class=\"o\">.<\/span><span class=\"n\">values<\/span><span class=\"p\">()))<\/span>\n    <span class=\"nb\">print<\/span> <span class=\"p\">(<\/span><span class=\"s2\">&quot;unique&quot;<\/span><span class=\"p\">,<\/span> <span class=\"n\">k<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;=&quot;<\/span><span class=\"p\">,<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">v<\/span><span class=\"p\">),<\/span> <span class=\"n\">end<\/span><span class=\"o\">=<\/span><span class=\"s1\">&#39;<\/span><span class=\"se\">\\n\\n<\/span><span class=\"s1\">&#39;<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>words\n     \u0909\u0928\u094d\u0939\u0947\u0902 : 2\n     \u092c\u0941\u0926\u094d\u0927\u093f : 1\n     \u0914\u0930 : 2\n     \u0905\u0928\u094d\u0924\u0930\u093e\u0924\u094d\u092e\u093e : 1\n     \u0915\u0940 : 1\n     \u0926\u0947\u0928 : 1\n     \u092a\u094d\u0930\u093e\u092a\u094d\u0924 : 1\n     \u0939\u0948 : 1\n     \u092a\u0930\u0938\u094d\u092a\u0930 : 1\n     \u092d\u093e\u0908\u091a\u093e\u0930\u0947 : 1\n     \u0915\u0947 : 1\n     \u092d\u093e\u0935 : 1\n     \u0938\u0947 : 1\n     \u092c\u0930\u094d\u0924\u093e\u0935 : 1\n     \u0915\u0930\u0928\u093e : 1\n     \u091a\u093e\u0939\u093f\u090f : 1\ntotal words = 18\nunique words = 16\n\nsyllables\n     \u0909 : 2\n     \u0928\u094d\u0939\u0947\u0902 : 2\n     \u092c\u0941 : 1\n     \u0926\u094d\u0927\u093f : 1\n     \u0914 : 2\n     \u0930 : 5\n     \u0905 : 1\n     \u0928\u094d\u0924 : 1\n     \u0930\u093e : 1\n     \u0924\u094d\u092e\u093e : 1\n     \u0915\u0940 : 1\n     \u0926\u0947 : 1\n     \u0928 : 1\n     \u092a\u094d\u0930\u093e : 1\n     \u092a\u094d\u0924 : 1\n     \u0939\u0948 : 1\n     \u092a : 1\n     \u0938\u094d\u092a : 1\n     \u092d\u093e : 2\n     \u0908 : 1\n     \u091a\u093e : 2\n     \u0930\u0947 : 1\n     \u0915\u0947 : 1\n     \u0935 : 2\n     \u0938\u0947 : 1\n     \u092c : 1\n     \u0930\u094d\u0924\u093e : 1\n     \u0915 : 1\n     \u0928\u093e : 1\n     \u0939\u093f : 1\n     \u090f : 1\ntotal syllables = 41\nunique syllables = 31\n<\/code><\/pre><\/div>\n\n<h3>Edge&nbsp;cases<\/h3>\n<p>The presence of <span class=\"caps\">ZWJ<\/span> or <span class=\"caps\">ZWNJ<\/span> after virama might suggest the termination of a grapheme&nbsp;cluster.<\/p>\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">text<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">&#39;\u0915\u094d\u0915 \u0915\u094d\u200d\u0915 \u0915\u094d\u200c\u0915&#39;<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code><span class=\"n\">syllabify<\/span><span class=\"p\">(<\/span><span class=\"n\">text<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>\n\n<div class=\"highlight\"><pre><span><\/span><code>[&#39;\u0915\u094d\u0915&#39;, &#39;\u0915\u094d\\u200d&#39;, &#39;\u0915&#39;, &#39;\u0915\u094d\\u200c&#39;, &#39;\u0915&#39;]\n<\/code><\/pre><\/div>\n\n<h2>Next&nbsp;steps<\/h2>\n<p>The issue with the above approach is that it requires manual definition of character classes. This is suitable for a single script. But, if a use case requires analysis of, say, all twenty-two official languages of India, then there will be a need to handle not just Devanagari, but up to ten additional scripts. The upside is that these additional scripts are based upon the same orthographic structure as Devanagari, but the downside is that each script has its own features. In an upcoming post, I will show how to derive character classes programmatically from the Unicode Character&nbsp;Database.<\/p>","category":{"@attributes":{"term":"articles"}}}]}