| 08 November 2026 | Challenge 148 |
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.
\[\sqrt[3]{a + b \sqrt{c}} + \sqrt[3]{a - b \sqrt{c}} = 1\]A triplet of positive integers (a,b,c) is called a Cardano Triplet if it satisfies the below condition.
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:
- loop over sizes until the requested number of triplets has been found
- loop over compositions and find all Cardano Triplets of that size
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.