#!/usr/bin/perl -w use strict qw (vars); use IO::Handle; use POSIX; our ($ship, %have, %price); my $usage = <] [ ] where is three arguments: the prices for swill, grog and fine rum is a ship name or an amount of fine rum are amounts on board for swill, grog and fine rum END ; sub main () { if (@ARGV==4) { ($ship, $have{Swill}, $have{Grog}, $have{Fine}) = @ARGV; print_inputs(); compute_restock_requirements(); } elsif (@ARGV==3) { ($price{Swill}, $price{Grog}, $price{Fine}) = @ARGV; print_inputs(); compute_cheapest_rum(); } elsif (@ARGV==7) { ($price{Swill}, $price{Grog}, $price{Fine}, $ship, $have{Swill}, $have{Grog}, $have{Fine}) = @ARGV; print_inputs(); compute_cheapest_rum(); compute_restock_requirements(); compute_restock_cheapest_rum(); } else { die $usage; } } our @rums= qw(Swill Grog Fine); our %proof= qw(Swill 40 Grog 60 Fine 100); our $ff = '%6.1f'; sub prvff ($$\%$) { my ($what, $format, $ary, $unit) = @_; printf("%-40s", "$what:"); map { my $x= $ary->{$_}; my $y= defined $x ? sprintf $format, $x : ' x'; printf " %-10s", $y; } @rums; printf " %s\n", $unit; } sub pr ($\%$) { my ($what, $ary, $unit) = @_; prvff($what, '%4d ', %$ary, $unit); } sub prf ($\%$) { my ($what, $ary, $unit) = @_; prvff($what, $ff, %$ary, $unit); } sub pr1 ($$) { my ($k,$v) = @_; printf "%-20s %s\n", "$k:", $v; } our ($best_kind); sub compute_cheapest_rum() { $best_kind= undef; my %norm_price; my $best_norm_price= 1e6; foreach $_ (@rums) { next unless defined $price{$_}; $norm_price{$_} = $price{$_} * $proof{Fine} / $proof{$_}; if ($norm_price{$_} <= $best_norm_price) { $best_kind= $_; $best_norm_price= $norm_price{$_}; } }; prf('normalised prices', %norm_price, 'poe/fine'); if (defined $best_kind) { printf "best is %s\n\n", $best_kind; } else { die "no rum available ?\n"; } } our $have_proof; sub print_inputs () { printf("%40s",''); map { printf " %5s ", $_ } @rums; print "\n\n"; if (defined $price{Swill}) { map { $price{$_}= undef if $price{$_} eq 'x' } @rums; pr('prices', %price, 'poe ea.'); } if (defined $have{Swill}) { $have_proof= 0; map { $have_proof += $have{$_} * $proof{$_} } @rums; pr('stock on board', %have, 'rum'); } } our ($need_proof, %need, %buy); sub compute_restock_requirements () { if ($ship =~ m/^\d+/) { $need{Fine} = $ship; } else { $ship =~ y/_/ /; open F, "/home/ian/private/puzzle-pirates" or die $!; my $this_ship= 0; my $the_ship; while () { if (!m/\S/ || m/^\s*\#/) { $this_ship= 0; next; } if (!m/^\@/) { next; } if (m/^\@(( [A-Z][-a-z]+){2,})\s*$/) { $this_ship= (uc $1 eq uc " $ship" or uc $+ eq uc " $ship"); $the_ship= $1; next; } next unless $this_ship; if (m/^\@\s+(\d+)\s+fine\s*/) { $need{Fine} = $1; last; } } die $! if F->error; die "unknown ship $ship" unless defined $need{Fine}; if (defined $ship) { pr1("vessel",$the_ship); } } pr1('desired stock level', sprintf("%4d fine rum", $need{Fine})); $need_proof= $need{Fine} * $proof{Fine} - $have_proof; map { $buy{$_} = $need_proof / $proof{$_}; } @rums; pr1("stock equivalent", sprintf "$ff fine rum", $have_proof / $proof{Fine}); pr1("restock equivalent", sprintf "$ff fine rum", $need_proof / $proof{Fine}); prf('would need', %buy, 'rum'); } sub compute_restock_cheapest_rum() { my %bill; map { $bill{$_} = $buy{$_} * $price{$_} if defined $price{$_}; } @rums; prf('nominal bill', %bill, 'poe'); print "\n"; if ($need_proof < 0) { printf "stocks are sufficient"; } else { my $buy= ceil($buy{$best_kind}); printf "buy %d %s at %d poe each for %d poe", $buy, $best_kind, $price{$best_kind}, $buy * $price{$best_kind}; } print "\n\n"; } main();