Simple ColdFusion Feed Caching Manager

ColdFusion 8 added the cffeed tag, a great and simple utility for fetching and parsing rss and atom feeds. It’s a great and simple to use utility, but there are a couple of issues to keep in mind.

Every time you make a “read” call to an external source, you’re preforming an http request. Most feeds that I’ve pulled in aren’t updated more than a few times per week. Just using cffeed, even a modest hit count can quickly add up to thousands of unnecessary requests. Aside from the bandwidth, you’re fully at the mercy of that external server. Each request is potentially slow, invalid, or (ahem, Twitter) otherwise unavailable.

You can totally bypass these problems by simply caching a copy of the feed to diske, and then quickly and safely parsing that file as needed. If you can grab it once, then you’ll always have that information quickly available. I wrote a lightweight utility for doing just this. It’s simple, but it’s made my life so much easier that I thought I’d share.

First create and instantiate the feed manager.

  feedManager = createObject( "component", "feedManager" );
  feedManager.init( folder = absolutePathToSaveFeedFiles );

Then add the feeds, with unique keys for retrieval.

  feedManager.addFeedURL(
    key = "BLOG",
    url = "http://joezack.com/index.php/feed"
  );

  feedManager.addFeedURL(
    key = "CNN",
    url = "http://cnn.com/feed"
  );

Fetch and save the feeds to disk, if available and valid. I run this in a scheduled task, every hour or so.

  feedManager.cacheFeeds();

  // or to just cache one feed
  feedManager.cacheFeed("CNN");

Finally, to retrieve the cffeed parsed file, just call the getFeed method! So long as there has ever been a feed successfully retrieved, you’ll have data.

  // Request feed from disk.
  feed = feedManager.getFeed(key = "BLOG");

Download the file!

Populating Select Boxes with Prototype

Adding removing options from drop downs can be down right annoying, but I came up with a simple prototype function that I think makes it a lot easier.

You just pass your select box object, an object with an enumerable-esque ‘each’ method, and a method for creating the individual options. On the advice of my wonderful co-worker Jim, you can pass an optional 4th argument that lets you maintain the options length. It’s defaulted to 1 in order to preserve the first element in a drop down, which we typically leave blank.

Here’s the function:

// Requires Prototype: http://www.prototypejs.org/
function setDropDown(field, data, method, index) {
  field.options.length = index == null ? 1 : index;
  data.each(
    function(e) {
      field.options.add(method(e));
    }
  );
}

And here are some quick examples:

To clear a drop down:

setDropDown(selectBoxObject,[]);

To copy items from one drop down to another:

setDropDown(
  selectBoxObject,
  otherSelectBoxObject.options,
  function(e) {
    return new Option(e.text, e.value);
  }
);

Quick example using JSON

var json = Object.toJSON( {"COUNTRIES":[{"COUNTRY":"Hong Kong","ID":1},{"COUNTRY":"Japan","ID":2}]} );

setDropDown(
  selectBoxObject,
  json.COUNTRIES,
  function(e) {
    return new Option( e.COUNTRY, e.ID );
  }
);

Project Euler: Problem 30 in Ruby

I realize this isn’t the fast solution, but the more I optimized, the uglier it got so I’m done playing with it. The hardest part was figuring out what the upper bound limit was.

Problem 30

Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.

power, total = 5, 0

(power * 9**power).times do |i|
  total += i if i == i.to_s.split('').inject(0) {
    |sum, n|
    sum + n.to_i**power
  }
end

puts total - 1

Merging Netflix Accounts with ColdFusion and JavaScript

I wrote a little script using ColdFusion and JavaScript to merge two NetFlix accounts. It’s ugly and cheesy, but it works so I thought I’d share.

Here’s how you do it:

  1. Register for a developer key.
  2. Grab the RSS feed url of the queue you want to merge FROM. This can be obtained by logging into the FROM account and clicking on the “RSS” link in the footer.
  3. Log in to the account that you’d like to merge TO.
  4. Hit this script in the same browser you logged into the TO account with, and make sure you allow pop-ups!
<!--- enter your feed here! --->
<cfset feed = "http://rss.netflix.com/QueueRSS?id=P4806480653914107620156446228102116" />
<!--- enter your consumer key here! --->
<cfset key  = "your-consumer-key-here" />
<cfset href = "http://widgets.netflix.com/addToQueue.jsp?output=json&devKey=#key#&queue_type=disc&movie_id=http://api.netflix.com/catalog/movie/" />

<cffeed action="read" name="queue" source="#feed#" />

<cfset movies = queue.item />
<cfset idList = "" />

<cfloop array="#movies#" index="i">
	<cfset idList = ListAppend(idList,ListLast(i.guid.value,"/")) />
</cfloop>

<cfoutput>
	<script src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js"/>
	<--- Pop up a new window, swap the href every second. Told ya it was cheesy! --->
	<script>
		var popUp = window.open('http://google.com');
		var idList = [#idList#];

		new PeriodicalExecuter(
			function(pe) {
				if (idList.length == 0) {
					pe.stop();
				} else {
					popUp.location.href = "#href#" + idList.pop();
				}
			},
			1
		);
	</script>

</cfoutput>

Note: I don’t know if this allowed by the EULA, or if there even is a EULA…so, use at your own risk!

Project Euler: Problem 26 in Ruby

I knew I’d be implementing my own division algorithm for this problem, but I had a hard time figuring out a good way to detect the repeating sequence.

That’s all I have to say about that.

Problem #26

Find the value of d 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

def divide n, d, repo = []
  return repo.size - repo.index(n) if repo.include? n
  divide 10 * (n - (n / d) * d), d, repo << n
end

highest = {"d" => 1, "count" => 1}

(1..499).each do |i|
  x     = i * 2 + 1
  count = divide 1, x
  if count > highest['count']
    highest = {"d" => x, "count" => count}
  end
end

puts highest["d"]

Ow!

Listen, Railo. There’s something I’ve been meaning to talk to you about. I think you’re great, fantastic even. You’re you’re elegant, quick as a squirrel, the price is right and you’ve got a lot of really nice features. But this, this makes my eyes bleed.

My Eyes!

Project Euler: Problem 28 in Ruby

I noticed a simple pattern of odd squares traveling up the rightmost corner of the spiral and after a little bit of toying around with the numbers I was able to come up with my solution. There are some truly beautiful and well explained solutions in the forums, but I’m pretty happy with mine, I could have been a nice guy and split it up, but I had a rough time coming up with appropriate variable names. This is what you get.

Problem #28

Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:

21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13

It can be verified that the sum of both diagonals is 101.

What is the sum of both diagonals in a 1001 by 1001 spiral formed in the same way?

def sum_corners n
  return 1 if n == 1
  4 * ((n * 2 - 1) ** 2 - (3 * n - 3)) + sum_corners(n - 1)
end

puts sum_corners((1001 + 1) / 2)

Project Euler: Problems 1 – 5 in JavaScript

I’ve been wanting to check out Rhino for a while, and I’ve been particularly interested in seeing how it compares to Ruby in terms of speed. The results have been a little varied, and it’s a deeply flawed comparison. But it’s something.

These scripts are just ports of my ruby solutions. There are a few places where I had to roll my own JavaScript functions instead of baked in Ruby methods, but other than that it was nearly line by line translation.

Problem 1Ruby solution

Add all the natural numbers below one thousand that are multiples of 3 or 5.

var total = 0;

for(var i = 0; i < 1000; i++) {
  if(i % 3 == 0 || i % 5 == 0) {
    total += i;
  }
}

print(total);

Problem 2Ruby solution

Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million.

function fib(stack, n) {
  if(n == 0) {
    return 1;
  }
  if(n == 1) {
    return 2;
  }
  return stack[n - 1] + stack[n - 2];
}

var max   = 4000000;
var total = 0;
var stack = [];

for(var i = 0; i < max; i++) {
  stack[i] = fib(stack,i);
  if(stack[i] > max) {
    break;
  }
  if(stack[i] % 2 == 0) {
    total += stack[i]
  }
}

print(total);

Problem 3Ruby solution

Find the largest prime factor of a composite number.

function find_highest_prime_factor(n) {
  var max = Math.round(Math.sqrt(n));
  for(var i = max; i >= 2; i--) {
    if(n % i == 0 && find_highest_prime_factor(i) == 1) {
      return i;
    }
  }
  return 1;
}

var target = 600851475143;
print(find_highest_prime_factor(target));

Problem 4Ruby solution

Find the largest palindrome made from the product of two 3-digit numbers.

function get_highest_palindrome(high, low) {
  var highest = 0;
  for(var i = high; i >= low; i--) {
	for(var j = high; j >= low; j--) {
      sum = i * j;
      if(sum <= highest) {
        break;
	  }
      if(is_palindrome(sum.toString())) {
        highest = max(highest, sum);
	  }
    }
  }
  return highest;
}

function reverse(string) {
  var array = string.split('').reverse();
  var out   = '';
  for(key in array) {
	out += array[key];
  }
  return out;
}

function max(a,b) {
  if(a > b) {
	return a;
  }
  return b;
}

function is_palindrome(string) {
  return string == reverse(string);
}

print(get_highest_palindrome(999, 100));

Problem 5 - Ruby solution

What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?

function gcd(a,b) {
  var x = a;
  var y = b;
  var result;
  
  while (y != 0) {
	result = x % y;
    x      = y;
    y      = result;
  }
  return x;
}

function lcm(a,b) {
  return (a * b) / gcd(a, b);
}

var max = 20;
var min = 11;
var n   = min;

for(var i = min; i <= max; i++) {
  n = lcm(n,i);
}

print(n);