site.base_url }}/">The Bear's Den -->

The Bear's Den

Enter at your own risk

Randomly Extremal

Task 1: Self Spammer

Submitted by: David Ferrone


Write a program which outputs one word of its own script / source code at random. A word is anything between whitespace, including symbols.

Example 1

If the source code contains a line such as: 'open my $fh, "<", "ch-1.pl" or die;'
then the program would output each of the words
{ open, my, $fh,, "<",, "ch-1.pl", or, die; }
(along with other words in the source) with some positive probability.

Example 2

Technically 'print(" hello ");' is *not* an example program, because it does not
assign positive probability to the other two words in the script.
It will never display print(" or ");

Example 3

An empty script is one trivial solution, and here is another:
echo "42" > ch-1.pl && perl -p -e '' ch-1.pl

Solution

The program source is available from the DATA file handle after rewinding it to the start. We just have to make sure the file handle does exist.

Here we slurp the source, split it into pairs of (word, ‘’), build an anonymous hash reference thereof and pick the first key from the dereferenced hash. The selected key will be random, though the quality of randomness is rather poor.

This is certainly not one of the simplest solutions to this task, but as we could add anything to the script that doesn’t produce any output, it is kind of universal.

#!/usr/bin/perl -w0777

use v5.12;
seek DATA, 0, 0;
say +(keys %{ {<DATA> =~ /(\S+)()/g} })[0];
__DATA__
Hello David!

The solution comes accompanied by a shell script that repeatedly calls the perl script and counts the produced words.

See the full solution to task 1.

Task 2: Order Game

Submitted by: Mohammad Sajid Anwar


You are given an array of integers, @ints, whose length is a power of 2.

Write a script to play the order game (min and max) and return the last element.

Example 1

Input: @ints = (2, 1, 4, 5, 6, 3, 0, 2)
Output: 1

Operation 1:

    min(2, 1) = 1
    max(4, 5) = 5
    min(6, 3) = 3
    max(0, 2) = 2

Operation 2:

    min(1, 5) = 1
    max(3, 2) = 3

Operation 3:

    min(1, 3) = 1

Example 2

Input: @ints = (0, 5, 3, 2)
Output: 0

Operation 1:

    min(0, 5) = 0
    max(3, 2) = 3

Operation 2:

    min(0, 3) = 0

Example 3

Input: @ints = (9, 2, 1, 4, 5, 6, 0, 7, 3, 1, 3, 5, 7, 9, 0, 8)
Output: 2

Operation 1:

    min(9, 2) = 2
    max(1, 4) = 4
    min(5, 6) = 5
    max(0, 7) = 7
    min(3, 1) = 1
    max(3, 5) = 5
    min(7, 9) = 7
    max(0, 8) = 8

Operation 2:

    min(2, 4) = 2
    max(5, 7) = 7
    min(1, 5) = 1
    max(7, 8) = 8

Operation 3:

    min(2, 7) = 2
    max(1, 8) = 8

Operation 4:

    min(2, 8) = 2

Solution

We may modify the rules of the game in a way that they do not change the result for lists having a length of a power of 2, but permit lists of arbitrary lengths and are simpler to implement:

until there is only one element left.

use strict;
use warnings;
use experimental 'signatures';

sub order_game (@ints) {
    my $f = 1;
    while (@ints > 1) {
        my ($i, $k) = splice @ints, 0, 2;
        push @ints, ($f *= -1) * ($k - $i) > 0 ? $k : $i;
    }
    shift @ints;
}

See the full solution to task 2.


If you have a question about this post or if you like to comment on it, feel free to open an issue in my github repository.