Last active
December 20, 2015 15:00
-
-
Save ultimape/e0aa38cb922440f29445 to your computer and use it in GitHub Desktop.
A Perl program to solve the challenge presented at https://www.hackerrank.com/contests/nov13/challenges/utopian-tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/perl | |
# A Perl program to solve the challenge presented at https://www.hackerrank.com/contests/nov13/challenges/utopian-tree | |
# modified for formatting and spelling mistakes. | |
# Author: Nicholas Perry | |
# Scores of entry: https://www.hackerrank.com/challenges/utopian-tree/submissions/code/1442434 | |
# Test Case #0: 0.25s | |
# Test Case #1: 0.03s | |
# Test Case #2: 0.03s | |
# Test Case #3: 0.03s | |
# Test Case #4: 0.02s | |
# Test Case #5: 0.02s | |
# Test Case #6: 0.02s | |
# Test Case #7: 0.03s | |
# Test Case #8: 0.03s | |
# Test Case #9: 0.02s | |
use strict; # because diagnostics doesn't work in this hakerrank thing for some reason | |
# This subroutine reads in the test values from STDIN | |
sub readInTestCases { | |
my @input = (); | |
while (<>) { | |
chomp; #those pesky newlines, breaking all our stuffs | |
push @input, $_; | |
} | |
# Here we can do some some simple sanity checks against what we are given. | |
die "expected some numbers per format specification, got nothing" unless scalar @input >= 1; | |
foreach (@input) { | |
die "expected some numbers per format specification, got something that isn't a number" unless m/^[+-]?d+$/; | |
die "expected a positive integer value for number of iterations, got a negative number of iterations" if m/^-/; | |
} | |
# Massage the incoming data into something more usable. | |
# I could just keep everything in the one array and use fancy indexing tricks, but this way will help me keep my variables straight | |
my $numEntries = shift @input; | |
my @testCases = @input[0..($numEntries-1)]; | |
# Now that we know more about our data, we can make some more in-depth assertions. | |
die "number of test cases was exceeded" unless scalar @testCases <= $numEntries; | |
die "number of test cases was not met" unless scalar @testCases >= $numEntries; | |
return @testCases; | |
#Usage Note: We don't actually care about the number of test cases since that is intrinsically implied by the size of the list | |
} | |
# here we are using a hash to store the business logic function -> season mappings. | |
my %applySeasonGrowthRate = ( | |
monsoon => &monsoonGrowth, | |
summer => &summerGrowth, | |
); | |
# Here are the actual functions defining the business logic. | |
# If this project was significant enough, I would consider writing these as a polymorphic season object with a .grow method | |
sub monsoonGrowth { | |
my $currentValue = @_[0]; | |
#Hooray, business logic | |
my $newValue = $currentValue * 2; | |
#monsoon growth rate is double what it was before | |
return $newValue; | |
} | |
sub summerGrowth { | |
my $currentValue = @_[0]; | |
#Hooray, business logic | |
my $newValue = $currentValue + 1; | |
#summer growth rate is just one meter | |
return $newValue; | |
} | |
# This lets us define arbitrary transitions between seasons as a state machine. | |
# I don't know enough about the problem domain, but I could imagine a place with a summer, a spring, and two monsoon seasons. | |
# This lets me represent those kind of odd season configurations. | |
# If this project was significant enough, I would consider writing this as a .getNext season method on some plant object, | |
# and possibly have it pull the mappings from an externally editable file for the sysOp to configure. | |
my %getNextSeason = ( | |
first => "monsoon", #initial case for the state machine | |
monsoon => "summer", | |
summer => "monsoon", | |
); | |
sub calculateGrowth { | |
my ($numIterations, $initialHeight) = @_; | |
my $currentTreeHeight = $initialHeight; | |
# No Iterations means the tree doesn't grow beyond its inital state. | |
return $currentTreeHeight if $numIterations == 0; | |
# initialize the state | |
my $currentSeason = $getNextSeason{"first"}; | |
# for each season | |
for ( 1 .. $numIterations) { | |
# get old value | |
my $oldTreeHeight = $currentTreeHeight; | |
# mutate value based on business logic rule-set given current state | |
my $newTreeHeight = $applySeasonGrowthRate{$currentSeason}->($oldTreeHeight); | |
# persist the new value | |
$currentTreeHeight = $newTreeHeight; | |
#update state | |
$currentSeason = $getNextSeason{ | |
$currentSeason | |
}; | |
} | |
return $currentTreeHeight; | |
} | |
sub Main { | |
my @testCases = readInTestCases(); | |
my $initialHeight = 1; | |
#this is a given value, assumed true; | |
die "Unable to read in test case" unless scalar @testCases > 0; | |
foreach my $numIterations (@testCases) { | |
my $treeHeight = calculateGrowth($numIterations, $initialHeight); | |
print $treeHeight; | |
print "n"; | |
} | |
} | |
#and execute | |
Main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment