aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-11-14 17:12:35 +0000
committerGitHub <noreply@github.com>2025-11-14 17:12:35 +0000
commite4f95af26374a568704a6256fd8a94343961f62e (patch)
tree4cefe6a3367eb72c44695feee958987c0f607ac8
parent349fcb363ce1d6422484849a9a118baff2eb1827 (diff)
parentff9bf5ea41fe76a7c1acf1abe0b5b57b538e309d (diff)
downloadperlweeklychallenge-club-e4f95af26374a568704a6256fd8a94343961f62e.tar.gz
perlweeklychallenge-club-e4f95af26374a568704a6256fd8a94343961f62e.tar.bz2
perlweeklychallenge-club-e4f95af26374a568704a6256fd8a94343961f62e.zip
Merge pull request #13026 from fluca1978/PWC347
PWC 347
-rw-r--r--challenge-347/luca-ferrari/blog-1.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-10.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-2.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-3.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-4.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-5.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-6.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-7.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-8.txt1
-rw-r--r--challenge-347/luca-ferrari/blog-9.txt1
-rw-r--r--challenge-347/luca-ferrari/pljava/pom.xml72
-rw-r--r--challenge-347/luca-ferrari/pljava/src/main/java/Task1.java76
-rw-r--r--challenge-347/luca-ferrari/pljava/src/main/java/Task2.java92
-rw-r--r--challenge-347/luca-ferrari/plperl/ch-1.plperl39
-rw-r--r--challenge-347/luca-ferrari/plperl/ch-2.plperl39
-rw-r--r--challenge-347/luca-ferrari/plpgsql/ch-1.sql49
-rw-r--r--challenge-347/luca-ferrari/plpgsql/ch-2.sql60
-rw-r--r--challenge-347/luca-ferrari/python/ch-1.py40
-rw-r--r--challenge-347/luca-ferrari/python/ch-2.py38
-rw-r--r--challenge-347/luca-ferrari/raku/ch-1.raku28
-rw-r--r--challenge-347/luca-ferrari/raku/ch-2.raku25
21 files changed, 568 insertions, 0 deletions
diff --git a/challenge-347/luca-ferrari/blog-1.txt b/challenge-347/luca-ferrari/blog-1.txt
new file mode 100644
index 0000000000..7d8a425d20
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-1.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task1
diff --git a/challenge-347/luca-ferrari/blog-10.txt b/challenge-347/luca-ferrari/blog-10.txt
new file mode 100644
index 0000000000..04cc9108ed
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-10.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task2pljava
diff --git a/challenge-347/luca-ferrari/blog-2.txt b/challenge-347/luca-ferrari/blog-2.txt
new file mode 100644
index 0000000000..5e1ea3d0ae
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-2.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task2
diff --git a/challenge-347/luca-ferrari/blog-3.txt b/challenge-347/luca-ferrari/blog-3.txt
new file mode 100644
index 0000000000..c6a4d84329
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-3.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task1plperl
diff --git a/challenge-347/luca-ferrari/blog-4.txt b/challenge-347/luca-ferrari/blog-4.txt
new file mode 100644
index 0000000000..53e0f402b9
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-4.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task2plperl
diff --git a/challenge-347/luca-ferrari/blog-5.txt b/challenge-347/luca-ferrari/blog-5.txt
new file mode 100644
index 0000000000..630d6544d0
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-5.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task1plpgsql
diff --git a/challenge-347/luca-ferrari/blog-6.txt b/challenge-347/luca-ferrari/blog-6.txt
new file mode 100644
index 0000000000..d8edbc7ad7
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-6.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task2plpgsql
diff --git a/challenge-347/luca-ferrari/blog-7.txt b/challenge-347/luca-ferrari/blog-7.txt
new file mode 100644
index 0000000000..129ddd3b22
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-7.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task1python
diff --git a/challenge-347/luca-ferrari/blog-8.txt b/challenge-347/luca-ferrari/blog-8.txt
new file mode 100644
index 0000000000..a8c07374ae
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-8.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task2python
diff --git a/challenge-347/luca-ferrari/blog-9.txt b/challenge-347/luca-ferrari/blog-9.txt
new file mode 100644
index 0000000000..a61297e251
--- /dev/null
+++ b/challenge-347/luca-ferrari/blog-9.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/13/PerlWeeklyChallenge347.html#task1pljava
diff --git a/challenge-347/luca-ferrari/pljava/pom.xml b/challenge-347/luca-ferrari/pljava/pom.xml
new file mode 100644
index 0000000000..9d238d7670
--- /dev/null
+++ b/challenge-347/luca-ferrari/pljava/pom.xml
@@ -0,0 +1,72 @@
+
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>PWC</groupId>
+ <artifactId>
+ PWC347
+ </artifactId>
+ <version>
+ 1
+ </version>
+
+ <name>Perl Weekly Challenge 347 with package PWC347</name>
+ <description>Implementation of the tasks in PL/Java for PWC 347</description>
+
+ <properties>
+ <project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>pljava-api</artifactId>
+ <version>1.6.6</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <release>9</release>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <!-- This identifies and version-stamps the jar.
+ Not essential, but easy and useful. -->
+ <addDefaultImplementationEntries>
+ true
+ </addDefaultImplementationEntries>
+ </manifest>
+
+ <manifestSections>
+ <!-- This identifies a file in the jar named
+ pljava.ddr as an SQLJDeploymentDescriptor. -->
+ <manifestSection>
+ <name>pljava.ddr</name>
+ <manifestEntries>
+ <SQLJDeploymentDescriptor>
+ true
+ </SQLJDeploymentDescriptor>
+ </manifestEntries>
+ </manifestSection>
+ </manifestSections>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/challenge-347/luca-ferrari/pljava/src/main/java/Task1.java b/challenge-347/luca-ferrari/pljava/src/main/java/Task1.java
new file mode 100644
index 0000000000..55a579ff0f
--- /dev/null
+++ b/challenge-347/luca-ferrari/pljava/src/main/java/Task1.java
@@ -0,0 +1,76 @@
+
+
+
+package PWC347;
+
+/**
+ * PL/Java implementation for PWC 347
+ * Task 1
+ * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+ *
+ *
+ * To compile on the local machine:
+
+ $ export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ # if not already set
+ $ mvn clean build
+ $ scp target/PWC347-1.jar luca@rachel:/tmp
+
+
+ * To install into PostgreSQL execute:
+
+ select sqlj.install_jar( 'file:///tmp/PWC347-1.jar', 'PWC347', true );
+ select sqlj.set_classpath( 'public', 'PWC347' );
+
+ select pwc347.task2_pljava();
+
+ and then to redeploy:
+
+ select sqlj.replace_jar( 'file:///tmp/PWC347-1.jar', 'PWC347', true );
+
+*/
+
+import org.postgresql.pljava.*;
+import org.postgresql.pljava.annotation.Function;
+import static org.postgresql.pljava.annotation.Function.Effects.IMMUTABLE;
+import static org.postgresql.pljava.annotation.Function.OnNullInput.RETURNS_NULL;
+
+import java.util.*;
+import java.util.stream.*;
+import java.sql.SQLException;
+import java.util.logging.*;
+import java.sql.ResultSet;
+import java.sql.Date;
+
+public class Task1 {
+
+ private final static Logger logger = Logger.getAnonymousLogger();
+
+ @Function( schema = "pwc347",
+ onNullInput = RETURNS_NULL,
+ effects = IMMUTABLE )
+ public static final String task1_pljava( String date ) throws SQLException {
+ logger.log( Level.INFO, "Entering pwc347.task1_pljava" );
+
+ Map<String, Integer> months = new HashMap<String, Integer>();
+
+ months.put( "Jan", 1 );
+ months.put( "Feb", 2 );
+ months.put( "Mar", 3 );
+ months.put( "Apr", 4 );
+ months.put( "May", 5 );
+ months.put( "Jun", 6 );
+ months.put( "Jul", 7 );
+ months.put( "Aug", 8 );
+ months.put( "Sep", 9 );
+ months.put( "Oct", 10 );
+ months.put( "Nov", 11 );
+ months.put( "Dec", 12 );
+
+
+ String[] parts = date.split( "\\s+" );
+ return String.format( "%04d-%02d-%02d",
+ Integer.parseInt( parts[ 2 ] ),
+ months.get( parts[ 1 ] ),
+ Integer.parseInt( parts[ 0 ].replace( "st", "" ).replace( "nd", "" ).replace( "rd", "" ).replace( "rh", "" ) ) );
+ }
+}
diff --git a/challenge-347/luca-ferrari/pljava/src/main/java/Task2.java b/challenge-347/luca-ferrari/pljava/src/main/java/Task2.java
new file mode 100644
index 0000000000..b51d95c8d2
--- /dev/null
+++ b/challenge-347/luca-ferrari/pljava/src/main/java/Task2.java
@@ -0,0 +1,92 @@
+
+
+
+package PWC347;
+
+/**
+ * PL/Java implementation for PWC 347
+ * Task 2
+ * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+ *
+ *
+ * To compile on the local machine:
+
+ $ export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/ # if not already set
+ $ mvn clean build
+ $ scp target/PWC347-1.jar luca@rachel:/tmp
+
+
+ * To install into PostgreSQL execute:
+
+ select sqlj.install_jar( 'file:///tmp/PWC347-1.jar', 'PWC347', true );
+ select sqlj.set_classpath( 'public', 'PWC347' );
+
+ select pwc347.task2_pljava();
+
+ and then to redeploy:
+
+ select sqlj.replace_jar( 'file:///tmp/PWC347-1.jar', 'PWC347', true );
+
+*/
+
+import org.postgresql.pljava.*;
+import org.postgresql.pljava.annotation.Function;
+import static org.postgresql.pljava.annotation.Function.Effects.IMMUTABLE;
+import static org.postgresql.pljava.annotation.Function.OnNullInput.RETURNS_NULL;
+
+import java.util.*;
+import java.util.stream.*;
+import java.sql.SQLException;
+import java.util.logging.*;
+import java.sql.ResultSet;
+import java.sql.Date;
+
+public class Task2 {
+
+ private final static Logger logger = Logger.getAnonymousLogger();
+
+ @Function( schema = "pwc347",
+ onNullInput = RETURNS_NULL,
+ effects = IMMUTABLE )
+ public static final String task2_pljava( String phone ) throws SQLException {
+ logger.log( Level.INFO, "Entering pwc347.task2_pljava" );
+
+ phone = phone.replaceAll( "-", "" ).replaceAll( " ", "" );
+ List<String> groups = new LinkedList<String>();
+
+ String current = "";
+ for( int i = 0; i < phone.length(); i++ ) {
+ current += phone.charAt( i );
+ if ( current.length() % 3 == 0 ) {
+ groups.add( current );
+ current = "";
+ }
+ }
+
+ if ( current.length() > 0 ) {
+ groups.add( current );
+ }
+
+
+ if ( groups.get( groups.size() - 1 ).length() != 2
+ || groups.get( groups.size() - 1 ).length() != 3 ) {
+
+ String begin = groups.get( groups.size() - 2 );
+ String end = groups.get( groups.size() - 1 );
+ groups.remove( groups.size() - 1 );
+ groups.remove( groups.size() - 1 );
+
+ String last = begin + end;
+
+ groups.add( "" + last.charAt( 0 ) + last.charAt( 1 ) );
+ groups.add( "" + last.charAt( 2 ) + last.charAt( 3 ) );
+ }
+
+ String result = "";
+ for ( String s : groups ) {
+ result += s + "-";
+ }
+
+ return result;
+ }
+}
diff --git a/challenge-347/luca-ferrari/plperl/ch-1.plperl b/challenge-347/luca-ferrari/plperl/ch-1.plperl
new file mode 100644
index 0000000000..c41ffa56a7
--- /dev/null
+++ b/challenge-347/luca-ferrari/plperl/ch-1.plperl
@@ -0,0 +1,39 @@
+--
+-- Perl Weekly Challenge 347
+-- Task 1
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc347;
+
+CREATE OR REPLACE FUNCTION
+pwc347.task1_plperl( text )
+RETURNS date
+AS $CODE$
+
+ my ( $date ) = @_;
+
+ my %months = ( 'Jan' => 1,
+ 'Feb' => 2,
+ 'Mar' => 3,
+ 'Apr' => 4,
+ 'May' => 5,
+ 'Jun' => 6,
+ 'Jul' => 7,
+ 'Aug' => 8,
+ 'Sep' => 9,
+ 'Oct' => 10,
+ 'Nov' => 11,
+ 'Dec' => 12 );
+
+ if ( $date =~ / ^ (?<day>\d{1,2}) \D{2} \s+ (?<month>\D{3}) \s+ (?<year>\d{4}) $ /x ) {
+ return sprintf '%04d-%02d-%02d', $+{year}, $months{ $+{month} }, $+{day};
+ }
+ else {
+ elog( WARN, "No valid date format" );
+ return undef;
+ }
+
+
+$CODE$
+LANGUAGE plperl;
diff --git a/challenge-347/luca-ferrari/plperl/ch-2.plperl b/challenge-347/luca-ferrari/plperl/ch-2.plperl
new file mode 100644
index 0000000000..0ca024bdf2
--- /dev/null
+++ b/challenge-347/luca-ferrari/plperl/ch-2.plperl
@@ -0,0 +1,39 @@
+--
+-- Perl Weekly Challenge 347
+-- Task 2
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc347;
+
+CREATE OR REPLACE FUNCTION
+pwc347.task2_plperl( text )
+RETURNS text
+AS $CODE$
+
+ my ( $phone ) = @_;
+
+ $phone =~ s/ [- ] //gx;
+
+ my @groups;
+ while ( length( $phone ) >= 3 ) {
+ push @groups, join( '', ( ( split( //, $phone ) )[ 0 .. 2 ] ) );
+ $phone =~ s/ ^ .{3} //xg;
+ }
+
+ if ( $phone ) {
+ push @groups, $phone;
+ }
+
+ if ( length( $groups[ $#groups ] ) != 2 || length( $groups[ $#groups ] ) != 3 ) {
+ my ( $end, $begin ) = ( pop @groups, pop @groups );
+ my $last = $begin . $end;
+ push @groups, join( '', ( split( //, $last ) )[ 0 .. 1 ] );
+ push @groups, join( '', ( split( //, $last ) )[ 2 .. 3 ] );
+ }
+
+
+ return join( '-', @groups );
+
+$CODE$
+LANGUAGE plperl;
diff --git a/challenge-347/luca-ferrari/plpgsql/ch-1.sql b/challenge-347/luca-ferrari/plpgsql/ch-1.sql
new file mode 100644
index 0000000000..e67a4442c4
--- /dev/null
+++ b/challenge-347/luca-ferrari/plpgsql/ch-1.sql
@@ -0,0 +1,49 @@
+--
+-- Perl Weekly Challenge 347
+-- Task 1
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc347;
+
+CREATE OR REPLACE FUNCTION
+pwc347.task1_plpgsql( d text )
+RETURNS date
+AS $CODE$
+DECLARE
+ x text[];
+ r text;
+
+BEGIN
+ CREATE TEMPORARY TABLE IF NOT EXISTS months( i int, m text );
+ TRUNCATE TABLE months;
+
+ INSERT INTO months( i, m )
+ VALUES
+ ( 1, 'Jan' )
+ , ( 2, 'Feb' )
+ , ( 3, 'Mar' )
+ , ( 4, 'Apr' )
+ , ( 5, 'May' )
+ , ( 6, 'Jun' )
+ , ( 7, 'Jul' )
+ , ( 8, 'Aug' )
+ , ( 9, 'Sep' )
+ , ( 10, 'Oct' )
+ , ( 11, 'Nov' )
+ , ( 12, 'Dec' );
+
+ r := '';
+ x := regexp_matches( d, '(\d+).{2}\s+(\D{3})\s+(\d{4})' );
+
+ SELECT x[ 3 ] || '-' || m.i || '-' || x[ 1 ]
+ INTO r
+ FROM months m
+ WHERE m = x[ 2 ];
+
+
+ RETURN r;
+
+END
+$CODE$
+LANGUAGE plpgsql;
diff --git a/challenge-347/luca-ferrari/plpgsql/ch-2.sql b/challenge-347/luca-ferrari/plpgsql/ch-2.sql
new file mode 100644
index 0000000000..353663cfda
--- /dev/null
+++ b/challenge-347/luca-ferrari/plpgsql/ch-2.sql
@@ -0,0 +1,60 @@
+--
+-- Perl Weekly Challenge 347
+-- Task 2
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc347;
+
+CREATE OR REPLACE FUNCTION
+pwc347.task2_plpgsql( phone text )
+RETURNS text
+AS $CODE$
+DECLARE
+ x text;
+ r text;
+ i int;
+
+ groups text[];
+BEGIN
+
+ i := 0;
+
+
+ FOREACH x IN ARRAY regexp_split_to_array( phone, '' ) LOOP
+
+
+ IF x = '-' OR x = ' ' THEN
+ CONTINUE;
+ END IF;
+
+ RAISE INFO 'x = %', x;
+ IF r IS NULL THEN
+ r := x;
+ ELSE
+ r := r || x;
+ END IF;
+
+ i := i + 1;
+
+ IF i = 3 THEN
+ groups := groups || r;
+ r := NULL;
+ i := 0;
+ END IF;
+ END LOOP;
+
+ IF i <> 0 THEN
+ groups := groups || r;
+ END IF;
+
+ IF length( groups[ array_length( groups, 1 ) ] ) THEN
+ RETURN pwc347.task2_plperl( phone );
+ END IF;
+
+
+ RETURN array_to_string( groups, '-' );
+
+END
+$CODE$
+LANGUAGE plpgsql;
diff --git a/challenge-347/luca-ferrari/python/ch-1.py b/challenge-347/luca-ferrari/python/ch-1.py
new file mode 100644
index 0000000000..0457123160
--- /dev/null
+++ b/challenge-347/luca-ferrari/python/ch-1.py
@@ -0,0 +1,40 @@
+#!python
+
+#
+# Perl Weekly Challenge 347
+# Task 1
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+#
+
+import sys
+import re
+
+# task implementation
+# the return value will be printed
+def task_1( args ):
+ months = { 'Jan' : 1,
+ 'Feb' : 2,
+ 'Mar' : 3,
+ 'Apr' : 4,
+ 'May' : 5,
+ 'Jun' : 6,
+ 'Jul' : 7,
+ 'Aug' : 8,
+ 'Sep' : 9,
+ 'Oct' : 10,
+ 'Nov' : 11,
+ 'Dec' : 12 }
+
+
+ r = re.compile( r'\s+' )
+ parts = r.split( args[ 0 ] )
+
+ return '-'.join( [ parts[ 2 ],
+ str( months[ parts[ 1 ] ] ),
+ parts[ 0 ].replace( 'st', '' ).replace( 'nd', '' ).replace( 'rd', '' ).replace( 'th', '' ) ] )
+
+
+# invoke the main without the command itself
+if __name__ == '__main__':
+ print( task_1( sys.argv[ 1: ] ) )
diff --git a/challenge-347/luca-ferrari/python/ch-2.py b/challenge-347/luca-ferrari/python/ch-2.py
new file mode 100644
index 0000000000..fab86b9763
--- /dev/null
+++ b/challenge-347/luca-ferrari/python/ch-2.py
@@ -0,0 +1,38 @@
+#!python
+
+#
+# Perl Weekly Challenge 347
+# Task 2
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+#
+
+import sys
+
+
+# task implementation
+# the return value will be printed
+def task_2( args ):
+ phone = args[ 0 ].replace( '-', '' ).replace( ' ', '' )
+
+ groups = []
+ while len( phone ) > 0:
+ if len( phone ) >= 3:
+ groups.append( phone[ 0 : 3 ] )
+ phone = phone[ 3: ]
+ else:
+ groups.append( phone )
+ phone = ''
+
+ if len( groups[ -1 ] ) != 2 and len( groups[ -1 ] ) != 3:
+ begin = groups[ -2 ]
+ end = groups[ -1 ]
+ last = begin + end
+ groups[ -2 ] = last[ 0 : 2 ]
+ groups[ -1 ] = last[ 2 : 4 ]
+
+ return '-'.join( groups )
+
+# invoke the main without the command itself
+if __name__ == '__main__':
+ print( task_2( sys.argv[ 1: ] ) )
diff --git a/challenge-347/luca-ferrari/raku/ch-1.raku b/challenge-347/luca-ferrari/raku/ch-1.raku
new file mode 100644
index 0000000000..02c6f2ca6d
--- /dev/null
+++ b/challenge-347/luca-ferrari/raku/ch-1.raku
@@ -0,0 +1,28 @@
+#!raku
+
+#
+# Perl Weekly Challenge 347
+# Task 1
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+#
+
+sub MAIN( Str $date ) {
+ my %months = 'Jan' => 1,
+ 'Feb' => 2,
+ 'Mar' => 3,
+ 'Apr' => 4,
+ 'May' => 5,
+ 'Jun' => 6,
+ 'Jul' => 7,
+ 'Aug' => 8,
+ 'Sep' => 9,
+ 'Oct' => 10,
+ 'Nov' => 11,
+ 'Dec' => 12;
+
+ if ( $date ~~ / ^ $<day> = ( \d{1 .. 2} ) ( 'st' | 'nd' | 'rd' | 'th' ) \s+ $<month> = ( \w+ ) \s+ $<year> = ( \d+ ) $ / ) {
+ say '%04d-%02d-%02d'.sprintf: $/<year>, %months{ $/<month> }, $/<day>;
+ }
+
+}
diff --git a/challenge-347/luca-ferrari/raku/ch-2.raku b/challenge-347/luca-ferrari/raku/ch-2.raku
new file mode 100644
index 0000000000..617a58d299
--- /dev/null
+++ b/challenge-347/luca-ferrari/raku/ch-2.raku
@@ -0,0 +1,25 @@
+#!raku
+
+#
+# Perl Weekly Challenge 347
+# Task 2
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-347>
+#
+
+sub MAIN( Str $phone is copy ) {
+ $phone .= subst( / \s+ /, '', :g );
+ $phone .= subst( / <[-]> /, '', :g );
+ my @groups = $phone.comb( :skip-empty ).rotor( 3, :partial );
+ @groups .= map( *.join );
+
+ if @groups[ * - 1 ].chars != 2|3 {
+ my $adjust = @groups[ * - 2 ] ~ @groups[ * - 1 ];
+ @groups.pop;
+ @groups.pop;
+ @groups.push: |$adjust.comb.rotor( 2 ).map( *.join );
+ }
+
+ @groups.join( '-' ).say;
+
+}