From: Ian Jackson Date: Sun, 17 May 2009 15:40:41 +0000 (+0100) Subject: ypp-restock-rum as found on liberator X-Git-Tag: 1.0~23 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.db-test.git;a=commitdiff_plain;h=4fe752be5883e1b781c1e73f81eb30e3df0a23d1 ypp-restock-rum as found on liberator --- diff --git a/ypp-restock-rum b/ypp-restock-rum new file mode 100755 index 0000000..7e10a46 --- /dev/null +++ b/ypp-restock-rum @@ -0,0 +1,175 @@ +#!/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();