aboutsummaryrefslogtreecommitdiff
path: root/challenge-148/bruce-gray/README
blob: 19a8ae9e9b56a2cb2d81d14b0774daa50fe48a85 (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
Solutions by Bruce Gray for https://theweeklychallenge.org/blog/perl-weekly-challenge-148/

The Raku solution to Task#2 shows four different results for "first 5",
to show the different orderings produced by different algorithms.

Output:
$ perl perl/ch-1.pl
    2 4 6 30 32 34 36 40 42 44 46 50 52 54 56 60 62 64 66
$ raku raku/ch-1.raku
    2 4 6 30 32 34 36 40 42 44 46 50 52 54 56 60 62 64 66

$ perl perl/ch-2.pl 
     2   1   5
     5   1  52
     8   1 189
    11   1 464
    14   1 925
$ raku raku/ch-2.raku
    ((  2   1   5) (  5   2  13) ( 17  18   5) ( 17   9  20) (  8   3  21))
    ((  2   1   5) (  5   2  13) (  8   3  21) ( 17   9  20) ( 17  18   5))
    ((  2   1   5) (  5   1  52) (  5   2  13) (  8   1 189) (  8   3  21))
    ((  2   1   5) (  5   1  52) (  8   1 189) ( 11   1 464) ( 14   1 925))
    

Analysis of Task#2:

If I get a blogpost written, I plan to delve into how `=~=` is insufficient for this task, as the default $*TOLERANCE misses some cases.

Original equation: (a + b√c)^⅓ + (a - b√c)^⅓ = 1
When solved for `c` via https://www.wolframalpha.com/ :
  Solve[ Cbrt[a + bSqrt[c]] + Cbrt[a - bSqrt[c]] = 1, c ]
      c = (a + 1)² * (8a - 1) / 27b²
  Useful!
  Also means that:
      (a + 1)² * (8a - 1) / 27b²c = 1

# Full derivation:
# https://math.stackexchange.com/questions/2160805/cardano-triplet-transformation
Original equation:
    (a + b√c)^⅓ + (a - b√c)^⅓ = 1
Move 2nd term across:
    (a + b√c)^⅓  = 1 - (a - b√c)^⅓
Cubing just removes the cube-root on the left, and expands on the right to:
    Expand[ (1 - Cbrt[a - bSqrt[c]])³ ]
                    3 ((a - b√c)^⅓)² - 3 (a - b√c)^⅓ - a + b√c + 1
     a + b√c == 1 + 3 ((a - b√c)^⅓)² - 3 (a - b√c)^⅓ - a + b√c
     a       == 1 + 3 ((a - b√c)^⅓)² - 3 (a - b√c)^⅓ - a      
    2a       == 1 + 3 ((a - b√c)^⅓)² - 3 (a - b√c)^⅓          
    2a - 1   ==     3 ((a - b√c)^⅓)² - 3 (a - b√c)^⅓
    2a - 1   ==    -3 ((a - b√c)^⅓) (1 - (a - b√c)^⅓)
Use original equality to substitute the last part from (a-...) to (a+...) :
    2a - 1   ==    -3 ((a - b√c)^⅓) ((a + b√c)^⅓)
Cube both sides again:
    Expand[ (2a - 1)³ ]
        8a³ - 12a² + 6a - 1
    Expand[ (-3 ((a - b√c)^⅓) ((a + b√c)^⅓))³ ]
        27b²c - 27a²
    8a³ - 12a² + 6a - 1 == 27b²c - 27a²
    8a³ + 15a² + 6a - 1 == 27b²c
Factor[8a³ + 15a² + 6a - 1]
    (a + 1)² (8a - 1) == 27b²c
Now solving for `c` is easy:
    (a + 1)² (8a - 1) / 27b² == c
`c` can only be a whole number if (a + 1)² (8a - 1) can be evenly divided by 27b².


Jean Marie goes further, in https://math.stackexchange.com/questions/1885095/parametrization-of-cardano-triplet ,
showing (halfway through) that 𝑎 ≡ 2 𝑚𝑜𝑑 3. 

Humor:
Easy to prove that, if we lock `b` to always be 1, and `𝑎 ≡ 2 𝑚𝑜𝑑 3` , then `c` will be integer for all `a` generated from 3k+2.
    (a + 1)² (8a - 1) / 27 == c
    Expand[((3k + 2) + 1)² * (8(3k + 2) - 1)]
        216k² + 567k² + 486k + 135
    Factor[Expand[((3k + 2) + 1)² * (8(3k + 2) - 1)]]
        27 (k + 1)² (8k + 5)
    Aha! Always divisible by 27!
So, a cheap way to generate Cardano triplets is (3k+2, 1, (k + 1)² (8k + 5)) for k=0..Inf.
Since 1 in the lowest possible `b`, using k=0..4 would give a reasonable (although unexpected) answer for the task.