Jabox has asked for the wisdom of the Perl Monks concerning the following question:

Good day everyone!

I am trying to practice push and pop so I was making this little project similar to an NPC that stores your items.

The snippet probably looks like something that doesn't exist or make sense because I'm still learning so I apologize and I accept all responses even if they are suppose to offend me.

So here is a snippet, will post problem afterwards!

my @storage = qw(knife wand bow); my @inventory = qw( axe sword shovel ); sub depo { sleep (1); print "Which item would you like to deposit?\n", "1. Nevermind\n"; foreach my $inv (map(ucfirst, @inventory)){ print "$num. $inv\n"; $num++; } $choice = lc(<STDIN>); chomp $choice; if ($choice =~ $item) { my $item = splice @inventory, $choice; push(@storage,$item); print "You have stored a \"$item\".\n"; }

SO what I am trying to do is that if I put in "Axe" from my @inventory and it exist, it will take the "axe" from @inventory and add it to @storage so then @storage will equals to knife wand bow axe while @inventory will equals to only sword and shovel.

And if it doesn't exist, it will do

else { print "Please input a valid answer!\n"; sleep (1); &bank; }

Thank you for your time :D!

P.S. there was a grep function before the if($choice =~$item).. thats why the $item was there if you were wondering.. I was experimenting :D!

Replies are listed 'Best First'.
Re: Push,pop, and splice!
by davido (Cardinal) on Mar 18, 2014 at 17:19 UTC

    An array makes a poor database because searches for individual items (in an unsorted array) will be linear searches, and inserts/deletions anywhere other than the first or last element will also be linear. A hash would get you constant time searches insertions, and deletions. Though because a hash's keys are unique, if there's the possibility of having more than one axe, for example, you would need to store a hash-of-arrays to accommodate them.

    But this exercise is just for amusement and learning. So here's one way you might do it. I used the IO::Prompt::Hooked module to facilitate the prompting / taking input logic. You could implement it by hand if you wanted, and it wouldn't be all that hard. The module just provides a little sugar.

    I've got a couple of data validity checking steps in this solution. Both of them (the ones that include die) should be unreachable. In this trivial code they're not really useful. However, in non-trivial code, it's often worthwhile to complain loudly when something unexpected happens.

    use strict; use warnings; use IO::Prompt::Hooked 'prompt'; my @storage = qw( knife wand bow ); my @inventory = qw( axe sword shovel ); while(@inventory) { print "\nYour inventory contains: ( @inventory )\n"; print "Your storage contains: ( @storage )\n"; my $wanted = prompt( message => 'Which item would you like to deposit? (blank to quit) +:', validate => sub { my $i = lc shift; return 1 if ! length $i; return grep { $i eq $_ } @inventory }, error => "Please input a valid answer: ( @inventory ).\n" ); last unless $wanted; my( $item_index ) = grep { $inventory[$_] eq $wanted } 0 .. $#invent +ory; die "Couldn't find $wanted\n" unless defined $item_index; # Impossible. push @storage, splice @inventory, $item_index, 1; die "push/splice failure with <$wanted>.\n" if $storage[-1] ne $wanted; # Impossible. } print <<"EOD"; Now inventory and storage respectively contain: ( @inventory ) ( @storage ) EOD

    Here is a sample run:

    $ ./mytest.pl Your inventory contains: ( axe sword shovel ) Your storage contains: ( knife wand bow ) Which item would you like to deposit? (blank to quit): swwrd Please input a valid answer: ( axe sword shovel ). Which item would you like to deposit? (blank to quit): sword Your inventory contains: ( axe shovel ) Your storage contains: ( knife wand bow sword ) Which item would you like to deposit? (blank to quit): axe Your inventory contains: ( shovel ) Your storage contains: ( knife wand bow sword axe ) Which item would you like to deposit? (blank to quit): shovel Now inventory and storage respectively contain: ( ) ( knife wand bow sword axe shovel )

    Dave

Re: Push,pop, and splice!
by toolic (Bishop) on Mar 18, 2014 at 16:37 UTC
    This defeats the purpose of your title, but another approach is hashes:
    use warnings; use strict; my %storage = map { $_ => 1 } qw(knife wand bow); my %inventory = map { $_ => 1 } qw(axe sword shovel); while (1) { print "Which item would you like to deposit?\n"; print "$_\n" for sort keys %inventory; my $choice = lc <STDIN>; chomp $choice; if (exists $inventory{$choice}) { delete $inventory{$choice}; $storage{$choice}++; print qq(You have stored a "$choice".\n); } elsif ($choice eq 'end') { last; } } use Data::Dumper; $Data::Dumper::Sortkeys=1; print Dumper(\%storage); print Dumper(\%inventory);
Re: Push,pop, and splice!
by mtmcc (Hermit) on Mar 18, 2014 at 16:56 UTC

    Firstly, I agree with toolic above, that hashes are likely to be much better for what you are trying to do.

    Second, have a look at splice for the splice syntax. Rather than using the name of the item you want to splice, you should provide the index, and number of items. Something like this:

    #!/usr/bin/perl use warnings; use strict; depo(); sub depo { my @storage = qw(knife wand bow); my @inventory = qw(axe sword shovel); my $num = 1; my $choice; my $item; sleep (1); print "Which item would you like to deposit?\n", "$num. Nevermind\n"; foreach my $inv (map(ucfirst, @inventory)){ $num++; print "$num. $inv\n"; } $choice = lc(<STDIN>); chomp $choice; my $index = 'N'; for (my $x = 0; $x <= $#inventory; $x+= 1) { if ($inventory[$x] eq "$choice") { $index = $x; $item = $inventory[$x]; } } if ($index eq 'N') { print "$choice is not available.\n\n"; return; } $item = splice (@inventory, $index, 1); push(@storage,$item); print "You have stored a \"$item\".\n\n"; print STDERR "STORAGE: @storage\nINVENTORY: @inventory\n\n"; }

    I hope that helps a little.

Re: Push,pop, and splice!
by Don Coyote (Hermit) on Mar 18, 2014 at 21:43 UTC

    please do not make me wait

    else { print "Please input a valid answer!\n"; # --> sleep (1); #blocking &bank; }

    Add a condition triggered by a flag passed in to the bank sub

    sub bank{ unless( $_[0] eq 'inv' ){ Print "Greetings traveller, there is much rain today, can I inte +rest you in our laundry deals?\n" }else{ Print "I can not Deposit that, not after the licensing fees went + up on those, maybe you have some other valuables you need me to stor +e for you?\n" } #rest of bank sub } ... else { &bank('inv') }

    with all the items I am sure to need to store and retrieve, I do not want to be hanging round for a dozy bank teller :)