Skip to main content
Commonmark migration
Source Link

#Perl, 46 bytes, 10 numbers, safe

Perl, 46 bytes, 10 numbers, safe

#Perl, 46 bytes, 10 numbers, safe

Perl, 46 bytes, 10 numbers, safe

add a (fairly important) missing semicolon
Source Link
user62131
user62131
__b_b_\__}_b_b_b_0_;
$b[0]=10;$b{0}=1;say$b[0]
__b_b_\__}_b_b_b_0_;
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=9;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=9;say$b[0]

Explanation

ExplanationThe first thing to comenote is that the solution isn't really golfed apart from removing whitespace: if we lay it out with more readable whitespace, we get this:

sub b { \@_ }
*b = b $b{0};
$b[0] = 10;
$b{0} = 1;
say $b[0];

Normally, when you access the arguments of a subroutine in Perl, you do so via copying them out of @_. There's a good reason for this: @_ aliases the arguments the subroutine is given (so, for example, (sub { $_[0] = 3 })->($x) will assign to $x), something that isn't normally desirable.

Although @_ might seem magical, it's actually just using a standard feature of the Perl internals (which is readily available from XS but only comes up in a few weird cases in pure Perl, such as @_ itself): an array doesn't store its elements directly, but rather by reference. Thus, when we call b in the second line below, Perl generates an array (calling it @_) whose first element is a reference to the same storage that $b{0} uses. (Hash values are also stored by reference; $_[0] and $b{0} are both referencing the same storage at this point.) Because @_ isn't doing anything special from an internals point of view, we can take a reference to it just like we could with any other array, causing it to outlive the subroutine it's defined in.

Perl variables also refer to data storage by reference. A long time ago, people used to use code like *x = *y; to set $x as an alias to $y (via making them reference the same thing), likewise @x as an alias to @y, %x as an alias to %y, and so on. That rather breaks the invariant that variables with similar names don't have to act similarly, so modern Perl provides an alternative; assigning a reference to a typeglob overrides only the variable that matches the type of the reference (so *x = \%y would alias %x to point to the same storage as %y but leave, say, $x alone). This syntax notably doesn't care about whether the storage you're aliasing to has a name, so when we assign the return value of b (which is an array reference that's keeping the array formerly called @_ alive) to *b, what happens is that @b is changed to alias the argument list to the call to b (while leaving %b unchanged). This means, notably, that $b[0] and $b{0} now point to the same storage, and assigning to one will therefore change the other. Everything from then on is completely straightforward.

The Perl documentation doesn't really talk about this sort of detail, so I'm not surprised anyone got the crack; the nature of @_ as not quite being like other arrays isn't something that's really emphasised, and most coding styles aim to minimize the effects that this has rather than amplifying them.

__b_b_\__}_b_b_b_0_;
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=9;say$b[0]

Explanation to come.

__b_b_\__}_b_b_b_0_;
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=1;say$b[0]
sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=9;say$b[0]

Explanation

The first thing to note is that the solution isn't really golfed apart from removing whitespace: if we lay it out with more readable whitespace, we get this:

sub b { \@_ }
*b = b $b{0};
$b[0] = 10;
$b{0} = 1;
say $b[0];

Normally, when you access the arguments of a subroutine in Perl, you do so via copying them out of @_. There's a good reason for this: @_ aliases the arguments the subroutine is given (so, for example, (sub { $_[0] = 3 })->($x) will assign to $x), something that isn't normally desirable.

Although @_ might seem magical, it's actually just using a standard feature of the Perl internals (which is readily available from XS but only comes up in a few weird cases in pure Perl, such as @_ itself): an array doesn't store its elements directly, but rather by reference. Thus, when we call b in the second line below, Perl generates an array (calling it @_) whose first element is a reference to the same storage that $b{0} uses. (Hash values are also stored by reference; $_[0] and $b{0} are both referencing the same storage at this point.) Because @_ isn't doing anything special from an internals point of view, we can take a reference to it just like we could with any other array, causing it to outlive the subroutine it's defined in.

Perl variables also refer to data storage by reference. A long time ago, people used to use code like *x = *y; to set $x as an alias to $y (via making them reference the same thing), likewise @x as an alias to @y, %x as an alias to %y, and so on. That rather breaks the invariant that variables with similar names don't have to act similarly, so modern Perl provides an alternative; assigning a reference to a typeglob overrides only the variable that matches the type of the reference (so *x = \%y would alias %x to point to the same storage as %y but leave, say, $x alone). This syntax notably doesn't care about whether the storage you're aliasing to has a name, so when we assign the return value of b (which is an array reference that's keeping the array formerly called @_ alive) to *b, what happens is that @b is changed to alias the argument list to the call to b (while leaving %b unchanged). This means, notably, that $b[0] and $b{0} now point to the same storage, and assigning to one will therefore change the other. Everything from then on is completely straightforward.

The Perl documentation doesn't really talk about this sort of detail, so I'm not surprised anyone got the crack; the nature of @_ as not quite being like other arrays isn't something that's really emphasised, and most coding styles aim to minimize the effects that this has rather than amplifying them.

safe!
Source Link
user62131
user62131

#Perl, 46 bytes, 10 numbers b_b_}b_b_b_0; $b[0]=10;$b{0}=1;say$b[0], safe

The problem

__b_b_\__}_b_b_b_0_;
$b[0]=10;$b{0}=1;say$b[0]

The shorter problems tend to get cracked quickly, so I thought I'd try a longer one. The longer ones also tend to get cracked if people leave enough of a gap to sneak something naughty like say or exit in, so all the gaps here are short. Hidden characters are represented using _.

My solution

sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=1;say$b[0]

To print 2, 3, etc., up to 9, keep changing the number assigned to $b{0} in the second line (i.e. $b{0}=2, $b{0}=3, etc.). The program for 9 looks like this:

sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=9;say$b[0]

Then to produce 10, comment out the first line by prepending a # character to it.

Explanation to come.

#Perl, 46 bytes, 10 numbers b_b_}b_b_b_0; $b[0]=10;$b{0}=1;say$b[0]

The shorter problems tend to get cracked quickly, so I thought I'd try a longer one. The longer ones also tend to get cracked if people leave enough of a gap to sneak something naughty like say or exit in, so all the gaps here are short. Hidden characters are represented using _.

#Perl, 46 bytes, 10 numbers, safe

The problem

__b_b_\__}_b_b_b_0_;
$b[0]=10;$b{0}=1;say$b[0]

The shorter problems tend to get cracked quickly, so I thought I'd try a longer one. The longer ones also tend to get cracked if people leave enough of a gap to sneak something naughty like say or exit in, so all the gaps here are short. Hidden characters are represented using _.

My solution

sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=1;say$b[0]

To print 2, 3, etc., up to 9, keep changing the number assigned to $b{0} in the second line (i.e. $b{0}=2, $b{0}=3, etc.). The program for 9 looks like this:

sub b{\@_}*b=b$b{0};
$b[0]=10;$b{0}=9;say$b[0]

Then to produce 10, comment out the first line by prepending a # character to it.

Explanation to come.

Source Link
user62131
user62131
Loading