# Perl Weekly Challenge 260: Occurrencies and Permutations

This post presents my solutions to the Perl Weekly Challenge 260.I keep doing the Perl Weekly Challenge in order to mantain my coding skills in good shape, as well as in order to learn new things, with particular regard to Raku, a language that I love.

This week, I solved the following tasks:

- PWC 260 - Task 1 - Raku
- PWC 260 - Task 2 - Raku
- PWC 260 - Task 1 in PostgreSQL PL/Perl
- PWC 260 - Task 2 in PostgreSQL PL/Perl
- PWC 260 - Task 1 in PostgreSQL PL/PgSQL
- PWC 260 - Task 2 in PostgreSQL PL/PgSQL
- PWC 260 - Task 1 in PL/Java
- PWC 260 - Task 2 in PL/Java
- PWC 260 - Task 1 in Python
- PWC 260 - Task 2 in Python

# Raku Implementations

## PWC 260 - Task 1 - Raku Implementation

The first task was to find out if, in a given list of numbers, every number has an occurency count unique.```
sub MAIN( *@nums where { @nums.grep( * ~~ Int ).elems == @nums.elems } ) {
my $bag = Bag.new( @nums );
for $bag.values -> $current {
'0'.say and exit if ( $bag.values.grep( * ~~ $current ).elems > 1 );
}
'1'.say;
}
```

The idea is to store into a

`Bag`

the number with their occurrencies, and then to see how many times the values (i.e., the occurrencies) are repeated within the `$bag`

values.
## PWC 260 - Task 2 - Raku Implementation

This is one case where I find the second task simpler than the first one. Given a word, compute its*dictionary classification (rank)*that is computed as the index (numbered from one) in the list of all the sorted permutations of the letters of the word.

```
sub MAIN( $word ) {
say $word.comb.permutations.map( *.join ).sort.grep( * ~~ $word, :k ).first + 1;
}
```

I first split the

`$word`

into letters by means of `comb`

, then compute all the `permutations`

and remape every array of letters into a word, `sort`

the list of words and `grep`

the initial word into this list, extracting only the index. The `first + 1`

is the way I obtain only the value of the index and add one.
# PL/Perl Implementations

## PWC 260 - Task 1 - PL/Perl Implementation

I use a`$bag`

hash to store every number with the count of its occurrencies, but storing only once for every repretition of the number.
Then I iterate over the values of the hash, to see if there is more than one value repeated.
```
CREATE OR REPLACE FUNCTION
pwc260.task1_plperl( int[] )
RETURNS boolean
AS $CODE$
my ( $nums ) = @_;
my $bag = {};
for my $current ( $nums->@* ) {
next if $bag->{ current }; # no need to reinitialize
$bag->{ $current } = scalar grep { $current == $_ } $nums->@*;
}
for my $current ( values $bag->%* ) {
return 0 if ( scalar( grep { $current == $_ } values( $bag->%* ) ) > 1 );
}
return 1;
$CODE$
LANGUAGE plperl;
```

## PWC 260 - Task 2 - PL/Perl Implementation

I use`List::Permutor`

to obtain all the permutations of the array of letters, and then pushing the join result into a words list.
Last, I search into the list the position of the given word.
```
CREATE OR REPLACE FUNCTION
pwc260.task2_plperl( text )
RETURNS int
AS $CODE$
use List::Permutor;
my ( $word ) = @_;
my @words;
my $engine = List::Permutor->new( split //, $word );
while ( my @letters = $engine->next ) {
push @words, join( '', @letters );
}
@words = sort @words;
for my $index ( 0 .. @words - 1 ) {
return $index + 1 if ( $words[ $index ] eq $word );
}
return -1;
$CODE$
LANGUAGE plperlu;
```

# PostgreSQL Implementations

## PWC 260 - Task 1 - PL/PgSQL Implementation

A single query can do the trick.```
CREATE OR REPLACE FUNCTION
pwc260.task1_plpgsql( nums int[] )
RETURNS boolean
AS $CODE$
WITH numbers AS (
SELECT n
FROM unnest( nums ) n
)
, counting AS (
SELECT n, count(*) AS c
FROM numbers
GROUP BY n
)
, grouping AS (
SELECT c, count(*) AS g
FROM counting
GROUP BY c
)
SELECT NOT EXISTS( SELECT g
FROM grouping
WHERE g > 1
);
$CODE$
LANGUAGE sql;
```

The common table expression is built in incremental way:

`numbers`

provides a table with the given list of numbers;`counting`

counts how many times the same number appears in the list;`grouping`

counts how many times the counting appears.

*grouping*greater than one to know if there are occurrencies repetitions.

## PWC 260 - Task 2 - PL/PgSQL Implementation

I cheated here, using PL/Perl, since permutations in SQL are too time wasting in my opinion.```
CREATE OR REPLACE FUNCTION
pwc260.task2_plpgsql( w text )
RETURNS int
AS $CODE$
SELECT pwc260.task2_plperl( w );
$CODE$
LANGUAGE ùsql;
```

# Java Implementations

## PWC 260 - Task 1 - PostgreSQL PL/Java Implementation

There is more code to translate types than to do the real work!```
public class Task1 {
private final static Logger logger = Logger.getAnonymousLogger();
@Function( schema = "pwc260",
onNullInput = RETURNS_NULL,
effects = IMMUTABLE )
public static final boolean task1_pljava( int[] nums ) throws SQLException {
logger.log( Level.INFO, "Entering pwc260.task1_pljava" );
List<Integer> numList = new LinkedList<Integer>();
for ( int n : nums )
numList.add( n );
Map<Integer, List<Integer>> bag = new HashMap<Integer, List<Integer>>();
for ( int current : numList ) {
int occurrency = Collections.frequency( numList, current );
bag.putIfAbsent( occurrency, new LinkedList<Integer>() );
if ( ! bag.get( occurrency ).contains( current ) )
bag.get( occurrency ).add( current );
}
for ( int k : bag.keySet() )
if ( bag.get( k ).size() > 1 )
return false;
return true;
}
}
```

The idea is the same as in PL/Perl:

`bag`

is used to classify the numbers (uniquely) with their occurrencies, that is computed by means of `Collections.frequency()`

. For every `occurrency`

I place into the `bag`

the list of numbers that have such frequency. Then, I search if there’s a list in the `bag`

that has more than one element, and if found, I return a `false`

value.
## PWC 260 - Task 2 - PostgreSQL PL/Java Implementation

Doing permutations in Java is such a mess!```
public class Task2 {
private final static Logger logger = Logger.getAnonymousLogger();
@Function( schema = "pwc260",
onNullInput = RETURNS_NULL,
effects = IMMUTABLE )
public static final int task2_pljava( String word ) throws SQLException {
logger.log( Level.INFO, "Entering pwc260.task2_pljava" );
List<String> chars = new LinkedList<String>();
for ( String s : word.split( "" ) ) {
logger.log( Level.INFO, "CHAR " + s );
chars.add( s );
}
List<String> words = new LinkedList<String>();
BigInteger limit = BigInteger.ONE;
for ( int i = 1; i <= chars.size(); i++ ) {
limit = limit.multiply( new BigInteger( "" + i ) );
}
while ( BigInteger.ZERO.compareTo( limit ) < 0 ) {
String newWord = "";
do {
Collections.shuffle( chars );
newWord = String.join( "", chars );
} while ( words.contains( newWord ) );
words.add( newWord );
limit = limit.subtract( BigInteger.ONE );
}
Collections.sort( words );
for ( int i = 0; i < words.size(); i++ )
if ( words.get( i ).equals( word ) )
return i + 1;
return -1;
}
}
```

I first split the

`word`

into a list of characters, named `chars`

. Then I compute the `limit`

in terms of possible permutations, and I use a `BigInteger`

because a factorial number could quickly become very large.
The next step is to `shuffle`

the list of characters, so that they are randomly arranged. **This is not the same as computing all the possible permutations**since

`shuffle()`

could return the same value over and over, so I need to add the shuffled word to the list of words only if not already placed, and only then decrease the `limit`

value.
Last is the same as in other implementations: sorting the list and searching for an entry that matches the inital word.
# Python Implementations

## PWC 260 - Task 1 - Python Implementation

Use the same bag approach used in Raku.```
import sys
# task implementation
# the return value will be printed
def task_1( args ):
nums = list( map( int, args ) )
bag = {}
for n in nums:
occurrencies = len( list( filter( lambda x: x == n, nums ) ) )
if not n in bag:
bag[ n ] = occurrencies
for o in bag.values():
if len( list( filter( lambda x: x == o, bag.values() ) ) ) > 1:
return 0
return 1
# invoke the main without the command itself
if __name__ == '__main__':
print( task_1( sys.argv[ 1: ] ) )
```

## PWC 260 - Task 2 - Python Implementation

Luckily, Python has a way to create permutations!```
import sys
import array
from itertools import permutations
# task implementation
# the return value will be printed
def task_2( args ):
word = args[ 0 ]
words = []
engine = permutations( list( word ) )
for p in list( engine ):
words.append( ''.join( p ) )
words = sorted( words )
for i in range( 0, len( words ) ):
if words[ i ] == word:
return i + 1
# invoke the main without the command itself
if __name__ == '__main__':
print( task_2( sys.argv[ 1: ] ) )
```

The idea is to create the permutations of characters of the original word, re-joining them and adding to a

`words`

list. Then, as for other implementations, sort and search for the position of the initial word.