aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Ferrari <fluca1978@gmail.com>2025-11-20 10:48:16 +0100
committerLuca Ferrari <fluca1978@gmail.com>2025-11-20 14:11:19 +0100
commit244472371574d4832deb16a75279e93b4a5a1498 (patch)
treebaa459e687f55eace42f94fbcfa4cf1afd857a02
parentaa283ea4bec57f330a917dba4a1c8b13102c6008 (diff)
downloadperlweeklychallenge-club-244472371574d4832deb16a75279e93b4a5a1498.tar.gz
perlweeklychallenge-club-244472371574d4832deb16a75279e93b4a5a1498.tar.bz2
perlweeklychallenge-club-244472371574d4832deb16a75279e93b4a5a1498.zip
PWC 348
Task 1 Raku done Task 2 Raku done Task 1 PL/Perl done Task 2 PL/Perl done Task 1 PL/PgSQL done Task 2 PL/PgSQL done Task 1 PL/Java done Task 2 PL/Java done Task 1 Python done Task 2 Python done
-rw-r--r--challenge-348/luca-ferrari/blog-1.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-10.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-2.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-3.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-4.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-5.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-6.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-7.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-8.txt1
-rw-r--r--challenge-348/luca-ferrari/blog-9.txt1
-rw-r--r--challenge-348/luca-ferrari/pljava/pom.xml6
-rw-r--r--challenge-348/luca-ferrari/pljava/src/main/java/Task1.java74
-rw-r--r--challenge-348/luca-ferrari/pljava/src/main/java/Task2.java80
-rw-r--r--challenge-348/luca-ferrari/plperl/ch-1.plperl25
-rw-r--r--challenge-348/luca-ferrari/plperl/ch-2.plperl34
-rw-r--r--challenge-348/luca-ferrari/plpgsql/ch-1.sql40
-rw-r--r--challenge-348/luca-ferrari/plpgsql/ch-2.sql46
-rw-r--r--challenge-348/luca-ferrari/python/ch-1.py36
-rw-r--r--challenge-348/luca-ferrari/python/ch-2.py44
-rw-r--r--challenge-348/luca-ferrari/raku/ch-1.raku18
-rw-r--r--challenge-348/luca-ferrari/raku/ch-2.raku33
21 files changed, 443 insertions, 3 deletions
diff --git a/challenge-348/luca-ferrari/blog-1.txt b/challenge-348/luca-ferrari/blog-1.txt
new file mode 100644
index 0000000000..5a5d09aa8c
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-1.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task1
diff --git a/challenge-348/luca-ferrari/blog-10.txt b/challenge-348/luca-ferrari/blog-10.txt
new file mode 100644
index 0000000000..52a7be9f85
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-10.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task2pljava
diff --git a/challenge-348/luca-ferrari/blog-2.txt b/challenge-348/luca-ferrari/blog-2.txt
new file mode 100644
index 0000000000..314ed9263a
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-2.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task2
diff --git a/challenge-348/luca-ferrari/blog-3.txt b/challenge-348/luca-ferrari/blog-3.txt
new file mode 100644
index 0000000000..841ebeab44
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-3.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task1plperl
diff --git a/challenge-348/luca-ferrari/blog-4.txt b/challenge-348/luca-ferrari/blog-4.txt
new file mode 100644
index 0000000000..f1f2e95017
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-4.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task2plperl
diff --git a/challenge-348/luca-ferrari/blog-5.txt b/challenge-348/luca-ferrari/blog-5.txt
new file mode 100644
index 0000000000..645252a466
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-5.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task1plpgsql
diff --git a/challenge-348/luca-ferrari/blog-6.txt b/challenge-348/luca-ferrari/blog-6.txt
new file mode 100644
index 0000000000..3e77e2e266
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-6.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task2plpgsql
diff --git a/challenge-348/luca-ferrari/blog-7.txt b/challenge-348/luca-ferrari/blog-7.txt
new file mode 100644
index 0000000000..89d805e7f7
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-7.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task1python
diff --git a/challenge-348/luca-ferrari/blog-8.txt b/challenge-348/luca-ferrari/blog-8.txt
new file mode 100644
index 0000000000..382d75fa2e
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-8.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task2python
diff --git a/challenge-348/luca-ferrari/blog-9.txt b/challenge-348/luca-ferrari/blog-9.txt
new file mode 100644
index 0000000000..a17b662d46
--- /dev/null
+++ b/challenge-348/luca-ferrari/blog-9.txt
@@ -0,0 +1 @@
+https://fluca1978.github.io/2025/11/20/PerlWeeklyChallenge348.html#task1pljava
diff --git a/challenge-348/luca-ferrari/pljava/pom.xml b/challenge-348/luca-ferrari/pljava/pom.xml
index 9d238d7670..d1e54ecdf9 100644
--- a/challenge-348/luca-ferrari/pljava/pom.xml
+++ b/challenge-348/luca-ferrari/pljava/pom.xml
@@ -7,14 +7,14 @@
<groupId>PWC</groupId>
<artifactId>
- PWC347
+ PWC348
</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>
+ <name>Perl Weekly Challenge 348 with package PWC348</name>
+ <description>Implementation of the tasks in PL/Java for PWC 348</description>
<properties>
<project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding>
diff --git a/challenge-348/luca-ferrari/pljava/src/main/java/Task1.java b/challenge-348/luca-ferrari/pljava/src/main/java/Task1.java
new file mode 100644
index 0000000000..9440f7a628
--- /dev/null
+++ b/challenge-348/luca-ferrari/pljava/src/main/java/Task1.java
@@ -0,0 +1,74 @@
+
+
+
+package PWC348;
+
+/**
+ * PL/Java implementation for PWC 348
+ * Task 1
+ * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+ *
+ *
+ * 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/PWC348-1.jar luca@rachel:/tmp
+
+
+ * To install into PostgreSQL execute:
+
+ select sqlj.install_jar( 'file:///tmp/PWC348-1.jar', 'PWC348', true );
+ select sqlj.set_classpath( 'public', 'PWC348' );
+
+ select pwc348.task2_pljava();
+
+ and then to redeploy:
+
+ select sqlj.replace_jar( 'file:///tmp/PWC348-1.jar', 'PWC348', 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 = "pwc348",
+ onNullInput = RETURNS_NULL,
+ effects = IMMUTABLE )
+ public static boolean task1_pljava( String text ) throws SQLException {
+ logger.log( Level.INFO, "Entering pwc348.task1_pljava" );
+
+ if ( text == null || text.isEmpty() || text.length() %2 != 0 )
+ return false;
+
+ int left = 0, right = 0, middle = text.length() / 2;
+ int index = 0;
+ String vowels = "aeiou";
+ for ( String c : text.split( "" ) ) {
+ index++;
+
+ if ( vowels.indexOf( c ) < 0 )
+ continue;
+
+ if ( index <= middle )
+ left++;
+ else
+ right++;
+ }
+
+ return left == right;
+ }
+}
diff --git a/challenge-348/luca-ferrari/pljava/src/main/java/Task2.java b/challenge-348/luca-ferrari/pljava/src/main/java/Task2.java
new file mode 100644
index 0000000000..ffa6ecd5e9
--- /dev/null
+++ b/challenge-348/luca-ferrari/pljava/src/main/java/Task2.java
@@ -0,0 +1,80 @@
+
+
+
+package PWC348;
+
+/**
+ * PL/Java implementation for PWC 348
+ * Task 2
+ * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+ *
+ *
+ * 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/PWC348-1.jar luca@rachel:/tmp
+
+
+ * To install into PostgreSQL execute:
+
+ select sqlj.install_jar( 'file:///tmp/PWC348-1.jar', 'PWC348', true );
+ select sqlj.set_classpath( 'public', 'PWC348' );
+
+ select pwc348.task2_pljava();
+
+ and then to redeploy:
+
+ select sqlj.replace_jar( 'file:///tmp/PWC348-1.jar', 'PWC348', 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 = "pwc348",
+ onNullInput = RETURNS_NULL,
+ effects = IMMUTABLE )
+ public static final int task2_pljava( String source, String target ) throws SQLException {
+ logger.log( Level.INFO, "Entering pwc348.task2_pljava" );
+
+ int src_mins = 0;
+ int dst_mins = 0;
+ int[] multipliers = { 60, 1 };
+ List<Integer> operations = new LinkedList<Integer>();
+
+ int index = 0;
+ for ( String part : source.split( ":" ) )
+ src_mins += Integer.parseInt( part ) * multipliers[ index++ ];
+
+
+ index = 0;
+ for ( String part : target.split( ":" ) )
+ dst_mins += Integer.parseInt( part ) * multipliers[ index++ ];
+
+
+ int ops[] = { 60, 15, 10, 5, 1 };
+ for ( int op : ops )
+ while ( dst_mins - src_mins >= op ) {
+ src_mins += op;
+ operations.add( op );
+ }
+
+
+ return operations.size();
+
+ }
+}
diff --git a/challenge-348/luca-ferrari/plperl/ch-1.plperl b/challenge-348/luca-ferrari/plperl/ch-1.plperl
new file mode 100644
index 0000000000..b276c70cb1
--- /dev/null
+++ b/challenge-348/luca-ferrari/plperl/ch-1.plperl
@@ -0,0 +1,25 @@
+--
+-- Perl Weekly Challenge 348
+-- Task 1
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc348;
+
+CREATE OR REPLACE FUNCTION
+pwc348.task1_plperl( text )
+RETURNS boolean
+AS $CODE$
+
+ my ( $text ) = @_;
+
+ return 0 unless ( length( $text ) % 2 == 0 );
+
+ my @chars = split //, $text;
+ my ( @left, @right ) = ( @chars[ 0 .. $#chars / 2 - 1 ],
+ @chars[ $#chars / 2 .. $#chars ] );
+
+ return scalar( grep( { $_ =~ / [aeiou] / } @left ) ) == scalar( grep( { $_ =~ / [aeiou] / } @right ) );
+
+$CODE$
+LANGUAGE plperl;
diff --git a/challenge-348/luca-ferrari/plperl/ch-2.plperl b/challenge-348/luca-ferrari/plperl/ch-2.plperl
new file mode 100644
index 0000000000..b6a87150d7
--- /dev/null
+++ b/challenge-348/luca-ferrari/plperl/ch-2.plperl
@@ -0,0 +1,34 @@
+--
+-- Perl Weekly Challenge 348
+-- Task 2
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc348;
+
+CREATE OR REPLACE FUNCTION
+pwc348.task2_plperl( text, text )
+RETURNS int
+AS $CODE$
+
+ my ( $source, $target ) = @_;
+
+ my @elems = split /[:]/, $source;
+ my $src_mins = $elems[ 0 ] * 60 + $elems[ 1 ];
+
+ @elems = split /[:]/, $target;
+ my $dst_mins = $elems[ 0 ] * 60 + $elems[ 1 ];
+
+ my @operations;
+ for my $current ( 60, 15, 10, 5, 1 ) {
+ while ( $dst_mins - $src_mins >= $current ) {
+ push @operations, $current;
+ $src_mins += $current;
+ }
+ }
+
+ return scalar( @operations );
+
+
+$CODE$
+LANGUAGE plperl;
diff --git a/challenge-348/luca-ferrari/plpgsql/ch-1.sql b/challenge-348/luca-ferrari/plpgsql/ch-1.sql
new file mode 100644
index 0000000000..c293c3fafe
--- /dev/null
+++ b/challenge-348/luca-ferrari/plpgsql/ch-1.sql
@@ -0,0 +1,40 @@
+--
+-- Perl Weekly Challenge 348
+-- Task 1
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc348;
+
+CREATE OR REPLACE FUNCTION
+pwc348.task1_plpgsql( s text )
+RETURNS boolean
+AS $CODE$
+DECLARE
+ lc int;
+ rc int;
+ sz int;
+BEGIN
+ if mod( length( s ), 2 ) <> 0 then
+ return false;
+ else
+ sz := length( s ) / 2;
+ end if;
+
+ SELECT count( t.* )
+ INTO lc
+ FROM ( SELECT regexp_matches( lower( left( s, sz ) ), '[aeiou]' ) ) t;
+
+ SELECT count( t.* )
+ INTO rc
+ FROM ( SELECT regexp_matches( lower( right( s, sz ) ), '[aeiou]' ) ) t;
+
+
+ IF lc = rc THEN
+ RETURN true;
+ ELSE
+ RETURN false;
+ END IF;
+END
+$CODE$
+LANGUAGE plpgsql;
diff --git a/challenge-348/luca-ferrari/plpgsql/ch-2.sql b/challenge-348/luca-ferrari/plpgsql/ch-2.sql
new file mode 100644
index 0000000000..8d0573787b
--- /dev/null
+++ b/challenge-348/luca-ferrari/plpgsql/ch-2.sql
@@ -0,0 +1,46 @@
+--
+-- Perl Weekly Challenge 348
+-- Task 2
+-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+--
+
+CREATE SCHEMA IF NOT EXISTS pwc348;
+
+CREATE OR REPLACE FUNCTION
+pwc348.task2_plpgsql( s text, t text )
+RETURNS int
+AS $CODE$
+DECLARE
+ operations int := 0;
+ src_mins int := 0;
+ dst_mins int := 0;
+ multiplier int := 0;
+ v text;
+ x int;
+BEGIN
+
+ multiplier := 60;
+ FOR v IN SELECT * FROM regexp_split_to_table( s, '[:]' ) LOOP
+ src_mins := src_mins + v::int * multiplier;
+ multiplier := 1;
+ END LOOP;
+
+ multiplier := 60;
+ FOR v IN SELECT * FROM regexp_split_to_table( t, '[:]' ) LOOP
+ dst_mins := dst_mins + v::int * multiplier;
+ multiplier := 1;
+ END LOOP;
+
+ FOREACH x IN ARRAY array[ 60, 15, 10, 5, 1 ]::int[] LOOP
+ WHILE dst_mins - src_mins >= x LOOP
+ src_mins := src_mins + x;
+ operations := operations + 1;
+ END LOOP;
+ END LOOP;
+
+ RETURN operations;
+
+
+END
+$CODE$
+LANGUAGE plpgsql;
diff --git a/challenge-348/luca-ferrari/python/ch-1.py b/challenge-348/luca-ferrari/python/ch-1.py
new file mode 100644
index 0000000000..d864fd413a
--- /dev/null
+++ b/challenge-348/luca-ferrari/python/ch-1.py
@@ -0,0 +1,36 @@
+#!python
+
+#
+# Perl Weekly Challenge 348
+# Task 1
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+#
+
+import sys
+
+# task implementation
+# the return value will be printed
+def task_1( args ):
+ lc = 0
+ rc = 0
+ middle = len( args[ 0 ] ) / 2
+ index = 0
+ vowels = [ 'a', 'e', 'i', 'o', 'u' ]
+
+ for c in args[ 0 ].lower() :
+ index += 1
+
+ if c in vowels :
+ if index <= middle :
+ lc += 1
+ else :
+ rc += 1
+
+ return lc == rc
+
+
+
+# invoke the main without the command itself
+if __name__ == '__main__':
+ print( task_1( sys.argv[ 1: ] ) )
diff --git a/challenge-348/luca-ferrari/python/ch-2.py b/challenge-348/luca-ferrari/python/ch-2.py
new file mode 100644
index 0000000000..1a5ffc63b0
--- /dev/null
+++ b/challenge-348/luca-ferrari/python/ch-2.py
@@ -0,0 +1,44 @@
+#!python
+
+#
+# Perl Weekly Challenge 348
+# Task 2
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+#
+
+import sys
+
+# task implementation
+# the return value will be printed
+def task_2( args ):
+ source = args[ 0 ]
+ target = args[ 1 ]
+ multi = [ 60, 1 ]
+ index = 0
+
+ src_mins = 0
+ dst_mins = 0
+
+
+ for p in source.split( ':' ) :
+ src_mins += int( p ) * multi[ index ]
+ index += 1
+
+ index = 0
+ for p in target.split( ':' ) :
+ dst_mins += int( p ) * multi[ index ]
+ index += 1
+
+ op_list = []
+ operations = [ 60, 15, 10, 5, 1 ]
+ for op in operations :
+ while dst_mins - src_mins >= op :
+ src_mins += op
+ op_list.append( op )
+
+ return len( op_list )
+
+# invoke the main without the command itself
+if __name__ == '__main__':
+ print( task_2( sys.argv[ 1: ] ) )
diff --git a/challenge-348/luca-ferrari/raku/ch-1.raku b/challenge-348/luca-ferrari/raku/ch-1.raku
new file mode 100644
index 0000000000..2d58a16bbb
--- /dev/null
+++ b/challenge-348/luca-ferrari/raku/ch-1.raku
@@ -0,0 +1,18 @@
+#!raku
+
+#
+# Perl Weekly Challenge 348
+# Task 1
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+#
+
+sub MAIN( Str $string ) {
+ # if the string has an even length, nothing to do
+ 'False'.say and exit( 1 ) if ( $string.chars !%% 2 );
+ 'False'.say and exit( 2 ) unless ( $string.comb[ 0 ..^ $string.chars / 2 ].fc.grep( * ~~ /<[aeiou]>/ ).elems ==
+ $string.comb[ $string.chars / 2 .. * ].fc.grep( * ~~ /<[aeiou]>/ ).elems );
+
+
+ 'True'.say;
+}
diff --git a/challenge-348/luca-ferrari/raku/ch-2.raku b/challenge-348/luca-ferrari/raku/ch-2.raku
new file mode 100644
index 0000000000..8959ef64ef
--- /dev/null
+++ b/challenge-348/luca-ferrari/raku/ch-2.raku
@@ -0,0 +1,33 @@
+#!raku
+
+#
+# Perl Weekly Challenge 348
+# Task 2
+#
+# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-348>
+#
+
+sub MAIN( Str $source, Str $target where { $source ~~ / ^ \d ** 2 <[:]> \d ** 2 $ / && $target ~~ / ^ \d ** 2 <[:]> \d ** 2 $ / } ) {
+ my %begin = hour => $source.split( ':' )[ 0 ],
+ mins => $source.split( ':' )[ 1 ];
+
+ my %end = hour => $target.split( ':' )[ 0 ],
+ mins => $target.split( ':' )[ 1 ];
+
+
+ %begin<mins> = %begin<mins> + %begin<hour> * 60;
+ %end<mins> = %end<mins> + %end<hour> * 60;
+
+ my @operations;
+
+ for ( 60, 15, 10, 5, 1 ) -> $current {
+ while ( %end<mins> - %begin<mins> >= $current ) {
+ %begin<mins> += $current;
+ @operations.push: $current;
+
+ }
+ }
+
+ @operations.elems.say;
+
+}