Anyone Speak English here?

Hey, this is the first problem in a series of programming problems/puzzles I’ll be posting during my study abraod in Budapest, Hungary. If you like this puzzle and its solution, come back for more. If you don’t, tell me how I could improve the puzzle and/or  solutions format via comments on this blog.

Before arriving Budapest, I tried to learn basic hungarian phrases used in day-to-day discussions. I learned to introduced myself: Jo napot, a nevem Daniel. I also learned to ask to use the toilet, ask for directions, and let my interlocutor know that I don’t speak Hungarian. But how much Hungarian have I used in my conversations thus far? None. Most young people in Budapest speak acceptable english. I’d rather speak in a language with which I’m very familiar with than converse in a very beautiful language that I have a strenuous grasp on. The puzzle below is a fictional attempt to sift out the young people who speak english very well.

Puzzle 1: Anyone Speak English Here?

I currently live around Astoria in Budapest. I want to go to the mall to purchase a video camera to use during the Hungarian drinking festival in the Buda Castle in the Buda side of Budapest. I have to use the subway. But I don’t know which metro line I should use. I’m determined to figure it out by asking someone, in English, around the metro station area to tell me when to get on and when to get out of the metro line when I arrive the Castle. To do that, I must first sift out the young people who speak English by using some algorithm (maybe?).

I’ll give my target young person an English word and ask him/her to give me another English word that’s closest to it. The distance metric I use to measure closesness of words uses costs on substitution, insertion, and deletion of characters in the word given. I prefer that fewer characters be deleted from or inserted into the source word. Substituting one character for another is, therefore, preferred over insertions or deletions of characters.

Example:
Source word: rain
Target words: pain, raining, in
pain is the preferred word here since the character ‘p’ is substituted for ‘r’ and no insertions or deletions take place. The other words (in, raining) are gotten through a rain of deletions and insertions (me don’t like this!).

Now, you’ve gotten my gist (or my dilemma), try to come up with an algorithm that’ll accept as input a source word and a list of target words and output what word I prefer the most. By knowing what target word is “closest” to the source word given, I can determine which youth speaks the better English and finally find my way to the mall!

The solution to the problem is here. But before you go there try to solve it on your own. A hint – this problem is very similar to another distance metric problem.

FlyLatex: A Real Time Collaborative Environment. Some Screen shots of the App

Visit the Github repository of the Free and Open Source FlyLatex app here for more information.

Enjoy!

JSON Pretty Print and JSON Multi level Collapse Code in Javascript and Python

If you are the type of programmer that deals with JSON objects a lot, you are probably familiar with some online programming tools to print out the JSON in a very “pretty” format. These tools not only make dealing with JSON easier and less frustrating but, I must admit, make it more fun too!

A “JSON viewer” app that I use regularly to “pretty-print” complicated JSON objects is at jsonviewer.stack.hu. The app has a very intuitive interface and is thus really easy to use. You can just copy a JSON object to the front page of the app or pull a JSON object from a remote location and then “format” the json. There are many more helpful JSON viewer apps and extensions that are helpful for viewing JSON.

Have you ever had the problem of trying to “pretty-print” your JSON object in your program or app for users to see, or to “collapse” your multi-level JSON object (which might contain arrays in objects and objects of arrays and …) programmatically into one level? I have certainly. Programmers that usually have these problems regularly use or make RESTFUL api calls — although RESTful “resources” can be transmitted in XML, SOAP, or even YAML, the predominant format on the web is JSON.

“JSON multi-level Collapse” Code in Javascript and Python

I cooked up the “multi-level collapse JSON” algorithm three days ago because I needed to, given a bunch of streaming JSON objects, collapse each JSON object into the most minimal form and then assemble the JSON objects into a CSV file where each JSON object occupies only one line in the CSV. Yes, my program had to first collapse any JSON object (might contain embedded objects or arrays of objects of arrays of objects of…) into a one-level JSON object without losing any information.

“Multi-level collapse” code in Javascript


// CollapseLib by Daniel Alabi (alabidan.me)
// isPlainObject is part of the jQuery source (I modified the method a little)
/**
* Example use:
* complicated = {"dict1key": {"dict2key": [{"dict3key": {"tell":"me"}}]}}
*
* var dict = CollapseLib.collapseDict(collapse);
* console.log(JSON.stringify(dict, undefined, 2));
*
*/
// todo: fix bug with empty plain object
var CollapseLib = {
/**
*
* @warning allowed types for complexDict : {}, [], JS primitives (int, float, or string)
*
* @param complexDict : a JS object that might have inner JS objects and arrays OR
* a JS array that might have inner JS objects and arrays OR
* @param plainDict : a one-level collapse JS object
*/
// if you have an empty object, just return an empty object
collapseDict : function(complexDict) {
// make plain object to return
var plainDict = {}
, sawComplex = false
, subDict;
if (CollapseLib.isPlainObject(complexDict)) {
// if complexDict is a JS object
sawComplex = false;
for (var complexKey in complexDict) {
// if complexDict[complexKey] is an inner dict
if (CollapseLib.isPlainObject(complexDict[complexKey])) {
if (CollapseLib.isEmptyObject(complexDict[complexKey])) {
return complexDict;
}
subDict = complexDict[complexKey];
sawComplex = true;
for (var subKey in subDict) {
plainDict[complexKey+"."+subKey] = CollapseLib.collapseDict(subDict[subKey]);
}
} else if (Array.isArray && Array.isArray(complexDict[complexKey])) {
if (!CollapseLib.isComplexArray(complexDict[complexKey])) {
plainDict[complexKey] = CollapseLib.getStrFromArray(complexDict[complexKey]);
} else {
sawComplex = true;
for (var i = 0; i < complexDict[complexKey].length; i++) {
plainDict[complexKey + "[" + i + "]"] = CollapseLib.collapseDict(complexDict[complexKey][i]);
}
}
} else {
plainDict[complexKey] = CollapseLib.collapseDict(complexDict[complexKey]);
}
}
if (sawComplex) {
return CollapseLib.collapseDict(plainDict);
} else {
return plainDict;
}
} else {
if (Array.isArray && Array.isArray(complexDict)) {
plainDict = {};
// if complexDict is an array
// that contains an inner array or inner plain object
if (CollapseLib.isComplexArray(complexDict)) {
for (var i = 0; i < complexDict.length; i++) {
plainDict["["+i+"]"] = CollapseLib.collapseDict(complexDict[i]);
}
}
return CollapseLib.collapseDict(plainDict);
} else {
return complexDict.toString();
}
}
}
, isComplexArray : function(arr) {
for (var i = 0; i < arr.length; i++) {
if ((Array.isArray && Array.isArray(arr[i]))
|| CollapseLib.isPlainObject(arr[i])) {
return true;
}
}
return false;
}
, getStrFromArray : function(arr) {
return arr.toString();
}
, isPlainObject: function( obj ) {
var hasOwn = Object.prototype.hasOwnProperty;
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if ( !obj || typeof obj !== "object" || obj.nodeType) {
return false;
}
try {
// Not own constructor property must be Object
if ( obj.constructor &&
!hasOwn.call(obj, "constructor") &&
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for ( key in obj ) {}
return key === undefined || hasOwn.call( obj, key );
}
, isEmptyObject: function(obj) {
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
return false;
}
}
return true;
}
}

“Multi-level collapse” code in Python


"""
# How to use:
complicated_dict = {"dict1key": {"dict2key": [{"dict3key": {"tell":"me"}}]}}
one_level_dict = makeSimpleDict(complicated_dict)
print one_level_dict
# prints out {'dict1key.dict2key.[0].dict3key.tell': u'me'}
"""
def makeSimpleDict(complex_dict):
"""
@param complex_dict : a python dict that might have inner dicts and arrays OR
a python list that might have inner dicts and arrays OR
a python object that's neither list of dict
@return plain_dict : plain dict that has only one level or a plain python object
"""
# make plain dict that you will return
plain_dict = {}
if isinstance(complex_dict, dict):
# if complex_dict is a dict
# loop through the keys of this complex dict
sawComplex = False
for complex_key in complex_dict:
# if complex_dict[complex_key] is a dict
if isinstance(complex_dict[complex_key], dict):
sub_dict = complex_dict[complex_key]
# loop through the keys of this sub_dict
sawComplex = True
for sub_key in sub_dict:
plain_dict[complex_key+"."+sub_key] = makeSimpleDict(sub_dict[sub_key])
elif isinstance(complex_dict[complex_key], list):
if not isComplexList(complex_dict[complex_key]):
plain_dict[complex_key] = getStrFromList(complex_dict[complex_key])
else:
sawComplex = True
for i in range(len(complex_dict[complex_key])):
plain_dict[complex_key+"["+str(i)+"]"] = makeSimpleDict(complex_dict[complex_key][i])
else:
plain_dict[complex_key] = makeSimpleDict(complex_dict[complex_key])
if sawComplex:
return makeSimpleDict(plain_dict)
else:
return plain_dict
else:
# if not a dict
if isinstance(complex_dict, list):
# if complex_dict is a list
# is complex_dict a list
# that contains a dict or an inner list?
if not isComplexList(complex_dict):
accum = getStrFromList(complex_dict)
plain_dict = accum
else:
# loop through the complex_dict
for i in range(len(complex_dict)):
plain_dict["["+str(i)+"]"] = makeSimpleDict(complex_dict[i])
return makeSimpleDict(plain_dict)
else:
# if neither a list nor a dict
return unicode(complex_dict)
def isComplexList(ls):
for each in ls:
if isinstance(each, dict) or isinstance(each, list):
return True
return False
def getStrFromList(ls):
if isinstance(ls, list):
return ", ".join([unicode(each) for each in ls])
else:
return ls

For example, the output of the “multi-level” algorithm on input the JSON object


{"apiVersion":"2.0","data":{"updated":"2010-01-07T19:58:42.949Z","totalItems":800,"startIndex":1,"itemsPerPage":1,"items":[{"id":"hYB0mn5zh2c","uploaded":"2007-06-05T22:07:03.000Z","updated":"2010-01-07T13:26:50.000Z","uploader":"GoogleDeveloperDay","category":"News","title":"Google Developers Day US – Maps API Introduction","description":"Google Maps API Introduction …","tags":["GDD07","GDD07US","Maps"],"thumbnail":{"default":"http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg&quot;,"hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;},"player":{"default":"https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,"mobile":"https://m.youtube.com/details?v=hYB0mn5zh2c&quot;},"content":{"1":"rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;,"5":"http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,"6":"rtsp://v1.cache1.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;},"duration":2840,"aspectRatio":"widescreen","likeCount":171,"rating":4.63,"ratingCount":68,"viewCount":220101,"favoriteCount":201,"commentCount":22,"status":{"value":"restricted","reason":"limitedSyndication"},"accessControl":{"syndicate":"allowed","commentVote":"allowed","rate":"allowed","list":"allowed","comment":"allowed","embed":"allowed","videoRespond":"moderated"}}]}}

is


{
"apiVersion": "2.0",
"data.updated": "2010-01-07T19:58:42.949Z",
"data.totalItems": "800",
"data.startIndex": "1",
"data.itemsPerPage": "1",
"data.items.[0].id": "hYB0mn5zh2c",
"data.items.[0].uploaded": "2007-06-05T22:07:03.000Z",
"data.items.[0].updated": "2010-01-07T13:26:50.000Z",
"data.items.[0].uploader": "GoogleDeveloperDay",
"data.items.[0].category": "News",
"data.items.[0].title": "Google Developers Day US – Maps API Introduction",
"data.items.[0].description": "Google Maps API Introduction …",
"data.items.[0].tags": "GDD07,GDD07US,Maps",
"data.items.[0].thumbnail.default": "http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg&quot;,
"data.items.[0].thumbnail.hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;,
"data.items.[0].player.default": "https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,
"data.items.[0].player.mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c&quot;,
"data.items.[0].content.1": "rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp",
"data.items.[0].content.5": "http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,
"data.items.[0].content.6": "rtsp://v1.cache1.c.youtube.com/CiILENy…/0/0/0/video.3gp",
"data.items.[0].duration": "2840",
"data.items.[0].aspectRatio": "widescreen",
"data.items.[0].likeCount": "171",
"data.items.[0].rating": "4.63",
"data.items.[0].ratingCount": "68",
"data.items.[0].viewCount": "220101",
"data.items.[0].favoriteCount": "201",
"data.items.[0].commentCount": "22",
"data.items.[0].status.value": "restricted",
"data.items.[0].status.reason": "limitedSyndication",
"data.items.[0].accessControl.syndicate": "allowed",
"data.items.[0].accessControl.commentVote": "allowed",
"data.items.[0].accessControl.rate": "allowed",
"data.items.[0].accessControl.list": "allowed",
"data.items.[0].accessControl.comment": "allowed",
"data.items.[0].accessControl.embed": "allowed",
"data.items.[0].accessControl.videoRespond": "moderated"
}

“Pretty Print” Code in Javascript

The goal of the “Pretty Print” code is to, given a JSON object (usually used for complicated json objects that’s multi-level and really nested), print the JSON object in a very clear way so that the user sees the embedded arrays, embedded JSON objects, and embedded arrays in objects and vice versa present in the initial parent object.

So for example, the output of the “pretty print” algorithm on input the JSON object below


{"apiVersion":"2.0","data":{"updated":"2010-01-07T19:58:42.949Z","totalItems":800,"startIndex":1,"itemsPerPage":1,"items":[{"id":"hYB0mn5zh2c","uploaded":"2007-06-05T22:07:03.000Z","updated":"2010-01-07T13:26:50.000Z","uploader":"GoogleDeveloperDay","category":"News","title":"Google Developers Day US – Maps API Introduction","description":"Google Maps API Introduction …","tags":["GDD07","GDD07US","Maps"],"thumbnail":{"default":"http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg&quot;,"hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;},"player":{"default":"https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,"mobile":"https://m.youtube.com/details?v=hYB0mn5zh2c&quot;},"content":{"1":"rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;,"5":"http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,"6":"rtsp://v1.cache1.c.youtube.com/CiILENy…/0/0/0/video.3gp&quot;},"duration":2840,"aspectRatio":"widescreen","likeCount":171,"rating":4.63,"ratingCount":68,"viewCount":220101,"favoriteCount":201,"commentCount":22,"status":{"value":"restricted","reason":"limitedSyndication"},"accessControl":{"syndicate":"allowed","commentVote":"allowed","rate":"allowed","list":"allowed","comment":"allowed","embed":"allowed","videoRespond":"moderated"}}]}}

is


{
"apiVersion": "2.0",
"data": {
"updated": "2010-01-07T19:58:42.949Z",
"totalItems": 800,
"startIndex": 1,
"itemsPerPage": 1,
"items": [
{
"id": "hYB0mn5zh2c",
"uploaded": "2007-06-05T22:07:03.000Z",
"updated": "2010-01-07T13:26:50.000Z",
"uploader": "GoogleDeveloperDay",
"category": "News",
"title": "Google Developers Day US – Maps API Introduction",
"description": "Google Maps API Introduction …",
"tags": [
"GDD07",
"GDD07US",
"Maps"
],
"thumbnail": {
"default": "http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg&quot;,
"hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg&quot;
},
"player": {
"default": "https://www.youtube.com/watch?v=hYB0mn5zh2c&quot;,
"mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c&quot;
},
"content": {
"1": "rtsp://v5.cache3.c.youtube.com/CiILENy…/0/0/0/video.3gp",
"5": "http://www.youtube.com/v/hYB0mn5zh2c?f…&quot;,
"6": "rtsp://v1.cache1.c.youtube.com/CiILENy…/0/0/0/video.3gp"
},
"duration": 2840,
"aspectRatio": "widescreen",
"likeCount": 171,
"rating": 4.63,
"ratingCount": 68,
"viewCount": 220101,
"favoriteCount": 201,
"commentCount": 22,
"status": {
"value": "restricted",
"reason": "limitedSyndication"
},
"accessControl": {
"syndicate": "allowed",
"commentVote": "allowed",
"rate": "allowed",
"list": "allowed",
"comment": "allowed",
"embed": "allowed",
"videoRespond": "moderated"
}
}
]
}
}

The “pretty print” code in Javascript

It’s just a simple line of JS but not many people know about how to pretty print using an already existing function in JS.


JSON.stringify(objectToPrettyPrint, undefined, 2);

For more information, check out the MDN Docs