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

Dear fellow Monks,
Here is the matrix I am building.
It is a chessboard, i.e. a 64 items array
   +-----------------------+
 8 |a8 b8 c8 d8 e8 f8 g8 h8|
 7 |a7 b7 c7 d7 e7 f7 g7 h7|
 6 |a6 b6 c6 d6 e6 f6 g6 h6|
 5 |a5 b5 c5 d5 e5 f5 g5 h5|
 4 |a4 b4 c4 d4 e4 f4 g4 h4|
 3 |a3 b3 c3 d3 e3 f3 g3 h3|
 2 |a2 b2 c2 d2 e2 f2 g2 h2| ^
 1 |a1 b1 c1 d1 e1 f1 g1 h1| ^
   +-----------------------+ ^
    a  b  c  d  e  f  g  h   |
 - ->-->-->-->-->-->-->-->---^
 And this is the reading direction
 i.e.  a1 - h1, a2 - h2, etc.
Therefore I need an array holding items like
a1 b1 c1 d1 e1 f1 g1 h1 a2 b2 c2 d2 e2 f2 g2 h2 a3 b3 ... and so on.
For my application, I need to create the array and assign the values in one statement only, or create an anonimous array, which is conceptually the same.
In short, I need to do either
my @array = array_creation_statement; list_function @array;
or
list_function array_creation_statement;
This is what I have tried so far.
#!/usr/bin/perl -w use strict; # The easy try. (OK, but it's 6 lines, not one statement) # my @for_ar; for my $row (1..8) { for my $col ('a'..'h') { push @for_ar, $col.$row; } } # It can be squeezed to two lines, but still not one (and bad style) # my @for_ar; # for my $row (1..8) { for ('a'..'h') {push @for_ar, $_.$row;}}; # The nested map (right items, wrong order) # a1 a2 a3 ... instead of a1 b1 c1 ... my @map_ar = map { map {$_} ($_.'1'..$_.'8') } ('a'..'h'); # the "brute force" try (right items, wrong order) # a1 a2 a3 ... my @grep_ar = grep { /[1-8]$/ } ('a1' .. 'h8'); # sorted brute force (OK, but boy! it's ugly and LONG) # my @grep_sort_ar = sort {substr($a,1,1) <=> substr($b,1,1) || $a cmp $ +b} grep{/[1-8]$/}('a1'..'h8'); # the wrong "brute force" try (wrong items, and too many) # (uncomment the next and the last comment to see the results) #my @grep_map_ar = grep{ /[1-8]$/ } map{map {$_}('a'.$_..'h'.$_)}(1..8 +); # ******************************************************************* # Finally, the nested map with a correction (OK!) my @map2_ar = map {my $row = $_; map { $_.$row } ('a'..'h') } (1..8); # printing the results print @{[ join ",", @$_]}, "\n" for ( ["for (OK)"], \@for_ar, ["map"], \@map_ar, ["grep"], \@grep_ar, ["sorted grep (OK)"], \@grep_sort_ar, # ["wrong grep"], \@grep_map_ar, ["*map 2* (OK)"], \@map2_ar );
Is there any Golfer who can get the right sequence with one shorter (or perhaps more meaningful) assignment?
my @array = something_magic;
Thanks
 _  _ _  _  
(_|| | |(_|><
 _|   

Replies are listed 'Best First'.
Re: Filling an array. (Golf challenge?)
by CheeseLord (Deacon) on Dec 27, 2001 at 14:42 UTC

    It's bizarre, but it does what you ask...

    my @array = map scalar reverse, glob("{1,2,3,4,5,6,7,8}{a,b,c,d,e,f,g, +h}");

    Update: And in the interest of golfing:

    #23456789_123456789_123456789_123456789_123456789_ map$_=reverse,<{1,2,3,4,5,6,7,8}{a,b,c,d,e,f,g,h}> # A different try map{my$a=$_;map$_.$a,'a'..'h'}1..8 # 34

    Bleh - 51 50 34 chars. Someone can definitely do better...

    Update 2: For a really good explanation of the way this works, check out Sneaky glob trick (was Web-Safe Color Chart) and trantor's reply.

    His Royal Cheeziness

      This glob is really cool. When I posted my request I was just hoping to see something of this sort popping up.
      In your latest try
      map{my$a=$_;map$_.$a,'a'..'h'}1..8  # 34
      you managed to squeeze my best one, which is 50, but can be shrinked down to 40:
      my @map2_ar = map{my$r=$_;map{$_.$r}('a'..'h')}(1..8); # 123456789_123456789_123456789_1234567890 (40)
      just by removing the () and {}!
      Thanks for the tips.
       _  _ _  _  
      (_|| | |(_|><
       _|   
      
        my @a = map{$r=$_;map$_.$r,a..h}1..8; # 123456789_123456789_123456789 (29)
      Here's my best for the glob ... 34.
      sub f{ #234567890#234567890#234567890#234567890 $"=',';@a=a..h;@b=1..8;glob"{@a}{@b}" } my@c=f(); $"="\n"; print "@c\n";

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Re: Filling an array. (Golf challenge?)
by larsen (Parson) on Dec 27, 2001 at 14:42 UTC
    Something magic? Sorry, I can't resist :)...
    use Quantum::Superpositions # Wrong order, but faster than light! print any('a'..'h') . any(1..8);
(crazyinsomniac) Re: Filling an array. (Golf challenge?)
by crazyinsomniac (Prior) on Dec 27, 2001 at 14:47 UTC
    Not as cool as His Royal Cheeziness' or larsens, but useful:
    #!/usr/bin/perl -wl use strict; my @ASHT = map { my @ash = 'a' .. 'h'; for my $as(@ash) { $as .= $_; } @ash; # implicit return } 1 .. 8; print join ',',@ASHT; my @ASH2 = map { $a = $_; map( $_.$a, 'a' .. 'h' ) } 1 .. 8; print join ',',@ASH2; print "BETTER WAY"; my @ASH3 = map { $a = $_; [ map( $_.$a, 'a' .. 'h' ) ] } reverse (1 .. 8); for my $i ( 0 .. 7 ) { print 8 - $i, "{", join( ',', @{ $ASH3[$i] } ), "}"; } print join ' ','','a'..'h'; #print Dumper \@ASH3; # if you're confused __END__ a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a3,b3,c3,d3,e3,f3,g3,h +3,a4,b4,c4,d4,e4,f4,g4,h4,a5,b5,c5,d5,e5,f5,g5,h5,a6,b6,c6,d6,e6,f6,g +6,h6,a7,b7,c7,d7,e7,f7,g7,h7,a8,b8,c8,d8,e8,f8,g8,h8 a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a3,b3,c3,d3,e3,f3,g3,h +3,a4,b4,c4,d4,e4,f4,g4,h4,a5,b5,c5,d5,e5,f5,g5,h5,a6,b6,c6,d6,e6,f6,g +6,h6,a7,b7,c7,d7,e7,f7,g7,h7,a8,b8,c8,d8,e8,f8,g8,h8 BETTER WAY 8{a8,b8,c8,d8,e8,f8,g8,h8} 7{a7,b7,c7,d7,e7,f7,g7,h7} 6{a6,b6,c6,d6,e6,f6,g6,h6} 5{a5,b5,c5,d5,e5,f5,g5,h5} 4{a4,b4,c4,d4,e4,f4,g4,h4} 3{a3,b3,c3,d3,e3,f3,g3,h3} 2{a2,b2,c2,d2,e2,f2,g2,h2} 1{a1,b1,c1,d1,e1,f1,g1,h1} a b c d e f g h

     
    ___crazyinsomniac_______________________________________
    Disclaimer: Don't blame. It came from inside the void

    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

      Not as short as I was expecting, but definitely will find a place for it in my Perl backpack.

      I wouldn't have a separate array for printing, since I can manipulate the original one for my output:
      my @array = map {my $row = $_; map { $_.$row } ('a'..'h') } (1..8); print map { my $o =$_; $o =~ tr/123456788/87654321/; $o =~ /^h/ ? $o." \n" : $o." " } @array; __END__ a8 b8 c8 d8 e8 f8 g8 h8 a7 b7 c7 d7 e7 f7 g7 h7 a6 b6 c6 d6 e6 f6 g6 h6 a5 b5 c5 d5 e5 f5 g5 h5 a4 b4 c4 d4 e4 f4 g4 h4 a3 b3 c3 d3 e3 f3 g3 h3 a2 b2 c2 d2 e2 f2 g2 h2 a1 b1 c1 d1 e1 f1 g1 h1
      This was a nice brainstorming. Thanks.
       _  _ _  _  
      (_|| | |(_|><
       _|   
      
Re: Filling an array. (Golf challenge?)
by Aristotle (Chancellor) on Dec 27, 2001 at 19:19 UTC
    #12345678901234567890123456789012345678901234567 for$i(1..8){push@a,$_.$i for"a".."h"} for$i(1..8){push@a,map$_.$i,"a".."h"} # Hrm, only close. # And for a completely different approach: #12345678901234567890123456789012345678901234567 @a=("a".."h")x8;$_.=(1+int$i++/8)for @a; @a=("a".."h")x8;$a[$_].=1+int$_/8for 0..$#a; # Trying a combination.. #12345678901234567890123456789012345678901234567 push@a,$_.(1+int$i++/8)for(("a".."h")x8); # I'm on to something.. #12345678901234567890123456789012345678901234567 $_.=1+int$i++/8for @a=("a".."h")x8; # Bah! :) # Assuming 'use integer;' it's a winner though: #12345678901234567890123456789012 $_.=1+$i++/8for @a=("a".."h")x8; # 32 characters. But.. :/
      Nice. But it's two lines, counting the array declaration.
      I am addicted to strict! ;-)
      my @a; for$i(1..8){push@a,$_.$i for"a".."h"};
      update Of course it should be also
      my $i; # after my @a; sorry :-(
       _  _ _  _  
      (_|| | |(_|><
       _|   
      
        Then that would have to be:
        my (@a, $i);
        Pay attention! :P

        Unless of course, you go for for my $i.
Re: Filling an array. (Golf challenge?)
by simon.proctor (Vicar) on Dec 27, 2001 at 16:51 UTC
    Well, I came up with the following and then saw that Crazyinsomniac had done a variation on it already :P. Still, ++ for an interesting node!
    @temp = map{glob"{a$_,b$_,c$_,d$_,e$_,f$_,g$_,h$_}"}(1..8); print join '',@temp;
Re: Filling an array. (Golf challenge?)
by runrig (Abbot) on Dec 27, 2001 at 21:22 UTC
    I was under the impression that when golfing, strict doesn't matter (unless its specifically asked for, which I don't see specifically :). I came up with the same thing as CheeseLord, but un-strictified it to 28 characters:
    map{$a=$_;map$a.$_,1..8}a..h
      I am not a golf expert (not even a beginner!), and this is why there is a "?" in my title. :-)
      Of course strict shouldn't matter in golf, but I mentioned it because I need to have this statement as something that you can assign to an array.
      BTW, great shrinking job!
       _  _ _  _  
      (_|| | |(_|><
       _|   
      
Re: Filling an array. (Golf challenge?)
by Aighearach (Initiate) on Dec 28, 2001 at 02:36 UTC
    As an aside, you might want to look at Games::Chess which uses a 64 byte string to represent a board. Probably more effiecient, and more ugly too.
    --
    Snazzy tagline here
Re: Filling an array. (Golf challenge?)
by gmax (Abbot) on Dec 28, 2001 at 14:24 UTC
    Amazing! It is really true that if you want to achieve results, you should throw a competition!
    Here are the shortest ones so far: (29)
    map{$a=$_;map$a.$_,1..8}a..h; # by runrig
    map{$r=$_;map$_.$r,a..h}1..8; # by Anonymous
    Runrig's solution could be reduced to
    map{map{$_}$_.1..$_.8}a..h; #27, but unfortunately it's the wrong orde +r. #23456789_123456789_1234567
    update tilly's sharp eye noticed a possibility for further squeezing it down to 19 chars!
     _  _ _  _  
    (_|| | |(_|><
     _|   
    
      If you were reducing it, there is no need for the inner map:
      #23456789_123456789 map$_.1..$_.8,a..h;
      But, as you say, that is in the wrong order.
(MeowChow) Re: Filling an array. (Golf challenge?)
by MeowChow (Vicar) on Dec 30, 2001 at 01:18 UTC
    21 chars:
    grep!/9|0/,'a1'..'h8'

    update: whoops, wrong order ;)

       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
      Impressive all the same! ++
       _  _ _  _  
      (_|| | |(_|><
       _|