http://qs1969.pair.com?node_id=173613

The premise

Your job at HappyCartoonFriendFinder.com has taken a turn for the worse. All of the venture capital has dried out, subscriptions are down, and the pop-up ad revenue isn't paying the bills anymore. In order to keep the lights on for one more month, your boss decides to make a testimonial page, where toons can present their happy stories of new-found love, all thanks to HappyCartoonFriendFinder.com.

After querying the database, you find you've got just 5 paying couples who met through HappyCartoonFriendFinder.com, and you've already stored their names in a hash :
%couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" );

Unfortunately, your company is so low on funding, that they can't pay for more than 80 characters of coding. Not only that, somebody's stolen your remaining supply of newlines, slashes, backslashes and semi-colons, and grabbed all but 2 doublequotes!

Your goal is to produce a small alphabetically listed snippet of text which will be passed onto an p2b end-to-end hyper-business server for use in a larger HTML file, which should hopefully attract new subscribers.

this file should look like :
Barney is married to Betty
Fred is married to Wilma
George is married to Jane
...
and so on, for each of the couples.

The goal

print out the couple's information as formatted above to STDOUT. Do it in one line of code, using no more than 80 characters. You have only 2 '"' (doublequotes), and you can't use the characters ';', '\' or '/'.

You can assume a shebang line properly formatted for your system,a newline, the %couples hash as specified above, and one final newline. This means that your solution should be 9 lines long. Can you save HappyCartoonFriendFinder.com?
This is a relatively easy challenge, suitable for those who are starting to get comfortable with perl. If you say "that's easy!" or have written one or more books on perl, consider skipping this node :)

The reference answer

#! perl -l %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" ); print foreach sort map {"$_ is married to $couples{$_}"} keys %couples

Update

the 2 entries below are close, but using "\n" disqualifies them. What options in perl could take the place of a newline? (or is this a trick?)
An annoyed saint notes : "in your perl puzzle you should note that people *can* adjust command-line options.. we've been resorting to slurping `cat $0` and doing substitutions to get it to work" and 'maybe say "You can assume a shebang line of your choice, ...'

Replies are listed 'Best First'.
Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by BlueBlazerRegular (Friar) on Jun 11, 2002 at 21:08 UTC
    All right, I'll jump in. I'm not exactly a newbie, but I'm also not an 'expert' (fill in your own opinion on what an 'expert' is).

    So without further ado, this is what I ended up with:
    #!/usr/bin/perl -w %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" ); print "$_ is married to $couples{$_}\n" for (sort keys %couples);


    Looking at just the important line, I started with:
    foreach $key (sort keys %couples) {print "$key is married to $couples{ +$key}\n"};
    Hmm, exactly 80 characters. But wait, I can use the default variable ('$_') rather than creating my own, so I'm now down to 71 characters.
    foreach (sort keys %couples) {print "$_ is married to $couples{$_}\n"} +;
    Ahh, there's more. 'foreach' can be written as 'for' taking me done to 67 characters:
    for (sort keys %couples) {print "$_ is married to $couples{$_}\n"};
    Not quite - I can get rid of those pesky brackets by reversing the 'for' and 'print' statements, reducing it down to 65 characters:
    print "$_ is married to $couples{$_}\n" for (sort keys %couples);

    And that's as far as I've gotten. I've noticed that my solution got more 'perlish' (albeit not much) as I went along, so I was hoping that some of our more experienced monks would contribute as well - and notes as to how you got there are most welcome. Most Perl golf I see is from a realm I'm not familiar with, so a map to that wonderful place would be appreciated greatly.

    Pat

    P.S. Viewng my post in VIM with syntax checking on leads to some strange colored text...
Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by mrbbking (Hermit) on Jun 11, 2002 at 23:57 UTC
    My solution ended up nearly identical to BlueBlazerRegular's, but I dropped a bit of excess punctuation and whitespace, to come in with 21 chars to spare:
    # 1 2 3 4 5 6 #23456789012345678901234567890123456789012345678901234567890 print"$_ is married to $couples{$_}\n"for sort keys%couples
    Bonus (for me, anyhow): I played with map a bit, and found that it was actually longer that way.
    # 1 2 3 4 5 6 #2345678901234567890123456789012345678901234567890123456789012 print map{"$_ is married to $couples{$_}\n"}sort keys%couples
    Update: Whoops. I can get away with '\n' since it's not an actual 'newline', but may casual disregard of the "can't use a backslash" rule was just silly. I'm out!
      Building off mrbbking, why don't we try and get rid of \n. After thinking and messing around bit, I ended up using $*: The multiline matching variable. I'd love to know *why* this works, and if it's compatible with *nix, as I used activestate.

      Update: Tested on a FreeBSD shell, and it *does* work, as long as we run it with perl -l...

      Please don't run this with warnings, as it won't work because $* is a deprecated special variable.

      Here Goes: Still 59 Letters
      #! perl -l %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" ); print"$_ is married to $couples{$_}$*"for sort keys%couples
      Another idea that may or may not have merit is to set %couples to a shorter word, and call that in the print. Something that would (logically) be *like*
      print"$_ is married to $c{$_}$*"for sort keys(%c=%couples)
      That code doesn't work, though, and would save you just one character.

      Update 2: I found it strange that I was getting newlines, instead of 0 or 1 from $*, so I investigated. From perldoc perlrun: -l enables automatic line-ending processing. If octnum is omitted, sets $\ to the current value of $/. That means that there's no reason to use $*, as -l will give us $/, anyways.

      You will then realize that the previous answers would be correct, if we got rid of \n, or in my case $* (-l chops the last letter off in addition, which meant that my $* which should have been evaluated as 0 or 1, was being chopped off and replaced by a newline ($/). Strage, but we don't even need to print newlines, with perl -l :)

      That means: print"$_ is married to $couples{$_}"for sort keys%couples can replace the respective line in the previous solution(s)

      Gyan Kapur
      gyan.kapur@rhhllp.com
        Damn keys
        print"$_ is married to $a{$_}$*"for sort keys%{*a=*couples}
        is the same whereas
        print"$_ is married to $a{$_}$*"for sort keys*a=*couples
        is no go and
        print"$_ is married to $a{$_}$*"for sort keys%a=%couples
        is just not right...

        --
        perl -pew "s/\b;([mnst])/'$1/g"

Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by perigeeV (Hermit) on Jun 12, 2002 at 10:55 UTC

    the 2 entries below are close, but using "\n" disqualifies them. What options in perl could take the place of a newline? (or is this a trick?)

    print "$_ is married to $couples{$_}<br>" for(sort keys %couples)

    You don't need a newline. You need a <br> tag. The output is going to an HTML file.


      You don't need a newline. You need a <br> tag. The output is going to an HTML file

      The requirement is...
      print out the couple's information as formatted above to STDOUT

      The final output might be to HTML but the output of this code does need newlines.

Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by Cybercosis (Monk) on Jun 12, 2002 at 08:05 UTC
    well, here's something that qualifies (it's only a slight improvement over previous answers for better rules-conformity.
    weighing in at 67 chars:

    print"$_ is married to $couples{$_}",chr 0x0a for sort keys%couples

    just tr/0x0a/0x0d/ if your system uses that for newline. and, at 76 chars (ever so short of the limit...), the same code with microsoft newline:

    print"$_ is married to $couples{$_}",chr 0x0d, chr 0x0a for sort keys%couples

    ~Cybercosis

      Unless you have done binmode STDOUT, you can print "\n" and it will print the appropriate newline for your system, including those with a two character newline (CP/M and DOS use "\x0D\x0A").

      Also, why use chr 0x0a instead of the shorter chr 10?

Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by mothra (Hermit) on Jun 12, 2002 at 14:08 UTC
    Either:

    map{print"$_ is married to $couples{$_}".chr 10}sort keys%couples}

    or:

    map{print"$_ is married to $couples{$_}<br>"}sort keys%couples}

    The latter, of course, only newlines in HTML.

    Update: print"$_ is married to $couples{$_}<br>"for sort keys%couples :)

Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by Abigail-II (Bishop) on Jun 12, 2002 at 14:40 UTC
    Without using any slashes, backslashes, semi-colons, double quotes, command line options, and using 72 characters:
    map{print qq{$_ is married to $couples{$_}@{[chr 10]}}}sort keys%coupl +es

    Abigail

      My approch was similar.

      Without using any slashes, backslashes, semi-colons, command line options, only two double quotes, and using 64 characters:

      printf"$_ is married to $couples{$_}%c",10 for sort keys%couples
      Changing the double-quotes into  qq{} makes it 67 characters.

      Of course, mine fails if anyone has a % in their name. In real Golf, it is the sort of thing they would update the test script to catch.

      The most evil newline variant I considered was:

      $:=~m{.(.)}s and print "something$1"

Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by danger (Priest) on Jun 13, 2002 at 04:19 UTC

    If they're paying me for 80 characters then 80 characters they'll get!

    #!/usr/bin/perl %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" ); print`perl -lne'tr! ",!!d and s!=>(?=[A-Z])! is married to ! and print +' $0|sort`

    I mean, if we don't use our budget of 80 characters this time around, they'll just budget 70 characters for us next time! (and I'm hiding my spare double quote for an emergency, so don't ask me if you used up both of yours).

Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by Aristotle (Chancellor) on Jun 13, 2002 at 02:46 UTC
    And now, for something entirely different.
    # 1 2 3 4 5 6 #234567890123456789012345678901234567890123456789012345678901234 {(@c=each%couples)&&printf("%s is married to %s%c",@c,10)&&redo}
    Pity I've been beaten. :-)
    # Update: trickier, same char. count {(@c=each%couples)?printf("%s is married to %s%c",@c,10)&redo:1}
    ____________
    Makeshifts last the longest.
Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by gumby (Scribe) on Jun 12, 2002 at 19:44 UTC
    $c=[{Fred=>1, Barney=>2, George=>3, Homer=>4, Peter=>5} "Wilma", "Betty", "Jane", "Marge", "Lois" ]; while(my($h,$w)=each %$c){print"$h is married to $w\n";}
    I have noticed that this is an extremely braindead post. D'oh!
      #!/usr/bin/perl -w -l %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" ); print"$h is married to $w"while(($h,$w)=each%couples)
Re: perl puzzle - cartoon couple registry (beginner, semi-golf)
by Pug (Monk) on Jun 12, 2002 at 23:45 UTC
    I have been on a map kick recently so...
    using 2 " and no ; / \ or enter keys

    #!/usr/bin/perl -l %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Pter=>"Lous" ); map print, map "$_ is married to $couples{$_}",sort keys%couples
    It weights in at 63 characters.
    I was reading the above posts and I was able to get this
    %c=%couples,map print,map "$_ is married to $c{$_}",sort keys%c
    Which is 62 characters.
    Update. Thanks for the getting rid of the extra map belg4mit.

    I don't know what I was thinking *grin*
    In a semi related note I used this when someone wanted to a print out of the @INC.
    --
    Mortic

      map print("$_ is married to $couples{$_}"),sort keys%couples

      60 char, who needs a semi-colon? map map is inefficient and in this case wasteful.

      --
      perl -pew "s/\b;([mnst])/'$1/g"

Re: perl puzzle - cartoon couple registry (TMTOWTDI)
by jynx (Priest) on Jun 13, 2002 at 01:32 UTC

    Since i can't think of a good way to golf this well, i'll bend the rules slightly. Here's a solution that you place before the couples declaration. It uses command line options, two quotes, and weighs in at 58 chars. Slightly amusing...
    #!/usr/bin/perl -l #23456789_123456789_123456789_123456789_123456789_123456789_ sub _{print shift()." is married to ".shift while@_}_ sort %couples = ( Fred=>"Wilma", Barney=>"Betty", George=>"Jane", Homer=>"Marge", Peter=>"Lois" );
    jynx

    Update: Ah, err, uh, whoops... LOL! This is a non-working solution. It's really amusing who's married to whom in it though! Sorry about that, apparently my eyesight is going (i thought it looked fine until i retested a couple minutes ago) -- it must be time to go home...