Posted: August 24th, 2009 | Author: Michel Rijnders | Filed under: Haskell, Ruby Quiz | No Comments »
The Quiz
Write a program that tells whether a given integer is happy. A happy number is found using the following process: Take the sum of the squares of its digits, and continue iterating this process until it yields 1, or produces an infinite loop. (The complete, original quiz is here.)
A Haskell Solution
module Main where
import System (getArgs)
digits :: Int -> [Int]
digits = map (\c -> read [c] :: Int) . show
happy :: Int -> Bool
happy n = happy' n []
where
s = sum . map (\x -> x * x) . digits
happy' n ns
| s n == 1 = True
| s n `elem` ns = False
| otherwise = happy' (s n) (n : ns)
main :: IO ()
main = do
args <- getArgs
if happy (read (head args) :: Int)
then putStrLn ":-)"
else putStrLn ":-("
return ()
Posted: August 24th, 2009 | Author: Michel Rijnders | Filed under: Cake, Open Source Projects | No Comments »
Cake is progressing rather slowly at the moment. Its next release (0.2) is about receiving requests, and thus will involve lots of networking code. Since I know very little about network programming I am first working my way through "UNIX Network Programming", Volume 1.
In the meantime, to still do some Haskell coding, I’m trying to solve some Perl and Ruby quizzes in Haskell. I’ll post my solutions plus explanations here.
Posted: August 19th, 2009 | Author: Michel Rijnders | Filed under: Haskell, Perl Quiz of the Week | 1 Comment »
The Quiz
We are given two positive integers $L and $R we need to find Plusified
expressions of both for which Eval($E_L) == Eval($E_R). So what is a plusified
expression? It is an expression where we can choose whether to add a single
"+" between any consecutive digit. So for example the number 123 has the
following plusified expression:
So if we are given 123 and 96 we can form the following plusified equation:
Your mission is to write a Perl program (or an equivalent program in any
programming language) that will find all solutions to the plusified equation
of two numbers given as input. To normalise the output we’ll rule that:
- The equations should be given one at each line.
- They will be sorted so consecutive digits will take precedence over "+"'s.
- A "+" has no surrounding spaces.
- The = sign does have a preceding and following space.
A Haskell Solution
Listing of the complete solution:
module Main where
import Data.List (iterate)
import System (getArgs)
split :: Char -> String -> [String]
split delim s =
let (s', s'') = break (== delim) s
in s' : case s'' of
delim : _ -> split delim (tail s'')
otherwise -> []
plusify :: String -> [String]
plusify "" = [""]
plusify (c : "") = [c : ""]
plusify (c : cs) = concatMap (\cs' -> [c : cs', c : '+' : cs']) (plusify cs)
combis :: String -> String -> [(String, String)]
combis x y =
[(l, r) | l <- plusify x, r <- plusify y, sum' l == sum' r]
where sum' = sum . map (\s -> read s :: Int) . split '+'
main :: IO ()
main = do
args <- getArgs
mapM_ (putStrLn . \(l, r) -> l ++ " = " ++ r) (combis (args!!0) (args!!1))
return ()
Posted: July 22nd, 2009 | Author: Josh Kalderimis | Filed under: Ruby | Tags: i18n, open source, paperclip | 3 Comments »
Paperclip is a fantastic library used by many many many developers, its github project page shows 1500 watchers but I have a feeling even more than that use the plugin in some shape or form.
The one thing that has been missing for me is proper I18n support and not basic interpolations using the :message option. I recently chanced upon an issue in the github issues registry (#14) which included a fork that implemented a basic version of I18n support but did not go far enough in my opinion. So after taking some advice from validates_timeliness, I have created a fork with goes a little bit further and adds two new messages for the attachment size.
The only thing now is to get some support for this fork so it gets patched into paperclip.
So without further ado, please support this change by leaving a message in the google group thread regarding this change:
Google Group Message – I18n changes and additions
And voting for this issue to be resolved:
Github Issue – Support for I18n
Also, if you have any questions, comments or advice regarding the fork, please don’t hesitate to leave a message below.
Posted: July 16th, 2009 | Author: Josh Kalderimis | Filed under: Ruby, Web Development | No Comments »
One of the most popular open-source indexers for web development has to be Sphinx, an sql full-text search engine. Sphinx has been used by many high profile site, including The Pirate Bay, Craigs List, and NetLog, to name the big ones (more here).
But this post is not about Sphinx, but its Ruby helper library, Thinking Sphinx. In fact, its not just about Thinking Sphinx, finding and fixing a problem yourself.
Thinking Sphinx is an amazing open source gem/plugin/library for Rails, masterminded by the great Pat Allan (@pat), and available to all on github. In fact, with 89 contributors and climbing, this library has had some tender love and care for many caring developers. If you are a Ruby developer and you are interested in indexing, have a look at Thinking Sphinx today, it is simple to install and use, fast and effective, and has some excellent documentation and a very active google group.
Recently while working on a new project for a client of ours I encountered an annoying issue/problem/bug with Thinking Sphinx, more specifically, DateTime multi-value attributes. A multi-value attribute (MVA) is like specifying an array of values for a specific field, for example, employee names, the trouble is that MVAs can only be integers so strings need to be converted (CRC values, CRC32) and datetimes need to be converted to unix timestamps. In Thinking Sphinx MVAs are usually defined through the relationships a model might hold, eg. an office has many employees.
Thinking Sphinx had no problem with me specifying MVAs of integers, but datetimes where a bit of an issue due to two issues, one is the converting, and the other is the group concat to add them all together with commas (like an array). Now, to say that it was an issue makes it sound worse than it really was, because by breaking down the issue into the two parts, converting and concatenating, two improvements could be made at the same time.
So after a brief chat with Pat on the google group to confirm the issue, and on a perfect sunday to be inside (hungover and not great weather), I forked Thinking Sphinx on github (gotta love github for making forking projects so easy) and created a four commit patch which solved the MVA datetime issue for everyone. This patch has since been pulled into the master Thinking Sphinx project so others can use datetime columns as MVAs without having to think about it.
The whole experience of finding this bug, fixing it, and submitting a patch, has reenforced a very important lesson for all developers. If you run into a problem which you do not believe is excepted behavior, do not run away from it and try to find a workaround, get into the code and try to find out where and why the problem is occurring. Its very easy to use libraries and gems and plugins without really knowing how they work or what they do, but if you never get your hands dirty and investigate what is going on then you never learn.
If you can’t find the problem, ask for help on the message boards or by emailing the maintainer. On the other hand, if you do find the problem, check with the maintainer if he can confirm your findings.
Next, create a patch which fixes the issue and does not break or alter current functionality (unless it really does need altering).
And last but not least, share the patch with the community. (make the world a better place)
By the time you have finished with the patch you will not only know the code a lot better, but you would have learnt a truck load about the library, which in the long run is a huge advantage as you are not blindly trusting code written by a hoard of other developers but know first hand what is going on.
Posted: June 21st, 2009 | Author: Michel Rijnders | Filed under: Haskell, Real World Haskell | No Comments »
My solution to the exercise on p. 352.
1.Rewrite getRandom to use do notation.
getRandom :: Random a => RandomState a
getRandom = do
gen <- get
let (val,gen') = random gen
put gen'
return val