Friday Puzzler: Color Rotator

This post is more than 2 years old.

It has been a while since my last ColdFusion Friday puzzler, so I hope you enjoy this one. It occurred to me while driving my eldest to school Wednesday morning and in my "not quite awake yet" semi-conscious daze, it seemed like a sneaky little puzzle. I figured out a possible simple solution before I got home, but I'm curious to see what others make of it. Ready?

Your client wants their web site to make use of a rotating color background. Each day, the background color of the web site will change. The list of colors used for the background are: red,blue,green,yellow,orange. (I know, I know, this is why I don't do web design.)

Your goal is to write a UDF that accepts a date and selects a color. If you pass the day after that initial date, you should pick the next day in the list. On the day you pick orange, the next day would pick red.

You may think - why not simply use the the day of the week modded by 5?

But this doesn't work on the edges. You could switch to the day of the year but would have the same issue (although a heck of a lot less). So how would you solve this issue? Note that you cannot persist anything in the database (or file system, etc).

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Tim Leach posted on 3/1/2013 at 5:38 PM

You said not persist to DB or file, but can we persist in memory?
Server.SiteBgIndex++;

And day of year would work except for leap year. So starting with that method and making it work better we could do DateDiff now() '01-01-2000' Mod 5.

Comment 2 by Danny posted on 3/1/2013 at 5:54 PM

Unix timestamp seemed to work nicely, tested it through a 1000 iterations

https://gist.github.com/dan...

Comment 3 by Raymond Camden posted on 3/1/2013 at 6:03 PM

@Tim - nope - no persistence allowed. Why? Because. ;)

Comment 4 by GrumpyCFer posted on 3/1/2013 at 6:10 PM

<cfset colorIndex = (DateDiff("s", DateConvert("utc2Local", "January 1 1970 00:00"), day) \ 86400 % ArrayLen(colors))+1>

Comment 5 by Raymond Camden posted on 3/1/2013 at 7:56 PM

GrumpyCFer - that is interesting. I assume day is now()?

Comment 6 by Paul Rowe posted on 3/1/2013 at 8:23 PM

You could also go for:
<cfset iColor = (DateDiff("dd", "1/1/2000", Now()) MOD ArrayLen(colorsRotation)) + 1 />
Now, this takes care of things server-side. Question is, this tells the user which color is today's background. It doesn't let the user "select" a color and it doesn't update the background color until another request is made. You could perhaps store some information in a cookie (if that sort of persistence is allowed) and implement some JavaScript to update the background color if the user is still viewing the same page before and after midnight.

Comment 7 by Raymond Camden posted on 3/1/2013 at 8:24 PM

Thanks Paul. I'm not so much worried about the implementation per se (I try to keep these puzzles to small, atomic challenges).

Comment 8 by AXL posted on 3/1/2013 at 9:13 PM
Comment 9 by WebManWalking posted on 3/2/2013 at 12:22 PM

Given a properly chosen start date and 4 properly chosen constants, you can calculate the number of days since that start date, blindingly fast, in fewer than 10 arithmetic operations and one if. Is that the sort of thing you were looking for?

Comment 10 by Raymond Camden posted on 3/2/2013 at 6:20 PM

I was looking for solutions - so yes. :)

Comment 11 by AXL posted on 3/3/2013 at 4:08 PM

So what was your possible simple solution? Is mine close to yours?
BTW, "Driving a car" + "Thinking of coding" = "Nooooooooooooooooooooooooooooooooooooooooooooooooooot a good idea. ^^;

Comment 12 by Raymond Camden posted on 3/3/2013 at 7:53 PM

Both you and Danny were what I was thinking of. Use an arbitrary date in the past and take the diff from that.

Comment 13 by GrumpyCFer posted on 3/9/2013 at 6:59 AM

@Ray Insert my line between your 4 and 5 and the array index on 5 (now 6) to colorIndex. The date diff is just to get Epoch time. Could be shortened, as Danny did, but prefer the hinting.