Archive for October, 2008
Word Cheat, a simple anagram engine
Posted by Giovanni Intini | Filed under Ruby
Those of you who follow this blog since its inception will be aware of my obsession with word games, and specifically algorithms that solve word games.
Yesterday I was playing Word Challenge on Facebook, a simple game where you have to find all the words that can be composed with six random letters. After a couple of trials I decided to try and solve it with a ruby program, but since I didn’t want to use my previous code I decided to try a new approach to solve this problem.
First of all I took an extensive list of Italian words and filtered it to suit my needs, leaving only the words ranging from three to six letters.
Once I had my wordlist I had to build a data structure that could be used for fast anagrams retrieval, thus the WordHash class was born.
class WordHash attr_reader :words def initialize(wordlist) @words = {} wordlist.each do |word| if @words.has_key?(w = word.strip.signature) @words[w] << word.strip else @words[w] = [word.strip] end end end def get_anagrams(word) result = [] wordlist = @words.each do |k,w| result << w if word.contains?(k) end result end end
This class makes use of two helper methods I added to String, that I think should be really part of the Ruby standard library:
module StringExtensions def signature self.split('').sort.join end def contains?(search) !Regexp.new(search.signature.split("").join(".*")).match(self.signature).nil? end end String.class_eval do include StringExtensions end
The get_anagrams method is used to also get anagrams with a length less than that of the original word.
The whole project, complete with tests and a helper script is available on GitHub, feel free to contribute.
Also, big thanks to Stefano Cobianchi, who contributed with the contains? method, that I really couldn’t code
Radiant iPhone Extension 0.0.1
Posted by Giovanni Intini | Filed under Radiant
Fellow Mikamai – er, all around nice guy, great guitarist and top notch developer Andrea “Pilu” Franz has just released an incredibile extension for the Radiant CMS, the iPhone Extension, it allows you to access your radiant admin interface via iPhone using a nice iPhone optimized GUI. Please check the original article on his blog.
Two improvements to your Capfiles
Posted by Giovanni Intini | Filed under Capistrano, Drupal, Ruby
I have lately started using a pattern that has become quite common among capistrano users: setting the server names and locations in a task. Doing this allows you to have multiple deployment environments, like development, staging, production, and so on.
desc "deploy to development environment" task :development do set :deploy_to, "/var/apps/#{application}" role :web, "servername.mikamai.com", :primary => true role :app, "servername.mikamai.com", :primary => true role :db, "servername.mikamai.com", :primary => true set :user, "username" set :password, "secr3t" set :remote_mysqldump, "/usr/bin/mysqldump" set :db_user, "username" set :db_password, "secre7" set :db_name, "db_name" end
This technique has proven itself to be really useful, especially when clients start to ask for deployments on their test servers, and you still want to be able to deploy to your development servers.
While refactoring my Capfiles I also took the time to rewrite the drupal:db namespace, adding the much needed tasks that allow you dump the remote databases and download them to your development box.
namespace :db do namespace :dump do desc "Deletes old database dumps, leaves only the latest on the server" task :cleanup, :roles => :db do dumps = capture("ls -xt #{shared_path}/dumps").split.reverse run "cd #{shared_path}/dumps; rm #{dumps[0..-2].join(" ")}" end desc "Dumps the local database" task :local, :roles => :db do raise RuntimeError.new("failed dump") unless system "#{local_mysqldump} -u #{local_db_user} --password=#{local_db_password} #{local_db_name} > dump.sql" end namespace :remote do desc "Dumps the remote database" task :default, :roles => :db do filename = "#{Time.now.to_i.to_s}.dump.sql" run "cd #{shared_path}/dumps; #{remote_mysqldump} -u #{db_user} --password=#{db_password} #{db_name} > #{filename}" run "cd #{shared_path}/dumps; bzip2 #{filename}" end namespace :download do desc "Dumps and downloads the remote database" task :default do drupal::db::dump::remote::default latest end desc "Downloads the latest database dump" task :latest, :roles => :db do dumps = capture("ls -xt #{shared_path}/dumps").split.reverse get("#{shared_path}/dumps/#{dumps.last}", "./#{dumps.last}") end end end end