The Bear's Den

Enter at your own risk

Banned Triplets

TASK #1 › Eban Numbers

Submitted by: Mohammad S Anwar


Write a script to generate all Eban Numbers <= 100.

An Eban number is a number that has no letter ’e’ in it when the number is spelled in English (American or British).

Example

2, 4, 6, 30, 32 are the first 5 Eban numbers.



Solution

Convert numbers to strings using Lingua::Any::Numbers and discard all that contain an e.

Perl

use strict;
use warnings;
use Lingua::Any::Numbers ':std2';

sub eban_numbers {
     grep to_string($_) !~ /e/, 0 .. shift;
}

See the full solution to task 1.

TASK #2 › Cardano Triplets

Submitted by: Mohammad S Anwar


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.

\[\sqrt[3]{a + b \sqrt{c}} + \sqrt[3]{a - b \sqrt{c}} = 1\]

Example

(2,1,5) is the first Cardano Triplets.

Solution

There is a minor issue with this task: Triplets have no underlying order and therefore the concept of “the first 5 triplets” is rather vague.

For the sake of convenience, ordering the triplets by the sum of their elements and lexicographically for identical sums.

Though Cardano triplets are defined as fulfilling the equation exactly, here we need to allow an approximate equality.

I didn’t investigate a way to find Cardano Triplets better than scanning through all triplets.

Perl

Need to define a helper function for the cubic root that handles negative arguments.

use strict;
use warnings;
use experimental 'signatures';
use Math::Prime::Util 'forcomp';

sub cubrt ($x) {
    abs($x) ** (1/3) * ($x < 0 ? -1 : 1);
}

sub card ($a, $b, $c) {
    cubrt($a + $b * sqrt($c)) + cubrt($a - $b * sqrt($c));
}

sub cardano_triplets ($cnt) {
    my @card;
    my $n = 3;
    while (@card < $cnt) {
        forcomp {
            push @card, [@_] if abs(card(@_) - 1) < 1e-8
        } $n++, {n => 3};
    }
    @card;
}

See the full solution to task 2.

J

The code to generate compositions was taken from the J Wiki.

Again, cubic roots need to be treated especially: J’s “root” primitive %: handles negative arguments, but returns the principal value of the root, which is a complex number. Applying the root to the absolute value and adjusting the sign to get the trivial result.

The comparison between numbers in J is tolerant by default.

It’s the same logic as in the Perl solution:

NB. enumerate all compositions of x in y parts
comp=: 4 : 0
 if. 1 >: x do. ((x>:&*y),x)$y
 else.
  c=. (x-2)!(x-2)+|.k=. i.1+y
  (c#k) ,. ((x-1){."0 c#-k) + (-1+;i.&.>-c) { (x-1) comp y
 end.
)

NB. Cardano Triplets having a sum of y + 3
cardano_s =: _(adverb define)
  NB. the Cardano term with a placeholder for the inner operation +/-
  '`a b c' =. (0&{)`(1&{)`(2&{)
  cubrt =. * * 3&%:@|
  card =. [:`cubrt`a`]:`b`*`(%:@c)`:6

  NB. sum of both terms
  csum =. (+ card + - card)"1

  NB. generate all triplets as incremented compositions and
  NB. select Cardano Triplets
  (] #~ 1 = csum) @: >: @ (3&comp) f.
)

NB. - loop over sizes and collect results while less
NB.   than x triplets have been found
NB. - provide a monad with a suitable start argument
cardano =: _(adverb define)
  '`size triplets' =. (0&{::@])`(1&{::@])
  init =. 0 ; 0 3 $ 0
  while =. ^:^:_.

  $:&init : ((>:@size ; triplets , cardano_s @ size) while (> #@triplets) f.)
)

See the full solution.