Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How's your Perl?

by xmath (Hermit)
on Oct 27, 2003 at 00:16 UTC ( #302287=perlmeditation: print w/ replies, xml ) Need Help??

As part of our continuing crusade against sanity, we of #perlhelp (EFnet) have created a modest perl quiz to test for all the skills required to make the maintainance programmer voluntarily leap into the gaping chasm of madness. We hope it will reinforce everyone's appreciation of our favorite language, by itself and as a tool towards this noble goal.   ;-)

Only those who know and truly understand the answers to all these questions can call themselves [insert awesome title here].

For all exercises: no fork/exec/system/qx/open, no cmdline options, no user input, no modules, no tie, no bless, no %SIG. Make sure you don't depend on random factors, such as exact values of addresses. All solutions should be executable from the cmdline using perl -e For extra points, try to make them work under strict (warning: for one exercise no strict solution is known (yet))
UPDATE Thanks to mauke, strict solutions are now known for all exercises! :-)
Exercise 1: Create an array @x such that changing $x[0] also sets $x[1] to the same value Exercise 2: Given a pre-declared function "foo", write a code snippet that invokes it in an infinite loop; in 10 chars Exercise 3a: Create $foo such that \$foo->[1] == \$foo->{1} Exercise 3b: Create $foo such that \$foo->[1] == \$foo->(1) You must use different solutions for the two Exercise 4: Dump core in 6 chars Exercise 5: Create a static variable lexically scoped to a sub, and no wider than that. It's ok if it blows up under recursion Exercise 6: Create $x, $y such that $x eq $y && $$x ne $$y Exercise 7: Create $foo such that fileno($foo) && !*$foo Exercise 8: Create $foo such that ($foo^=0)++ eq $foo++ Exercise 9a: Create $foo such that eval(q[$$foo]) != eval(q[0+$$foo]) Exercise 9b: Create $foo such that eval(q[$$foo =~ / /]) && !$$foo Exercise 10: Make $x::y::x::y::y::x::y::x::x::y::y::y::y::x::y::y true in 26 chars of code Exercise 11: Make <STDOUT> eq <+STDOUT> in 25 chars Bonus Exercise: The code snippet 'sub foo{} goto +foo' produces an error: "Can't find label SCALAR(0x31c70c)" (the address may vary) Where does that ref come from? What does it point to?

Please black-box solutions/spoilers so people can safely read discussion without seeing all the answers. (for example use: <table bgcolor="#00000000"><tr><td><font color="#00000000">Text goes here</font></table>)

UPDATE: clarification of exercise 5: "static variable" means a variable whose value is retained across multiple invocations of the sub (like static vars in C), and being "scoped to a sub and no wider" means that the standard solution { my $x; sub { ... } } doesn't qualify, because $x is one block wider than the sub. (it is static though)
UPDATE: minor reformatting to make everything fit in 70 columns
UPDATE: they're designed for 5.8, though most probably have solutions on older versions too.

UPDATE: Strict solutions are now available for all exercises.

UPDATE: (21-7-2004) How's your Perl? (II)

This waste of time is sponsored by:
#perlhelp - Where people with no life teach people with no clue.

Comment on How's your Perl?
Select or Download Code
_
by xmath (Hermit) on Oct 27, 2003 at 00:22 UTC
    (comment deleted)
Re: How's your Perl?
by tachyon (Chancellor) on Oct 27, 2003 at 03:08 UTC
    # 1 my @x = ( \$_, \$_ ); # 2 sub foo { print "Agree :-)\n" } {foo;redo} # 4 dump()

    The closure bug/feature Unusual Closure Behaviour

    # 5 sub foo { my $x if 0; ++$x; }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Though I'm almost certain that's what the OP had in mind, it relies on a bug rather than a documented feaure. For that reason I happen to like this solution to question #5 of the OP's quiz:

      sub{my$x=\$x};

      Updated version that creates only one $x:

      sub { my $x; $x = \$x; }

      The anonymous sub is created and immediately falls out of existance because it's not passed to a scalar variable. And yet $x never disappears because its reference count is always going to be 1; it refers to itself.

      It probably doesn't qualify as a static, and is pretty much useless, but it meets the definition of static that the OP gave.


      Dave


      "If I had my life to live over again, I'd be a plumber." -- Albert Einstein
        I do not think your code does what you think it does. You have two different $x variables shown in your anonymous subroutine, not a single one referencing itself.
        A static variable in a subroutine context would be created only once and hold its value between invocations. You've created a circular reference in an uninvokable routine. Even if it weren't optimized away, of which I am uncertain, it bears no resemblance to a static variable.
        oops, you're right, my definition of "static" in the clarification was flawed :-)

        I do mean function-scoped static like in C/C++ ofcourse

        btw tachyon, your #1 solution isn't:
        perl -le 'my @x = ( \$_, \$_ ); $x[0]=42; print $x[1]'

      my @x = ( \$_, \$_ );

      No, that's not good enough :)

      my @x = ( \$_, \$_ ); $x[0] = 5; $x[1] == 5 or die;

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How's your Perl?
by Roger (Parson) on Oct 27, 2003 at 03:27 UTC

      Why the strike through your solution to Exercise 4? It was exactly what we had in mind.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How's your Perl?
by pg (Canon) on Oct 27, 2003 at 03:29 UTC

    What has this to do with a person's Perl ability ;-?

      It doesn't. If I saw any of these on a test for a job, I'd probably walk.

      I think you should gauge the quiz as a refresher or an exercise in what else you can learn. There are many aspects to learning Perl and after 4 years I haven't even come close to learning half of them. A quiz like this helps to shine a light on other things I didn't know.

      --
      Barbie | Birmingham Perl Mongers | http://birmingham.pm.org/

Re: How's your Perl?
by Anonymous Monk on Oct 27, 2003 at 07:01 UTC
    # 1 { package MyTie; require Tie::Array; @ISA = qw/Tie::StdArray/; sub STORE {@{$_[0]}[$_[1],$_[1]+1] = ($_[2]) x 2} } tie my @x, 'MyTie'; # 6 $x = \42; $y = "$x";

      tie my @x, 'MyTie';

      For all exercises: no fork/exec/system/qx/open, no commandline options, no user input, no modules, no tie, no bless, no %SIG.

      I guess the first and most important exercise is reading.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How's your Perl?
by seattlejohn (Deacon) on Oct 27, 2003 at 07:10 UTC
    # 1: $[=1; @x = (10); # confirm it: print $x[0], ",", $x[1], "\n"; $x[1]=20; print $x[0], ",", $x[1], "\n"; $x[0]=30; print $x[0], ",", $x[1], "\n";

            $perlmonks{seattlejohn} = 'John Clyman';

      $[=1;

      Not quite what we had in mind, but a valid and creative solution ;)

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How's your Perl?
by Juerd (Abbot) on Oct 27, 2003 at 08:15 UTC

    Bonus Exercise: The code snippet 'sub foo{} goto +foo' produces an error: "Can't find label SCALAR(0x31c70c)" (the address may vary) Where does that ref come from? What does it point to?

    Please note that this bug has been fixed in bleedperl.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How's your Perl?
by BrowserUk (Pope) on Oct 27, 2003 at 10:13 UTC
    1. perl -e"sub t{ \@_ }; $s='this'; *x = t $s, $s; $x[0] = 'that'; print join' ',@x;"
    2. perl -e"foo while1" or perl -e"{foo;redo}"
      1. perl -e"$foo = [{1=>1}, 'foo']; print \$foo->{1}, \$foo->[1]; "
      2. ?
    3. ?
    4. ?
    5. ?
    6. ?
    7. ?
      1. perl -e"$foo = \\1; print eval(q[$$foo]), eval(q[$$foo + 0])"
      2. ?
    8. ?
    9. ?
    10. perl -e"sub STDOUT{\*STDOUT}"
    11. Bonus perl -e"print \undef; sub foo{} goto +foo"
      1. yes

      2. no and yes (perl treats while1 as one identifier)

      3a. yes

      8a. yes, cool, unexpected solution :-)   our official version uses a much much more obscure trick.. funny we never saw this one
      Try this instead: eval(q[$$foo]) ne eval(q["$$foo"])
      •Update: actually, no, the original was fine too.. even though $$foo and $$foo + 0 print differently, they don't compare numerically unequal, which is what the exercise was

      11. doesn't appear to work for me..

      % perl -e 'sub STDOUT{\*STDOUT} <STDOUT> eq <+STDOUT> or die' Died at -e line 1.

      12. yes, but why? :-)

      •Update: fixed the "try this".. initially said "!=" instead of "ne"

        12. yes, but why? :-)

        I missed this before.

        For the same reason that these give a similar error

        D:\TEMP>perl -e"sub f{'fred'} goto +f" Can't find label SCALAR(0x15d7c1c) at -e line 1. D:\TEMP>perl -e"sub f{'fred'} goto(f)" Can't find label SCALAR(0x15d7c1c) at -e line 1. D:\TEMP>perl -e"sub f{'fred'} goto f->()" Can't find label SCALAR(0x15d7c1c) at -e line 1.

        But these do not ;^)

        D:\TEMP>perl -e"sub f{'fred'} goto ~~f" Can't find label fred at -e line 1. D:\TEMP>perl -e"sub f{'fred'} goto ''.f" Can't find label fred at -e line 1. D:\TEMP>perl -e"sub f{'fred'} goto scalar f" Can't find label fred at -e line 1. D:\TEMP>perl -e"sub f{'fred'} goto ${\f}" Can't find label fred at -e line 1.

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        Hooray!

      I couldn't get :foo while1" to work on my PC (Windows, perl 5.8.0).

      I could get to work by rewriting it as "1while foo" or "1until!foo".

      My own try involved a for loop--no dice. The best I could do was "for(;;foo){};" which is slightly too long.

        I could get to work by rewriting it as "1while foo" or "1until!foo".

        That loop will stop as soon as foo() returns false. The quiz didn't specify that foo() will always return a true value, so you can't assume it.

        ----
        I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
        -- Schemer

        :(){ :|:&};:

        Note: All code is untested, unless otherwise stated

Re: How's your Perl?
by talexb (Canon) on Oct 27, 2003 at 16:14 UTC

    This isn't "How's your Perl?", it's "How's your ObfuPerl?"

    None of this is useful for someone looking to test Perl skills. But it was properly labelled as a "waste of time" .. I'm just thinking that it may put off anyone not familiar with the weird on-line Perl community.

    --t. alex
    Life is short: get busy!

      This isn't "How's your Perl?", it's "How's your ObfuPerl?"

      Nevertheless this test is a good way to found out if you really know Perl intimately. You don't need to know all Perl to answer these questions in order to be a professional Perl coder that makes mission critical business applications, but that does not mean this test is useless.

      None of this is useful for someone looking to test Perl skills. But it was properly labelled as a "waste of time"

      Not just waste of time, but waste of time in our effort against sanity. We want you to break your brain cells over this. Your current lazy attitude is not really appreciated and we think you're afraid to admit you are not an [insert awesome title here].

      I'm just thinking that it may put off anyone not familiar with the weird on-line Perl community.

      Your inability to not understand what this is all about is probably not shared by the people who come here unbiased. They will probably read the introduction, which I quote for you here, with my emphasis added:

      As part of our continuing crusade against sanity, we of #perlhelp (EFnet) have created a modest perl quiz to test for all the skills required to make the maintainance programmer voluntarily leap into the gaping chasm of madness. We hope it will reinforce everyone's appreciation of our favorite language, by itself and as a tool towards this noble goal.

      ;-)

      I hope you understand now. We do this not for fun, but for a greater good.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: How's your Perl?
by tilly (Archbishop) on Oct 27, 2003 at 16:26 UTC
    My answers without looking at existing ones...
    1. 1: I've seen this in chatter mentioned by tye, but the trick slips my memory at the moment. :-(
    2. 2: {foo;redo} # See RE: My favorite looping mechanism in Perl is:
    3. 3: This is actually two questions
      • My first thought was pseudohashes but pseudohashes are deprecated and IIRC removed in 5.8.0. Then it was $foo = \*bar; $$foo->[1] = $$foo->{1} = "hello" Hrm, Pseudohashes are allowed? OK then, $x = [{1=>1}, "hi"]; Your test will pass, albeit with an ugly scalar for each, but they are not accidentally the same, they are both references to the same string.
      • Trivial with overload, but I am not sure if that is breaking your rules. OK, sub bar {$bar[$_[0]]} $foo = \*bar; $bar[1]="hi";, that isn't a different idea than what I originally did for 3a, but it works. UPDATE 3 I don't know how to do this after all.
    4. 4: dump # So sorry, did you want solutions that aren't supposed to core dump? :-P
    5. 5: my $static if 0; # See Tie::Static for my opinion on this...
    6. 6: Is it cheating for me to use a module but not write one?
      # Reformat to one line if you want -e use overload qq("")=>sub{"same"}; $x = bless \$foo; $y = bless \$bar; $$x= "x"; $$y= "x";
      UPDATE You do this like so: $x = do {local *foo}; $y = *foo; $foo = "hello";
    7. 7: UPDATE 2 $foo = *STDOUT{IO};
    8. 8: *x = \$|
    9. 9: This is actually two questions UPDATE Um, in the questions shouldn't q be qq everywhere? If you don't let $$foo interpolate, it shouldn't matter what is in it...
      • UPDATE 3 $foo = \$!; $!=1; UPDATE 5 Oops, this is wrong. I should test these answers a little, ya think?
      • 9b
    10. 10
    11. 11: UPDATE 4 Put sub CORE'GLOBAL'glob{""} at the END of your code. Location matters, this code has to be seen by the Perl interpreter after Perl has seen some evidence that it needs to load File::Glob (which will overwrite us).
    Bonus
    I, um, would have gotten more if I didn't have to go to work. Yeah, that's the ticket...

    UPDATE Minor fixes. BTW I should add that while I am not terribly bad at this kind of trivia, I think that focussing on it is a horrible mistake.

    UPDATE 2 Answered 7.

    UPDATE 3 Took time out for 9a. I had been thinking about 10, but because nobody else bothers to hide their answers, I saw mtye's version already. 3b has me puzzled again (see Roy Johnson's note).

    UPDATE 4 Added a solution to problem 11.

    UPDATE 5 Admit my mistake in problem 9a. I think that I'll admit to not knowing stupid Perl trivia that well these days. Particularly since nobody else seems to be trying these too hard. Also note that my solution to problem 11 can't be placed in front with glob-assign without adding a semi-colon, which puts you over the character limit.

      3. who cares about deprecated, they still work ;-)

      3/6. overload is a module which isn't allowed (though there are ways to circumvent that), but more importantly bless is explicitly forbidden by the rules

      the others look good :-)

      UPDATE Re 9: it really is q, not qq. (notice the eval? :-)

      UPDATE 2 As Roy Johnson pointed out, your 3b currently doesn't work (it's only a small one-char mistake though)

      UPDATE 3 Your 9a doesn't work, they print differently but compare numerically equal. make sure to test your answers with perl -e '......; eval(q[$$foo]) != eval(q[0+$$foo]) or die' rather than using print, to avoid traps like these :-)

      UPDATE 4 ex 11 works.. note that you can place it in front by using glob-assign

      UPDATE 5 strictly speaking the semi isn't needed to make the condition true (which is the exercise), but even if you do include it it's still possible by dropping the "" from the sub

        If by a fix you mean sub bar {$bar[$_[0]]} $foo = *bar; $bar[1]="hi";, that does not work to the given spec.

        Test it with print "yes" if \$foo->(1) eq \$foo->[1] and you see that it fails for me on 5.8.1. Get rid of the backslashes and it works, but the problem is that Perl's functions are pass by reference, return by value. Therefore the return of bar(1) is a new string with the same value as $bar[1], but you get something different by taking a reference to it.

      For #4, perl -edump also works... :)


      ----
      Zak
      undef$/;$mmm="J\nutsu\nutss\nuts\nutst\nuts A\nutsn\nutso\nutst\nutsh\ +nutse\nutsr\nuts P\nutse\nutsr\nutsl\nuts H\nutsa\nutsc\nutsk\nutse\n +utsr\nuts";open($DOH,"<",\$mmm);$_=$forbbiden=<$DOH>;s/\nuts//g;print +;
      On your 3b, I get
      Not an ARRAY reference at testit line 7.
      upon trying to
      printf "Value: %s\n", \$foo->[1];
      I had been thinking about 10, but because nobody else bothers to hide their answers, I saw mtye's version already

      Note that his version doesn't work under strict, while a strict solution is possible. (the 'official' solution is very different from mtye's), so the exercise isn't spoiled just yet ;-)

        How about an answer for #10 at 24 characters that passes strict?
        use strict; #23456789_123456789_1234 BEGIN{$'y=*x::=*y::=*::} print "Yes\n" if $x::y::x::y::y::x::y::x::x::y::y::y::y::x::y::y;
Re: How's your Perl?
by jryan (Vicar) on Oct 27, 2003 at 16:44 UTC

    Is it just me, or is #8 undefined behaivor?

      undefined in what sense? Perl's behavior is defined by its source code, perhaps unless contradicted by docs.

      UPDATE ick, I got pulled into a pointless discussion. To short-circuit it: anything that works consistently (that is, not dependent on random or OS/environment-dependent factors) in perl 5.8.* is acceptable for these exercises.

        ($foo^=0)++ eq $foo++ involves an auto-increment on top of an assignment, which is undefined as far as I know.

        For more discussion: Re: Incrementing a Hash Value.

Re: How's your Perl?
by mtve (Chaplain) on Oct 27, 2003 at 17:56 UTC

    Exercise 10 in 24 chars:

    #23456789012345678901234 $$_++for glob"'{x,y}"x16

    Exercise 6 is easy.

      cool! now under strict :-)

        shouldn't N8 be:

        $foo++ eq ($foo^=0)++

        ?

Re: How's your Perl?
by diotalevi (Canon) on Oct 28, 2003 at 18:20 UTC
    There's a bunch of spoilers here so click readmore to read them.
      re 8: perl has a fixed evaluation order (L->R for most operators, including eq), so you can use that. That it's not officially defined/documented is ofcourse of no concern :-)
        I've now see the answer (and its obvious) for #8 and in that rare case the evaluation order doesn't actually matter since it won't affect anything but if it were anything else then I'd have to call shenanigans on you for the trick question since you'd only be testing on the implementation and not the specified language.
Re: How's your Perl?
by Beechbone (Pilgrim) on Oct 28, 2003 at 18:25 UTC
Solutions
by xmath (Hermit) on Oct 28, 2003 at 23:43 UTC
    Strict solutions to all exercises, base64-encoded:

    1b3VyIEB4OyBteSAkeTsgKng9c3Vie1xAX30tPigkeSwkeSk=
    2e2ZvbztyZWRvfQ==
    3abXkgJGZvbyA9IFt7MSwgMX1d
    3bc3ViIHogOiBsdmFsdWUgeyAkOjp6WzFdIH0gbXkgJGZvbyA9ICp6
    4ZHVtcDs7 or ZHVtcCgp or fn5kdW1w, etc :-)
    5c3ViIGZvbyB7IG15ICR4IGlmIDA7IC4uLiB9
    6b3VyICgkeCwgJHkpID0gKCp4LCBldmFsICJsb2NhbCAqeCIp
    7bXkgJGZvbyA9ICpTVERPVVR7SU99
    8b3VyICRmb287ICpmb28gPSBcKyskfA==
    9abXkgJGZvbyA9IFwkXlM=
    9bcGFja2FnZSBZO291ciRmb289XDA7JFg6OmZvbz1cIiAiOypZOjo9Klg6Og==
    or JGZvbz0iXzwoZXZhbCAxKSI= (non-strict original)
    10QkVHSU57Knk6Oj0qeDo6PSQ6Onk9Kjo6fQ==
    11KkNPUkU6OkdMT0JBTDo6Z2xvYj1zdWJ7fQ==

    For the bonus exercise, see the explanation above

      Fun! Now let's see you come up with 10 more for next weeks quiz:)


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Hooray!

        argh :-)
      Another solution for E8:
      KmZvbyA9IFxsb2NhbCAkMQ==
      This one relies on a bug in perl.
      Another (strict) solution for 9b:
      BEGIN {$^H |= 0x30000} $^H{'qr'} = sub {''}; my $foo = \'';
      I think the answer to number 2 is unnecessarily obfu. You can actually do it with while too... Perhaps it should ask without using while? UPDATE: I'm pretty sure they shortened the number of characters since I wrote this.

      -Paul

        In 10 chars?
        while(){foo} # 12 chars foo while 1 # 11 chars
Re: How's your Perl?
by ambrus (Abbot) on Nov 02, 2003 at 16:47 UTC

    I could solve 5 of them.

    UPDATE: read some solutions. So you accept mine for 3 and 4. Quiestion 10 is really trickey.

    UPDATE: please someone explain why my solution to 8 works. I don't understand. Thx.

    UPDATE: I still don't know how my solution to 8 works, I've found it accidentally, but I see that there's a similar solution using $^N. (And one even with $1, wow!) (The official solution which uses $| is eaasier to understand.)

Re: How's your Perl?
by ccn (Vicar) on Mar 27, 2004 at 23:07 UTC
    6 of 12
    Exercise 1: Create an array @x such that changing $x[0] also sets $x[1] to the same value
    $[=1;@x=();

    Exercise 2: Given a pre-declared function "foo", write a code snippet that invokes it in an infinite loop; in 10 chars
    {foo;redo}

    Exercise 4: Dump core in 6 chars
    dump()

    Exercise 5: Create a static variable lexically scoped to a sub, and no wider than that. It's ok if it blows up under recursion
    sub foo{my $static if 0}

    Exercise 6: Create $x, $y such that $x eq $y && $$x ne $$y
    $x=\1;$y="$x"

    Exercise 8: Create $foo such that ($foo^=0)++ eq $foo++
    *foo=*|;$|=1;

Re: How's your Perl?
by ambrus (Abbot) on Jun 08, 2005 at 09:32 UTC

    Here's a new solution for question 3a. This is not strict in the sense that you have to turn off strict for the set-up code to work. However, the actual test \$foo->[1] == \$foo->{1} runs under strict, unlike in my original symbolic ref solution.

    I think that this solution differs from all the solutions given so far, so I submit it even though this puzzle is now quite old.

Re: How's your Perl?
by thospel (Hermit) on Jul 02, 2005 at 19:22 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://302287]
Approved by antirice
Front-paged by antirice
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (9)
As of 2014-07-22 22:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (129 votes), past polls