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

Tags: Codehire Cup, coding contests