Duncan’s blog

November 25, 2008

Sith Sigma

Filed under: Web — duncan @ 11:59 pm
Tags: , , , , , ,

Found this interesting blog about management tips for technology organisations. Covering topics such as leadership skills, workforce efficiency, business intelligence, etc. Fairly typical to many other blogs on the same topic.

However, check the name: Sith Sigma. Yes, that’s right; it’s a blog from the Sith Lords, Darth Sidious and Darth Vader! They’ve obviously learnt many management and leadership tips while running the Empire. The title itself is a pun on Motorola’s Six Sigma business management strategy.

For example, here’s an excerpt from a post about Employee Performance Appraisals:

Storm troopers need to bring in Jawas for interrogation. Do we evaluate them on the sheer number of Jawas they bring in, or on the quality of the intelligence extracted from them? Obviously it’s a combination of both.

Another Storm trooper evaluation may have the very narrow categories of: 1) Following orders, 2) Number of prisoners who escaped.

This may seem like an ok set of metrics to evaluate a guard on, but we don’t want them to think that is the only aspect of their jobs. We don’t want narrow metrics to define the job. We may also care about: Initiative, efficiency, attendance record, prisoner health etc.

If it’s important to the organization, it should be in the performance evaluation.

November 21, 2008

Here be dragons!

Filed under: Funny,Software,Web — duncan @ 9:48 pm
Tags: , , , , , , ,

Trying to resolve an issue I’ve been having with the Adobe Flash plugin for Firefox. I found some useful tips at MozillaZine.org which at one point directed me towards the about:config page in Firefox.

Accessing the about:config page then brought up this delightful warning message.

here be dragons

There aren’t enough dragons in the software industry! Or humorous warning messages for that matter…

Humour aside, this is a great example of an easy to understand warning message. No redundant ‘Cancel’ button. No verbose jargon that would just get ignored. A Submit button that is related to the action, and thus might be read rather than immediately clicked on in a Pavlovian response.

November 19, 2008

Information you shouldn’t display to users

Filed under: Web — duncan @ 5:26 pm
Tags: , , ,

Received an email newsletter from some company, and decided to unsubscribe. Clicking on the link gave me this page:
Senior Send

For some reason, Senior Send have decided it’s a good idea to output what SQL they’re using to delete me from their client’s mailing list. This sometimes happens, especially with Coldfusion, when you accidentally get an error. It’s not a good idea to display this much information even then. It’s an even worse idea to display this to any or all of your users.

SELECT id,status_id, mail_subscriber.name FROM mail_subscriber WHERE id = 94523

found 1

And the URL looks like:
http://internal.seniordev.co.uk/mailer/mail_unsubscribe.asp?id=696&subscriber=94523

I wonder what happens if I just change the subscriber ID to anything else? How long would it take to write a script to loop from 1 to 94522 deleting all users?

Maybe they should have just passed my email address, or a UUID, or an encrypted version of my ID. Maybe they shouldn’t have output their SQL.

November 17, 2008

How not to display images

Filed under: Web — duncan @ 7:00 am
Tags: , , ,

Trying to register at xbox.com. For some reason their Flash detection seems not to work for me (using Firefox 3.04, Flash 10.0 r12). So they display an image telling me to "Please download Flash Player". If you look at the fullsize version of the screenshot, you’ll see the image looks sort of distorted.
xbox.com screenshot

It seems that Microsoft in their infinite wisdom, are stretching that image to fill the screen. This makes the text all fuzzy, and the female character they’ve used seem somewhat wider than her designer originally intended.

It’s kind of an amateur web technique. Often you’ll see it being done the opposite way, where a much larger image is squashed down to fit into a smaller space. In this case, the image often looks ok, but with the effect of increasing download time. If the end user is on broadband, they probably won’t even notice. However the amount of bandwidth your site uses will be higher than it should be. I saw a particularly bad example of this recently where two small logos on the page were actually very large .bmp files. The cumulative filesize of those files was over 750Kb. I converted them to .gifs, grand total about 10Kb.

The original image for comparison:
xbox original image

A separate discussion could be had over whether they even need an image on this page anyway. A simple text message telling me to download Flash Player would have sufficed.

November 16, 2008

Quantum of Solace review

Filed under: Film — duncan @ 1:07 pm
Tags: , , , , , , ,

Went to see the latest Bond film, Quantum of Solace, yesterday. This is a direct sequel to Casino Royale, and if you haven’t seen that one, you might find some of the plot points confusing. Even if you have seen it, you’ll still find the plot confusing I think!

The film starts with a frenetic car chase in Italy, ending up in a marble quarry, which briefly reminded me of the majestic photography of Edward Burtynsky. But only briefly… Cut to opening credits, with a pleasant enough but totally forgettable song by Jack White and Alisha Keys. They’d have been better using the proposed theme song by Joe Cornish of Adam and Joe fame:

There then follows many action sequences. It seems this film has done away with the Bond signature style of huge iconic stunts. No Union Jack themed parachutes or giant bungee jumps. The previous film had two amazing stunt sequences; the crane jumping parkour at the start, and the Aston Martin crash. This one has many great sequences, including another bit of parkour, but nothing really similar.

The action scenes are all edited together with very short cuts, many around the 1 second mark. This can make it hard to follow all the action sometimes.

Without giving too much away, one of the two Bond girls is very strong and sassy, and gets lots of screen time. There’s talk of her reappearing in a future Bond film. The other has a much shorter time on screen and we don’t find out much about her. She even has a stupid name in the best Bond girl tradition – Strawberry Fields, although she’s only ever referred to as Fields in the film.

The villain isn’t particularly scary; you couldn’t really imagine him torturing Bond like Le Chiffre did, for instance. He vaguely resembles the young Roman Polanski; coincidentally the plot has a nod towards Polanksi’s classic Chinatown.

Product placement isn’t perhaps quite as blatant in this as in Casino Royale, except for a clumsy moment near the start when a police officer states “a grey Aston Martin being chased by a black Alfa Romeo”. Just in case you hadn’t recognised what cars they were.

I think being a sequel was a good idea; I’d like to see the next Bond film continue the story. There’s certainly scope for that based on the plot that’s revealed in Quantum.

007 out of 010.

November 13, 2008

Why you need to test your code – Racing Green

Filed under: Web — duncan @ 7:00 am
Tags: , , , , ,

After bemoaning the lack of personal touch from House of Fraser greeting me as [ncgi::value emailaddr_], I got the following email from Racing Green:

Racing Green email

I love it when you call me NULL!

Also you might notice a distinct lack of images showing up in this email (in Gmail). It seems to be because they haven’t properly formatted the URLs of the images. Looking at the source, it’s full of HTML like:
<img src=”http://srg-cms.snowvalley.com/upload/email_assets/NL RG Accessories Banner 11th Nov 08.jpg” alt=”Accessories Offer” style=”BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none” />

I’m guessing Gmail baulks at the unescaped spaces in the URL.

November 12, 2008

Why you need to test your code – House of Fraser

Filed under: Web — duncan @ 6:38 pm
Tags: ,

For some reason I ended up subscribed to the House of Fraser mailing list. Clicking on the link in their email to unsubscribe, I got this useful error message informing me that "[ncgi::value emailaddr_] has been removed from our mailing list.":

house-of-fraser unsubscribe
(click image to see full size)

I love the personal touch!

November 11, 2008

Project Euler: problem 21

Problem 21:

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
If d(a) = b and d(b) = a, where a != b, then a and b are an amicable pair and each of a and b are called amicable numbers.

For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

Evaluate the sum of all the amicable numbers under 10000.

I passed over this one initially, and came back to it later. It wasn’t too difficult, but I got the wrong answer first time round.

We need to loop up to 9999. For each number (i), work out what its factors are, and add them up (let’s call this sum1). Then work out what the factors of sum1 are, and add them up (sum2). If i equals sum2, then i and sum1 are amicable numbers.

My mistake was forgetting to check that i and sum1 are different. It turns out several numbers seem to be amicable, but are the same. e.g. the factors of 6 are 1, 2 and 3, which add up to 6; but (6, 6) is not an amicable pair.

<cfset d = StructNew()>

<cfscript>
function getFactors(x)
{
	var i = 0; 
	var factors = ArrayNew(1);
	
	for (i = 1; i LTE x/2; i = i + 1)
	{
		if (NOT x MOD i)
		{	// its a factor
			ArrayAppend(factors, i);
		}
	}
	
	return factors;
}

function sumFactors(x)
{
	var i = 0;
	var sum = 0 ;
	
	for (i = 1; i LTE ArrayLen(x); i = i + 1)
	{
		sum = sum + x[i];
	}
	
	return sum;
}
</cfscript>

<cfloop index="i" from="1" to="9999">
	<cfset j = getFactors(i)>	<!--- factors of i --->
	<cfset k = sumFactors(j)>	<!--- sum of those factors --->
	<cfset l = getFactors(k)>	<!--- factors of that sum --->
	<cfset m = sumFactors(l)>	<!--- sum of those factors --->
	
	<cfif m EQ i AND NOT StructKeyExists(d, i) AND NOT StructKeyExists(d, k) AND i NEQ k>
	<!--- amicable pair --->
		<cfset d[i] = k>
		<cfset d[k] = m>
	</cfif>
</cfloop>

<cfset sum = 0>
<cfset d2 = StructKeyArray(d)>

<cfloop index="i" from="1" to="#ArrayLen(d2)#">
	<cfset sum = sum + d[d2[i]]>
</cfloop>

<cfoutput>#sum#</cfoutput>

This code is pretty slow, taking about eight minutes to run. The PDF available after you complete it has a more optimised version. After doing a minor rewrite based on that, it only took 15 seconds! So ignore the code above, take a look at this instead:

<cfscript>
function sumFactors(x)
{
	var i = 0; 
	var sum = 1;
	
	for (i = 2; i LTE SQR(x); i = i + 1)
	{
		if (NOT x MOD i)
		{	// its a factor
			sum = sum + i;
			if (i NEQ (x / i))
				sum = sum + (x / i);
		}
	}
	
	return sum;
}
</cfscript>

<cfset sum = 0>

<cfloop index="i" from="1" to="9999">
	<cfset j = sumFactors(i)>	<!--- sum factors of i --->
	<cfset k = sumFactors(j)>	<!--- sum of those factors --->
	
	<cfif i EQ k AND j NEQ k>
	<!--- amicable pair --->
		<cfset sum = sum + j>
	</cfif>
</cfloop>

<cfoutput>#sum#</cfoutput>

So what’s the difference? Firstly, I was using a Struct to store each amicable pair. I did away with that, and just added directly to my total. I wouldn’t normally code like that; for these sort of things its good to have a variable that you can then interrogate later to see actually what numbers are we calling amicable. However, on the assumption that the code is now correct, doing away with it removes one level of complexity. I can then remove one StructNew function call, the two StructKeyExists function calls, one StructKeyArray function call, and one cfloop.

Secondly, instead of having one function to get all the factors, and another function to then add those together, I simplified this to just one function that both finds the factors and adds them together.

This function originally extended to half of x, e.g. if the number was 198, the largest factor of that is 99. However the function rewritten only extends to the square root of x, and adds both the factor and x / factor. e.g. for 220 we only go as far as 14, and add 1 (outwith our loop), 2 and 110 (220/2), 4 and 55 (220/4), 5 and 44 (220/5), 10 and 22 (220/10), 11 and 20 (220/11).

Then we sum those factors (sum1), then find the factors of sum1, sum them (sum2) and compare i and sum2. Assuming they match and sum1 and sum2 are different, we add sum1 to our total.

November 10, 2008

Project Euler: problem 49

Problem 49:

The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the 4-digit numbers are permutations of one another.

There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property, but there is one other 4-digit increasing sequence.

What 12-digit number do you form by concatenating the three terms in this sequence?

There are three aspects to this:

  • Work out how to loop through the numbers
  • Work out if the digits are the same in each case
  • Work out if each number is prime

So, each number has to be 4 digits. The largest 4 digit number is 9999. If we add 3330 each time, the largest number can’t be any more than 9999 – 3330 – 3330. On re-reading the brief, it says “there is one other 4-digit increasing sequence“, and I had a nasty thought that it maybe wasn’t one that increased by 3330, but some other number. However that’s not the case thankfully.

If we know 1487 is the other number that this works for, we can exclude that. I made the assumption that the second number would be larger than 1487. However this could have been a wrong assumption, and my code should have started at 1001, and deliberately stepped over 1487. But my assumption turned out be correct, so the code worked as it was.

All primes apart from 2 are odd, so I started at the next odd number greater than 1487. Also setting the loop increment to +2, so we can exclude the even numbers.

To work out if the numbers are the same each time, I put two sets of numbers each into an array, sort the arrays, then compare them. If the numbers in the arrays differ, then the digits must be different.

I’m reusing my IsPrime() function from earlier problems.

<cfset end = 9999 - (3330 * 2)>

<cfscript>
function sameDigits(x, y)
{
	var i = 0; 
	var arrX = ArrayNew(1);
	var arrY = ArrayNew(1);
	
	for (i = 1; i LTE Len(x); i = i + 1)
	{
		ArrayAppend(arrX, Mid(x, i, 1));
	}
	for (i = 1; i LTE Len(y); i = i + 1)
	{
		ArrayAppend(arrY, Mid(y, i, 1));
	}
	ArraySort(arrX, "numeric");
	ArraySort(arrY, "numeric");
	
	for (i = 1; i LTE ArrayLen(arrX); i = i + 1)
	{
		if (arrX[i] NEQ arrY[i])
			return false;
	}
	
	return true;
}

function isPrime(x)
{
	var isPrime = true;
	var i = 0; 
	
	if (x LT 2)
	{
		return false;
	}
	
	if ((NOT x MOD 2) AND (x GT 2))
	{	// a multiple of 2, but not 2 itself
		return false;
	}
	
	for (i = 3; i LTE SQR(x); i = i + 2)
	{
		if (NOT x MOD i)
		{	// found a factor of x
			return false;
		}
	}
	
	return isPrime;
}
</cfscript>

<cfloop index="i" from="1489" to="#end#" step="2">
	<cfset num2 = i + 3330>
	<cfset num3 = num2 + 3330>
	
	<cfif 	sameDigits(i, num2) 
	AND 	sameDigits(i, num3) 
	AND 	IsPrime(i)
	AND 	IsPrime(num2)
	AND 	IsPrime(num3)>
		<cfoutput>#i##num2##num3#</cfoutput>
		<cfbreak>
	</cfif>
</cfloop>

November 9, 2008

Project Euler: problem 79

Filed under: Project Euler — duncan @ 7:00 am
Tags: ,

Problem 79:

A common security method used for online banking is to ask the user for three random characters from a passcode. For example, if the passcode was 531278, they may asked for the 2nd, 3rd, and 5th characters; the expected reply would be: 317.

The text file, keylog.txt, contains fifty successful login attempts.

Given that the three characters are always asked for in order, analyse the file so as to determine the shortest possible secret passcode of unknown length.

At first I started coding up a solution. It looked a bit complicated, so I decided to try it by hand with pen and paper. Doing it that way took about two minutes, much quicker than trying to code a solution! However if you were going to do this for say a hundred different users, you’d be better trying to work it out in code.

The theory would be to have an array, and insert each new digit encountered in the logins to the array. For each digit, check if it’s already in the array. If it is, compare its position against the next digit in the current block of three. If they’re not in the correct order in the array, shuffle them around until they are.

Doing it by hand, just draw ten columns on your page. Start putting the numbers into the array, manually working out where they should be each time. Doing it that way isn’t very hard at all…

Next Page »

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.