25 October 2012

Hamlet’s Monkey - Code for fun :)

Hamlet’s Monkey

We’ve all heard the jokes before that a monkey could do that job, or a monkey could type better than you. You may have even heard of the Infinite Monkey Theorem, well its something that made me laugh and an interesting programmatic problem:

http://en.wikipedia.org/wiki/Infinite_monkey_theorem

Given infinite time, could a monkey actually type out the works of William Shakespeare? Well I decided the complete works was a bit hard on our poor monkey. Lets start with just Hamlet!

A friend at work and I got to talking, how would we approach this programmatically? How would the monkey actually get on?
So it occurred to me there are two way of approaching this, the easy way and the hard way.

A few notes

  • My random character generator just generates A-Z
  • Case is just not fair, so I’ve made all strings lowercase
  • I’ve removed all punctuation

Green Light

I called it this because as soon as the monkey guesses a letter correctly, he gets a green light and moves onto the next letter. The correct letter is “banked” and he never has to start over. The hard bit here was really only how to progress, should we be removing the last letter added or just moving on?

Pastebin
<!--- Static Variables --->
<cfset variables.lstAlphabet         = "ABCDEFGHIJKLMNOPQRSTUVWXYZ">
<cfset variables.intNumLoops        = 100>
<cfset variables.Shakespeare        = "All your base are belong to me">

<cffunction name="generateRandomLetter" access="public" returntype="string" output="false">
    <cfset var strLowerCaseAlpha = "abcdefghijklmnopqrstuvwxyz">
    <cfreturn Mid(strLowerCaseAlpha,RandRange( 1, Len( strLowerCaseAlpha ) ),1)>
</cffunction>

<cfscript>
    variables.intCount                 = 0;
    variables.bProgress                = true;
    variables.strSubString            = "";
    variables.strShakespeare        = lcase(variables.Shakespeare.replaceAll("[^a-zA-Z]", "")); //Shakespeare without spaces etc
    variables.stuJson                = {};
    variables.strMonkeyString        = "";

    while (variables.intCount < variables.intNumLoops) {
        variables.intCount++;
        
        if(variables.bProgress EQ true){
            //we're adding a new letter
            variables.strMonkeyString    =    variables.strMonkeyString & generateRandomLetter();
        }else if(len(variables.strMonkeyString) EQ 1){
            //monkey string is just 1 char, just re-guess
            variables.strMonkeyString    =    generateRandomLetter();
        }else{
            //we're re-guessing the last letter, so we need to remove it, then add a new one.
            variables.strMonkeyString    =    left(variables.strMonkeyString,len(variables.strMonkeyString)-1) & generateRandomLetter();
        }
        
        //what we're expecting so far
        variables.strSubString    =    left(variables.strShakespeare,len(variables.strMonkeyString));

        //Did monkey do it?
        if(variables.strMonkeyString EQ variables.strSubString){
            if(variables.strMonkeyString EQ variables.strShakespeare){
                //100%
                customOutput("**WINNER**: " & variables.strMonkeyString);
                break;
            }else{
                //Good so far, progress to next letter
                variables.bProgress    =    true;
            }
        }else{
            variables.bProgress    =    false;
        }
    }
    
    writeoutput(variables.intCount);
    writeoutput("<br />");
    writeoutput(left(variables.strMonkeyString,len(variables.strMonkeyString)-1));
</cfscript>

Red Light

This is the hard way, the monkey has to get every letter of Hamlet correct and sequentially. If he makes a mistake, he starts from the beginning. I think this is the way the theorem is intended, but it probably won’t result in much success for the poor monkey! The code is actually pretty simple.

Pastebin
<!--- Static Variables --->
<cfset variables.lstAlphabet         = "ABCDEFGHIJKLMNOPQRSTUVWXYZ">
<cfset variables.intNumLoops        = 500>
<cfset variables.Shakespeare        = "All your base are belong to me">

<cffunction name="generateRandomLetter" access="public" returntype="string" output="false">
    <cfset var strLowerCaseAlpha = "abcdefghijklmnopqrstuvwxyz">
    <cfreturn Mid(strLowerCaseAlpha,RandRange( 1, Len( strLowerCaseAlpha ) ),1)>
</cffunction>

<cfscript>
    variables.intCount                 = 0;
    variables.strSubString            = "";
    variables.strShakespeare        = lcase(variables.Shakespeare.replaceAll("[^a-zA-Z]", "")); //Shakespeare without spaces etc
    variables.strMonkeyString        = "";
    variables.strBestSoFar            = "";
    
    while (variables.intCount LT variables.intNumLoops) {
        variables.intCount++;
        
        //generate the random guess, one keystroke at a time
        variables.strMonkeyString    = variables.strMonkeyString & generateRandomLetter();
        
        variables.strSubString        = left(variables.strShakespeare,len(variables.strMonkeyString));
        
        //check if we have a match
        if(variables.strMonkeyString EQ variables.strSubString){
            if(len(variables.strSubString) GT len(variables.strBestSoFar)){
                variables.strBestSoFar    =    variables.strSubString;
            }
        }else{
            variables.strMonkeyString    = "";
        }
    }
    
    writeoutput(variables.intCount);
    writeoutput("<br />");
    writeoutput(variables.strBestSoFar);
</cfscript>

Critisicm, comments and feedback welcome, but just a bit of fun.

19 July 2012

Connect Amazon EC2 Instance to RDS DB

This cost me some time and by the looks of some Google searches it cost a few other people time too.

You need to first click on DB Security Groups and add the Elastic IP of your EC2 instance as an CIDR. The important bit that I missed is you also need to add the EC2 Security Group that your EC2 instance is configured with.

This guy figured it out:
http://chris-allen-lane.com/2011/07/amazon-ec2-instance-cannot-connect-to-amazon-rds-database-server/

17 July 2012

Dropbox integration with EC2 Linux instance

So Dropbox has a great linux command line tool which comes in very useful for copying files to your Amazon linux EC2 instance, without having to open up FTP or copying each file by hand. It took me ages figuring out how to set this up, but it saves a lot of time.

First we download dropbox and unzip it:
$ wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86"
$ tar -xvzf dropbox.tar.gz
Run it:
$ ~/.dropbox-dist/dropboxd &

..and you should see a message like this:
"This client is not linked to any account... Please visit https://www.dropbox.com/cli_link?host_id=XXXXX to link this machine."
Copy/paste that URL into a Web browser on your local machine; log into dropbox; and voila! The directory ~/Dropbox will be linked into your home directory! The repeating message on your console should then stop. If it doesn't press Ctrl+C.

You should now see a new folder called "Dropbox" sync'd with your dropbox account.

Now we need a package called dropbox.py, this is the dropbox command line tool. Very useful, if a little tricky to use sometimes.

$ wget -O ~/dropbox.py "http://www.dropbox.com/download?dl=packages/dropbox.py"

First there's a few folders we don't want sync'd so we add them to the exclude list.

$ python dropbox.py exclude add ~/Dropbox/Public   
Excluded: 
Dropbox/public
$ python dropbox.py exclude add ~/Dropbox/Photos 
Excluded: 
Dropbox/photos

Now we're going to add a symbolic link. This links our dropbox folder to our web root.

$ python dropbox.py dropbox stop                   
Dropbox daemon stopped.
$ sudo mv ~/Dropbox /opt/railo/tomcat/webapps
$ ln -s /opt/railo/tomcat/webapps/Dropbox ~/
$ python dropbox.py dropbox start
Starting Dropbox...Done!

13 July 2012

13 May 2012

ColdFusion Railo deployment with Jelastic

I thought I'd try one of the cloud java hosting platforms out there and I must say I'm delighted I did. I wanted to start up a Jelastic instance and throw Railo on it and see how it worked out.

First up sign in is super simple, just your email and thats all you need. The user interface is clean, powerful and incredibly simple. With simple drop downs to create your environment and configure the number of instances etc that you need. In just a few minutes you can be up and running.
So i chose Tomcat 6. I did initally try Tomcat 7 but apparently they have a few problems with 7 at the moment. Not to worry 6 is fine. Deploy your environment and then wait for it to be deployed. This takes just a minute or so while they build your instance.

Then down at the bottom you'll see the deployment manager tab, under that you should see upload. You'll need to upload your Railo.war you can upload one you've downloaded, or I believe, upload direct from www.getrailo.org:

Once you've uploaded the .war file, you need to deploy it. Simple, still in the deployment manager tab, click on the box dropdown and click deploy. It'll ask you to confirm "ROOT" as the context, but root is fine. Once this is done you should be able to click the "launch in browser" button and see the railo admin show.

That's it, you're basically done. I expect you want your own application to run, but that's just as easy. If you click on the spanner / config option next to Tomcat 6 a settings tab will open and you can tweak the tomcat settings. Expand webapps and root. This is your application home, you can delete everything in there except for the WEB-INF folder. Then upload your cfm files and you're done!

I think this is a brilliant hosting environment and so brethlessly simple I'm very impressed.

07 May 2012

Setting up a custom domain for your Google App Engine (GAE) app

Setting up a Google App Engine application with a custom domain is a pain in the ass. Its overly complicated and takes much too long. Still, i did it and made it work, so I figured I’d write it down.

  1. Sign into GAE and in the list of my applications, click on your application. You should see the GAE dashboard. Somewhere down the list on the left you should see Application Settings. Click on that. Scroll way down and somewhere under “Domain Setup” you’ll see a button “Add Domain”. Now open a new window or something because we’ll need to come back to this tab later. This is where you’ll need to signup for Google Apps.

  2. Google Apps. I’m not 100% sure exactly how to define Google Apps, but I think it’s best described as a host of business services all under one roof. It’s basically a central place for businesses to utilise online tools to work and collaborate. My words, not Googles! Anyway, you need an account to make this work, it is free so go ahead and sign up and answer the endless questions. Get everything sorted and when its all up and running you can move on to adding the domain you bought to your Google Apps account.

  3. Register your domain. Next you need to add your domain to Google Apps, this means telling Google about the domain that you’ve already registered and proving you own it. Google is nice here, they have a few methods of doing this. The one I used is for Google to ask you to copy a verification code of sorts and add it to a special txt key on your domain. If you’re using goDaddy like I am, this is pretty straight forward. You just need to sign into your goDaddy domain manager and paste in the code. From there Google will verify the domain and add the domain to your account. You can also upload a special Google HTML file to your server, but that’s a lot of work!

  4. Update your DNS. Now we need to change our DNS to point to google. I use goDaddy and this was deceptively simple, basically just login to GoDaddy’s DNS manager and click edit zone for your domain name. You want to change the www attribute for your CNAME record. Change it to ghs.google.com and your done.

  5. Finally you can go back to your original tab from step 1 where you’re still in GAE and add “www” (not inverted commas) as the domain. This should magically link everything up and hey presto your domain should point to your gae app.

This is a much shorter, and helpful description, well done “Mark” who figured it out and helped me a lot: http://stackoverflow.com/questions/817809/how-to-use-google-app-engine-with-my-own-domain-not-subdomain

08 March 2012

Setup an AWS EC2 Instance Running Railo

Setup an AWS EC2 Instance Running Railo

OK so you want to delve deep into cloud computing and start your own instance Amazon Web Services (AWS) Elastic Cloud Compute (EC2) instance? Sadly the “official” Railo AMI seems to have died, so here we’ll be starting our own new one. We’ll be running firmly within the free criteria here and choosing options appropriately, most significantly this means linux! We’ll also be using putty to connect to our instance. For part of this tutorial we’re going to be running alongside the official Amazon starting an instance guide. So I will skimp on the details already covered by Amazon themselves:

http://docs.amazonwebservices.com/AWSEC2/latest/GettingStartedGuide/GetStartedLinux.html

Start-up an Instance

  1. Click the giant “Launch an Instance” button. Select Basic Amazon Linux AMI I choose 32bit because it’s cheaper and (at the moment) free.
  2. Ensure you’ve selected a micro instance.
  3. Skip the instance details section, just accepting the defaults.
  4. Create and download a Key Pair. This is important as it allows us to log onto our instance securely.
  5. Next is the firewall or security groups section. This bit is important as it configures what applications and ports are allowed to access your instance. Create a new security group. You should select SSH and HTTP as a minimum, you can accept the default of 0.0.0.0 but that allows any IP access to these ports. This is fine for HTTP but if your ISP has given you a static IP then put this in for SSH.
  6. Done, your instance will begin powering up. Watch the instances dashboard to see it’s status, eventually the status will flick to green, display “running” and the status checks will show 2/2. Once that happens we’re ready to logon.


Connect to your instance
I’m going to leave this bit a little to Amazon to explain. You’ll need to download and install putty and convert your key pair file (from step 4 above) into a putty private key file. Then grab your amazon public dns value (something like ec2-11-11-111-111.compute-1.amazonaws.com) and connect to it using putty. Don’t forget to enter the username ec2-user.

Get Linux straight & Install Railo

  1. First lets get Linux to update itself:
sudo yum update
  1. Download Railo to the instance:
wget http://www.getrailo.org/down.cfm?item=/railo/remote/download/3.3.1.000/tomcat/linux/railo-3.3.1.000-pl1-linux-installer.run
  1. Assign permissions
sudo chmod 777 railo-3.3.1.000-pl1-linux-installer.run
  1. Run Railo
sudo ./railo-3.3.1.000-pl1-linux-installer.run

Here you’ll want to accept all the defaults except three. First change the default password to something good. Second you should set the port to 80 (not 8888). This will allow normal connections to your server and links into why we had to allow HTTP (port 80) in the EC2 security group. Lastly you should say no to the apache connectors. This sets up railo with tomcat and installs tomcat for you. Of course if you’re more familiar with apache then go with that.

Hit your url
http://ec2-11-11-111-111.compute-1.amazonaws.com
The above link (customized for your public DNS) should show you the default Railo welcome page.

Use putty and VI to change your cfm files
  1. Navigate to the webroot:
cd /opt/railo/tomcat/webapps/ROOT/
  1. Remove all these files
sudo rm -rf *
  1. Create a new index.cfm file
sudo vi index.cfm
VI - Linux editor
  1. In vi to delete the contents of the whole file type
  2. :1,$d
  3. To swap between command and insert modes just press escape

  4. To exit without saving, switch to command mode and press
  5. :q!
  6. To exit and save switch to command mode and press
  7. :x