1 #!/usr/bin/perl -w
  2 
  3 # Perl script that implements the Lambda Lounge Vending Machine Specification
  4 # Tom Wheeler: Mon Apr  6 22:12:27 CDT 2009
  5 
  6 use strict;
  7 
  8 my $money_in = 0;
  9 
 10 # current stock of items for sale
 11 my %item_count = (
 12    'a' => 10, 'b' => 10, 'c' => 10,
 13 );
 14 
 15 my %item_value = (
 16    'a' => 65, 'b' => 100, 'c' => 150,
 17 );
 18 
 19 # current stock of various coins
 20 my %coin_count = (
 21    'nickel' => 10, 'dime' => 10, 'quarter' => 10, 'dollar' => 10,
 22 );
 23 
 24 my %coin_value = (
 25    'nickel'  => 5, 'dime' => 10, 'quarter' => 25, 'dollar' => 100,
 26 );
 27 
 28 prompt();
 29 while (chomp(my $input = <>)) {
 30     if    ($input =~ /^EXIT$/i)        { exit; }
 31     elsif ($input =~ /^NICKEL$/i)      { insert('nickel'); }
 32     elsif ($input =~ /^DIME$/i)        { insert('dime'); }
 33     elsif ($input =~ /^QUARTER$/i)     { insert('quarter'); }
 34     elsif ($input =~ /^DOLLAR$/i)      { insert('dollar'); }
 35     elsif ($input =~ /^GET-A$/i)       { sell('a'); }
 36     elsif ($input =~ /^GET-B$/i)       { sell('b'); }
 37     elsif ($input =~ /^GET-C$/i)       { sell('c'); }
 38     elsif ($input =~ /^COIN RETURN$/i) { coin_return(); }
 39     elsif ($input =~ /^SERVICE$/i)     { service(); }
 40     else  {
 41        print "\tIgnoring unrecognized command '$input'\n";
 42     }
 43 
 44     prompt();
 45 }
 46 
 47 sub prompt {
 48    print "> ";
 49 }
 50 
 51 sub insert {
 52    my $coin = shift;
 53    my $value = $coin_value{$coin};
 54 
 55    $money_in += $value;
 56    $coin_count{$coin} = $coin_count{$coin} + 1;
 57 
 58    my $count = $coin_count{$coin};
 59    print "\t$coin (value: $value cents) accepted; credit: $money_in cents\n";
 60 }
 61 
 62 sub sell {
 63    my $item = shift;
 64 
 65    my $count = $item_count{$item};
 66    if ($count <= 0) {
 67        print "\tSorry, we're out of stock on item '$item'\n";
 68        return;
 69    }
 70 
 71    my $value = $item_value{$item};
 72    if ($value > $money_in) {
 73        my $shortage = $value - $money_in;
 74        print "\tSorry, that costs $value. Insert $shortage cents, please.\n";
 75        return;
 76    }
 77 
 78    $item_count{$item} = $item_count{$item} - 1;
 79    $money_in = $money_in - $value;
 80 
 81    print "\tSold item '" . uc($item) . "' for $value cents; returning change\n";
 82    coin_return();
 83 }
 84 
 85 sub coin_return {
 86    # sort coins by descending order of value
 87    my @sorted_coins = sort { 
 88       $coin_value{$b} <=> $coin_value{$a};
 89    } keys %coin_count;
 90   
 91    foreach my $coin(@sorted_coins) {
 92       my $coin_value = $coin_value{$coin};
 93       next if $money_in < $coin_value;
 94 
 95       my $num_coins = int($money_in / $coin_value);
 96       my $count = $coin_count{$coin};
 97       $num_coins = $count if $num_coins > $count;
 98 
 99       $coin_count{$coin} = $count - $num_coins;
100       $money_in = $money_in - $num_coins * $coin_value;
101 
102       print "\tReturned $num_coins " . uc($coin) . "s\n";
103    }
104 
105    if ($money_in) {
106        print "\tInsufficient change: You have a credit of $money_in cents\n";
107    }
108 }
109 
110 sub service {
111    print "\tEntering machine service mode\n";
112 
113    print "\tCoins\n";
114    add_coins_or_items(\%coin_count);
115 
116    print "\tItems\n";
117    add_coins_or_items(\%item_count);
118 
119    print "\tExiting machine service mode\n";
120 }
121 
122 sub add_coins_or_items {
123    my $hash_ref = shift; 
124    my %hash = %$hash_ref;
125 
126    print "\n";
127    foreach my $thing(keys %hash) {
128        my $count = $hash{$thing};
129        print "\tHow many " . uc($thing) . "s to add (there are now $count)?\n";
130        prompt();
131        my $line = <STDIN>;
132 
133        last if $line =~ /END/i;
134        unless ($line && $line =~ /^[0-9]+$/) {
135            print "Ignoring invalid input\n";
136            next;
137        }
138 
139        my $num_to_add = int($line);
140        next unless $num_to_add > 0;
141 
142        $hash{$thing} = $count + $num_to_add;
143     }
144 
145     show_counts(\%hash);
146 }
147 
148 sub show_counts {
149    my $hash_ref = shift; 
150    my %hash = %$hash_ref;
151 
152    foreach my $thing(keys %hash) {
153        my $count = $hash{$thing};
154        print "\tThere are currently $count of '" . uc($thing) . "'\n";
155    }
156 }


syntax highlighted by Code2HTML, v. 0.9.1