tags:

views:

958

answers:

8

I'm looking for the shortest or most optimized solution for a simple game that generates a random number from 1 to 10 and then asks a user to enter their guess. If the user guesses the number then it's a win, if they don't guess then the program should say that it was either more or less than that.

Here's my solution to this:

#c:\Perl\bin\Perl.exe
use strict;
use warnings;

my $guess = int(rand 10);
my $inp;
do{
 print "Gimme your guess 1-10:\n";
 $inp = <STDIN>;
 chop($inp);
 if ($inp > $guess){print "too much\n"}
 if ($inp < $guess){print "too few\n"}
}while ($inp != $guess);

print "Bingo! It was: $guess";

What I'm looking for is some Perl magic. I don't have much Perl experience and I'd like to see some crazy Perl action here if it's true what they say about Perl scripts. Thanks for your time.

+9  A: 

I never played golf before. Here is the edited version following bubaker's suggestion.

#!/usr/bin/perl

use strict;
use warnings;

my @m = ('you win', 'too small', 'too big');
my $g = 1 + int rand 10;

do {
    print "Gimme your guess 1-10:\n";
    $_ = $g <=> <STDIN>;
    print "$m[$_]\n";
} while $_;

__END__
Sinan Ünür
definitely tidier than mine! thanks :)
Michal Rogozinski
It was a fun little exercise.
Sinan Ünür
nice job for your first drive! You could remove the last line of the while if you change it to a do { .., } while ($x);
bubaker
bubaker, I did not want to declare $x outside the loop, so I switched to using $_ instead of $x.
Sinan Ünür
+8  A: 
@_=('too small','you win','too big');$_=$v=int(rand 10)+1;while($_){print"Gimme your guess 1-10:\n";$_=<><=>$v;print$_[$_+1],"\n"}

130 characters

bdonlan
:) that's what I had in mind by perl magic :) Thanks!
Michal Rogozinski
It's not very magical yet. I'll revisit it tonight to see if I can do better :)
bdonlan
Well, this is only shorter because you decided to type it on one line.
Sinan Ünür
Actually, there are some minor changes, e.g. using <> instead of <STDIN>. The functionality is supposed to be the same, after all.
Rini
+4  A: 

154 characters (discounting newlines):

#!/usr/bin/perl -p
INIT{@m=((' few')x($g=1+int+rand+10),$g,(' much')x9),
$\="Gimme your guess 1-10:\n",print}s/.*/$m[$&]/;
s/ /Too /||undef$\^print("Bingo! It was: $_")+last

I was thinking, "if only I had some sort of comparison function returning (-1|0|1)!" while I was writing this...

Somehow completely forgot about <=>, which is winning the least-character count wars in here. Even pulling out the $\ trick doesn't win against that, so I conceed. **waves white flag**

                      ______________________________________________________
                     /                  ,.                                 ~
                    /       .           :%%%.    .%%%.                    ~
                   /    __%%%(\        `%%%%%   .%%%%%                   ~
                  /   /a  ^  '%        %%%% %: ,%  %%"`                 ~
                 /   '__..  ,'%     .-%:     %-'    %                  ~
                /     ~~""%:. `     % '          .   `.               ~
               /          %% % `   %%           .%:  . \.            ~
              /            %%:. `-'   `        .%% . %: :\          ~
             /             %(%,%..."   `%,     %%'   %% ) )        ~
            /               %)%%)%%'   )%%%.....- '   "/ (        ~
           /                %a:f%%\ % / \`%  "%%% `   / \))      ~
          /                  %(%'  % /-. \      '  \ |-. '.     ~
         /                   `'    |%   `()         \|  `()    ~
        /                          ||    /          ()   /    ~
       /                           ()   0            |  o    ~
      /                             \  /\            o /    ~
     /                              o  `            /-|    ~
    /                            ,-/ `           ,-/      ~
   /_____________________________________________________~
  //
 //
//  orz
ephemient
This changes the output text though, which makes it difficult to compare between different solutions...
bdonlan
I am not sure obfuscation was the purpose, this would take the cake. Now, I would recommend s/much/big/ and s/few/small/ above. The OP can learn a lot about Perl's internals from that but that has to be accompanied with a blood oath never to use anything like this in code that matters ;-)
Sinan Ünür
Ah, I didn't notice that the original printed out "Gimme your guess 1-10:" This will take some thought...
ephemient
The tradition is to count the options (-p adds 2) and the code (including whitespace), so your count is 97.
Chas. Owens
Adding in more strings makes it longer. Ah well.
ephemient
+5  A: 

130 character 1-liner from the command prompt (120 characters of code if you don't count perl -E):

perl -E '$g=1+int rand 10;@_=("Bingo! It was: $g","too few","too much");do{say"Gimme your guess 1-10:";say$_[$_=$g<=><>]}while$_;'

Version to put in a file (130 characters of code because I can't cheat and use -E):

use 5.010;$g=1+int rand 10;@_=("Bingo! It was: $g","too few","too much");do{say"Gimme your guess 1-10:";say$_[$_=$g<=><>]}while$_;

Thanks to pjf for suggesting I use 5.010 rather than use 5.10.0. Readable version (just formatted nicely for those of us who can't follow Perl one-liners):

use 5.010;
$guess = 1 + int rand 10;
@array = ("Bingo! It was: $guess", "too few", "too much");
do{
  say "Gimme your guess 1-10:";
  say $array[$_ = $guess <=> <>]
} while $_;

Of course, none of this is strict- or warnings-safe, but it works.

Chris Lutz
You can shave an extra character off your solution by 'use 5.010' rather than 'use 5.10.0'. ;)
pjf
+3  A: 

Here's an approach with recursion.

I fixed the range bug since int(rand(10) is 0-9. I'm also replicating the exact logic of the original, with strict, warnings and the exact text and without relying on a shebang line. Here it is with indentation so it's easier to follow:

use strict;
use warnings;
my($g,@m)=(1+int rand 10,'',"too much\n","too few\n");
sub g{
    print"Gimme your guess 1-10:\n";
    syswrite(STDOUT,$m[<><=>$g]) ? g() : $g;
}
print "Bingo! It was @{[g()]}\n";

Golfing with the same approach, without strict and warnings gets you this at 158 characters:

($g,@m)=(1+int rand 10,'',"too much\n","too few\n");sub g{print"Gimme your guess 1-10:\n";syswrite(STDOUT,$m[<><=>$g])?g():$g;}print"Bingo! It was @{[g()]}\n"
xdg
Nice! I haven't thought about recursion here:) Thx!
Michal Rogozinski
A: 
$im_thinking_of=int(rand 10);
print "Pick a number:";
$guess=<STDIN>;
chomp $guess;

if ($guess > $i'm_thinking_of) {
    print "You guessed too high!\n";
}
elsif ($Guess < $i'm_thinking_of) {
      print "You guessed too low!\n";

}
else {
     print "You got it right!\n";
}
Shaun Mallette
+2  A: 

124 characters :) (remove the newline)

use 5.010;$g=1+int rand 10;while(say"Gimme your guess 1-10:")
{say"too ",qw(0 much few)[<><=>$g]||last}say"Bingo! It was: $g"

expanded out

use 5.010;
$guess = 1 + int rand 10;
while (say "Gimme your guess 1-10:") { 
    say "too ", qw(0 much few)[<> <=> $guess] || last
}
say "Bingo! It was: $guess"
Eric Strom
+2  A: 

If you want to keep people busy so you can keep some work done, try:

 perl -E "while( <STDIN> ) {say 'Try again.'}"

This is the best guessing game evah because you get the maximum number of guesses every time you run it. There's none of that cripple-ware limited guessing programs.

If you want to tell users that eventually they can guess the number, you can make a slight modification:

  perl -E "while( <STDIN> ) {last if (\$_ == rand 100 ); say 'Try again.'}"

If they still complain that it's too hard, you can have a beginner version:

 perl -E "<STDIN>; say 'That's right. Good job. You are awesome.'"
brian d foy