The Most Advanced Simple Countdown Timer for Windows

Hourglass is the most advanced simple countdown timer for Windows. Just enter a time in just about any format, and hit Enter.

A few years ago, I needed a simple countdown timer utility for Windows. I wasn’t satisfied with any of the options available, so I wrote Orzeszek Timer.

The problem with Orzeszek Timer — other than that no one knew how to spell the name — was that it was too simple. It lacked basic features, such as the ability to pause and resume the timer, change the color of the window, or add a title to differentiate multiple timers.

Introducing Hourglass, the most advanced simple timer for Windows:

Hourglass - The simple countdown timer for Windows

Just like Orzeszek Timer, Hourglass allows you to enter the time to count down in just about any format. But now you can also enter a date or time of day to count down to, rather than just a duration. And, as with Orzeszek Timer, when the timer elapses you’ll be notified with a customizable audible alarm.

The interface is still simple and uncluttered, but now you can set the window color from one of a number of predefined colors — or pick your own. And you can add a title to your timers to help you manage multiple timers.

Hourglass - The simple countdown timer for Windows

Hourglass also supports command line arguments, so it can be automated if you need to do that. Every option that can be set using the graphical user interface can be set using a command line argument.

And, of course, Hourglass is free and open source. You can contribute code on GitHub, or open an issue to report a bug or request a feature.

Find out more and download Hourglass from its website here.

Read full post »

Tags: timer

Use Pygments in Middleman for Syntax Highlighting

Middleman switched from the Python-based Pygments to the pure-Ruby Rouge for syntax highlighting with version 1.2.0 of the middleman-syntax extension. You can switch back to Pygments by adding a few lines to your config.rb file.

Switching from Pygments to Rouge means no more spawning Python processes when building your site. But Rouge doesn’t do everything that Pygments does. Pygments has PowerShell and Windows batch file support, for example.

If you depend on Pygments features or simply prefer to use Pygments, add this to your config.rb file to switch back:

require 'pygments'

activate :syntax

module ::Middleman::Syntax::Highlighter
  def self.highlight(code, language=nil, opts={})
    Pygments.highlight(code, lexer: language)
  end
end

You will also need to add the pygments.rb gem to your Gemfile and run bundle install:

gem 'pygments.rb', '~> 0.6.3'

If you need to pass options to Pygments, pass them after lexer: language in the call to Pygments.highlight rather than on the activate :syntax line as you would for most Middleman extensions. A more elegant implementation would support the latter, but this quick-and-dirty solution works well enough for me.

Read full post »

Tags: Middleman, Pygments, Rouge, static site generator

Codehire Cup 2013 Solutions: Grand Final (Round 3)

A solution in Ruby to the Codehire Cup Grand Final (Round 3) problem in the second Codehire Cup held across Australia in June and July 2013.

In June and July 2013, Codehire held the second Codehire Cup across Australia. As last year, the contest featured some relatively simple coding problems. Contestants could choose to use C/C++, C#, Java, JavaScript, PHP, Python, or Ruby to submit solutions through a web-based interface.

Contestants were ranked according to the time taken to complete the problem, as well as by an assessment of their approach and coding style by a panel of judges.

The Problem

The Codehire Cup Grand Final (Round 3) problem read:

Elevators

A building has 100 floors (numbered 0 through 99) and 5 elevators (numbered 0 through 4) each with access to all floors.

You are given the following information:

  1. The floor on which each elevator is currently situated
  2. A list of pending requests by people waiting. Described as the floor on which the request was made and how long for which the request has been pending (the age of the request)

The elevator controller should satisfy the following goals:

  1. Always satisfy oldest requests first
  2. Minimize wait time after satisfying condition 1

Your program must determine which elevators (numbered 0, 1, 2, 3 or 4) will service each of the requests.

Assumptions

  1. A given elevator will only service one request in this exercise
  2. When deciding which elevator to send for a request, there will always be only one optimal candidate
  3. There will not be more requests than there are elevators
  4. All elevators travel at the same speed

Input

The input will be given to you on two lines. The fist line will be a comma separated list of the floors the five elevators are currently situated. eg:

10,5,7,9,1

The second line will be a list of requests containing the floor number and the age of the request in seconds separated by a comma. The individual requests are then separated by semicolons. eg:

7,45;11,10;

In other words, there is a request on level 7 which has been waiting for 45 seconds and a request on level 11 which has been waiting for 10 seconds.

Output

Your program should output the elevator numbers that will service each request in the order that the requests are provided to you.

Input:

0,1,19,9,56
13,15;67,60;68,35;

Output:

3,4,2

The Solution

The solution is simply to sort the requests from oldest to newest. Then, for each request, we find the closest elevator and associate it with that request. After associating an elevator with a request, we set the elevator’s floor notionally to infinity so that the elevator is not used again.

# Parse input
elevators = input.split[0].split(',').map { |e| e.to_i }
requests  = input.split[1].split(';').map { |r| r.split(',').map { |s| s.to_i } }

# Map elevators to requests
requests.sort_by { |r| -r[1] }.each do |r|
  r[2] = elevators.each_index.min_by { |e| (elevators[e] - r[0]).abs }
  elevators[r[2]] = Float::INFINITY
end
output << requests.map { |r| r[2] }.join(',')

The constraints listed in the assumptions section ensure that, at each stage of the computation, there is only one possible outcome. If that were not the case, it would be necessary to perform a more complicated computation where, for example, the total or average wait times are minimised.

More Codehire Cup 2013 Solutions

Codehire Cup 2012 Solutions

Read full post »

Tags: Codehire Cup, coding contests

Codehire Cup 2013 Solutions: Semi-final (Round 2)

A solution in Ruby to the Codehire Cup Semi-final (Round 2) problem in the second Codehire Cup held across Australia in June and July 2013.

In June and July 2013, Codehire held the second Codehire Cup across Australia. As last year, the contest featured some relatively simple coding problems. Contestants could choose to use C/C++, C#, Java, JavaScript, PHP, Python, or Ruby to submit solutions through a web-based interface.

Contestants were ranked according to the time taken to complete the problem, as well as by an assessment of their approach and coding style by a panel of judges.

The Problem

The Codehire Cup Semi-final (Round 2) problem read:

Instructions

Implement a firewall to process incoming TCP network packets. For each packet, the firewall must determine what action to take and the specific rule that triggered the action. Action will be either ALLOW, REJECT or DROP represented as strings.

You are given a rule set and a (simplified) representation of an incoming packet.

Rule Sets

A Rule Set comprises several rules with each rule containing an index (integer starting at 1), a field ID (character), a field match value (string) and the action to take. These values will be comma separated.

Field ID can be I, R or P (representing the attributes IP Address, Protocol and Port respectively).

Field values are an arbitrary string and can be the special value * which represents any value.

For example:

1,I,192.168.0.1,ALLOW
2,P,443,REJECT
3,R,Gopher,DROP
4,I,*,ALLOW

Packets

Packets are represented as a comma delimited string containing the source IP address (string), Protocol (string) and Port (Integer)

For example:

192.168.10.100,HTTP,80

Provided Input

The challenge provides you with sample inputs containing a packet definition on the first line followed by 1 or more lines of a rule set.

Matching

A firewall rule is matched when the given field and field value are present in the TCP packet representation. At this point traversal of the rule set should halt and your program should write the rule index and the action taken to the challenge output as a comma delimited pair.

For example:

3,DROP

No Match

If the packet matches none of the rules in the rule set then you must return the default action which will always be ALLOW. The rule index in this case is 0.

ie:

0,ALLOW

The Solution

Since the string representations of the various fields are the same for both the firewall rules and the packets, and since we’re only matching exact values, we don’t need to parse the individual fields. All that we have to do is compare the relevant field in the rule to the relevant field in the packet.

fields = %w(I R P)

packet, *rules = input.split("\n").map { |e| e.split(',') }

action = '0,ALLOW'
rules.each do |rule|
  field = fields.index(rule[1])
  if rule[2] == '*' or rule[2] == packet[field]
    action = rule[0] + ',' + rule[3]
    break
  end
end
output << action

The solution assumes well-formed input.

Another Solution

The shortest code golf (short but unreadable) solution I could come up with in Ruby is 143 characters.

p,*r=input.split("\n").map{|e|e.split(',')}+[%w{0 I * ALLOW}]
output<<(m=r.select{|r|r[2]=='*'||r[2]==p[%w{I R P}.index(r[1])]}[0])[0]+','+m[3]

More Codehire Cup 2013 Solutions

Codehire Cup 2012 Solutions

Read full post »

Tags: Codehire Cup, coding contests

Codehire Cup 2013 Solutions: Preliminary (Round 1)

A solution in Ruby to the Codehire Cup Preliminary (Round 1) problem in the second Codehire Cup held across Australia in June and July 2013.

In June and July 2013, Codehire held the second Codehire Cup across Australia. As last year, the contest featured some relatively simple coding problems. Contestants could choose to use C/C++, C#, Java, JavaScript, PHP, Python, or Ruby to submit solutions through a web-based interface.

Contestants were ranked according to the time taken to complete the problem, as well as by an assessment of their approach and coding style by a panel of judges.

The Problem

The Codehire Cup Preliminary (Round 1) problem read:

Summary

Calculate the card’s “inverse”.

A deck of playing cards has four suits: Hearts, Spades, Clubs and Diamonds. Cards within each suit are numbered from 2–9 with four additional cards being Jack, Queen, King and Ace.

For this exercise we will treat the Ace card as being a replacement for 1 with all other cards taking numbers through to 13. So each suit can be represented numerically as:

A  2  3  4  5  6  7  8  9  10  J   Q   K
1  2  3  4  5  6  7  8  9  10  11  12  13

We define the “inverse” of a card as being the inverse of its suit and the inverse of its number.

Inverses

The inverse of the card number is defined as:

Inverse(x) = 14 - x

We arbitrarily define the suit inverses as:

Suit          Inverse
Hearts     => Spades
Diamonds   => Clubs
Clubs      => Diamonds
Spades     => Hearts

Examples

Queen of Hearts would have the inverse 2 of Spades.

7 of Clubs would have the inverse of 7 of Diamonds.

Input and Output

You are given a card of the form:

<suit><number or face>

For example:

H7 => 7 of Hearts
SK => King of Spades

Challenge

Find the inverse of the given card and write to output in the same format.

The Solution

The simplest solution is to create an array of all of the suits and of all of the “numbers” of the card, and, for a given suit and “number”, select the suit and “number” at the opposite end of the relevant array.

suits = %w(H D C S)
cards = %w(A 2 3 4 5 6 7 8 9 10 J Q K)

suit = input[0]
card = input[1..-1]

inv_suit = suits[-suits.index(suit)-1]
inv_card = cards[-cards.index(card)-1]

output << inv_suit + inv_card

The solution assumes well-formed input.

Another Solution

As for last year’s Practice Challenge, we can squeeze the solution into the fewest number of characters possible to get a short, but not particularly elegant, solution. My solution in Ruby is 106 characters.

output<<(s=%w(H D C S))[-s.index(input[0])-1]+(c=%w(A 2 3 4 5 6 7 8 9 10 J Q K))[-c.index(input[1..-1])-1]

More Codehire Cup 2013 Solutions

Codehire Cup 2012 Solutions

Read full post »

Tags: Codehire Cup, coding contests