Range extraction: Difference between revisions

Content added Content deleted
(→‎{{header|Tailspin}}: update to stricter typing)
Line 5,156: Line 5,156:
{{out}}
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>

=={{header|SQL}}==
{{works with|ORACLE 19c}}
This is not a particularly efficient solution, but it gets the job done.

<lang SQL>
/*
This code is an implementation of "Range extraction" in SQL ORACLE 19c
p_list_of_sets -- input string
delimeter by default ","
p_format -- output format:
0 => [-2,-1] [0,2]
1 => -2--1,0-2
*/
with
function range_extraction(p_list_of_sets in varchar2, p_format integer default 0)
return varchar2 is
--
v_list_of_sets varchar2(32767) := p_list_of_sets;
v_output varchar2(32767) ;
v_set_1 varchar2(2000) ;
v_set_2 varchar2(2000) ;
v_set_2_gr pls_integer;
v_max pls_integer;
--
function sort_set(p_in_str varchar2)
return varchar2 is
v_out varchar2(32767) := p_in_str;
begin
--
with out_tab as
(select distinct to_number(regexp_substr(str, '[^,]+', 1, rownum, 'c', 0) default null on conversion error ) elem
from
(select p_in_str as str
from dual
)
connect by level <= regexp_count(str, '[^,]+')
)
select distinct listagg(elem, ',') within group(order by elem) end
into v_out
from out_tab;
--
return v_out;
end;
--
begin
--cleaning
v_list_of_sets := replace(v_list_of_sets, ' ', '') ;
v_list_of_sets := sort_set(v_list_of_sets) ;
--
<<loop_through_set>>
while regexp_count(v_list_of_sets, '[^,]+') > 0
loop
v_set_1 := regexp_substr(v_list_of_sets, '[^,]+', 1, 1) ;
v_list_of_sets := regexp_replace(v_list_of_sets,v_set_1,'',1,1);
--
<<loop_for>>
for i in 1..regexp_count(v_list_of_sets, '[^,]+')
loop
v_set_2_gr := nvl(v_set_2,v_set_1);
v_set_2 := regexp_substr(v_list_of_sets, '[^,]+', 1, 1) ;
--
if to_number(v_set_2) > to_number(v_set_1) + i then
v_output := v_output||' ['||v_set_1||case when v_set_1 != v_set_2_gr then ','||v_set_2_gr end||']';
continue loop_through_set;
end if;
--
v_list_of_sets := regexp_replace(v_list_of_sets,v_set_2,'',1,1);
--
end loop loop_for;
--
v_output := v_output||' ['||v_set_1||case when v_set_1 != v_set_2 then ','||v_set_2 end||']';
v_list_of_sets := regexp_replace(v_list_of_sets,v_set_1,'',1,1);
--
end loop loop_through_set;
--
--output format
v_output := nvl(v_output,'[]');
if p_format = 1 then
v_output := ltrim(trim(v_output), '[');
v_output := rtrim(v_output, ']');
v_output := replace(v_output, ',', '-');
v_output := replace(v_output, '] [', ',');
end if;
--
return trim(v_output);
end;

--Test
select '-- Test, Standart Format ' as output from dual
union all
select lpad(', ',125) || ' ==> ' || range_extraction(', ') as output from dual
union all
select lpad('0,-1,2,-2',125) || ' ==> ' || range_extraction('0,-1,2,-2') as output from dual
union all
select lpad('3,3,0,0,-2,-2',125) || ' ==> ' || range_extraction('3,3,0,0,-2,-2') as output from dual
union all
select lpad('+0,-X,swde, 2q, +4, 3,0 ,-0,-2 , -3',125) || ' ==> ' || range_extraction('+0,-X,swde, 2q, +4, 3,0 ,-0,-2 , -3') as output from dual
union all
select lpad('-1,-11,-12,-14,-15,-16,-17,-18,-19,-2,-20,-21,-22,-23,-24,-25,-0,-27,-28,-29,-30,-31,-32,-33,-35,-36,-37,-38,-39,-4,-6,-7,-8',125) || ' ==> ' || range_extraction('-1,-11,-12,-14,-15,-16,-17,-18,-19,-2,-20,-21,-22,-23,-24,-25,-0,-27,-28,-29,-30,-31,-32,-33,-35,-36,-37,-38,-39,-4,-6,-7,-8') as output from dual
union all
select lpad('1,11,12,14,15,16,17,18,19,2,20,21,22,23,24,25,0,27,28,29,30,31,32,33,35,36,37,38,39,4,6,7,8',125) || ' ==> ' || range_extraction('1,11,12,14,15,16,17,18,19,2,20,21,22,23,24,25,0,27,28,29,30,31,32,33,35,36,37,38,39,4,6,7,8') as output from dual
union all
--Test RosettaCode
select '-- Test RosettaCode, Standart Format ' as output from dual
union all
select lpad('-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20',125) || ' ==> ' || range_extraction('-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20') as output from dual
union all
select lpad('0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39',125) || ' ==> ' || range_extraction('0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39') as output from dual
union all
select '-- Test RosettaCode, RosettaCode Format' as output from dual
union all
select lpad('-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20',125) || ' ==> ' || range_extraction('-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20',1) as output from dual
union all
select lpad('0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39',125) || ' ==> ' || range_extraction('0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39',1) as output from dual
;
</lang>
/
{{out}}
<pre>
-- Test, Standart Format
, ==> []
0,-1,2,-2 ==> [-2,0] [2]
3,3,0,0,-2,-2 ==> [-2] [0] [3]
+0,-X,swde, 2q, +4, 3,0 ,-0,-2 , -3 ==> [-3,-2] [0] [3,4]
-1,-11,-12,-14,-15,-16,-17,-18,-19,-2,-20,-21,-22,-23,-24,-25,-0,-27,-28,-29,-30,-31,-32,-33,-35,-36,-37,-38,-39,-4,-6,-7,-8 ==> [-39,-35] [-33,-27] [-25,-14] [-12,-11] [-8,-6] [-4] [-2,0]
1,11,12,14,15,16,17,18,19,2,20,21,22,23,24,25,0,27,28,29,30,31,32,33,35,36,37,38,39,4,6,7,8 ==> [0,2] [4] [6,8] [11,12] [14,25] [27,33] [35,39]
-- Test RosettaCode, Standart Format
-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20 ==> [-6] [-3,1] [3,5] [7,11] [14,15] [17,20]
0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39 ==> [0,2] [4] [6,8] [11,12] [14,25] [27,33] [35,39]
-- Test RosettaCode, RosettaCode Format
-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20 ==> -6,-3-1,3-5,7-11,14-15,17-20
0,1,2,4,6,7,8,11,12,14,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39 ==> 0-2,4,6-8,11-12,14-25,27-33,35-39
</pre>
/


=={{header|Swift}}==
=={{header|Swift}}==