diff options
| author | Luca Ferrari <fluca1978@gmail.com> | 2024-03-04 09:39:17 +0100 |
|---|---|---|
| committer | Luca Ferrari <fluca1978@gmail.com> | 2024-03-04 14:19:40 +0100 |
| commit | 2b5457f572cf53ed6ff5b679de754feafa5b8eb6 (patch) | |
| tree | dee7a4007ed79c9bbbc87a1000d910eae4b80396 | |
| parent | ad381c1123e47114d3d98f1749f9f354eebafcdd (diff) | |
| download | perlweeklychallenge-club-2b5457f572cf53ed6ff5b679de754feafa5b8eb6.tar.gz perlweeklychallenge-club-2b5457f572cf53ed6ff5b679de754feafa5b8eb6.tar.bz2 perlweeklychallenge-club-2b5457f572cf53ed6ff5b679de754feafa5b8eb6.zip | |
PWC 259
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 Python done
Task 2 Python done
Task 1 PL/Java done
Task 2 PL/Java done
21 files changed, 530 insertions, 3 deletions
diff --git a/challenge-259/luca-ferrari/blog-1.txt b/challenge-259/luca-ferrari/blog-1.txt new file mode 100644 index 0000000000..f59eee9b34 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-1.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1 diff --git a/challenge-259/luca-ferrari/blog-10.txt b/challenge-259/luca-ferrari/blog-10.txt new file mode 100644 index 0000000000..3a8f05e0f8 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-10.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/[= date -%]/PerlWeeklyChallenge259.html#task2pljava diff --git a/challenge-259/luca-ferrari/blog-2.txt b/challenge-259/luca-ferrari/blog-2.txt new file mode 100644 index 0000000000..9fa1af6ea8 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-2.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2 diff --git a/challenge-259/luca-ferrari/blog-3.txt b/challenge-259/luca-ferrari/blog-3.txt new file mode 100644 index 0000000000..26ad2f3825 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-3.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1plperl diff --git a/challenge-259/luca-ferrari/blog-4.txt b/challenge-259/luca-ferrari/blog-4.txt new file mode 100644 index 0000000000..a1c1a8df1d --- /dev/null +++ b/challenge-259/luca-ferrari/blog-4.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2plperl diff --git a/challenge-259/luca-ferrari/blog-5.txt b/challenge-259/luca-ferrari/blog-5.txt new file mode 100644 index 0000000000..8f99d56a78 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-5.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1plpgsql diff --git a/challenge-259/luca-ferrari/blog-6.txt b/challenge-259/luca-ferrari/blog-6.txt new file mode 100644 index 0000000000..2956e4b204 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-6.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2plpgsql diff --git a/challenge-259/luca-ferrari/blog-7.txt b/challenge-259/luca-ferrari/blog-7.txt new file mode 100644 index 0000000000..ae78544493 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-7.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1python diff --git a/challenge-259/luca-ferrari/blog-8.txt b/challenge-259/luca-ferrari/blog-8.txt new file mode 100644 index 0000000000..0374c2d0a7 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-8.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task2python diff --git a/challenge-259/luca-ferrari/blog-9.txt b/challenge-259/luca-ferrari/blog-9.txt new file mode 100644 index 0000000000..7521039415 --- /dev/null +++ b/challenge-259/luca-ferrari/blog-9.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2024/03/04/PerlWeeklyChallenge259.html#task1pljava diff --git a/challenge-259/luca-ferrari/pljava/pom.xml b/challenge-259/luca-ferrari/pljava/pom.xml index 1a0d8dbf4d..30b7a337f3 100644 --- a/challenge-259/luca-ferrari/pljava/pom.xml +++ b/challenge-259/luca-ferrari/pljava/pom.xml @@ -5,11 +5,11 @@ <modelVersion>4.0.0</modelVersion> <groupId>PWC</groupId> - <artifactId>PWC258</artifactId> + <artifactId>PWC259</artifactId> <version>1</version> - <name>Perl Weekly Challenge 258</name> - <description>Implementation of the tasks in PL/Java for PWC 258</description> + <name>Perl Weekly Challenge 259</name> + <description>Implementation of the tasks in PL/Java for PWC 259</description> <properties> <project.build.sourceEncoding>US-ASCII</project.build.sourceEncoding> diff --git a/challenge-259/luca-ferrari/pljava/src/main/java/Task1.java b/challenge-259/luca-ferrari/pljava/src/main/java/Task1.java new file mode 100644 index 0000000000..de464e56c0 --- /dev/null +++ b/challenge-259/luca-ferrari/pljava/src/main/java/Task1.java @@ -0,0 +1,73 @@ + + + +package PWC259; + +/** + * PL/Java implementation for PWC 259 + * Task 1 + * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> + * + * + * 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/PWC259-1.jar luca@rachel:/tmp + + + * To install into PostgreSQL execute: + + select sqlj.install_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', true ); + + select pwc259.task2_pljava(); + + and then to redeploy: + + select sqlj.replace_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', 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 = "pwc259", + onNullInput = RETURNS_NULL, + effects = IMMUTABLE ) + public static final java.sql.Date task1_pljava( Date startDay, int how_many, Date[] holidays ) throws SQLException { + logger.log( Level.INFO, "Entering pwc259.task1_pljava" ); + + Calendar day = Calendar.getInstance(); + day.setTime( startDay ); + + while ( how_many > 0 ) { + day.add( Calendar.DAY_OF_YEAR, 1 ); + + while ( day.get( Calendar.DAY_OF_MONTH ) == Calendar.SUNDAY + || day.get( Calendar.DAY_OF_MONTH ) == Calendar.SATURDAY ) + day.add( Calendar.DAY_OF_YEAR, 1 ); + + if ( holidays != null ) + for ( Date skip : holidays ) + if ( skip.equals( day.getTime() ) ) + day.add( Calendar.DAY_OF_YEAR, 1 ); + + how_many--; + } + + return new java.sql.Date( day.getTimeInMillis() ); + } +} diff --git a/challenge-259/luca-ferrari/pljava/src/main/java/Task2.java b/challenge-259/luca-ferrari/pljava/src/main/java/Task2.java new file mode 100644 index 0000000000..1a33f13bea --- /dev/null +++ b/challenge-259/luca-ferrari/pljava/src/main/java/Task2.java @@ -0,0 +1,107 @@ + + + +package PWC259; + +/** + * PL/Java implementation for PWC 259 + * Task 2 + * See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> + * + * + * 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/PWC259-1.jar luca@rachel:/tmp + + + * To install into PostgreSQL execute: + + select sqlj.install_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', true ); + + select pwc259.task2_pljava(); + + and then to redeploy: + + select sqlj.replace_jar( 'file:///tmp/PWC259-1.jar', 'PWC259', 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.regex.*; +import java.util.stream.*; +import java.sql.SQLException; +import java.util.logging.*; +import java.sql.ResultSet; +import java.sql.Date; + +public class Task2 implements ResultSetProvider { + + private final static Logger logger = Logger.getAnonymousLogger(); + + @Function( schema = "pwc259", + onNullInput = RETURNS_NULL, + effects = IMMUTABLE ) + public static final ResultSetProvider task2_pljava( String line ) throws SQLException { + logger.log( Level.INFO, "Entering pwc259.task2_pljava : " + line ); + return new Task2( line ); + } + + + public Task2( String line ) throws SQLException { + params = new LinkedList< List<String> >(); + parse( line ); + } + + + private final void parse( String line ) throws SQLException { + Pattern pattern = Pattern.compile( "[{][%] (\\w+)\\s*(.*)\\s* [%][}]" ); + Matcher matcher = pattern.matcher( line ); + + if ( matcher.find() ) { + id = matcher.group( 1 ); + + Pattern subPattern = Pattern.compile( "(\\w+)[=](\\w+)\\s*" ); + Matcher subMatch = subPattern.matcher( matcher.group( 2 ) ); + + while ( subMatch.find() ) { + List<String> current = new LinkedList<String>(); + current.add( subMatch.group( 1 ) ); + current.add( subMatch.group( 2 ) ); + params.add( current ); + + } + } + else + throw new SQLException( "Cannot parse " + line ); + + } + + private List< List<String> > params; + private String id; + + @Override + public boolean assignRowValues(ResultSet rs, int row) + throws SQLException { + + // stop the result set + if ( row >= params.size() ) + return false; + + rs.updateInt( 1, row ); + rs.updateString( 2, id ); + rs.updateString( 3, params.get( row ).get( 0 ) ); + rs.updateString( 4, params.get( row ).get( 1 ) ); + return true; + } + + @Override + public void close() { + } +} diff --git a/challenge-259/luca-ferrari/plperl/ch-1.plperl b/challenge-259/luca-ferrari/plperl/ch-1.plperl new file mode 100644 index 0000000000..bd7a6e6a27 --- /dev/null +++ b/challenge-259/luca-ferrari/plperl/ch-1.plperl @@ -0,0 +1,41 @@ +-- +-- Perl Weekly Challenge 259 +-- Task 1 +-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +-- + +CREATE SCHEMA IF NOT EXISTS pwc259; + +CREATE OR REPLACE FUNCTION +pwc259.task1_plperl( date, int, date[] ) +RETURNS date +AS $CODE$ + +use DateTime; + + my ( $when, $offset, $holidays ) = @_; + + $when =~ / ^ (?<year>\d{4}) [-] (?<month>\d{2}) [-] (?<day>\d{2}) $ /x; + + my $day = DateTime->new( year => $+{ year}, month => $+{ month }, day => $+{ day } ); + + while ( $offset > 0 ) { + $day->add( days => 1 ); + $offset--; + + # skip weekends + while ( $day->day_of_week == 6 || $day->day_of_week == 7 ) { + $day->add( days => 1 ); + } + + if ( $holidays->@* ) { + while( grep { $_ eq $day->ymd } $holidays->@* ) { + $day->add( days => 1 ); + } + } + } + + return $day->ymd; + +$CODE$ +LANGUAGE plperlu; diff --git a/challenge-259/luca-ferrari/plperl/ch-2.plperl b/challenge-259/luca-ferrari/plperl/ch-2.plperl new file mode 100644 index 0000000000..b3500be853 --- /dev/null +++ b/challenge-259/luca-ferrari/plperl/ch-2.plperl @@ -0,0 +1,58 @@ +-- +-- Perl Weekly Challenge 259 +-- Task 2 +-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +-- + +CREATE SCHEMA IF NOT EXISTS pwc259; + +CREATE OR REPLACE FUNCTION +pwc259.task2_plperl( text) +RETURNS TABLE( id text, field_name text, field_value text ) +AS $CODE$ + + my ( $line ) = @_; + + if ( $line =~ / ^ [{] [%] \s* (?<id>\w+) \s* (?<options>.*) \s* [%] [}] $ /x ) { + my $id = $+{ id }; + my ( $name, $value ) = ( '', '' ); + if ( $+{ options } ) { + my $is_value = 0; + my $allowed_spaces = 0; + my $previous = ''; + + for ( split //, $+{ options } ) { + + + $is_value = 1 and $previous = $_ and next if ( $_ eq '=' ); + $allowed_spaces = 1 and $previous = $_ and next if ( $_ eq '"' and $previous eq '=' ); + + $name .= $_ if ( ! $is_value ); + $value .= $_ if ( $is_value ); + + if ( $is_value + && ( ( $_ eq ' ' && ! $allowed_spaces ) + || ( $_ eq '"' && $previous ne '\\' && $allowed_spaces ) ) + ) { + # stop here! + $value =~ s/^\s*|\s*$//g; + $value =~ s/^["]|["]$//g; + $value =~ s/\\"/"/g; + return_next( { id => $id , + field_name => $name, + field_value => $value } ); + + ( $name, $value, $is_value, $allowed_spaces ) = ( '', '', 0, 0 ); + } + + $previous = $_; + } + + + } + } + + return undef; + +$CODE$ +LANGUAGE plperl; diff --git a/challenge-259/luca-ferrari/plpgsql/ch-1.sql b/challenge-259/luca-ferrari/plpgsql/ch-1.sql new file mode 100644 index 0000000000..4b8f2eff5a --- /dev/null +++ b/challenge-259/luca-ferrari/plpgsql/ch-1.sql @@ -0,0 +1,36 @@ +-- +-- Perl Weekly Challenge 259 +-- Task 1 +-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +-- + +CREATE SCHEMA IF NOT EXISTS pwc259; + +CREATE OR REPLACE FUNCTION +pwc259.task1_plpgsql( day date, how_many_days int, holidays date[] ) +RETURNS date +AS $CODE$ +DECLARE + current_holiday date; +BEGIN + + WHILE how_many_days > 0 LOOP + day := day + 1; + + WHILE extract( dow from day ) IN ( 0, 6 ) LOOP + day := day + 1; + END LOOP; + + FOREACH current_holiday IN ARRAY holidays LOOP + IF current_holiday = day THEN + day := day + 1; + END IF; + END LOOP; + + how_many_days := how_many_days - 1; + END LOOP; + + RETURN day; +END +$CODE$ +LANGUAGE plpgsql; diff --git a/challenge-259/luca-ferrari/plpgsql/ch-2.sql b/challenge-259/luca-ferrari/plpgsql/ch-2.sql new file mode 100644 index 0000000000..15c2f30024 --- /dev/null +++ b/challenge-259/luca-ferrari/plpgsql/ch-2.sql @@ -0,0 +1,15 @@ +-- +-- Perl Weekly Challenge 259 +-- Task 2 +-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +-- + +CREATE SCHEMA IF NOT EXISTS pwc259; + +CREATE OR REPLACE FUNCTION +pwc259.task2_plpgsql( line text ) +RETURNS TABLE( id text, field_name text, field_value text ) +AS $CODE$ + SELECT pwc259.task2_plperl( line ); +$CODE$ +LANGUAGE sql; diff --git a/challenge-259/luca-ferrari/python/ch-1.py b/challenge-259/luca-ferrari/python/ch-1.py new file mode 100644 index 0000000000..9b3a0fd121 --- /dev/null +++ b/challenge-259/luca-ferrari/python/ch-1.py @@ -0,0 +1,37 @@ +#!python + +# +# Perl Weekly Challenge 259 +# Task 1 +# +# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +# + +import sys +from datetime import date, timedelta + +# task implementation +# the return value will be printed +def task_1( args ): + day = date.fromisoformat( args[ 0 ] ) + offset = int( args[ 1 ] ) + holidays = list( map( lambda x: date.fromisoformat( x ), args[ 2: ] ) ) + one_day = timedelta( days=1 ) + + while offset > 0 : + day += one_day + + while day.weekday() >= 6 or day.weekday() == 0: + day += one_day + + while day in holidays : + day += one_day + + offset -= 1 + + return day + + +# invoke the main without the command itself +if __name__ == '__main__': + print( task_1( sys.argv[ 1: ] ) ) diff --git a/challenge-259/luca-ferrari/python/ch-2.py b/challenge-259/luca-ferrari/python/ch-2.py new file mode 100644 index 0000000000..d8da389ecc --- /dev/null +++ b/challenge-259/luca-ferrari/python/ch-2.py @@ -0,0 +1,69 @@ +#!python + +# +# Perl Weekly Challenge 259 +# Task 2 +# +# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +# + +import sys + +# task implementation +# the return value will be printed +def task_2( args ): + line = args[ 0 ] + + parsed = {} + id = '' + key = '' + value = '' + is_value = False + is_key = False + + for c in line: + if c == '{' : + continue + elif c == '%': + continue + elif c == '}': + return parsed + elif c == ' ': + if not 'id' in parsed and len( id ) > 0 : + parsed[ 'id' ] = id + parsed[ 'fields' ] = [] + is_key = True + continue + elif 'fields' in parsed: + parsed[ 'fields' ].append( { key : value } ) + is_key = True + key = '' + value = '' + is_value = False + + elif c != '=' : + if not 'id' in parsed: + id += c + is_value = False + is_key = False + continue + else: + if is_key: + key += c + else: + value += c + + elif c == '=': + if is_key: + is_value = True + is_key = False + + + + + return parsed + + +# invoke the main without the command itself +if __name__ == '__main__': + print( task_2( sys.argv[ 1: ] ) ) diff --git a/challenge-259/luca-ferrari/raku/ch-1.raku b/challenge-259/luca-ferrari/raku/ch-1.raku new file mode 100644 index 0000000000..4835c0b013 --- /dev/null +++ b/challenge-259/luca-ferrari/raku/ch-1.raku @@ -0,0 +1,36 @@ +#!raku + +# +# Perl Weekly Challenge 259 +# Task 1 +# +# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +# + +sub MAIN( $date, + Int $offset is copy, + *@holidays + where { $date ~~ / ^ \d ** 4 <[-]>\d ** 2 <[-]> \d ** 2 $ / and $offset > 0 } ) { + + my $day = DateTime.new( $date, formatter => { sprintf "%04d-%02d-%02d", .year, .month, .day } ); + + + while ( $offset > 0 ) { + $day .= later( days => 1 ); + + # skip weekends + while ( $day.day-of-week == any( 7, 6 ) ) { + $day .= later( days => 1 ); + } + + while ( @holidays.elems > 0 && @holidays.grep( * ~~ $day.Str ) ) { + $day .= later( days => 1 ); + } + + + $offset--; + } + + $day.say; + +} diff --git a/challenge-259/luca-ferrari/raku/ch-2.raku b/challenge-259/luca-ferrari/raku/ch-2.raku new file mode 100644 index 0000000000..1005c9e48d --- /dev/null +++ b/challenge-259/luca-ferrari/raku/ch-2.raku @@ -0,0 +1,45 @@ +#!raku + +# +# Perl Weekly Challenge 259 +# Task 2 +# +# See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-259> +# + + +# {% id field1="value1" field2="value2" field3=42 %} + +# Where + +# a) "id" can be \w+. +# b) There can be 0 or more field-value pairs. +# c) The name of the fields are \w+. +# b) The values are either number in which case we don't need parentheses or string in +# which case we need parentheses around them. + + +sub MAIN() { + + my %parsed; + + my $line = '{% youtube video=foobar password=xyz abc=def donald="duck here \"escaped\" " %}'; + + my regex id { \w+ }; + my regex option { $<name>= [ \w+ ] \s* <[=]> $<value>= [ \w+ | \" \w+ \s* .* \" ] }; + my regex opening { <[{]> <[%]> }; + my regex closing { <[%]> <[}]> }; + + if ( $line ~~ / ^ <opening> \s+ <id> \s+ <option>* % \s \s* <closing> $ / ) { + + %parsed<name> = $/<id>; + + say $/<option>; + for $/<option> { + my ( $key, $value ) = .split( '=' ); + %parsed<fields>{ $key } = $value; + } + } + + say %parsed; +} |
