August 1st, 2006
Unmemoize
I tried to add an unmemoize function to the memoize module I talked about earlier:
module Memoize
def memoize(func_name)
cache = {}
(class<<self; self; end).send(:define_method, "#{func_name}u", method(func_name).clone)
(class<<self; self; end).send(:define_method, func_name) do |*args|
return cache[args] if cache.has_key? args
cache[args] = super
end
end
def unmemoize(func_name)
(class<<self; self; end).send(:define_method, func_name) do |*args|
eval(func_name.to_s+"u(#{args})")
end
end
end
So now you can memoize a function and then, at a later point, unmemoize:
def fib(n) return n if n < 2 fib(n-1) + fib(n-2) end include Memoize memoize(:fib) ... fib(15) ... unmemoize(:fib) ... fib(15) ...
It works — in that the function actually unmemoizes, but the function takes noticeably longer than the original function. There’s definitely something I’m not doing right — I don’t know what though.
Anyway, it’s been a long and tiring day. Later.
July 24th, 2006
Memoize
MJD was talking about Memoize. Here it is in Ruby:
module Memoize
def memoize(func_name)
cache = {}
(class<<elf; self; end).send(:define_method, func_name) { |*args|
return cache[args] if cache.has_key? args
cache[args] = super
}
end
endThere’s a lot of code in the Perl Memoize module; maybe it does other things—I haven’t really looked. Oh, and here’s this Memoize module from RAA. I’m some months late. :-)
Here’s some pictures from Portland.
May 4th, 2006
People in Bangalore like to eat out on Sundays
Interestingly, folks in Bombay seem to like eating out on Tuesdays:
Notes:
1. Most people seem to end up using the tag hotel when they really mean to use restaurant, so I’ve gone with the former.
2. I rely on Flickr photo data and my program. You don’t have to take the graphs seriously.
Here’s the script I wrote to draw that graph (requires flickr.rb and rgplot):
#!/usr/local/bin/ruby18
require "../flickr"
require "gnuplot"
API_KEY = "078be2728a42f4e8228f2c2b8c9b6cca"
flickrObj = Flickr::Flickr.new(API_KEY, "")
photosObj = Flickr::Photos.new
days = Hash.new { |h,k| h[k] = 0 }
photosObj.search(["#{ARGV[0]}","hotel"], "all", 0, 1000).each { |ele|
if /([0-9]+)\-([0-9]+)\-([0-9]+)/.match(photosObj.get_info(ele)["date_taken"])
begin
t = Time.mktime($1, $2, $3)
days[t.strftime("%a")] += 1
rescue
end
end
}
Gnuplot.open do |gp|
Gnuplot::Plot.new(gp) do |plot|
plot.title "Photos taken in restaurants in #{ARGV[0]}"
plot.ylabel "No. of Photos"
plot.xlabel "Days"
i = 0
plot.xtics("("+days.keys.map{|ele| "'#{ele}' #{i;i+=1}"}.join(",")+")")
plot.data << Gnuplot::DataSet.new([(1..7).to_a, days.values]) do |ds|
ds.with = "linespoints"
ds.notitle
end
end
end
Usage: ./eating-out.rb city_name
Enjoy!
March 30th, 2006
Export Firefox Bookmarks to Safari
Firefox on OS X sucks. Big time. I decided to move to Safari, but I couldn’t do that without exporting my bookmarks. Here’s how I did it:
The Firefox bookmarks is in an HTML file. It’s typically located at ~/Library/Application Support/Firefox/Profiles/<profile name>/bookmarks.html. Safari stores its bookmarks at ~/Library/Safari/Bookmarks.plist, which is a binary file.
Use this simple script to export your Firefox bookmarks as a readable XML, and follow these steps:
renegade:~ $ ruby ff2safari.rb > ~/Library/Safari/Bookmarks.xml renegade:~ $ cd ~/Library/Safari/ renegade:~/Library/Safari $ mv Bookmarks.plist Bookmarks.plist.backup renegade:~/Library/Safari $ plutil -convert binary1 -o Bookmarks.plist Bookmarks.xml
Note that this script simply dumps all your Firefox bookmarks in Safari’s Bookmarks Bar. (I have a very few bookmarks on my browser, most of which are in the Bookmarks Toolbar.) You could use an XML parser to export bookmarks as is. To understand the format of the XML you need to generate, you might want to export the existing Safari Bookmarks file to XML:
renegade:~/Library/Safari $ plutil -convert xml1 -o readable.xml Bookmarks.plist
One interesting thing to note: a ktrace/kdump on Safari didn’t do any open on Bookmarks.plist. I wonder why.
This post brought to you from Safari.
February 3rd, 2006
Watch Google videos in any country
I never used Google Video before. But now that some of Google’s tech talks are available online, I decided to take a look. Turns out I can’t view videos from India (and some other countries). This is the message you’d get, for example, when you try watching a Jessica Simpson video:
Thanks for your interest in Google Video.
Currently, the playback feature of Google Video isn't available in your country.
We hope to make this feature available more widely in the future, and we really appreciate your patience.
Of course, there are solutions, like using a proxy, etc. Anyway, here’s a Greasemonkey script to fix that thing.
January 29th, 2006
When Code Flows Like Poetry
It’s not always that you get to solve complex problems. Many a time you need to implement something—something that you know is silly enough. How do you feel? Bored, I know. However, there’s small amount of joy you get when the tool you use lets you be creative. (Of course, there’s a distinction between the larger problem at hand and the smallest implementable part of it; it is the typically joyless implementation of this small part that I’m talking about.)
I had a situation where I had to read a data file that had on each line data like thus:
foo:bar
Obviously, you want to hold all that data in a hash. Implementing this in a typical programming language would, in pseudocode, look something like thus:
data = file("data.txt").read
hsh = {}
foreach line in data do
k, v = line.split(":")
hsh["k"] = v
end
Simple enough, but boring too. With Ruby, I can play:
hsh = Hash.new
File.open("test.txt").readlines.each { |line|
hsh = hsh.update(Hash[ *line.split(":").
map { |ele| ele = ele.match(/(.*)\n/)[1] rescue ele }
])
}
The Ruby code flows like poetry. Literally. There’s an extremely elegant solution, like why pointed out to me:
Hash[*IO.read('test.txt').scan(/^(.+?):(.*)/).flatten]
But then I’d say there are no blocks there. :-)
There are many such Ruby gems scattered all around. I’ll point you to some of them I found on RedHanded:
Go use a better tool, if you can.
November 12th, 2005
360° Tagging (or Leveraging Existing Tagging Platforms)
Yahoo! 360°, as you know, doesn’t have the ability to tag entries as of now. I was wondering if there’s maybe a way I could add tagging to it. And then it struck me: Social Bookmarking!
Any sane social bookmarking site allows you to add a URL and associate a bunch of tags to it; and also has the capability to return a bunch of tags given a URL.
So, yeah, obviously it’s a Greasemonkey script. You get the idea now, I guess. I thought of using Yahoo!’s My Web 2.0 for this, but then there isn’t a push API. del.icio.us turned out to be my ideal candidate — they have post/get APIs, and they use HTTP authentication (which means no complications).
So this is how it works:
- The script basically figure out the permalinks and titles of the blog posts, and store then as hidden variables in the forms that you see.
- When you 'Add Tags', the permalink gets posted (through a PHP script proxy) as the URL to be bookmarked, and the title gets posted as the description (or the equivalent).
- Now when you want to view posts with any tag, I just append a ?tag=foo to the blog URL, and it displays titles of all those posts, pointing to their permalinks.
Let’s take a look at a couple screenshots:
So to add a tag, you need to go to your My Blog page. Adding tags (space-delimited) is pretty straightforward, as you can see in the screenshot above. Now one problem is that I couldn’t find an API in del.icio.us that lets me add tags to an existing bookmarked URL. (I could maybe figure out tags for an existing URL, then add the new tag to the list, delete the URL, and then bookmark again... but, well, that’s too much of a pain.)
That's the same My Blog page when you pass a tag query to it — ?tag=code, in this case.
One thing — and an important one at that — lacking here is that only the logged-in user can make use of the tags. That’s kinda sad, but del.icio.us doesn’t have an API where I can do a tag lookup without requiring authentication information. Once they have such an API, it’d be pretty cool — all you’ll need to do is install (a modified version of) this script, and you’ll be able to see what others have tagged their posts, and browse their posts using tags.
So as of now what this script does is it makes your life easier if you want to categorize your blog posts... for you.
More interestingly, this script demonstrates how to leverage an existing tagging platform (del.icio.us, in this case), and make use of it in an application (Yahoo! 360°, in this case). Of course, using Greasemonkey is not really a solution but, hey, it works!
The script: 360.user.js.
NOTE: Like I mentioned earlier, the script uses a PHP proxy to interact with del.icio.us. Now I don’t do anything evil within the script but, if you’re like me, you might wanna get the source and host it on your box or something.
August 3rd, 2005
GeoURL Yahoo! Mapping
Quick Yahoo! Maps hack that maps sites close to a given URL using GeoURL data. I think I remember seeing something like this on some site, but the mapping there was for the owner’s site only, AFAIK.
Try it out here.
The image that you see, that’s Jeremy’s blog’s geomap. And that’s Marc’s blog highlighted there.
FWIW, I couldn’t use my blog URL because I’m in Bangalore.
Oh yeah, hi all! :-)
July 21st, 2005
Greasemonkey Dict
It’s quite common to lookup dictionaries for words on web pages. I wrote a Greasemonkey script to make life a tad easier for me:
Now I don’t know if there’s such a script already. Anyway, doesn’t matter now. I’m using OneLook to fetch the definition. I know it’s probably not the best thing to do, however, I don’t know of any dictionary services that provide an API. Know any?
Well, I could set one up locally, but that’d work for me only. Oh well. Laters.
Oh yeah, using it: just double click on the word that you want to know the meaning of... if it does mean anything, a ncie box will appear, nothing happens otherwise.
Script’s here. That’s it for now from Monkeyland!
July 4th, 2005
Flickr Tags Autocomplete
Yeah, well, yet another Greasemonkey autocomplete script. If you go to Flickr’s Photos upload page, there’s no provision to select from your tags to add tags. Moreover, the default browser autocomplete obviously doesn’t understand Flickr’s space-delimited tagging. So when you type a character it’d provide you the entire set of tags that you might have typed earlier.
This script, on the other hand, has undergone rigorous training from folks at Flickrland and Monkeyland. After you type a space in the tags text box, the script will autocomplete for the character after the space. It’s kinda buggy, let me tell you. Get the script here. And don’t forget to set user_id—some-number@N00—in flickr_request().
That’s it from Monkeyland for now.
June 17th, 2005
Skip Slashdot Comment Preview
On any of Slashdot’s Post Comment pages—this, for example:
...
Logged-in users aren't forced to preview their comments.
...
Now forcing users—whether Anonymous Cowards or not—to preview sucks. I hate it. And it’s stupid considering I can get rid of it. Here’s the Greasemonkey script you’d require. It adds a ‘Submit’ button on the page, and sets a hidden variable op—which, apparently, Slashdot uses to identify whether it’s a preview, or submit, or whatever—set to value Submit.
Well, I thought that alone would have done the job. Turned out there’s some more weird shit that it does internally—and I’m not terribly sure what all. My guess is that it does some session stuff, where it sets some flag to indicate that the comment-to-be-posted has been previewed. So, the script, when you click on submit, first does a xmlhttpRequest with op=Preview, and then submits the form. Seems to work.
That’s it from Monkeyland for now.
June 4th, 2005
Lua API for Yahoo! Search Web Services
Lua is still very much an academic language—everyone seems to whip their own version to suit their needs. But it seems kinda interesting. Actually, I’m interested in taking a look at the C API. Later.
Anyway, not that I expect anyone to use it, but I whipped a Lua API for Yahoo! Search Web Services. Needs refactoring, I realize. Requires LuaSocket, and Roberto’s classic Lua-only XML parser.
Now, you can do stuff like this:
require "YahooSearch"
obj = YahooSearch.WebSearch('premshree')
print(obj[0]['Title']) -- title of first result
print(obj[2]['Url']) -- url of third result
Maybe I’ll try doing some dumb-ass wxLua thingie later.










