Autobiographical numbers constraints - last is zero

TL;DR

Remember Autobiographical numbers? We will go on looking at constraints for it!

Let’s move on to a more fixed and theoretical one, i.e. that the last slot MUST be 0. Code is in stage 2.

A preliminary note

Let’s first note one thing:

if slot x contains the value y, then there MUST be at least xy slots in the whole array.

Let’s see why, assuming that slot x contains value y:

  • by definition, value x is contained in exactly y slots
  • assume that z slot is one of these y slots, it means that it contains value x
  • as a consequence, there are exactly x slots that contain value z
  • because there are y such slots, each bearing a different value, then we need to accomodate at least xy slots.

The condition is actually stronger than this, as a simple extension of the reasoning above and observing that each slot can only contain a single value:

N=N1i=0ivi

where vi represents the value contained in slot i.

One more thing: N > 3

The autobiographical numbers puzzle can’t be solved for N3:

  • N=0 means that there is no slot.
  • N=1 means that there is only slot 0. It cannot contain 0 because otherwise it would have to contain 1 (there would be 1 value 0 in it, right?!?), and of course it cannot contain 1 because otherwise it would not contain any 0.
  • N=2 means that there are only slots 0 and 1. It’s easy to see that no value combination is possible:

    • both slots can only contain 0 or 1, because of what we discussed in the previous section;
    • slot 0 cannot contain 0 for the same reasons as the previous case where N=1, so it can only contain a 1 (if anything);
    • 10 is not a solution because there is one 1 and the slot for 1 is 0
    • 11 is not a solution because there are two values 1, but slot 1 contains a 1.
  • N=3 is equally impossible. Allowed values for quantities are 0, 1 and 2 because there are only slots 0, 1 and 2.
    • We already established that slot 0 cannot contain 0
    • in the previous section, we saw that slot 2 cannot contain 2 (it would mean that we need to have 4 slots, but we have only three)
    • so we are left with:
10* not a solution, the value of slot 1 cannot be less than 1
11* not a solution, the value of slot 1 cannot be less than 2
120 not a solution, slot 1 should be 1
121 not a solution, there is no 0
2*0 not a solution, the value of slot 2 cannot be less than 1
201 not a solution, the value of slot 1 should be 1
211 not a solution, the value of slot 1 should be 2 
22* not a solution, the value of slot 2 should be 2 but it can't

Hence, it only makes sense to consider cases where N>3.

Last slot MUST be 0?

Suppose you have N slots, numbered from 0 to N-1 and let’s focus on the last slot. Remember also that N>3.

Can it be greater than 1? Let’s remember the note in the previous section, and observe that k(N1) is greater than N (i.e. the total number of available slots!) for k>1 and N>2. So, for N>3 (as we are considering) we MUST have that k1.

Our next question is: can slot N - 1 actually take value 1? Well… no again. If it were true, then it would mean that the value N1 is written in some slot, which MUST be one of the first N1 slots (the last one is already occupied by the 1 and we already know that N1>1).

We know that N1 cannot be written in any slot from 2 on, again because of the constraints discussed in the previous section. Hence, it could only be either slot 0 or slot 1.

Can it be slot 0? No it can’t, because we would need to accomodate N1 slots with 0 inside, but we only have N2 left (remember that slot 0 is occupied by value N1, and slot N - 1 is occuped by value 1, so they cannot accomodate a 0 at the same time).

Can it be slot 1? No again, because if we take the equation in the previous section, we would end up with at least 1(N1)+(N1)1=2(N1)>N needed slots, which is impossible.

Let’s visualize this latter case explicitly:

  0   1   2   3
+---+---+---+---+
| 1 | 3 | 1 | 1 |
+---+---+---+---+

...

  0   1     2   3   4        N-2 N-1 
+---+-----+---+---+---+ ... +---+---+
| 1 | N-1 | 1 | 1 | 1 |     | 1 | 1 |
+---+-----+---+---+---+ ... +---+---+

All slots show either 1 or N1, and other values are absent. Which is a violation of the main constraint about the game rule: value 0 is supposed to appear once (there is a 1 in slot 0) but it does not appear at all.

Hence, the very last value in a suitable solution MUST be 0.

Coding

Now that we know it MUST be 0, it’s easy to code it - we will do this directly upon initialization.

 1 sub autobiographical_numbers ($n) {
 2    my $solution = [
 3       map {
 4          +{map { $_ => 1 } 0 .. $n - 2}  # "n-1" is always 0
 5       } 1 .. $n -1
 6    ];
 7    push $solution->@*, {0 => 1};         # "n-1" is always 0
 8    my @constraints = map { main->can('constraint_' . $_) }
 9       qw< basic >;
10    my $state = solve_by_constraints(
11       constraints    => \@constraints,
12       is_done        => \&is_done,
13       search_factory => \&explore,
14       start          => {solution => $solution},
15       logger         => ($ENV{VERBOSE} ? \&printout : undef),
16    );
17 } ## end sub autobiographical_numbers ($n)

There are two places where this insight is useful:

  • the obvious one is that… the last slot only allows for 0, which is what line 7 is about;
  • then, we can also get rid of value N1 from all other slots (line 4, the range goes up to N2 for this reason).

Is it of help?

Let’s see how it goes:

$ time ./run.sh 01-basic/ 30
solution => [26,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]

real	0m6.449s
user	0m6.404s
sys	0m0.032s

$ time ./run.sh 02-last-is-zero/ 30
solution => [26,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0]

real	0m5.679s
user	0m5.648s
sys	0m0.012s

Not bad!

So long…

Curious about the whole series? Here it is:

Comments? Please comment below!


Comments? Octodon, , GitHub, Reddit, or drop me a line!