# Perl Weekly Challenge 148: eban vs cardano

It is sad that, after more than two years of me doing Raku, I still don’t have any production code project to work on. Therefore, in order to keep my coding and Raku-ing (is that a term?) knowdledge, I try to solve every Perl Weekly Challenge tasks.

In the following, the assigned tasks for Challenge 148.

And this week, as for the previous PWC, I had time to quickly implement the tasks also on PostgreSQL `plpgsql` language:

## PWC 148 - Task 1

This task was about finding out Eban numbers, those numbers that do not contain the letter `e` within their english name. I was not really inspired by this task, so I brutally created a set of arrays that contains the numbers that do not copntain an `e` in their english name, and I `grep` for those numbers:

``````sub MAIN() {

my @eban-units = 2, 4, 6;
my @eban-teens = 12;
my @eban-tens  = 3, 4, 5, 6;

\$_.say if @eban-units.grep( \$_ ) for 1 .. 10;
\$_.say if @eban-teens.grep( \$_ ) for 11 .. 19;
\$_.say if @eban-tens.grep( ( \$_ / 10 ).Int ) && @eban-units.grep( \$_ % 10 ) for 20 .. 100;

}

``````

## PWC 148 - Task 2

This has been a more difficult task, that required me to learn about the `=~=` almost equality operator. The task required to print out the first five Cardano numbers, those that solve a particular equation given three variables. First of all, I implemented a couple of functions that, given the three variables, provide me the result of the Cardano domain belonging:

``````multi sub is-cardano-triplet( \$a, \$b, \$c ) {

my \$left  = .sign * .abs**( 1 / 3 ) given ( \$a + \$b * \$c.sqrt );
my \$right = .sign * .abs**( 1 / 3 ) given ( \$a - \$b * \$c.sqrt );
return 1 =~= ( \$left + \$right );
}

multi sub is-cardano-triplet( @triplet ) {
return is-cardano-triplet( @triplet[ 0 ], @triplet[ 1 ], @triplet[ 2 ] );
}

``````

The second implementation of the `is-cardano-triplet` function is only a placeholder to simplify when I use an array, and this will become clearer later. However, I could have simply used the `|@triplet` flatting operator.
The `\$left` and `\$right` are computed as the parts of the equation. The `.sign` method provides `+1` or `-1` depending on the sign of the result (the part in the `given`) and then I computer the third root of the absolute value, thus providing the resulting signed value. I needed a little help here about the math.
However, I was expecting this resulted in an integer result, but instead the result was a `Rat`, thus requiring me to use the new (to me) `=~=` operator, that is almost equal operator (see the documentation).
With all in place, I used a nested loop to generate a triplet, and then I compared every single permutation of the triple to see if the result was good enough:

``````sub MAIN( Int \$limit = 5 ) {
my @triplets = lazy gather {
for 1 .. Inf -> \$a {
for 1 ..^ \$a -> \$b {
for 1 ..^ \$b -> \$c {
\$_.take if is-cardano-triplet( \$_ ) for ( \$a, \$b, \$c ).permutations;

}
}
}
};

@triplets[ 0 .. \$limit ].join( "\n" ).say;
}

``````

I used a `lazy gather` to stop the computation as soon as the end is reached, and in fact I print out only the first `\$limit` entries. This took near 7 seconds on my machine.

## PWC 148 - Task 1 in PostgreSQL

The implementation, bit to bit, of the Raku solution for this task:

``````SELECT v
FROM generate_series( 1, 10 ) v
WHERE
v IN ( 2, 4, 6 )

UNION

SELECT v
FROM generate_series( 11, 19 ) v
WHERE v IN ( 12 )

UNION

SELECT v
FROM generate_series( 20, 100 ) v
WHERE
v % 10 IN ( 2, 4, 6 )
AND ( v / 10 )::int  IN ( 3, 4, 5, 6 );

``````

A single query can do the trick.

## PWC 148 - Task 2 in PostgreSQL

A recursive CTE implementation of the Raku solution for this task, limiting the numbers to `30` to avoid too much joins. Note that I search for the triplets that provide a sum that is near `1` by a small value.

``````WITH RECURSIVE
triplets AS
(
SELECT a::numeric, b::numeric, c::numeric
FROM generate_series( 1, 30 ) a
, generate_series( 1, 30 ) b
, generate_series( 1, 30 ) c
ORDER BY a, b, c
)
, cardano_sum AS
(
SELECT a, b, c,
( a + b * sqrt( c ) )   AS l
,( a - b * sqrt( c ) )  AS r
FROM triplets
)
, cardano AS
(
SELECT a, b, c, l, r
, CASE WHEN l < 0 THEN -1 ELSE 1 END * pow( abs( l )::numeric, 1/3::numeric )
+ CASE WHEN r < 0 THEN -1 ELSE 1 END * pow( abs( r )::numeric, 1/3::numeric )
AS triplet_sum
FROM cardano_sum
)

SELECT *
FROM cardano
WHERE
abs( 1 - triplet_sum::numeric ) <= 0.0000000001
LIMIT 5
;

``````

It takes 54 seconds to complete, and is a lot more of the Raku implementation. Why? Because the above query performs the computation for every join available.

The article Perl Weekly Challenge 148: eban vs cardano has been posted by Luca Ferrari on January 19, 2022
{"ft_lang_label":"__label__en","ft_lang_prob":0.79096586,"math_prob":0.9379348,"size":4443,"snap":"2022-40-2023-06","text_gpt3_token_len":1351,"char_repetition_ratio":0.1058797,"word_repetition_ratio":0.061433446,"special_character_ratio":0.32568085,"punctuation_ratio":0.17237799,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9797934,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-02-06T18:37:31Z\",\"WARC-Record-ID\":\"<urn:uuid:082ede0d-014c-4622-9a9c-cb4c92ee9ccb>\",\"Content-Length\":\"22852\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:e70fc3ab-345e-4d3f-996a-5088e0143667>\",\"WARC-Concurrent-To\":\"<urn:uuid:5ba197bb-75ff-46e0-92f5-aad2d57996b6>\",\"WARC-IP-Address\":\"185.199.108.153\",\"WARC-Target-URI\":\"https://fluca1978.github.io/2022/01/19/PerlWeeklyChallenge148.html\",\"WARC-Payload-Digest\":\"sha1:XCI35OASSWAZI4D3MEM6RNKXU2BHOQ5Z\",\"WARC-Block-Digest\":\"sha1:JDSS6VFUW6JR3D4J7J25ELYLCO7PGLYV\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-06/CC-MAIN-2023-06_segments_1674764500357.3_warc_CC-MAIN-20230206181343-20230206211343-00835.warc.gz\"}"}