aboutsummaryrefslogtreecommitdiff
path: root/challenge-148/duncan-c-white/perl/ch-2.pl
blob: aca65324f31e41589a63441132ae846ce95e629c (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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/perl
# 
# TASK #2 - Cardano Triplets
# 
# Write a script to generate first 5 Cardano Triplets.
# 
# A triplet of positive integers (a,b,c) is called a Cardano Triplet if
# it satisfies the below condition.
# 
#   cuberoot(a+b.sqrt(c)) + cuberoot(a-b.sqrt(c)) = 1
# 
# Example
# 
# (2,1,5) is the first Cardano Triplet.
# 
# MY NOTES: Ok, two mildly tricky things:
# 1. real arithmetic means "=" is imprecise, we can't even use rationals as
#    sqrt() and cuberoot() are involved, and
# 2. (2,1,5) is the "first" Cardano triplet - in what order?
# 
# The answer to the latter question will set the basic structure
# of the program.  Perhaps we should "order by minimum sum of triplet numbers"?
# 

use strict;
use warnings;
use feature 'say';
use Getopt::Long;
use Data::Dumper;


my $debug=0;
my $epsilon = 1e-7;

#
# my $root = cuberoot($x);
#	Return the cuberoot of $x; make sure it works even if $x<0
#
sub cuberoot ($)
{
	my( $x ) = @_;
	my $r = abs($x)**(1/3);
	$r = -$r if $x<0;
	return $r;
}


#
# my $isc = is_cardano($a,$b,$c);
#	Return 1 iff $a,$b,$c is a Cardano triplet; 0 otherwise.
#	Recall that a Cardano triplet has:
#	cuberoot(a+b.sqrt(c)) + cuberoot(a-b.sqrt(c)) = 1
#
sub is_cardano ($$$)
{
	my( $a, $b, $c ) = @_;
	my $x = $b * sqrt($c);
	my $q = cuberoot($a+$x) + cuberoot($a-$x);
	#say "iscard($a,$b,$c): x=$x, q=$q";

	return abs( $q-1 ) <= $epsilon ? 1 : 0;
}


#say is_cardano(2,1,5);
#exit 0;

die "Usage: first-N-cardano-triplets [--debug] [N default 5]\n" unless
	GetOptions( "debug"=>\$debug ) && @ARGV<2;

my $n = shift // 5;

my $nfound = 0;

for( my $sum=3; $nfound < $n; $sum++ )
{
	# find all Cardano triplets whose sum is $sum
	say "find all Cardano triplets with sum $sum" if $debug;
	for( my $a=1; $a<$sum-1; $a++ )
	{
		for( my $b=1; $a+$b<$sum; $b++ )
		{
			my $c = $sum-$a-$b;
			die "bad structure, a=$a, b=$b, c=$c\n"
				if $c<1;
			#say "$a,$b,$c";
			next unless is_cardano($a,$b,$c);
			$nfound++;
			say "Found $a,$b,$c";
		}
	}
}