aboutsummaryrefslogtreecommitdiff
path: root/challenge-125/james-smith/perl/ch-1.pl
blob: c0bf708d1053a465a7945a9e3e5b1a90f779ceca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/local/bin/perl

use strict;

use warnings;
use feature qw(say);
use Test::More;
use Benchmark qw(cmpthese timethis);
use Data::Dumper qw(Dumper);

my @TESTS = (
  [ 0, 1 ],
);

say $_,' > ', get_triples($_) foreach 1..500;

sub get_triples {
  my $n = shift;
  return $n < 3 ? -1 : join '; ', map { sprintf '(%s)', join ', ', @{$_} }
  (
    grep { $_->[1] == int $_->[1] }                ## Check if all int
    map  { [ $_, sqrt($n**2-$_**2), $n ] }         ## Generate triple
    3 .. sqrt($n**2/2)                   ## Shortest side ($n is hypotenuse)
  ),(
    map  { $_->[0]>$_->[1] ? [@{$_}[1,0,2]] : $_ } ## put in numerical order
    grep { $_->[1] == int $_->[1] }                ## Check all int
    map  { [ $n, sqrt($_**2-$n**2), $_ ] }         ## Generate triple
    ($n+1) .. ($n**2/2+1)       ## Hypotenuse ($n is one of other two sides)
  );
}

## Notes:

# Except for $n < 3 there is always a solution
# * If $n is odd then it can always be the short side of a triangle where the
#   other sides are ($n^2-1)/2 or ($n^2+1)/2
# * If $n has an odd factor - then we can rewrite $n as $o * $m
#   we can use the same trick to get sides of $m($o^2-1)/2 & $m($o^2+1)/2
# * This only leaves us with numbers of the form 2^n - but we know that 4 can be part of a Pyth.Triple
#   and so any number of the form 2^($n+2) in a triple of the form ( 3.2^$n, 4.2^$n, 5.2^$n ).
#
# * We have two cases where $n is the hypotenuse and where it is a shorter side.
#   * With the former we need to look at the shorter sides these can be 3 -> n-1
#     but to avoid dupes we limit our search to sqrt(n^2/2)...
#   * The latter is more complex to work out the range
#     But we note that the difference between two consecutive squares is ($m+1)^2-($m)^2 = 2m + 1
#     So the largest value for the hypotenuse is therefore (n^2+1)/2