This is in response to the challenge at Tic Tac Toe by Jeff Connely. This weighs in at 202 characters. I like the chop part myself. :)
$Z='ox'x5;$_="1 2 3\n4 5 6\n7 8 9 ";{$C=chop$Z;print "\n$_=>$C";{<>=~/^([\d])$/ && s/$1/$C/m or redo;}( m/(^($C.){3})|(($C.{5}){2}$C)|($C.{7}$C.{7}$C)|(^.(...$C){3})/sm or ++$T>8) or redo;}s/\d/-/g;print

Update: My original character count was off a bit. I think 202 is correct though.

Replies are listed 'Best First'.
RE: Tic Tac Chop
by turnstep (Parson) on Aug 18, 2000 at 06:55 UTC

    I'll try to break this down a little:

    $Z= 'ox' x 5; ## Only ten characters are needed because each ## game has a maximum of nine moves ## The grid, stored as a string: $_='1 2 3\n4 5 6\n7 8 9 "; { ## Start the generic loop $C = chop $Z; ## Strip the last character from $Z ('x' or 'o') ## and store it into $C print "\n$_=>$C"; ## Print the current grid, then the current letter + { ## Begin small inner loop <> =~ /^([\d])$/i && ## Grab input, must be a single digit... s/$1/$C/m ## Try to replace the number the user gave ($1) ## with the current character. or redo; ## If either of the above fails, redo this smal +l ## inner loop. } ## end inner loop m/(^($C.){3})|(($C.{5}){2}$C)|(($C.{7}){2}$C)|(^.(...$C){3})/sm ## The above is a nasty regular expression that checks to see if ## the game has been won. It checks for four ## things, inside the four parenthesis above. If any are true, ## then the expression is true, and the game is won (and over). ## Here they are: /^($C.){3})/ ## Checks for a horizontal match. Basically, it ## looks for the start of a line. Then it looks ## for the current letter followed by anything ## three times. In practice, this means it matches ## a character, a space, a character, a space, ## a character, and a newline /($C.{5}){2}$C/ ## This checks for a vertical match. Since the grid ## is constant, we know that three vertical characters + ## are a set distance apart. In this case, for our ## 3x3 grid, we are looking for the character, ## five anythings, the character, five anythings, ## and the character. /($C.{7}){2}$C/ ## This checks for a diagonal match, starting from ## the upper left-hand corner. Character, 7 anything, ## character, 7 anything, then the character. Only ## this diagonal matches this pattern. (^.(...$C){3}/ ## This checks for the opposite diagonal, starting fro +m ## the upper right-hand corner. It has the pattern ## of three anything, then the character, all three ## times. Since this could match other places, we use ## the anchor to specify only the diagonal we want or ++$T>8) or redo; ## Redo the outer loop *unless* one of the ## regular expressions matched *or* ## we have run 9 rounds. Anything else ## goes to the top of the generic loop } ## end the generic loop s/\d/-/g; print; ## We are done. Replace any numbers left in the ## grid with dashes, and re-display the grid.

    Hope that helps. I did change a couple things since it was first posted. The is not so much obfuscated code as it is very very short code. If I were really going for obfuscation, I would not use variables such as $T and $C. :) See Adam's code above for the same thing a bit more obfuscated.

    As far as making it a cgi, you could, but why? Nobody would be able to see it, only interact with it - as far as they know, it could be a 10,000 line perl script or a 1/2 Meg executable. Still, it should be possible. It's too late to type any more though. :)

RE: Tic Tac Chop
by Adam (Vicar) on Aug 18, 2000 at 03:57 UTC
    I started with your code and began removing stuff. Then I made it fit with use strict and -w and added a few obfuscation tricks of my own. This weighs in at 182 chars, 185 if you count the 3 newlines.
    $"='ox'x5,$_="1 2 3\n4 5 6\n7 8 9 ";{$^=chop$";print" $_$^ =>";{<>=~/^(\d)$/i&&s/$1/$^/m or redo}(m/^($^.){ 3}|($^.{5}){2}$^|$^.{7}$^.{7}$^|^.(...$^){3}/smx|$.>8 )or redo}y/0-9/-/;print
    Tested with ActiveState 5.6

    And yes, I like the chop.

    Update: I noticed a small bug, this fix cost me 3 chars. sigh. That puts me at 185 chars (188 with the newlines)

    $"='ox'x5,$_="1 2 3\n4 5 6\n7 8 9 ";{$^=chop$";print" $_$^ =>";{<>=~/^(\d)$/i&&s/$1/$^/m or$.--&&redo}/^($^ .){3}|($^.{5}){2}$^|$^.{7}$^.{7}$^|^.(...$^){3}/smx|8 <$. or redo}y/0-9/-/;print
      Passes with flying colors with Perl 5.00404 on Debian Slink, and 5.006 on OpenBSD 2.7.

      Would any fine Monks care to enlighten humble ybiC on how Adam's code works?   Special measures to adapt it to CGI use?

      Correction: the code is turnstep's, as tweaked by Adam.

      Update: sincere thanks to turnstep and Adam for explaining their obfuscations to pre-obfuscatory ybiC.
          cheers,
          ybiC

      #!/usr/bin/perl -w use strict; $"='ox'x5, $_="1 2 3\n4 5 6\n7 8 9 " {$^=chop$" print"$_$^ =>" {<>=~/^(\d)$/i&&s/$1/$^/m or redo} (m/^($^.){3}|($^.{5}){2}$^|$^.{7}$^.{7}$^|^.(...$^){3}/smx|$.>8) or redo}y/0-9/-/; print
      how about adding 'play against the computer' without hardcoding responses? -philip
RE: Tic Tac Chop
by xdb19 (Sexton) on Aug 18, 2000 at 20:45 UTC
    Your code could have been shortened a bit... Yours was 205... this is a variation of yours at a hefty 200....

    $Z='ox'x5;$_="1 2 3\n4 5 6\n7 8 9 ";{$C=chop$Z;print "\n$_=>$C";{<>=~/(\d)/&&s/$1/$C/m or redo}(/(^($C.){3}) |(($C.{5}){2}$C)|($C.{7}$C.{7}$C)|(^.(...$C){3})/sm or ++$T>8) or redo}s/\d/-/g;print;

    -XDB19
RE: Tic Tac Chop
by knurd (Initiate) on Aug 25, 2000 at 23:45 UTC
    Well, I did my best, but I could only squeeze it down to 177 characters long, assuming no newlines. I think it works. $"='ox'x5,$_="1 2 3\n4 5 6\n7 8 9 ";{$^=chop$";print"$_$^>"; {<>=~/^(\d)$/&&s/$1/$^/||$.--&&redo}/^($^.){3}|($^.{5}){2}$^ |($^.{7}){2}$^|^.(...$^){3}/sm|8<$.||redo}y/0-9/-/;print I must congratulate turnstep, it is quite exquisite. I did steal some stuff from Adam here, I must admit. I think I'm going to frame that and put it on my wall. I wouldn't be surprised if someone could still chop a character or two off, though.
      Mine is a hair shorter. 167 chars with newlines, 163 without them, and none of them are needed. The only whitespace is in the grid string.
      $_="1 2 3\n4 5 6\n7 8 9\n";$m="XOXOXOXOX"; {print;<>=~/^\d$/until$&&&s/$&/$p=chop$m/e; /^($p.){3}|($p.{5}){2}$p|^.(...$p){3}|($p.{7}){2}$p/ms||$m&&redo} y/0-9/-/,print


      japhy -- Perl and Regex Hacker
        you can trim a couple more off the $m assignment to:
        $_="1 2 3\n4 5 6\n7 8 9\n";$m="XO"x5; {print;<>=~/^\d$/until$&&&s/$&/$p=chop$m/e; /^($p.){3}|($p.{5}){2}$p|^.(...$p){3}|($p{7}){2}$p/ms||$m&&redo} y/0-9/-/,print
        I am still trying to grok a way to trim that regex down. a definite ++
RE: Tic Tac Chop
by xdb19 (Sexton) on Aug 18, 2000 at 20:45 UTC
    Your code could have been shortened a bit... Yours was 205... this is a variation of yours at a hefty 200.... $Z='ox'x5;$_="1 2 3\n4 5 6\n7 8 9 ";{$C=chop$Z;print "\n$_=>$C";{<>=~/(\d)/&&s/$1/$C/m or redo}(/(^($C.){3}) |(($C.{5}){2}$C)|($C.{7}$C.{7}$C)|(^.(...$C){3})/sm or ++$T>8) or redo}s/\d/-/g;print; -XDB19
RE: Tic Tac Chop
by xdb19 (Sexton) on Aug 18, 2000 at 20:46 UTC
    Your code could have been shortened a bit... Yours was 205... this is a variation of yours at a hefty 200....

    $Z='ox'x5;$_="1 2 3\n4 5 6\n7 8 9 ";{$C=chop$Z;print
    "\n$_=>$C";{<>=~/(\d)/&&s/$1/$C/m or redo}(/(^($C.){3})
    |(($C.{5}){2}$C)|($C.{7}$C.{7}$C)|(^.(...$C){3})/sm
    or ++$T>8) or redo}s/\d/-/g;print;

    -XDB19