Wednesday, December 16, 2015

Determining image file size in Javascript

After a lot of googling and searching, I realized the best way to do this is to create a service call to the backend witht he url of the image whose size needs to be figured out.

This service should make a HEAD call to the server to get the content - length. And pass it along as a response.

Not all servers support HEAD calls so as a fallback make a GET call to the get the request and determine the file size from the headers.

We need to set few headers for this to work universally. One of them is user-agent.

Code for the same is :

private void makeRequest(@FormParam("url") String url, Map response, String requestMethod) {
    try {
        HttpURLConnection urlCon =
                (HttpURLConnection) new URL(url).openConnection();
        urlCon.setRequestMethod(requestMethod);
        urlCon.setRequestProperty("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0");
        //urlCon.setDoOutput(true);        urlCon.setDoInput(true);
        urlCon.setUseCaches(false);
        urlCon.setDefaultUseCaches(false);
        urlCon.setConnectTimeout(2*60*1000); // 2 minute        urlCon.setReadTimeout(5*60*1000); // 5 minute
        if(urlCon.getResponseCode() == HttpURLConnection.HTTP_OK)
        {
            String contentLength =  urlCon.getContentLengthLong()+"";
            String contentType = urlCon.getContentType();
            response.put("content-length",contentLength);
            response.put("content-type",contentType);
            response.put("status","ok");
        }
        else        {
            response.put("status","nok");
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
        response.put("status","nok");
    }
}

Monday, December 14, 2015

Most expensive product on Amazon India By Category

Amazon India today has become the most visited e-commerce site in India. So, I decided to analyze the most expensive products that Amazon India Sells across various category.

So lets start.

Book worth Rs 53,46,000.00



This is quiet modest. I think its a must in every library!

DVD worth Rs 40,045.23



My kids are gonna die uneducated :(

A Flip Cover worth Rs 255,255.00




I would get around 40 actual Micromax Juice phone at the same price.

A pen worth Rs 1,700,000.00




"No doubt a pen is mightier (worthier) then a sword"

Telescope worth Rs 896,000.00



This might actually be a fair price. Should understand technical part of it to comment. Help!

Spoons worth Rs 2,183,731.00




I might by a house with a kitchen at the same price. Though each spoon would just cost you mere 33,000. Thats a relief!

A Game worth Rs 868,434.00



That might be correct again, with import duty on all. I don't know.

MultiGym worth Rs 2,950,000.00



Someone from gym community should comment on this

A bath cereal worth Rs 2,010,000.00



Just 20 lacs for it. I am not sure it would be most expensive breakfast ever or bath ever.

A pair of Socks worth Rs 200,997.98



Ahem! my feet feel warm.

A Shoe worth Rs 102,035.00 

(One of the variants with size 44)




Just for one variant price shoots up 5 times, can't a computer catch that.

A Bag worth Rs 90,000



I am not a fashionista. This might be fair.


So if you are feeling rich today then dare buy one of the above products. My favorite in the list is the flip cover.

Intent of the post is to show disparity in the pricing on the most visited E-Commerce site in India, and need for a AI based Anti-Spam engine on such e-commerce sites to keep a check spam pricing. Some people might actually end up ordering these by mistake. I hope not.
Jeff Bezos, are you listening!

Update 1: Amazon have responded to the query raised by this post. They have accepted that they do need a mechanism to detect price spam. Yoohoo! I love there Customer Service! Snippet of the response is below:



Fixing Deployment.AddInAlreadyInstalledException.



If you are building any VSTO for any of the office applications, then its quite common to run into this issue.


The error message would say that

"The customization cannot be installed because another version is currently installed and cannot be upgraded from this location. To install this version of the customization, first use Add or Remove Programs to uninstall this program: TestUpdatedVersion. Then install the new customization from the following location: file:///D:/Samples/TestUpdatedVersion/bin/Debug/TestUpdatedVersion.vsto ********** Exception Text ********** Microsoft.VisualStudio.Tools.Applications.Deployment.AddInAlreadyInstalledException: The customization cannot be installed because another version is currently installed and cannot be upgraded from this location. To install this version of the customization, first use Add or Remove Programs to uninstall this program: TestUpdatedVersion. Then install the new customization from the following location: file:///D:/Samples/TestUpdatedVersion/bin/Debug/TestUpdatedVersion.vsto at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.VerifySolutionCodebaseIsUnchanged(Uri uri, String subscriptionId, Boolean previouslyInstalled) at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.InstallAddIn()"


So let me explain a fool proof way to troubleshoot this. Would be quite useful for Support Engineers.


  1. Go to Control Panel and search for this application plugin. If its listed then try to uninstall this and then re run the set-up. If its not listed or re-running the setup.exe fails then continue with step 2.
  2. Try cleaning up registry and installed file list by using a "Fix it" package from Microsoft, available here https://support.microsoft.com/en-us/mats/program_install_and_uninstall
  3. Now most probably the application is uninstalled but it has left behind some registry. So let clear them. 
  4. Press Start+R. In run command prompt type regedit and press enter.
  5. Clear any application related keys from 
  6. In registry editor go HKEY_CURRENT_USER\Software\Microsoft\Office\/Addins/
  7. to HKEY_CURRENT_USER\Software\Microsoft\VSTO\SolutionMetadata\{GUID} and clean up the entry for the VSTO. Check on the right side of the screen to figure out the right registry entry.
  8. Then check if there is an entry for HKEY_CURRENT_USER\Software\Microsoft\VSTA\Solutions\{GUID}. If there exists an entry then clear this up too. 
  9. Now First you would have to install Visual Studio 2013 Community edition from here https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx,
  10. This should result in download of mage.exe with its dependencies. https://msdn.microsoft.com/en-us/library/acz3y3te(v=vs.110).aspx Then going to C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin you should see mage.exe there.
  11. Then cd into the location for mage.exe in commandprompt.
  12. Run the following command there: mage.exe -cc. It should produce an output "Application Cache Cleared"
  13. Now reinstall the VSTO by running the setup.exe. This time it should go through for sure. If it does not then please do leave a comment.

Wednesday, December 9, 2015

Buy Gobar Online on Amazon.

Ever wanted to gift someone Gobar? Now you can. Just follow the link below!





And suppose if you dont wanto buy Cow Dung Cake, then you can also get it in powder form here:

Tuesday, December 8, 2015

One Plus X invite Finder

Lots of people are looking for one plus X invite so I decided to write a crawler to scrape it. Use this buy link to test your invite. I would keep on updating new invites here and would request people to add invite in the comment section.



          Buy Here.




Another invite at https://invites.oneplus.net/claim/IN11-AD09-16B0-E083

Friday, October 9, 2015

Visual Studio Quirks

On clicking debug in Visual Studio, it gives "The debugger cannot continue running the process. Unable to start debugging"



The problem here is that no project is selected as default startup project. You would need to right click a project which is start up project and select "Set as start-up project".

Sunday, August 2, 2015

How to access banned sites in India?

Today lots of ISP's have banned tonnes of site in India. But they can still be accessed. There are various options to do that:

1) If its a page without media, video content, then search it on google, press the down arrow below the search result, and select cached. This would display the cached result of the page as stored in google.

2) Use a set of proxy server from here.

3) Go to https://www.proxysite.com/ and start accessing websites from there.

Happy Surfing!

Tuesday, July 28, 2015

Ubuntu DNS error on Virtualbox

Quite often on my Guest Ubuntu system on virtual box, I face this problem, where network is accessible via IP but not my domain name. I am able to ping any IP but DNS resolution fails. In those scenarios I have found the following command quite useful:

sudo dpkg-reconfigure resolvconf
This resets/regenrates the resolv.conf and everything is back to normal :)

Thursday, July 2, 2015

How to free up space on Windows?

I have been facing this problem where entire of my drive C had always been full, though it was having almost 50 GB, and no content apart from windows and program files.

I have tried disk clean up and  disk clean up with system files with no effect.

Finally to solve it, I went to I changed the attributed of the files on my drive C:


  • Write click on Drive C and click properties.
  • In properties, select "Compress drive to save disk space" and unselect "Allow files on the drive to have contents indexed in addition to file properties".
  • Press Apply. The process with take a couple of hours on my SSD drive.


and Hola, I had ann extra 7GB of space.

Other Techniques:

  1. Reduce the amount of space system restore takes. To do so go to system restore settings in control panel.
  2. Reduce the amount of space hibernate files take. Run command prompt as administrator and execute Powercfg.exe /hibernate /size 50 .  Additionally, switch off fast boot up /start up in control panel. This would give you a good amount of space. Stop using hibernate also.
  3. Or, Switch off hibernation and fast boot up all together. Run powercfg /h off  from administrator privilege command prompt.



Other important links:
http://windows.microsoft.com/en-in/windows-8/free-up-disk-space

Wednesday, May 20, 2015

Promises vs EventEmitters vs Callbacks

There is a lot of material online about these and I would try to keep it short and sweet to explain what is my current understanding of these.

Promises are syntax to implement callbacks, so lets get rid of callback from the proportions.

Now we are left with Promises vs EventEmitters. Internally or performance wise all are quite similar.

So based on coding practices these are my observations:

Promise:


Promise are good abstraction of asynchronous commands which will happen in given amount of time. Making a db query is a promise, making a rest cal is a promise. Your code needs to wait for promise to be fulfilled. Lets give it an analogy,  a cab driver promises to come to pick you up at 6AM and when he fulfills the promise, you promise him to sit in the cab and reach office. I know analogy is little lame, but hope it explains the idea.

EventEmitters:


EventEmitters are used for truely async events, like someone clicked on a particular button on a page, or while operating on a command you detected something which is not in scope of current command so you fire and forget. Its listener responsibility to act on it. Not yours.
Going back to real work example suppose at 5.55 AM your friend comes to pick you up then that's an event. Something which is not expected.

I hope I explained my understanding of these two mechanism to achieve asynchronous behavior in Nodejs.


Thursday, April 23, 2015

Linkedin Status Update Image not displayed

I was facing this problem when I was updating images from my site on linkedin. I even asked a question on stackoverflow (When using linkedin share api submitted-picture-url or sharing url via linkedin, particular url format doesnot work?) but never got a good response.

After that I did lots of experimentation to figure out few things about linkedin in status update image url. I would list them out below:


  1. Max size for image should be 100 MB (read somewhere, have not tried it myself.)
  2. Linkedin caches the images on its server for 7 days. So if the image on the url shared have changed, linkedin won't update it. A good workaround is to add a query parameter to the image url with some random string of the timestamp while sharing. So, this would make each image url unique.
  3. Set the correct mime-type on the servlet serving the image. I was using cdn and with my servlet acting at a proxy to cdn to serve the image. In the process I was missing out the mime-type in the response header. What this lead to was that linkedin was never displaying those images. So ideally linkedin caching mechanism makes a requests to the image url, reads the response header, if the header has a mime-type of image then downloads it and caches it other wise ignores it. So always set the correct mime-type.
  4. Obviously the image url should be reachable from open internet.
  5. Image should atleast be 80px by 150x to prevent it to be stretched.
I hope this list helps someone. Have a good day! Happy sharing!

Thursday, April 16, 2015

Email Validation Jquery Plugin.

Recently I wrote a jquery plugin which would allow you to validate an email address for:

  • Syntax checks (RFC defined grammar) 
  •  DNS validation
  • Spell checks 
  • Email Service Provider (ESP) specific local-part grammar (if available)
  •  MX Validation.
  • Free Email Service Check
  • Disposable Email Service check.
  • Sanatize email id based on service provider.
In future, I am planning to incorpoprate:
  • Corporate Company details.
If you have any suggestion then you can comment. 
You can download the plugin here.
Try a demo here.

Some screenshots of the demo are:






Monday, April 6, 2015

How to set Tomcat 7 source level to Java 7? Avoid "Resource specification not allowed here for source level below 1.7" error

I have been facing problem where whenever I was accessing jsp page which were using some Java 7 specific features, the compilation of such JSP pages use to fail with following error:

Resource specification not allowed here for source level below 1.7

To fix this I googled for hours and set up the JDK home correctly on my catalina.sh with env.sh to point to jdk7. But this never solved my problem.

Finally today I hit the gold while reading the apache tomcat jasper documentation. The JSP compiler had to be set to use 1.7 as target and source version.

To do this we need to add two extra init-params in the conf/web.xml file in the tomcat home.
 The JSP servlet configuration should have

     <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>false</param-value>
        </init-param>
          <init-param>
            <param-name>compilerSourceVM</param-name>
            <param-value>1.7</param-value>
        </init-param>
        <init-param>
            <param-name>compilerTargetVM</param-name>
            <param-value>1.7</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

Restart the server and boom it works.

NPM Install Failing with EROFS in npm-debug.log on VirtualBox shared Drive [Updated for ETXTBSY]

I have a set up where I use my IDE on my host system and build my code on an Ubuntu server and deploy there.

To achieve this I have used virtual box to install and run Ubuntu as a guest system. My host system is Windows.  I have shared a drive across to the guest. Every time my ubuntu comes up, I mount the drive using the command:

sudo mount -t vboxsf SHARE_NAME folder_to_mount_on

Things were working fine, with my Java server development. Now I decided to move my js and node environment to the same set up and BOOM! it failed.

Only hint was EROFS error on the npm-debug.log. Some googling and I find out that VirtualBox has a bug and it does not support sysmlink and since ubuntu by default support symlink creation, npm was failing at the time of creation of sysmlink.

My initial solution was to write a build script which rsynced my working directory to a level above and run the build command there. I worked but was slow and hacky.

Then I found out that we can switch on symlink on VirtaulBox and windows: To do so:

VBoxManage setextradata YOURVMNAME VBoxInternal2/SharedFoldersEnableSymlinksCreate/YOURSHAREFOLDERNAME 1

Verify by running:

VBoxManage getextradata YOURVMNAME enumerate

Restart VirualBox and run it as administrator, and things starts working :)

UPDATE:
Another new error I cam across in the similar environment was stack: 'Error: ETXTBSY, 
for this I have to end up adding  --no-bin-links so that no soft links are created.


Tuesday, March 24, 2015

Making Twitter Media Upload Api work with Java

I was trying to upload an image and do status update on twitter using there api version 1.1.
For this I was using media/upload.json . I was trying to send content of files as base64 encoded string and setting the appropriate content-type and content-transfer-encoding. But this didn't work.
I was getting errors like:

1) Missing paramter media
2) Could not authenticate.

My main reason to use this approach was I was getting image url and didn't wanted to save it into a file.

But this never worked, then I took a different approach of saving the imageurl into a file and doing a multi part upload. Code for it is below. Hope this helps someone.


private String uploadImage(String imageUrl)
{
File f = new File("/tmp/twitterUploadImage_"+StringUtil.encodeURL(imageUrl));
try
{
FileUtils.copyURLToFile(new URL(imageUrl), f);
}
catch (IOException e)
{
logger.severe("Failed to save image in a file");
return null;
}
UrlReader.FetchResponse resp = post(TWITTER_UPLOAD_URL + "media/upload.json", f, "media", true);
if (resp == null || StringUtil.isEmpty(resp.body)) return null;
try
{
logger.severe(resp.body);
JSONObject obj = new JSONObject(resp.body);
if (obj.has("media_id_string"))
{
return obj.getString("media_id_string");
}
else
{
logger.severe("Media Id not found "+ resp.body);
}
}
catch (JSONException jse)
{
logger.severe("JSON exception "+ resp.body);
}
return null;
}

public UrlReader.FetchResponse post(String url, File file, String paramName, boolean personaSpecific) //Not changing SocialAuthorization rightaway.
{
Persona person = this.loadPersona(index, personaSpecific);
if(person == null)
return null;
Token accessToken = new Token(person.getToken(), person.getKey());
OAuthRequest req = new OAuthRequest(Verb.POST, url);
OAUTHSERVICE.signRequest(accessToken, req);
HttpEntity entity = createMultipartEntity(file, paramName);
UrlReader.FetchResponse response = UrlReader.HttpPost(url, req.getHeaders(), entity);
return response;
}

private HttpEntity createMultipartEntity(File f, String paramName)
{
MultipartEntityBuilder builder = MultipartEntityBuilder.create();      
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
FileBody fileBody = new FileBody(f); //image should be a String
builder.addPart(paramName, fileBody);
HttpEntity entity = builder.build();
return entity;
}

Friday, March 20, 2015

Making Facebook Graph Photos Api Work with url

As per the documentation on Facebook https://developers.facebook.com/docs/graph-api/reference/v2.2/user/photos/

For /photos api if we want to post a photo to user timeline, using an url on open internet then we must:

POST /v2.2/me/photos HTTP/1.1
Host: graph.facebook.com

source=%7Bimage-data%7D


But this gives:

{
  "error": {
    "message": "An unknown error has occurred.",
    "type": "OAuthException",
    "code": 1
  }
}

We should avoid adding {} or encode %7B and %7D around image-url for this to work. So correct would be:


POST /v2.2/me/photos HTTP/1.1
Host: graph.facebook.com

source=image-data

Tuesday, March 17, 2015

Git CheatSheet/Quickguide

  • Git Rebase Command
git checkout branch name # checkout branch on which you want to merge
git rebase branch_name # Original branch would be rebased to current branch.

Rebase would remove changes in your branch and merge all the changes from the new branch then applyour changes on top of it.
  • Git merge from a branch.
git checkout branch name # checkout branch on which you want to merge
git merge branch_name # branch_name is the branch from which you want to merge
  • Reverting merge conflict files
git reset --hard HEAD file_name # hard revert to HEAD
  • Reverting to the last commited changes on a branch:
git reset --hard HEAD # hard revert to HEAD
  • Switching branches without committing changes:
git add uncommited_files # Add uncommitted files to index
git stash # Stash your changes
git checkout new_branch # Switch to new branch,
# Work on the new branch
git stash pop # Switch back to old branch with your changes
  • Creating a new branch on Git and checking it out:
git checkout -b new_branch # Create a new branch
  • Renaming a Git branch on Local and  on Remote:
git branch -m old_branch new_branch # Rename branch locally
git push origin :old_branch # Delete the old branch
git push --set-upstream origin new_branch # Push the new branch, set local branch to track the new remote

  • Working with stash:
git stash list # Lists all the saved stashed
git stash drop stash_name # Deletes a saved stash
git stash clear # Deletes all saved stash
http://www.gitguys.com/topics/temporarily-stashing-your-work

Thursday, February 19, 2015

How to run npm installed components from commandline in Windows?

When you are working with windows and nodejs, then you might face this problem, whatever npn packages you install might not be accessible through commandline. By this I mean, is that, suppose you did:

npm install -g bower

And then executed :

bower install

Windows might give you an error that 'bower' is unrecognized.
A solution to the problem is to add npm global repository to your system path. To do so execute

npm config get prefix

To get the npm global repository path. Copy this path and follow following steps to add to windows path:

  1. On your computer, select Start->Settings->Control Panel->System:
  2. A "System Properties" dialog box will appear. Click it's Advanced tab:
  3. Click the Environment variables button:
  4. An Environment Variables dialog box will appear. In the System variables section, scroll down until you find the PATH variable. Select this variable:
  5. Click the Edit button to edit the value of this variable.
  6. At the end of the "Variable value:" box, add
            ;
    
  7. Click the OK button in each dialog box, until they have all disappeared.

Once, added you would have to restart command prompt and Hola! everythings works :)

Wednesday, February 11, 2015

AI Planning Tree Search Algorithm for Missionary And Cannibal Problem in Java

I have been doing AI Planning course and I decided to implement the first basic problem in Java. To implement this, i tried to create the algorithm with right level of abstractions so that it can be applied to any problem in future.

Some take aways in my package structure is that, I have maintained all the generic reusable code in definitions package and problem specific code in monkcannibal package.

To solve the problem, I have implemented State which had successor method, IProblem which defined the problem to solve and IStrategy which defined the strategy to take for state transition. Here I have used two strategies for tree travesal, breadth first search aka, BFS and Depth First Search, aka DFS.

The code is available on github at: https://github.com/biplav/aiplanning

The main file is : com.biplav.aiplanning.problems.monkcanibbal.MissionaryCannibalPlan.java


And the output is:

1:L->3m1cfalseboat R->0m2ctrueboat
2:L->3m2ctrueboat R->0m1cfalseboat
3:L->3m0cfalseboat R->0m3ctrueboat
4:L->3m1ctrueboat R->0m2cfalseboat
5:L->1m1cfalseboat R->2m2ctrueboat
6:L->2m2ctrueboat R->1m1cfalseboat
7:L->0m2cfalseboat R->3m1ctrueboat
8:L->0m3ctrueboat R->3m0cfalseboat
9:L->0m1cfalseboat R->3m2ctrueboat
10:L->1m1ctrueboat R->2m2cfalseboat
11:L->0m0cfalseboat R->3m3ctrueboat
Time consumed is 3
1:L->2m2cfalseboat R->1m1ctrueboat
2:L->3m2ctrueboat R->0m1cfalseboat
3:L->3m0cfalseboat R->0m3ctrueboat
4:L->3m1ctrueboat R->0m2cfalseboat
5:L->1m1cfalseboat R->2m2ctrueboat
6:L->2m2ctrueboat R->1m1cfalseboat
7:L->0m2cfalseboat R->3m1ctrueboat
8:L->0m3ctrueboat R->3m0cfalseboat
9:L->0m1cfalseboat R->3m2ctrueboat
10:L->0m2ctrueboat R->3m1cfalseboat
11:L->0m0cfalseboat R->3m3ctrueboat

Time consumed is 1

Zopper Programming assignment Question 3 (Project Group)

The third question is also a simple one:

Link to the question is on HackerRank: http://www.hackerearth.com/problem/algorithm/project-team/

The submission code in python can be seen here:

Zopper Programming Assessment Problem 2 with solution

This is the second problem from HackerEarth that I tried for the friend for interview:

Problem:
HackerMan says that 5 and 8 are smart digits. A positive integer is called a smart number if it has only smart digits in its decimal representation.
HackerMan has three sets of numbers. And he needs your help to find out the number of distinct smart numbers that he can make using one number from each of the three sets. You have to help in it
Note: You must not count the same smart number more than once.
Constraints
  • The three sets will contain between 1 and 50 elements, inclusive.
  • Each number in the three sets will contain numbers between 1 and 30,000, inclusive.
Input Format
  • The first, third and fifth lines will contain a number N that will specify the count of numbers in the sets on the second, fourth and sixth lines of input.
  • The second, fourth and sixth line will contain the three sets of numbers respectively.
Output Format
Print a single line containing the count of distinct smart numbers.

Sample Input 
3
3 5 4
3
2 1 3
3
2 1 5
Sample Output
2
Explanation
We have two smart numbers 5 = 3 + 1 + 1 and 8 = 5 + 2 + 1. 8 can be also expressed as 4 + 2 + 2, but you must not count 8 twice.

Time Limit: 2 sec(s) for each input file.
Memory Limit: 256 MB
Source Limit: 1024 KB
Marking Scheme: Marks are awarded if any testcase passes.
Allowed languages: C, C++, Clojure, Go, Haskell, C#, Java, JavaScript, Objective-C, Perl, PHP, Python, Ruby

SUBMISSIONS

Solution: https://gist.github.com/biplav/69f8c0c305b378be2b35

if __name__ == "__main__":
        n = raw_input()
        list1 = raw_input()
        n=raw_input()
        list2 = raw_input()
        n=raw_input()
        list3 = raw_input()
        list1 = [int(n) for n in list1.split(" ")]
        list2 = [int(n) for n in list2.split(" ")]
        list3 = [int(n) for n in list3.split(" ")]
        bigList = []
        for n in list1:
                for m in list2:
                        for o in list3:
                                bigList.append(n+m+o)
        bigList = list(set(bigList))
        #print bigList
        #bigList.sort()
        smart_number = 0
        for n in bigList:
                smart_number = smart_number+1 if (n % 10 == 5 or n % 10 == 8) else smart_number
        print smart_number

Tuesday, February 10, 2015

Zopper online assesment question on HackerEarth with solution.

Recently a friend asked me to solve a problem which he got on one of the interview, online assessment test. I decided to document my solution here. The companies name was Zopper and the question was asked on the initial online screening test on HackerEarth.

Problem:

HackerMan says that 5 and 8 are smart digits. A positive integer is called a smart number if it has only smart digits in its decimal representation.
HackerMan has three sets of numbers. And he needs your help to find out the number of distinct smart numbers that he can make using one number from each of the three sets. You have to help in it
Note: You must not count the same smart number more than once.
Constraints
  • The three sets will contain between 1 and 50 elements, inclusive.
  • Each number in the three sets will contain numbers between 1 and 30,000, inclusive.
Input Format
  • The first, third and fifth lines will contain a number N that will specify the count of numbers in the sets on the second, fourth and sixth lines of input.
  • The second, fourth and sixth line will contain the three sets of numbers respectively.
Output Format
Print a single line containing the count of distinct smart numbers.

Sample Input 
3
3 5 4
3
2 1 3
3
2 1 5
Sample Output 
2
Explanation
We have two smart numbers 5 = 3 + 1 + 1 and 8 = 5 + 2 + 1. 8 can be also expressed as 4 + 2 + 2, but you must not count 8 twice.

Time Limit: 2 sec(s) for each input file.
Memory Limit: 256 MB
Source Limit: 1024 KB
Marking Scheme: Marks are awarded if any testcase passes.
Allowed languages: C, C++, Clojure, Go, Haskell, C#, Java, JavaScript, Objective-C, Perl, PHP, Python, Ruby




MAX_ROW=500
MAX_COL=500


def assign_walls(row,col):
        w = raw_input()
        inp = w.split(" ")
        if inp[0] is 'C':
                col.append(int(inp[1]))
        else:
                row.append(int(inp[1]))

def main():
        sections = []
        row = []
        col = []
        section_areas=[]
        row_counter = 0
        col_counter = 0
        row_section = [(0,MAX_ROW)]
        col_section = [(0,MAX_COL)]
        no_of_walls = raw_input()
        for i in range(int(no_of_walls)):
                assign_walls(row,col)
        row.sort()
        col.sort()
        #print row
        #print col
        for i in row:
                if(i < row_section[row_counter][1]):
                        row_end = row_section[row_counter][1]
                        row_start = row_section[row_counter][0]
                        row_section[row_counter] = (row_start,i)
                        row_section.append((i,row_end))
                        row_counter = row_counter+1
        for i in col:
                if(i < col_section[col_counter][1]):
                        col_end = col_section[col_counter][1]
                        col_start = col_section[col_counter][0]
                        col_section[col_counter] = (col_start,i)
                        col_section.append((i,col_end))
                        col_counter = col_counter+1
        #print row_section
        #print col_section
        for i in row_section:
                row_length = i[1]-i[0]
                #print row_length
                for j in col_section:
                        col_length = j[1]-j[0]
                        #print col_length
                        area = row_length*col_length
                        #print area
                        section_areas.append(area)
        return section_areas[len(section_areas)-1]


if __name__ == "__main__":
        out = []
        t = raw_input()
        for i in range(int(t)):
                out.append(main())
        for x in out:

Thursday, January 22, 2015

Breaking open https://web.whatsapp.com/

Today whatsapp have launched an online/web version of their overly popular smartphone messaging app.

I was very much interested in seeing the architecture of this app because as far as i knew, they never stored messages on their server but all the data was only stored in users phone. So I started to look under the hood of the webapp and what I saw was a beauty.

First let me list down the frameworks they have used in creating this app:


  1. React.js : A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES from Facebook.
  2. Underscore.js : Unerscore is a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects. It’s the answer to the question: “If I sit down in front of a blank HTML page, and want to start being productive immediately, what do I need?” … and the tie to go along with jQuery's tux and Backbone's suspenders.
  3. Velocity.js : Velocity is an animation engine with the same API as jQuery's $.animate(). It works with and without jQuery. It's incredibly fast, and it features color animation, transforms, loops, easings, SVG support, and scrolling. It is the best of jQuery and CSS transitions combined.
These are the major pieces. They have been using secured websockets for communication with your phone through there server. I wonder why they didn't use webrtc's dataChannel there? Hmmm as I ask this question answer became clear, because only android would have supported that.

They are using Chrome's FileSystem Api which makes their application Chrome specific. In this case even data channels could have been used, as it negates the previous argument. I think the reason for not using WebRtc based data channel is to avoid difficulty of setting up the initial connection, which websockets are solving by putting a server in between.

They seem to be using Google Material Design principles.


So, I see they have modified form of XMPP present in there chat protocol and they are forwarding stanzas which there phone receives to the webclient. So, to use the webclient phone should be on and working. And every communication that happens on webclient actually would go via your phone. So, webclient is a just a proxy UI for your phone.

What does this means?
  • More data transfer over phone. Check your data usage.
  • More  battery consumption because of data transfer.
Though the web-client of whatsapp makes our life easier, it does comes at a cost.

Going ahead I would try to see if I can write some sort of chrome plugin which can get me some data out of Wa object of js and store the data on my server. Keeping my fingers crossed. Though i think i can still write a dumb plugin to parse html and get me the data, but let me first attempt a more elegant solution if possible.


Edit: How does initial handshake takes place?


So you open the webclient and you see a qr code, how does that happen? What happens in the background?


See the above image, it would explain the steps:


  1. It first sent the details of the current client, os, browser and session id. 
  2. Then it sent the stored session details about the connected client.
  3. It got 401 unauthorized request from the server saying that current session is logged out and it needs to create a new one.
  4. I think the the third frame is the ttl frame.
When using your client you scan the QR code, the mobile client connects over websocket to the same channel as specified by the qr code and then sends its initial info.
See the frames recieved on the webclient below:




The selected frame is the most interesting one as it has all the data from the mobile client to the web client.

s1,["Conn",{"ref":"@4O46ffWiLT9bwxmLw4ilte86YFX6TKe+lCpNmN3J9bPQcc7/1Va2tr86","wid":"919844186612@c.us","connected":true,"isResponse":"false","serverToken":"GBH8CFMxtifHo2C6aFZN52C55HWRpALj+n/H4GQs/27y9okIPaCwIClP/M4rJe0ntzHY/fYAZYsIlnzxcu06qDGvve+o6W++FzHlrZb07SYko6wFcDAy6YRQSOm3w6zf","browserToken":"9qy+sI5tqMlxnbViLjET9gM/tt/wOzB23nHlySDPvn6RGFe6G4vj//ItYnU76gHTBPYx88oulI9ggI55L3XH7kpXarbYT1wNgUCMbUnRigTC7EdnfgUDMIFxbcy+rc/DxLe4pIl7cE9wQZV4V1WFeA==","clientToken":"RUZB+rzOCWc5TlxBgIUut5ligZSxKR99eJmtIxfrpFk=","lc":"US","lg":"en","is24h":true,"secret":"vDHtvSzOHNYp0luwrnnV6ycc50luz2sLCM7SDcCNyBZ+aUIQNHh80s6dePcFhfO1QTkYC2dZT9BmZ/GGCsT4NSbP3zdoZCqB3oLrCNbsi0PHGWx/jxuyr2qgrvpxxCcH+O/gqo5S5N356f6icOpuSjZfZDKZ+DbT28/pfycG0qAFaIZ2sDAorHendgtfVk6y","protoVersion":[0,3],"battery":42,"plugged":false,"platform":"android"}]

As you can see the info also has battery state and is the phone charging or not also sent in this frame.
I hope, I answered your question.