I started by drawing possible solutions by hand. I found one in about 15 minutes.
I then wrote several scripts that randomly tried to find a solution. I ran 3 of them in parallel, one of them finished in 74 minutes. Here's the program:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my ($rand, $minus);
sub maybe_visited {
my ($visited, $x, $y) = @_;
++$visited->{"$x:$y"} if $x >= 0 && $y >= 0
&& $x <= 3 && $y <= 3
&& $x == int $x
&& $y == int $y;
return ($visited->{"$x:$y"} // 0) < 2
}
sub gcd {
my ($x, $y) = @_;
($x, $y) = ($y, $x) if $y < $x;
($x, $y) = ($y % $x, $x) while $x;
return $y
}
sub check {
my @chain = @_;
my %visited;
for my $i (1 .. $#chain) {
my ($from, $to) = @chain[ $i - 1, $i ];
return if "@$from" eq "@$to";
my $x = abs($from->[0] - $to->[0]);
my $y = abs($from->[1] - $to->[1]);
my $g = gcd($x, $y);
my $step_x = $x / $g;
$step_x *= -1 if $from->[0] > $to->[0];
my $step_y = $y / $g;
$step_y *= -1 if $from->[1] > $to->[1];
my ($X, $Y) = @$from;
while ($X != $to->[0] || $Y != $to->[1]) {
maybe_visited(\%visited, $X, $Y) or return;
$X += $step_x;
$Y += $step_y;
}
}
maybe_visited(\%visited, @{ $chain[-1] }) or return;
say scalar keys %visited, ': ',
join ', ', map "[$_->[0], $_->[1]]", @chain
if keys %visited > 14;
return 16 == keys %visited
}
sub generate {
my @g = map [ int(rand($rand) - $minus),
int(rand($rand) - $minus) ],
1 .. 7;
for (1 .. 1 + int rand 3) {
$g[int rand @g][0] = (-1, 4, 5)[int rand 3];
}
return @g
}
my ($from, $to) = (0, 3);
$rand = $to - $from + 2;
$minus = 1 - $from;
1 until check(my @chain = generate());
The solution:
[3, 2], [1, 0], [5, 0], [-1, 3], [3, 3], [0, 0], [0, 2]
I used gnuplot to visualise the solutions. You can see a short video showing the solutions covering more than 14 dots here. The final solution is shown in the end. Note that the algorithm is really stupid, the fifth picture can be extended into the solution easily.
To generate the pictures, I used the following shell script:
#!/bin/bash
i=0
while read l ; do
l=${l#*: }
perl -pe 's/[^-\d.]+/(" ", "\n")[++$i % 2]/ge' <<< "$l" > 2
gnuplot -e "out='$(printf %04d $i)'" 4x4-16.gpl
echo "$l"
((++i))
done < <(sort -u 1)
and the following gnuplot script:
set xrange [-2:6]
set yrange [-2:6]
unset border
unset xtics
unset ytics
set term png
set output "4x4-16-" . out . ".png"
plot '2' using 1:2 with lines notitle, "4x4-16.grid" using 1:2:(0.1) w
+ith circles notitle
Where the "grid" file just contains all the coordinates of the points to connect.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] [select] |
Extra points for gnu plot and video!!! :)
But it's not solved yet: the challenge had three levels and you solved the easiest one.
And that to a very high cost. (75 min? Wow)
You seem to think that the vertices of the chain have to be at integer positions. (?)
That's not the case and crippling your solutions.
For the records:
Level 2: there is at least one solution with a real i.e. closed polygon! Or maybe more than one?
Level 3: what if the grid is bigger 5x5, 6x6 or even 6x5?
There doesn't seem to be much interest though and it might be a bit too challenging on the math level.
| [reply] |
This is a maths challenge, not a coding challenge. The big allure is coming up with the required insight how to generate solutions, and then how to express them in a program will be drudgery and comparatively trivial. | [reply] |
I can't follow. ..
Can you prove there is only one perfect solution?
Otherwise you need code to check them all.
If you know of better coding challenges feel free to post them. :)
| [reply] |
Well looks similar to Traveling Salesman, don't you think?
| [reply] |
Any deadline? Do you want one or all solutions? Anything besides "closed" polygons seems trivial.
Coding challenges usually come with a test suite and an API.
If you say "bigger grids", are they still equidistant and quadratic? I suppose n x m is still legit? | [reply] |
| [reply] |
And if you want *all* solutions you might exclude symmetries by rotation or mirroring.
| [reply] |
Good questions!!!
>
Any deadline?
I'll share the level 2 solution end of June.
> Do you want one or all solutions?
At least one, the more the better.
> Anything besides "closed" polygons seems trivial.
Indeed.
> Coding challenges usually come with a test suite and an API.
Yes but I posted this w/o preparation to help bliako with his request.
See it rather as a mediation on a possible challenge.
But I'm starting to believe that it's too challenging on the mathematical side
(though it's part of the curriculum of my 15 year old niece :-/ )
> If you say "bigger grids", are they still equidistant and
quadratic? I suppose n x m is still legit?
Equidistant: yes
Quadratic: no
Disclaimer: But I'm not aware of higher level solutions yet.
> And if you want all solutions you might exclude symmetries by rotation or mirroring.
I think it should be obvious that you need to handle symmetries when trying to find all solutions.
The complexity of a branch and bound algorithm might explode otherwise.
> I forgot: Any language restrictions? Is Perl 6 ok?
Any Perl*
> A solution in JavaScript could also draw the polygon.
You are free to generate JS or SVG, but the algorithm has to be Perl.
BTW Haukex's WebPerl would do too.
| [reply] [d/l] |