Skip to content

Instantly share code, notes, and snippets.

@ultimape
Last active December 20, 2015 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ultimape/e0aa38cb922440f29445 to your computer and use it in GitHub Desktop.
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
#!/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