aboutsummaryrefslogtreecommitdiff
path: root/challenge-212/luca-ferrari/postgresql/ch-2.sql
blob: bfdcae3f6858af515285bf6dbf557fad37843f97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
--
-- Perl Weekly Challenge 212
-- Task 2
--
-- See <https://perlweeklychallenge.org/blog/perl-weekly-challenge-212/>
--

CREATE SCHEMA IF NOT EXISTS pwc212;

CREATE OR REPLACE FUNCTION
pwc212.task2_plpgsql( a int[], s int)
RETURNS SETOF int[]
AS $CODE$
DECLARE
	current int[];
	done    int := 0;
	next_value int;
BEGIN

	-- check if the array can be divided into batches
	IF mod( array_length( a, 1 ), s ) <> 0 THEN
	   RETURN;
	END IF;

	CREATE TEMPORARY TABLE IF NOT EXISTS bag( v int, c int default 1 );
	TRUNCATE TABLE bag;
	INSERT INTO bag
	SELECT v, count(*)
	FROM unnest( a ) v
	GROUP BY v;


	WHILE done < ( array_length( a, 1 ) / s ) LOOP
	      current = array[]::int[];

	      WHILE array_length( current, 1 ) IS NULL OR array_length( current, 1 ) < s LOOP
	      	    SELECT min( v )
		    INTO next_value
		    FROM   bag
		    WHERE  c > 0
		    AND   v NOT IN ( SELECT * FROM unnest( current ) );

		    UPDATE bag
		    SET c = c - 1
		    WHERE v = next_value;

		    current := array_append( current, next_value );
	      END LOOP;

	      done := done + 1;
	      RETURN NEXT current;
	END LOOP;

RETURN;
END
$CODE$
LANGUAGE plpgsql;