Friday, October 7, 2022

Reversing a Odia Unicode String

Odia is a language with lot of combining characters. Therefore simple reversal of string like str.split('').reverse().join('') will not work . With this naive approach, the reverse of string like ଜଳାର୍ଣ୍ଣବ will end up in ବଣ୍ଣ୍ରାଳଜ where as the expected reversal would be ବର୍ଣ୍ଣଳାଜ. 

Even I failed with BreakIterator of Java with Odia Locale. I also tried packages like esrever but failed. Finally I tried with basic decomposition of Unicode Odia syllables. A string like ଜଳାର୍ଣ୍ଣବ is composed of characters like [  'ଜ', 'ଳ', 'ା', 'ର',  '୍',  'ଣ', '୍',  'ଣ',  'ବ' ], therefore handling the matras and falas did the job. Here is the code in JavaScript: 

function reverseOdia(str)
{
   var reverseStr = "" ;
   var chars = [...str] ;
   var maatraas = "ାିୀୁୂୃେୈୋୌଂଁ";
   var isEnd = false ;
   syllable = "" ;
   for (let index = 0; index < str.length; index++) {
      char = str[index] ;
      nextChar = str[index+1] ;
      syllable += char ;
      if (maatraas.indexOf(nextChar) != -1 ) {
         syllable += nextChar ;
         index++ ;
         isEnd = true ;
      }
      else {
         if( nextChar == '୍') {
            isEnd = false ;
            syllable += nextChar ;
            index++ ;
         }
         else {
            isEnd = true ;
         }
      }
      if (isEnd)
      {
         reverseStr = syllable + reverseStr ;
         syllable = "" ;
      }
   }
   return reverseStr ;
}

str = "ଜଳାର୍ଣ୍ଣବ" ; // କଟକ // ଅସତ୍‌କର୍ମ // ନୃପସ୍ଥାୟକ ;
console.log(reverseOdia(str)) ;

Saturday, July 30, 2022

Katex: Cool Math for Web

 Well, I was late to discover Katex. It's really cool and faster in rendering Math in Web. Just downloaded the Katex Release, and got it working. Sample code below:

<!DOCTYPE html>
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
<html>
  <head>
    <!-- 
    <link href="fonts/KaTeX_Main-Regular.woff2" as="font" type="font/woff2">
    <link href="fonts/KaTeX_Math-Italic.woff2" as="font" type="font/woff2">
    <link href="fonts/KaTeX_Size2-Regular.woff2" as="font" type="font/woff2">
    <link href="fonts/KaTeX_Size4-Regular.woff2" as="font" type="font/woff2">
    -->
    <link rel="stylesheet" type="text/css" href="katex.min.css">
    <script src="katex.min.js"></script>
    <script src="contrib/mhchem.min.js"></script>
    <script src="contrib/copy-tex.min.js"></script>
    <script src="contrib/auto-render.min.js"></script>
    <script>
        function ready() {
            renderMathInElement(document.body, {
                delimiters: [
                  {left: "$$", right: "$$", display: true},
                  {left: "\\[", right: "\\]", display: true},
                  {left: "$", right: "$", display: false},
                  {left: "\\(", right: "\\)", display: false}
                ]
            });
        }
    </script>
  </head>
  <body onload="ready()">
    <div>The formula $a^2+b^2=c^2$ will be rendered inline, but $$a^2+b^2=c^2$$ will be rendered as a block element.</div>
    <br>
    <div>The formula \(a^2+b^2=c^2\) will be rendered inline, but \[a^2+b^2=c^2\] will be rendered as a block element.</div>
    
</body>
</html>

Monday, January 3, 2022

How to Geotag a Photo safely and effectively

Of late, I found that, If a photo is shared over Whatsapp, the Geotag is lost. I guess, WhatsApp removes it in order to compress the image so as to reduce the size.

Many Android users use third party software to Geotag the photos. These software impose the location on top of the photo like a watermark. Actually the Geotag Location information is stored internally as extra information in the image. Those software just impose that location information on top of the photo just to give an impression to the ordinary user that the photo got geotagged.  However these software MAY be harmful because you dont know what all permissions you have allowed while installing it.

The trouble comes, when the photo is shared over Whatsapp. Whatsapp simply remove the Geotag Location information (EXIF data) when shared as a photo. The location information imposed by those third-party software as a watermark on those photos are still visible when shared over Whatsapp but technically those photos are NOT geotagged.

How to Geotag safely and effectively

You really dont need any third-party software to Geotag a photo.

1. Just enable Location/GPS in your phone

2. Also enable Location in your Camera app's settings. Dont worry if such option is not there in your phone.

3. Take the photo.

4. Do not share over Whatsapp as a photo. If you do so, the location information is lost. However you can share it as document in Whatsapp.

5. You can transfer the photo using phone cable, Email, Bluetooth, Wifi-Direct etc.

In few of the gallery apps, you can find the location of the photo in the details view. Alternatively you can use this service http://exif.regex.info/exif.cgi to check if the photo is geotagged or not.

Saturday, April 24, 2021

How to create and Link Static and Dynamic Libraries

Let’s try to create a math library with two functions add and sub.

// add.c

int add(int x, int y)

{

     return x+y ;

}

//sub.c

int sub(int x, int y)

{

     return x-y ;

}

//main.c

#include <stdio.h>

int add(int, int) ; // you can create a header file

int sub(int, int) ; // and put these

int main(int argc, char **argv)

{

     printf("%d\n", add(5,7)) ;

     printf("%d\n", sub(5,7)) ;

     return 0 ;

}

Now compile it with -c option

gcc -c add.c sub.c

so you will get the object files add.o and sub.o


Creating and Linking a Static Library

Use the ar tool

ar crv libzmath.a add.o sub.o

see the content of

ar -t libzmath.a

Now statically link it like

gcc -o test main.c -L. -lzmath

or

gcc -o test main.c .libzmath.a


Creating and linking the dynamically linked library (shared object)

Again compile while generating Position Independent Code

gcc -c -fpic add.c sub.c

-fpic option is for Position Independent Code

Create the shared library like the following:

gcc -shared -o libmymath.so add.o sub.o

Remember with gcc, all the .so files must start with "lib".

So if library file is libmymath.so, then you have to link it like with the –l option like -lmymath

gcc -Wall -o test main.c -L/home/swarup/work/c -lmymath

-L option is to specify the location where my libmymath.so is present.

Now running ./test may not work, because the .so file is not in the path where linux is looking for to load it. It first searches /usr/local/lib, /usr/lib and so on. So for the ld to work, we need to provide the library path in the environment variable LD_LIBRARY_PATH. We do it like:

export LD_LIBRARY_PATH=/home/swarup/work/c:$LD_LIBRARY_PATH

Note: You can see all the standard libraries in the directory /lib/x86_64-linux-gnu. The functions like printf are part of libc.so.xxx


Saturday, September 19, 2020

Writing Odia in LaTeX

Finally I was able to write Odia letters in LaTeX. I tried polyglossia but somehow couldn't make it work. Then I succeeded with the fontspec package. It came out to be simpler than all the complex indic examples found in web. Here is the document. 

 Note: Odia unicode font file kalinga.ttf must be present in C:\Windows\Fonts folder. PdfLatex wont work, One must use XeLatex to compile the document

\documentclass{article}
\usepackage{fontspec}
\newfontfamily\oriyafont{kalinga.ttf}
\DeclareTextFontCommand{\textodia}{\oriyafont}
\title{\LaTeX \textodia{ରେ ଓଡ଼ିଆ ଲେଖା}}
\author{\textodia{ସ୍ୱରୁପାନନ୍ଦ ବିଷୟୀ}}
\begin{document}
\date{}
\maketitle
\section{\textodia{ଓଡ଼ିଆ ଉଇକିପିଡ଼ିଆରୁ}}
\textodia{ଓଡ଼ିଆ ଏକ ଭାରତୀୟ ଭାଷା ଯାହା ଏକ ଇଣ୍ଡୋ-ଇଉରୋପୀୟ ଭାଷାଗୋଷ୍ଠୀ ଅନ୍ତର୍ଗତ ଇଣ୍ଡୋ-ଆର୍ଯ୍ୟ ଭାଷା । ଏହା ଭାରତ ଦେଶର ଓଡ଼ିଶା ପ୍ରଦେଶରେ ସର୍ବାଧିକ ବ୍ୟବ‌ହାର କରାଯାଉଥିବା ମୁଖ୍ୟ ସ୍ଥାନୀୟ ଭାଷା ଯାହା ୯୧}.\textodia{୮୫}\% \textodia{ଲୋକ ବ୍ୟବ‌ହର କରନ୍ତି । ଓଡ଼ିଶା ସମେତ ଏହା ପଶ୍ଚିମ ବଙ୍ଗ, ଛତିଶଗଡ଼, ଝାଡ଼ଖଣ୍ଡ, ଆନ୍ଧ୍ର ପ୍ରଦେଶ ଓ ଗୁଜରାଟ (ମୂଳତଃ ସୁରଟ)ରେ କୁହାଯାଇଥାଏ । ଏହା ଓଡ଼ିଶାର ସରକାରୀ ଭାଷା । ଏହା ଭାରତର ସମ୍ବିଧାନ ସ୍ୱିକୃତୀପ୍ରାପ୍ତ ୨୨ଟି ଭାଷା ମଧ୍ୟରୁ ଗୋଟିଏ ଓ ଝାଡ଼ଖଣ୍ଡର ୨ୟ ପ୍ରଶାସନିକ ଭାଷା । ଓଡ଼ିଆ ଷଷ୍ଠ ଭାରତୀୟ ଭାଷା ଭାବରେ ଏକ ସ୍ୱତନ୍ତ୍ର ଓ ଅନ୍ୟ ଭାଷାଦ୍ୱାରା ପ୍ରଭାବିତ ହୋଇ ନ‌ ଥିବା ଭାଷା ଭାବରେ ଶାସ୍ତ୍ରୀୟ ଭାଷାର ମାନ୍ୟତା ପାଇଛି ।}

\end{document}

Friday, August 7, 2020

Divisibility

 One of my friends asked me to come up with a solution for this problem in Java/C#

public int isXDivisibleByY(int x, int y)
{
/* 
The method should meet the following conditions:

1. Method returns 1, if X can   be divided by Y without a remainder
2. Method returns 0, if X can't be divided by Y without a remainder
3. Solution must not include any conditional checks (if condition, equality operators, the ternary and null-coalescing operators etc.)
4. Solution must not include any exception handling (try-catch-finally)
5. It should work all kinds of inputs of x and y
*/
}

Challenges & Solutions

  1. I had failed to notice that there is no straight forward way to cast a boolean to int in Java. This is missing in Java because Java designers (correctly) recognized that the boolean / integer overloading in C and C++ was a significant source of errors. Source (https://stackoverflow.com/questions/16281760/why-doesnt-java-allow-casting-boolean-int). Thank God, there's this weird compareTo method in Boolean.
  2. Without a try-catch-Finally, Handling divide by Zero gracefully is not easy. However a simple cast of float to the divisor is handy. Thanks to the division rules https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.2


Final Solution by me:

public int isXDivisibleByY(int x, int y )
{
return 1 - Boolean.compare((x%(float)y) > 0, false) ;
}

Well, compare method may use conditionals internally but I guess, this is one possible solution without a visible conditional...

Next thing to try: Applying https://en.wikipedia.org/wiki/Divisibility_rule

Tuesday, August 14, 2012

XML Serialization in Android

I needed XML serialization in Android badly. I had lot of schemas and I didn’t have the patience to parse the XML using Sax. You can use JAXB to marshal and unmarshal XML. Using XJC - the JAXB Binding compiler you can generate the java classes from your schema.

JAXB is not available for Android, because dalvik does not support Reflection.

But thanks to Simple XML ,  with few modifications of JAXB generated, I could entirely convert my xml to java class object.

The articles at simple xml site are really helpful.

Edited the schema book.xsd from msdn link as follows:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="catalog">

    <xs:complexType>

      <xs:sequence>

        <xs:element name ="book" type="Book" maxOccurs="unbounded"/>

      </xs:sequence>

    </xs:complexType>

  </xs:element>



  <xs:complexType name="Book">

    <xs:sequence>

      <xs:element name="author" type="xs:string"/>

      <xs:element name="title" type="xs:string"/>



      <xs:element name="price" type="xs:float"/>

      <xs:element name="description" type="xs:string"/>

      <xs:sequence>

        <xs:element name ="UserReview" type="UserReview" maxOccurs="unbounded"/>

      </xs:sequence>

    </xs:sequence>

    <xs:attribute name="id" type="xs:string"/>

    <xs:attribute name="genre" type="Genre"/>

  </xs:complexType>

 

  <xs:complexType name="Review">

    <xs:simpleContent>

      <xs:extension base="xs:string">

        <xs:attribute name="language" type="xs:string" />

      </xs:extension>

    </xs:simpleContent>

  </xs:complexType>



  <xs:complexType name="UserReview">

    <xs:sequence>

      <xs:element maxOccurs="1" name="Date" type="xs:string" />

      <xs:sequence>

        <xs:element name="Review" type="Review" minOccurs="0" maxOccurs="2" />

      </xs:sequence>

    </xs:sequence>

    <xs:attribute name="userid" type="xs:string" use="required" />

  </xs:complexType>



  <xs:simpleType name="Genre">

    <xs:restriction base="xs:string">

      <xs:enumeration value="Fiction"/>

      <xs:enumeration value="NonFiction"/>

      <xs:enumeration value="Children"/>

    </xs:restriction>

  </xs:simpleType>

 

</xs:schema>



Xjc.exe must be found in your JAVA_HOME/bin folder. Add the bin path to your system Path variable.

Now create the java classes from the book schema using xjc. For ex:

xjc -p in.blogspot.negabinary book.xsd

Add the generated package to your application source.

It’s time to replace the JAXB annotations with SimpleXML annotations.

Download Simple XML Serialization library from here

Copy the simple-xml-2.6.6.jar (found inside the folder simple-xml-2.6.6\jar) to your application source libs folder.

Remove all import javax.xml.bind.* from the generated sources. Edit your class sources like the table below:

(Note: this table does not contain all the replacements)

Original JAXB generated class
Replace with SimpleXML annotation
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "book"
})
@XmlRootElement(name = "catalog")
@Root
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Review", propOrder = {
    "value"
})
@Default
@XmlAttribute(name = "language")
    protected String language;
@Attribute(name = "language", required=false)
    protected String language;

Note: unless specified, required=true. Therefore you have to make required=false
@XmlElement(name = "Date", required = true)
    protected String date;
@Element(name = "Date", required = true)
    protected String date;
@XmlValue
    protected String value;
@Text(required=false)
@XmlElement(name = "UserReview", required = true)
        protected List<UserReview> userReview;
@ElementList(entry = "UserReview", inline = true)
        protected List<UserReview> userReview;

Note: ElementList is bit tricky. ‘name’ won’t work, ‘entry’ works.
@XmlType(name = "Genre")
@XmlEnum
public enum Genre {
I don’t know how to do.
Used String instead




Once you modify all your classes in SimpleXML format, its time to test your application.

A simple try as follows:

Catalog catalog ;

              try {

                     StringReader sr = new StringReader("<?xml version='1.0' encoding='utf-8'?> <catalog> <book id='id1' genre='Fiction'> <author>author1</author> <title>title1</title> <price>1</price> <description>description1</description> <UserReview userid='userid1'> <Date>Date1</Date> <Review language='language1'>Review1</Review> <Review language='language2'>Review2</Review> </UserReview> <UserReview userid='userid2'> <Date>Date2</Date> <Review language='language3'>Review3</Review> <Review language='language4'>Review4</Review> </UserReview> <UserReview userid='userid3'> <Date>Date3</Date> <Review language='language5'>Review5</Review> <Review language='language6'>Review6</Review> </UserReview> </book> <book id='id2' genre='NonFiction'> <author>author2</author> <title>title2</title> <price>-3.40282347E+38</price> <description>description2</description> <UserReview userid='userid4'> <Date>Date4</Date> <Review language='language7'>Review7</Review> <Review language='language8'>Review8</Review> </UserReview> <UserReview userid='userid5'> <Date>Date5</Date> <Review language='language9'>Review9</Review> <Review language='language10'>Review10</Review> </UserReview> <UserReview userid='userid6'> <Date>Date6</Date> <Review language='language11'>Review11</Review> <Review language='language12'>Review12</Review> </UserReview> </book> </catalog>") ;



                     Serializer serializer = new Persister();

                     catalog = serializer.read(Catalog.class, sr);

                     Log.v("TEST", catalog.getBook().get(0).getAuthor()) ;

              } catch (Exception e) {

                     e.printStackTrace();

              }

 That’s it folks.. !!


~Swarup