Range consolidation: Difference between revisions

(Add source for Rust)
 
(30 intermediate revisions by 17 users not shown)
Line 1:
{{task}}
 
Define a range of numbers <code>&nbsp; '''R</code>''', &nbsp; with bounds <code>&nbsp; '''b0</code>''' &nbsp; and <code>&nbsp; '''b1</code>''' &nbsp; covering all numbers ''between and including both bounds''. That range can be shown as:<br>
 
: <code>[b0, b1]</code><br>
 
or equally as:<br>
That range can be shown as:
: <code>[b1, b0]</code>.
::::::::: '''[b0, b1]'''
:::::::: &nbsp;&nbsp; or equally as:
::::::::: '''[b1, b0]'''
 
 
Given two ranges, the act of consolidation between them compares the two ranges:
* &nbsp; If one range covers all of the other then the result is that encompassing range.
* &nbsp; If the ranges touch or intersect then the result is &nbsp; ''one'' &nbsp; new single range covering the overlapping ranges.
* &nbsp; Otherwise the act of consolidation is to return the two non-touching ranges.
 
Given N ranges where N>2 then the result is the same as repeatedly replacing all combinations of two ranges by their consolidation until no further consolidation between range pairs is possible. If N<2 then range consolidation has no strict meaning and the input can be returned.
 
Given &nbsp; '''N''' &nbsp; ranges where &nbsp; '''N > 2''' &nbsp; then the result is the same as repeatedly replacing all combinations of two ranges by their consolidation until no further consolidation between range pairs is possible.
;'''Example 1:'''
:Given the two ranges <tt>[1, 2.5]</tt> and <tt>[3, 4.2]</tt> then there is no
:common region between the ranges and the result is the same as the input.
;'''Example 2:'''
:Given the two ranges <tt>[1, 2.5]</tt> and <tt>[1.8, 4.7]</tt> then there is
:an overlap <tt>[2.5, 1.8]</tt> between the ranges and the result is the single
:range <tt>[1, 4.7]</tt>. Note that order of bounds in a range is not, (yet), stated.
;'''Example 3:'''
:Given the two ranges <tt>[6.1, 7.2]</tt> and <tt>[7.2, 8.3]</tt> then they
:touch at <tt>7.2</tt> and the result is the single range <tt>[6.1, 8.3]</tt>.
;'''Example 4:'''
:Given the three ranges <tt>[1, 2]</tt> and <tt>[4, 8]</tt> and <tt>[2, 5]</tt>
:then there is no intersection of the ranges <tt>[1, 2]</tt> and <tt>[4, 8]</tt>
:but the ranges <tt>[1, 2]</tt> and <tt>[2, 5]</tt> overlap and consolidate to
:produce the range <tt>[1, 5]</tt>. This range, in turn, overlaps the other range
:<tt>[4, 8]</tt>, and so consolidates to the final output of the single range
:<tt>[1, 8]</tt>
 
If &nbsp; '''N < 2''' &nbsp; then range consolidation has no strict meaning and the input can be returned.
;'''Task:'''
Let a normalized range display show the smaller bound to the left; and show the
range with the smaller lower bound to the left of other ranges when showing multiple
ranges.
 
 
Output the ''normalised'' result of applying consolidation to these five sets of ranges:
;Example 1:
<pre>
: &nbsp; Given the two ranges &nbsp; '''[1, 2.5]''' &nbsp; and &nbsp; '''[3, 4.2]''' &nbsp; then
[1.1, 2.2]
: &nbsp; there is no common region between the ranges and the result is the same as the input.
[6.1, 7.2], [7.2, 8.3]
 
[4, 3], [2, 1]
 
[4, 3], [2, 1], [-1, -2], [3.9, 10]
;Example 2:
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]
: &nbsp; Given the two ranges &nbsp; '''[1, 2.5]''' &nbsp; and &nbsp; '''[1.8, 4.7]''' &nbsp; then
</pre>
: &nbsp; there is : &nbsp; an overlap &nbsp; '''[2.5, 1.8]''' &nbsp; between the ranges and
Show output here.
: &nbsp; the result is the single range &nbsp; '''[1, 4.7]'''.
<br>
: &nbsp; Note that order of bounds in a range is not (yet) stated.
<br>
 
'''See also'''
 
;Example 3:
: &nbsp; Given the two ranges &nbsp; '''[6.1, 7.2]''' &nbsp; and &nbsp; '''[7.2, 8.3]''' &nbsp; then
: &nbsp; they touch at &nbsp; '''7.2''' &nbsp; and
: &nbsp; the result is the single range &nbsp; '''[6.1, 8.3]'''.
 
 
;Example 4:
: &nbsp; Given the three ranges &nbsp; '''[1, 2]''' &nbsp; and &nbsp; '''[4, 8]''' &nbsp; and &nbsp; '''[2, 5]'''
: &nbsp; then there is no intersection of the ranges &nbsp; '''[1, 2]''' &nbsp; and &nbsp; '''[4, 8]'''
: &nbsp; but the ranges &nbsp; '''[1, 2]''' &nbsp; and &nbsp; '''[2, 5]''' &nbsp; overlap and
: &nbsp; consolidate to produce the range &nbsp; '''[1, 5]'''.
: &nbsp; This range, in turn, overlaps the other range &nbsp; '''[4, 8]''', &nbsp; and
: &nbsp; so consolidates to the final output of the single range &nbsp; '''[1, 8]'''.
 
 
;Task:
Let a normalized range display show the smaller bound to the left; &nbsp; and show the
range with the smaller lower bound to the left of other ranges when showing multiple ranges.
 
Output the ''normalized'' result of applying consolidation to these five sets of ranges: <big>
[1.1, 2.2]
[6.1, 7.2], [7.2, 8.3]
[4, 3], [2, 1]
[4, 3], [2, 1], [-1, -2], [3.9, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] </big>
Show all output here.
 
 
;See also:
* [[Set consolidation]]
* [[Set of real numbers]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F consolidate(ranges)
F normalize(s)
R sorted(s.filter(bounds -> !bounds.empty).map(bounds -> sorted(bounds)))
 
V norm = normalize(ranges)
L(&r1) norm
V i = L.index
I !r1.empty
L(j) i + 1 .< norm.len
V& r2 = norm[j]
I !r2.empty & r1.last >= r2[0]
r1 = [r1[0], max(r1.last, r2.last)]
r2.clear()
R norm.filter(rnge -> !rnge.empty)
 
L(s) [[[1.1, 2.2]],
[[6.1, 7.2], [7.2, 8.3]],
[[4.0, 3.0], [2.0, 1.0]],
[[4.0, 3.0], [2.0, 1.0], [-1.0, -2.0], [3.9, 10.0]],
[[1.0, 3.0], [-6.0, -1.0], [-4.0, -5.0], [8.0, 2.0], [-6.0, -6.0]]]
print(String(s)[1 .< (len)-1]‘ => ’String(consolidate(s))[1 .< (len)-1])</syntaxhighlight>
 
{{out}}
<pre>
[1.1, 2.2] => [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] => [6.1, 8.3]
[4, 3], [2, 1] => [1, 2], [3, 4]
[4, 3], [2, 1], [-1, -2], [3.9, 10] => [-2, -1], [1, 2], [3, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] => [-6, -1], [1, 8]
</pre>
 
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
{{libheader|Action! Real Math}}
<syntaxhighlight lang="action!">INCLUDE "H6:REALMATH.ACT"
 
DEFINE PTR="CARD"
DEFINE RANGESIZE="12"
DEFINE LOW_="+0"
DEFINE HIGH_="+6"
TYPE Range=[CARD l1,l2,l3,h1,h2,h3]
 
PROC Inverse(Range POINTER r)
REAL tmp
 
RealAssign(r LOW_,tmp)
RealAssign(r HIGH_,r LOW_)
RealAssign(tmp,r HIGH_)
RETURN
 
PROC Normalize(Range POINTER r)
IF RealLess(r HIGH_,r LOW_) THEN
Inverse(r)
FI
RETURN
 
INT FUNC Compare(Range Pointer r1,r2)
IF RealLess(r1 LOW_,r2 LOW_) THEN
RETURN (-1)
ELSEIF RealLess(r2 LOW_,r1 LOW_) THEN
RETURN (1)
ELSEIF RealLess(r1 HIGH_,r2 HIGH_) THEN
RETURN (-1)
ELSEIF RealLess(r2 HIGH_,r1 HIGH_) THEN
RETURN (1)
FI
RETURN (0)
 
PTR FUNC GetItemAddr(PTR data INT index)
RETURN (data+index*RANGESIZE)
 
PROC Swap(Range POINTER r1,r2)
REAL tmp
 
RealAssign(r1 LOW_,tmp)
RealAssign(r2 LOW_,r1 LOW_)
RealAssign(tmp, r2 LOW_)
RealAssign(r1 HIGH_,tmp)
RealAssign(r2 HIGH_,r1 HIGH_)
RealAssign(tmp, r2 HIGH_)
RETURN
 
PROC Sort(PTR data INT count)
INT i,j,minpos
Range POINTER r1,r2
 
FOR i=0 TO count-2
DO
minpos=i
FOR j=i+1 TO count-1
DO
r1=GetItemAddr(data,minpos)
r2=GetItemAddr(data,j)
IF Compare(r1,r2)>0 THEN
minpos=j
FI
OD
IF minpos#i THEN
r1=GetItemAddr(data,minpos)
r2=GetItemAddr(data,i)
Swap(r1,r2)
FI
OD
RETURN
 
PROC Consolidate(PTR data INT POINTER count)
INT i,j,newCount
Range POINTER r1,r2
 
FOR i=0 TO count^-1
DO
r1=GetItemAddr(data,i)
Normalize(r1)
OD
Sort(data,count^)
 
newCount=0 i=0
WHILE i<count^
DO
j=i+1
WHILE j<count^
DO
r1=GetItemAddr(data,i)
r2=GetItemAddr(data,j)
IF RealLess(r1 HIGH_,r2 LOW_) THEN
EXIT
ELSEIF RealLess(r1 HIGH_,r2 HIGH_) THEN
RealAssign(r2 HIGH_,r1 HIGH_)
FI
j==+1
OD
r1=GetItemAddr(data,i)
r2=GetItemAddr(data,newCount)
RealAssign(r1 LOW_,r2 LOW_)
RealAssign(r1 HIGH_,r2 HIGH_)
newCount==+1
i=j
OD
count^=newCount
RETURN
 
PROC PrintRanges(PTR data INT count)
INT i
Range POINTER r
 
FOR i=0 TO count-1
DO
IF i>0 THEN Put(' ) FI
r=GetItemAddr(data,i)
Put('[) PrintR(r LOW_)
Put(',) PrintR(r HIGH_) Put('])
OD
RETURN
 
PROC Append(PTR data INT POINTER count
CHAR ARRAY sLow,sHigh)
Range POINTER r
 
r=GetItemAddr(data,count^)
ValR(sLow,r LOW_)
ValR(sHigh,r High_)
count^=count^+1
RETURN
 
INT FUNC InitData(BYTE case PTR data)
INT count
 
count=0
IF case=0 THEN
Append(data,@count,"1.1","2.2")
ELSEIF case=1 THEN
Append(data,@count,"6.1","7.2")
Append(data,@count,"7.2","8.3")
ELSEIF case=2 THEN
Append(data,@count,"4","3")
Append(data,@count,"2","1")
ELSEIF case=3 THEN
Append(data,@count,"4","3")
Append(data,@count,"2","1")
Append(data,@count,"-1","-2")
Append(data,@count,"3.9","10")
ELSEIF case=4 THEN
Append(data,@count,"1","3")
Append(data,@count,"-6","-1")
Append(data,@count,"-4","-5")
Append(data,@count,"8","2")
Append(data,@count,"-6","-6")
FI
RETURN (count)
 
PROC Main()
BYTE ARRAY data(100)
INT count
BYTE i
 
Put(125) PutE() ;clear the screen
FOR i=0 TO 4
DO
count=InitData(i,data)
PrintRanges(data,count)
Print(" -> ")
Consolidate(data,@count)
PrintRanges(data,count)
PutE() PutE()
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Range_consolidation.png Screenshot from Atari 8-bit computer]
<pre>
[1.1,2.2] -> [1.1,2.2]
 
[6.1,7.2] [7.2,8.3] -> [6.1,8.3]
 
[4,3] [2,1] -> [1,2] [3,4]
 
[4,3] [2,1] [-1,-2] [3.9,10] -> [-2,-1] [1,2] [3,10]
 
[1,3] [-6,-1] [-4,-5] [8,2] [-6,-6] -> [-6,-1] [1,8]
</pre>
 
=={{header|Ada}}==
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
with Ada.Containers.Vectors;
 
Line 139 ⟶ 377:
Show (Set_4);
Show (Set_5);
end Range_Consolidation;</langsyntaxhighlight>
 
{{out}}
Line 149 ⟶ 387:
( 1.0 3.0) ( -6.0 -1.0) ( -4.0 -5.0) ( 8.0 2.0) ( -6.0 -6.0) ( -6.0 -1.0) ( 1.0 8.0)
</pre>
 
=={{header|ALGOL 68}}==
<syntaxhighlight lang="algol68">
BEGIN # range consolidation #
 
MODE RANGE = STRUCT( REAL lb, ub );
 
# returns a with the bounds swapped if necessary, so lb OF a <= ub OF a #
OP NORMALISE = ( RANGE a )RANGE:
( IF lb OF a < ub OF a THEN lb OF a ELSE ub OF a FI
, IF ub OF a > lb OF a THEN ub OF a ELSE lb OF a FI
) # NORMALISE # ;
# returns a with each element normalised #
OP NORMALISE = ( []RANGE a )[]RANGE:
BEGIN
[ LWB a : UPB a ]RANGE result;
FOR a pos FROM LWB a TO UPB a DO result[ a pos ] := NORMALISE a[ a pos ] OD;
result
END # NORMALISE # ;
OP < = ( RANGE a, b )BOOL: lb OF a < lb OF b;
OP > = ( RANGE a, b )BOOL: lb OF a > lb OF b;
 
# sorts a into order of each element's lb #
OP SORT = ( []RANGE a )[]RANGE:
BEGIN
# in-place quick sort an array of RANGEs from element lb #
# to element ub #
PROC quicksort = ( REF[]RANGE a, INT lb, ub )REF[]RANGE:
IF ub <= lb
THEN
# empty array or only 1 element #
a
ELSE
# more than one element, so must sort #
INT left := lb;
INT right := ub;
# choosing the middle element of the array as the pivot #
RANGE pivot := a[ left + ( ( right + 1 ) - left ) OVER 2 ];
WHILE
WHILE IF left <= ub THEN a[ left ] < pivot ELSE FALSE FI DO left +:= 1 OD;
WHILE IF right >= lb THEN a[ right ] > pivot ELSE FALSE FI DO right -:= 1 OD;
left <= right
DO
RANGE t := a[ left ];
a[ left ] := a[ right ];
a[ right ] := t;
left +:= 1;
right -:= 1
OD;
quicksort( a, lb, right );
quicksort( a, left, ub );
a
FI # quicksort # ;
quicksort( HEAP[ LWB a : UPB a ]RANGE := a, LWB a, UPB a )
END # SORT # ;
 
# returns the consolidation of the ranges in a in #
OP CONSOLIDATE = ( []RANGE a in )[]RANGE:
IF UPB a in <= LWB a in
THEN a in # 0 or 1 range #
ELSE # multiple ranges #
[]RANGE a = SORT NORMALISE a in;
[ 1 : 2 * ( ( UPB a - LWB a ) + 1 ) ]RANGE result;
INT r max := 1;
result[ r max ] := a[ LWB a ];
FOR a pos FROM LWB a + 1 TO UPB a DO
RANGE m = result[ r max ], n = a[ a pos ];
IF ub OF m < lb OF n THEN
result[ r max +:= 1 ] := n # distinct ranges #
ELSE
result[ r max ] # overlapping ranges #
:= ( IF lb OF m < lb OF n THEN lb OF m ELSE lb OF n FI
, IF ub OF m > ub OF n THEN ub OF m ELSE ub OF n FI
)
FI
OD;
result[ : r max ]
FI # CONSOLIDATE # ;
 
OP FMT = ( REAL v )STRING: # prints v with at most 3 decimal places #
BEGIN
STRING result := fixed( ABS v, 0, 3 );
IF result[ LWB result ] = "." THEN "0" +=: result FI;
WHILE result[ UPB result ] = "0" DO result := result[ : UPB result - 1 ] OD;
IF result[ UPB result ] = "." THEN result := result[ : UPB result - 1 ] FI;
IF v < 0 THEN "-" ELSE "" FI + result
END # FMT # ;
 
OP TOSTRING = ( RANGE a )STRING: "[ " + FMT lb OF a + ", " + FMT ub OF a + " ]";
OP TOSTRING = ( []RANGE a )STRING:
BEGIN
STRING result := "[";
STRING prefix := " ";
FOR r pos FROM LWB a TO UPB a DO
result +:= prefix + TOSTRING a[ r pos ];
prefix := ", "
OD;
result + " ]"
END # TOSTRING # ;
PRIO PAD = 8; # right pads s with blanks to w characters #
OP PAD = ( STRING s, INT w )STRING:
IF INT len = ( UPB s - LWB s ) + 1;
len >= w
THEN s
ELSE s + ( ( w - len ) * " " )
FI # PAD # ;
 
# task test cases #
 
PROC test = ( []RANGE a )VOID:
BEGIN print( ( ( TOSTRING a PAD 60 ), " -> ", TOSTRING CONSOLIDATE a, newline ) ) END;
test( []RANGE( RANGE( 1.1, 2.2 ) ) );
test( ( ( 6.1, 7.2 ), ( 7.2, 8.3 ) ) );
test( ( ( 4, 3 ), ( 2, 1 ) ) );
test( ( ( 4, 3 ), ( 2, 1 ), ( -1, -2 ), ( 3.9, 10 ) ) );
test( ( ( 1, 3 ), ( -6, -1 ), ( -4, -5 ), ( 8, 2 ), ( -6, -6 ) ) )
 
END
</syntaxhighlight>
{{out}}
<pre>
[ [ 1.1, 2.2 ] ] -> [ [ 1.1, 2.2 ] ]
[ [ 6.1, 7.2 ], [ 7.2, 8.3 ] ] -> [ [ 6.1, 8.3 ] ]
[ [ 4, 3 ], [ 2, 1 ] ] -> [ [ 1, 2 ], [ 3, 4 ] ]
[ [ 4, 3 ], [ 2, 1 ], [ -1, -2 ], [ 3.9, 10 ] ] -> [ [ -2, -1 ], [ 1, 2 ], [ 3, 10 ] ]
[ [ 1, 3 ], [ -6, -1 ], [ -4, -5 ], [ 8, 2 ], [ -6, -6 ] ] -> [ [ -6, -1 ], [ 1, 8 ] ]
</pre>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">RangeConsolidation(arr){
arr1 := [], arr2 := [], result := []
for i, obj in arr
arr1[i,1] := min(arr[i]*), arr1[i,2] := max(arr[i]*) ; sort each range individually
for i, obj in arr1
if (obj.2 > arr2[obj.1])
arr2[obj.1] := obj.2 ; creates helper array sorted by range
i := 1
for start, stop in arr2
if (i = 1) || (start > result[i-1, 2]) ; first or non overlapping range
result[i, 1] := start, result[i, 2] := stop, i++
else ; overlapping range
result[i-1, 2] := stop > result[i-1, 2] ? stop : result[i-1, 2]
return result
}</syntaxhighlight>
Examples:<syntaxhighlight lang="autohotkey">test1 := [[1.1, 2.2]]
test2 := [[6.1, 7.2], [7.2, 8.3]]
test3 := [[4, 3], [2, 1]]
test4 := [[4, 3], [2, 1], [-1, -2], [3.9, 10]]
test5 := [[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]]
 
result := ""
loop, 5
{
output := ""
for i, obj in RangeConsolidation(test%A_Index%)
output .= "[" format("{:g}", obj.1) ", " format("{:g}", obj.2) "], "
result .= Trim(output, ", ") "`n"
}
MsgBox % result
return</syntaxhighlight>
{{out}}
<pre>[1.1, 2.2]
[6.1, 8.3]
[1, 2], [3, 4]
[-2, -1], [1, 2], [3, 10]
[-6, -1], [1, 8]</pre>
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 240 ⟶ 647:
test_consolidate_ranges(test5, LENGTHOF(test5));
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 253 ⟶ 660:
=={{header|C sharp}}==
{{works with|C sharp|7}}
<langsyntaxhighlight lang="csharp">using static System.Math;
using System.Linq;
using System;
Line 291 ⟶ 698:
private static (double s, double e) Normalize((double s, double e) range) =>
(Min(range.s, range.e), Max(range.s, range.e));
}</langsyntaxhighlight>
{{out}}
<pre>
Line 301 ⟶ 708:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <iostream>
#include <utility>
Line 370 ⟶ 777:
}
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 383 ⟶ 790:
 
=={{header|Clojure}}==
<langsyntaxhighlight Clojurelang="clojure">(defn normalize [r]
(let [[n1 n2] r]
[(min n1 n2) (max n1 n2)]))
Line 408 ⟶ 815:
(remove #(contains? (set used) %) rs))]
(recur (conj res (consolidate-touching-ranges touching))
(remove-used (rest rs) touching))))))</langsyntaxhighlight>
 
{{out}}
Line 430 ⟶ 837:
{{trans|C#}}
 
<langsyntaxhighlight lang="dyalect">functype maxPt(xs, ye) {with Lookup
if x > y {
x
} else {
y
}
}
func Pt.Min() => min(xthis.s, ythis.e) {
func Pt.Max() => max(this.s, this.e)
if x < y {
func Pt.ToString() => "(\(this.s), \(this.e))"
x
} else {
y
}
}
let rng = [
func overlap(left, right) {
if[ maxPt(left:s1.1, left:e2.2) > max(right:s], right:e) {
[ maxPt(right:s6.1, right:e7.2), >= minPt(left:s7.2, left:e8.3) ],
[ Pt(4.0, 3.0), Pt(2, 1) ],
} else {
[ Pt(4.0, 3.0), Pt(2, 1), maxPt(left:s-1, left:e2), >= minPt(right:s3.9, right:e10) ],
[ Pt(1.0, 3.0), Pt(-6, -1), Pt(-4, -5), Pt(8, 2), Pt(-6, -6) ]
}
]
}
func consolidateoverlap(left, right) {=>
left.Max(s) => minright.Max(min(left:s, left:e), min(right:s,? right:e.Max()), e >= max(max(left:s, left:e), max.Min(right:s, right:e)))
: left.Max() >= right.Min()
}
func consolidate(left, right) => Pt(min(left.Min(), right.Min()), max(left.Max(), right.Max()))
func normalize(range) {
(s = min(range:s, range:e), e = max(range:s, range:e))
func normalize(range) => Pt(range.Min(), range.Max())
}
for list in rng {
var z = list.Length() - 1
for list in [
[ (s = 1.1, e = 2.2) ],
[ (s = 6.1, e = 7.2), (s = 7.2, e = 8.3) ],
[ (s = 4.0, e = 3.0), (s = 2, e = 1) ],
[ (s = 4.0, e = 3.0), (s = 2, e = 1), (s = -1, e = 2), (s = 3.9, e = 10) ],
[ (s = 1.0, e = 3.0), (s = -6, e = -1), (s = -4, e = -5), (s = 8, e = 2), (s = -6, e = -6) ]
] {
var z = list.len()-1
while z >= 1 {
for y in (z - 1)^-1..0 when overlap(list[z], list[y]) {
iflist[y] = overlapconsolidate(list[z], list[y]) {
break list[y] = consolidate.RemoveAt(list[z], list[y])
list.removeAt(z)
break
}
}
z -= 1
}
for i in list.indices() {
for i in list.Indices() {
list[i] = normalize(list[i])
}
list.sort((x,y) => x:s - y:s)
list.Sort((x,y) => x.s - y.s)
print(list)
}</langsyntaxhighlight>
 
{{out}}
 
<pre>[(s: 1.1, e: 2.2)]
[(s: 6.1, e: 8.3)]
[(s: 1, e: 2), (s: 3, e: 4)]
[(s: -1, e: 2), (s: 3, e: 10)]
[(s: -6, e: -1), (s: 1, e: 8)]</pre>
 
=={{header|Factor}}==
{{works with|Factor|0.99 2021-06-02}}
<syntaxhighlight lang="factor">USING: arrays combinators formatting kernel math.combinatorics
math.order math.statistics sequences sets sorting ;
 
: overlaps? ( pair pair -- ? )
2dup swap [ [ first2 between? ] curry any? ] 2bi@ or ;
 
: merge ( seq -- newseq ) concat minmax 2array 1array ;
 
: merge1 ( seq -- newseq )
dup 2 [ first2 overlaps? ] find-combination
[ [ without ] keep merge append ] when* ;
 
: normalize ( seq -- newseq ) [ natural-sort ] map ;
 
: consolidate ( seq -- newseq )
normalize [ merge1 ] to-fixed-point natural-sort ;
 
{
{ { 1.1 2.2 } }
{ { 6.1 7.2 } { 7.2 8.3 } }
{ { 4 3 } { 2 1 } }
{ { 4 3 } { 2 1 } { -1 -2 } { 3.9 10 } }
{ { 1 3 } { -6 -1 } { -4 -5 } { 8 2 } { -6 -6 } }
} [ dup consolidate "%49u => %u\n" printf ] each</syntaxhighlight>
{{out}}
<pre>
{ { 1.1 2.2 } } => { { 1.1 2.2 } }
{ { 6.1 7.2 } { 7.2 8.300000000000001 } } => { { 6.1 8.300000000000001 } }
{ { 4 3 } { 2 1 } } => { { 1 2 } { 3 4 } }
{ { 4 3 } { 2 1 } { -1 -2 } { 3.9 10 } } => { { -2 -1 } { 1 2 } { 3 10 } }
{ { 1 3 } { -6 -1 } { -4 -5 } { 8 2 } { -6 -6 } } => { { -6 -1 } { 1 8 } }
</pre>
 
=={{header|FreeBASIC}}==
{{trans|Yabasic}}
<syntaxhighlight lang="freebasic">
Dim Shared As Integer i
Dim Shared As Single items, temp = 10^30
 
Sub ordenar(tabla() As Single)
Dim As Integer t1, t2
Dim As Boolean s
Do
s = True
For i = 1 To Ubound(tabla)-1
If tabla(i, 1) > tabla(i+1, 1) Then
t1 = tabla(i, 1) : t2 = tabla(i, 2)
tabla(i, 1) = tabla(i + 1, 1) : tabla(i, 2) = tabla(i + 1, 2)
tabla(i + 1, 1) = t1 : tabla(i + 1, 2) = t2
s = False
End If
Next i
Loop Until(s)
End Sub
 
Sub normalizar(tabla() As Single)
Dim As Integer t
For i = 1 To Ubound(tabla)
If tabla(i, 1) > tabla(i, 2) Then
t = tabla(i, 1)
tabla(i, 1) = tabla(i, 2)
tabla(i, 2) = t
End If
Next i
ordenar(tabla())
End Sub
 
Sub consolidar(tabla() As Single)
normalizar(tabla())
For i = 1 To Ubound(tabla)-1
If tabla(i + 1, 1) <= tabla(i, 2) Then
tabla(i + 1, 1) = tabla(i, 1)
If tabla(i + 1, 2) <= tabla(i, 2) Then
tabla(i + 1, 2) = tabla(i, 2)
End If
tabla(i, 1) = temp : tabla(i, 2) = temp
End If
Next i
End Sub
 
Data 1, 1.1, 2.2
Data 2, 6.1, 7.2, 7.2, 8.3
Data 2, 4, 3, 2, 1
Data 4, 4, 3, 2, 1, -1, -2, 3.9, 10
Data 5, 1,3, -6,-1, -4,-5, 8,2, -6,-6
 
For j As Byte = 1 To 5
Read items
Dim As Single tabla(items, 2)
For i = 1 To items
Read tabla(i, 1), tabla(i, 2)
Next i
consolidar(tabla())
For i = 1 To items
If tabla(i, 1) <> temp Then Print "[";tabla(i, 1); ", "; tabla(i, 2); "] ";
Next i
Print
Next j
Sleep
</syntaxhighlight>
 
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 570 ⟶ 1,073:
fmt.Println(s[1 : len(s)-1])
}
}</langsyntaxhighlight>
 
{{out}}
Line 582 ⟶ 1,085:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.List (intercalate, maximumBy, sort)
import Data.Ord (comparing)
 
------------------- RANGE CONSOLIDATION ------------------
 
consolidated :: [(Float, Float)] -> [(Float, Float)]
consolidated xs = foldr go [] . sort . fmap ab
where
let go xy [] = [xy]
go xy@(x, y)[] abetc@((a,= b):etc)[xy]
go |xy@(x, y) >=abetc@((a, b = xy) : etc)
| y >= ab = (x, b)xy : etc
| y |>= otherwisea = xy(x, b) : abetcetc
ab| (a,otherwise b)= xy : abetc
| a <= b =ab (a, b)
| a |<= otherwiseb = (ba, ab)
in foldr go [] (sort| .otherwise fmap= ab $(b, xsa)
 
 
-- TEST -------------------------- TEST -------------------------
tests :: [[(Float, Float)]]
tests =
[ [],
, [(1.1, 2.2)],
, [(6.1, 7.2), (7.2, 8.3)],
, [(4, 3), (2, 1)],
, [(4, 3), (2, 1), (-1, -2), (3.9, 10)],
, [(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)]
]
 
Line 612 ⟶ 1,117:
main =
putStrLn $
tabulated
tabulated "Range consolidations:" showPairs showPairs consolidated tests
"Range consolidations:"
 
showPairs
showPairs
consolidated
tests
 
-- DISPLAY FORMATTING ------------------- DISPLAY FORMATTING ------------------
 
tabulated ::
tabulated :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> String
String ->
(a -> String) ->
(b -> String) ->
(a -> b) ->
[a] ->
String
tabulated s xShow fxShow f xs =
let w =
let w = length $ maximumBy (comparing length) (xShow <$> xs)
rjust n c s = drop (length s) (replicate n c ++ s)$
maximumBy
in unlines $
(comparing length)
s : fmap (((++) . rjust w ' ' . xShow) <*> ((" -> " ++) . fxShow . f)) xs
(xShow <$> xs)
rjust n c s = drop (length s) (replicate n c <> s)
in unlines $
s :
fmap
( ((<>) . rjust w ' ' . xShow)
<*> ((" -> " <>) . fxShow . f)
)
xs
 
showPairs :: [(Float, Float)] -> String
showPairs xs
| null xs = "[]"
| otherwise = '[' : intercalate ", " (showPair <$> xs) ++ "]"
'[' :
intercalate
", "
(showPair <$> xs)
<> "]"
 
showPair :: (Float, Float) -> String
showPair (a, b) = '(' : showNum a ++ ", " ++ showNum b ++ ")"
'(' :
showNum a
<> ", "
<> showNum b
<> ")"
 
showNum :: Float -> String
showNum n
| 0 == (n - fromIntegral (round n)) = show (round n)
| otherwise = show n</langsyntaxhighlight>
{{Out}}
<pre>Range consolidations:
Line 647 ⟶ 1,181:
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">ensure2D=: ,:^:(1 = #@$) NB. if list make 1 row table
normalise=: ([: /:~ /:~"1)@ensure2D NB. normalises list of ranges
merge=: ,:`(<.&{. , >.&{:)@.(>:/&{: |.) NB. merge ranges x and y
consolidate=: (}.@] ,~ (merge {.)) ensure2D</langsyntaxhighlight>
'''Required Examples:'''
<langsyntaxhighlight lang="j"> tests=: <@".;._2 noun define
1.1 2.2
6.1 7.2 ,: 7.2 8.3
Line 665 ⟶ 1,199:
| | |3 4| 1 2| 1 8|
| | | | 3 10| |
+-------+-------+---+-----+-----+</langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.Arrays;
Line 778 ⟶ 1,312:
 
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 796 ⟶ 1,330:
{{Trans|Haskell}}
{{Trans|Python}}
<langsyntaxhighlight lang="javascript">(() => {
'use strict';
 
Line 972 ⟶ 1,506:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>Range consolidations:
Line 980 ⟶ 1,514:
[[4,3],[2,1],[-1,-2],[3.9,10]] -> [[-2,-1],[1,2],[3,10]]
[[1,3],[-6,-1],[-4,-5],[8,2],[-6,-6]] -> [[-6,-1],[1,8]]</pre>
 
=={{header|jq}}==
{{trans|Julia}}
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq">def normalize: map(sort) | sort;
def consolidate:
normalize
| length as $length
| reduce range(0; $length) as $i (.;
.[$i] as $r1
| if $r1 != []
then reduce range($i+1; $length) as $j (.;
.[$j] as $r2
| if $r2 != [] and ($r1[-1] >= $r2[0]) # intersect?
then .[$i] = [$r1[0], ([$r1[-1], $r2[-1]]|max)]
| .[$j] = []
else .
end )
else .
end )
| map(select(. != [])) ;
def testranges:
[[1.1, 2.2]],
[[6.1, 7.2], [7.2, 8.3]],
[[4, 3], [2, 1]],
[[4, 3], [2, 1], [-1, -2], [3.9, 10]],
[[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]]
| "\(.) => \(consolidate)"
;
testranges</syntaxhighlight>
{{out}}
<pre>
[[1.1,2.2]] => [[1.1,2.2]]
[[6.1,7.2],[7.2,8.3]] => [[6.1,8.3]]
[[4,3],[2,1]] => [[1,2],[3,4]]
[[4,3],[2,1],[-1,-2],[3.9,10]] => [[-2,-1],[1,2],[3,10]]
[[1,3],[-6,-1],[-4,-5],[8,2],[-6,-6]] => [[-6,-1],[-5,-4],[1,8]]
</pre>
 
 
=={{header|Julia}}==
Line 987 ⟶ 1,564:
of the Python code is done, rather than using a native Julia Range.
{{trans|Python}}
<langsyntaxhighlight lang="julia">normalize(s) = sort([sort(bounds) for bounds in s])
 
function consolidate(ranges)
Line 1,013 ⟶ 1,590:
 
testranges()
</langsyntaxhighlight>{{output}}
<pre>
Array{Float64,1}[[1.1, 2.2]] => Array{Float64,1}[[1.1, 2.2]]
Line 1,023 ⟶ 1,600:
 
=={{header|Kotlin}}==
<langsyntaxhighlight Kotlinlang="kotlin">fun <T> consolidate(ranges: Iterable<ClosedRange<T>>): List<ClosedRange<T>> where T : Comparable<T>
{
return ranges
Line 1,088 ⟶ 1,665:
 
inputRanges.associateBy(Any::toString, ::consolidateDoubleRanges).forEach({ println("${it.key} => ${it.value}") })
}</langsyntaxhighlight>
 
{{Out}}
Line 1,098 ⟶ 1,675:
[[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]] => [[-6.0, -1.0], [1.0, 8.0]]
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Using the Wolfram Language's built-in Interval operations:
<syntaxhighlight lang="mathematica">data={{{1.1,2.2}},
{{6.1,7.2},{7.2,8.3}},
{{4,3},{2,1}},
{{4,3},{2,1},{-1,-2},{3.9,10}},
{{1,3},{-6,-1},{-4,-5},{8,2},{-6,-6}}};
Column[IntervalUnion@@@Map[Interval,data,{2}]]</syntaxhighlight>
{{out}}
<pre>Interval[{1.1,2.2}]
Interval[{6.1,8.3}]
Interval[{1,2},{3,4}]
Interval[{-2,-1},{1,2},{3,10}]
Interval[{-6,-1},{1,8}]</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import algorithm, strutils
 
# Definition of a range of values of type T.
type Range[T] = array[2, T]
 
proc `<`(a, b: Range): bool {.inline.} =
## Check if range "a" is less than range "b". Needed for sorting.
if a[0] == b[0]:
a[1] < b[1]
else:
a[0] < b[0]
 
 
proc consolidate[T](rangeList: varargs[Range[T]]): seq[Range[T]] =
## Consolidate a list of ranges of type T.
 
# Build a sorted list of normalized ranges.
var list: seq[Range[T]]
for item in rangeList:
list.add if item[0] <= item[1]: item else: [item[1], item[0]]
list.sort()
 
# Build the consolidated list starting from "smallest" range.
result.add list[0]
for i in 1..list.high:
let rangeMin = result[^1]
let rangeMax = list[i]
if rangeMax[0] <= rangeMin[1]:
result[^1] = [rangeMin[0], max(rangeMin[1], rangeMax[1])]
else:
result.add rangeMax
 
 
proc `$`[T](r: Range[T]): string {.inline.} =
# Return the string representation of a range.
when T is SomeFloat:
"[$1, $2]".format(r[0].formatFloat(ffDecimal, 1), r[1].formatFloat(ffDecimal, 1))
else:
"[$1, $2]".format(r[0], r[1])
 
proc `$`[T](s: seq[Range[T]]): string {.inline.} =
## Return the string representation of a sequence of ranges.
s.join(", ")
 
 
when isMainModule:
 
proc test[T](rangeList: varargs[Range[T]]) =
echo ($(@rangeList)).alignLeft(52), "→ ", consolidate(rangeList)
 
test([1.1, 2.2])
test([6.1, 7.2], [7.2, 8.3])
test([4, 3], [2, 1])
test([4.0, 3.0], [2.0, 1.0], [-1.0, -2.0], [3.9, 10.0])
test([1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6])</syntaxhighlight>
 
{{out}}
<pre>[1.1, 2.2] → [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] → [6.1, 8.3]
[4, 3], [2, 1] → [1, 2], [3, 4]
[4.0, 3.0], [2.0, 1.0], [-1.0, -2.0], [3.9, 10.0] → [-2.0, -1.0], [1.0, 2.0], [3.0, 10.0]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] → [-6, -1], [1, 8]</pre>
 
=={{header|Perl}}==
Line 1,103 ⟶ 1,759:
Note: the output is shown in the standard [https://perldoc.perl.org/perlop.html#Range-Operators Perl notation for Ranges].
 
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 1,133 ⟶ 1,789:
$out .= join('..', @$_). ' ' for consolidate($intervals);
printf "%44s => %s\n", $in, $out;
}</langsyntaxhighlight>
{{out}}
<pre> [1.1, 2.2] => 1.1..2.2
Line 1,142 ⟶ 1,798:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function consolidate(sequence sets)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
for i=length(sets) to 1 by -1 do
<span style="color: #008080;">function</span> <span style="color: #000000;">consolidate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span>
sets[i] = sort(sets[i])
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">)</span>
atom {is,ie} = sets[i]
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
for j=length(sets) to i+1 by -1 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">l</span> <span style="color: #008080;">do</span>
atom {js,je} = sets[j]
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">re</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
bool overlap = iff(is<=js?js<=ie:is<=je)
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">></span><span style="color: #000000;">re</span><span style="color: #0000FF;">?{</span><span style="color: #000000;">re</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">}:{</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">,</span><span style="color: #000000;">re</span><span style="color: #0000FF;">})</span>
if overlap then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
sets[i] = {min(is,js),max(ie,je)}
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">l</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
sets[j..j] = {}
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">il</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ih</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">l</span> <span style="color: #008080;">to</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
end for
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">jl</span><span style="color: #0000FF;">,</span><span style="color: #000000;">jh</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #004080;">bool</span> <span style="color: #000000;">overlap</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">il</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">jl</span><span style="color: #0000FF;">?</span><span style="color: #000000;">jl</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">ih</span><span style="color: #0000FF;">:</span><span style="color: #000000;">il</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">jh</span><span style="color: #0000FF;">)</span>
return sort(sets)
<span style="color: #008080;">if</span> <span style="color: #000000;">overlap</span> <span style="color: #008080;">then</span>
end function
<span style="color: #0000FF;">{</span><span style="color: #000000;">il</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ih</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">il</span><span style="color: #0000FF;">,</span><span style="color: #000000;">jl</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ih</span><span style="color: #0000FF;">,</span><span style="color: #000000;">jh</span><span style="color: #0000FF;">)}</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">l</span><span style="color: #0000FF;">]</span>
procedure test(sequence set)
<span style="color: #000000;">l</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
printf(1,"%40v => %v\n",{set,consolidate(set)})
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
 
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">il</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ih</span><span style="color: #0000FF;">}</span>
test({{1.1,2.2}})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
test({{6.1,7.2},{7.2,8.3}})
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">l</span><span style="color: #0000FF;">])</span>
test({{4,3},{2,1}})
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
test({{4,3},{2,1},{-1,-2},{3.9,10}})
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
test({{1,3},{-6,-1},{-4,-5},{8,2},{-6,-6}})</lang>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%40v =&gt; %v\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">set</span><span style="color: #0000FF;">,</span><span style="color: #000000;">consolidate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">1.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.2</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">6.1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">7.2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8.3</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3.9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}})</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">6</span><span style="color: #0000FF;">}})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,178 ⟶ 1,845:
=={{header|Prolog}}==
{{works with|SWI Prolog}}
<langsyntaxhighlight lang="prolog">consolidate_ranges(Ranges, Consolidated):-
normalize(Ranges, Normalized),
sort(Normalized, Sorted),
Line 1,220 ⟶ 1,887:
(consolidate_ranges(Ranges, Consolidated),
write_ranges(Ranges), write(' -> '),
write_ranges(Consolidated), nl)).</langsyntaxhighlight>
 
{{out}}
Line 1,233 ⟶ 1,900:
=={{header|Python}}==
===Procedural===
<langsyntaxhighlight lang="python">def normalize(s):
return sorted(sorted(bounds) for bounds in s if bounds)
 
Line 1,255 ⟶ 1,922:
]:
print(f"{str(s)[1:-1]} => {str(consolidate(s))[1:-1]}")
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,270 ⟶ 1,937:
{{Trans|Haskell}}
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Range consolidation'''
 
from functools import reduce
Line 1,357 ⟶ 2,024:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Consolidation of numeric ranges:
Line 1,368 ⟶ 2,035:
=={{header|Racket}}==
 
<langsyntaxhighlight lang="racket">#lang racket
 
;; Racket's max and min allow inexact numbers to contaminate exact numbers
Line 1,395 ⟶ 2,062:
([1 3] [-6 -1] [-4 -5] [8 2] [-6 -6])))
 
(for ([xs (in-list inputs)]) (printf "~a => ~a\n" xs (solve xs)))</langsyntaxhighlight>
 
{{out}}
Line 1,413 ⟶ 2,080:
Note: the output is in standard [https://docs.raku.org/type/Range Raku notation for Ranges].
 
<syntaxhighlight lang="raku" perl6line># Union
sub infix:<∪> (Range $a, Range $b) { Range.new($a.min,max($a.max,$b.max)) }
 
Line 1,439 ⟶ 2,106:
printf "%46s => ", @intervals.raku;
say reverse consolidate |@intervals.grep(*.elems)».sort.sort({ [.[0], .[*-1]] }).map: { Range.new(.[0], .[*-1]) }
}</langsyntaxhighlight>
{{out}}
<pre> [[1.1, 2.2],] => (1.1..2.2)
Line 1,452 ⟶ 2,119:
 
The actual logic for the range consolidation is marked with the comments: &nbsp; &nbsp; <big> <tt> /*■■■■►*/ </tt> </big>
<langsyntaxhighlight lang="rexx">/*REXX program performs range consolidation (they can be [equal] ascending/descending). */
#.= /*define the default for range sets. */
parse arg #.1 /*obtain optional arguments from the CL*/
Line 1,506 ⟶ 2,173:
do k=j+1 to n; if word(@.k,1)>=word(_,1) then iterate; @.j=@.k; @.k=_; _=@.j
end /*k*/
end /*j*/; return</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 1,532 ⟶ 2,199:
Most of the implementation below belongs to the test and formatting support.
If the output might be more arbitrary, the source would be quite small.
The algorithm relies on normalizing the ranges and folding a sorted sequence of them.
 
<syntaxhighlight lang="rust">use std::fmt::{Display, Formatter};
 
<lang Rust>use std::fmt::{Display, Formatter};
 
// We could use std::ops::RangeInclusive, but we would have to extend it to
Line 1,687 ⟶ 2,354:
 
println!("Run: cargo test -- --nocapture");
}</langsyntaxhighlight>
 
{{out}}
Line 1,704 ⟶ 2,371:
 
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
</pre>
 
=={{header|SQL}}==
{{works with|ORACLE 19c}}
This is not a particularly efficient solution, but it gets the job done.
 
<syntaxhighlight lang="sql">
/*
This code is an implementation of "Range consolidation" in SQL ORACLE 19c
p_list_of_sets -- input string
delimeter by default "|"
*/
with
function range_consolidation(p_list_of_sets in varchar2)
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_pos_set_1 pls_integer;
v_pos_set_2 pls_integer;
v_set_1_min number;
v_set_1_max number;
v_set_2_min number;
v_set_2_max number;
--
function sort_set(p_in_str varchar2)
return varchar2 is
v_out varchar2(32767) := p_in_str;
begin
--
with out_tab as
(select to_number(regexp_substr(str, '[^,]+', 1, rownum, 'c', 0)) elem
from
(select p_in_str as str
from dual
)
connect by level <= regexp_count(str, '[^,]+')
)
select min(elem)||','||max(elem) end
into v_out
from out_tab;
--
return v_out;
end;
--
function sort_output(p_in_str varchar2)
return varchar2 is
v_out varchar2(32767) := p_in_str;
begin
--
with out_tab as
(select to_number(regexp_substr(regexp_substr(str, '[^|]+', 1, rownum, 'c', 0), '[^,]+', 1, 1)) low_range
, regexp_substr(str, '[^|]+', 1, rownum, 'c', 0) range_def
from
(select p_in_str as str
from dual
)
connect by level <= regexp_count(str, '[^|]+')
)
select listagg(range_def, '|') within group(order by low_range)
into v_out
from out_tab;
--
return v_out;
end;
--
begin
--
execute immediate ('alter session set NLS_NUMERIC_CHARACTERS = ''.,''');
--
--cleaning
v_list_of_sets := ltrim(v_list_of_sets, '[');
v_list_of_sets := rtrim(v_list_of_sets, ']');
v_list_of_sets := replace(v_list_of_sets, ' ', '');
--set delimeter "|"
v_list_of_sets := regexp_replace(v_list_of_sets, '\]\,\[', '|', 1, 0);
--
<<loop_through_sets>>
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, sort_set(v_set_1), 1, 1);
v_set_1 := sort_set(v_set_1);
v_pos_set_1 := regexp_instr(v_list_of_sets, '[^|]+', 1, 1);
--
v_set_1_min := least(to_number(regexp_substr(v_set_1, '[^,]+', 1, 1)),to_number(regexp_substr(v_set_1, '[^,]+', 1, 2)));
v_set_1_max := greatest(to_number(regexp_substr(v_set_1, '[^,]+', 1, 1)),to_number(regexp_substr(v_set_1, '[^,]+', 1, 2)));
--
<<loop_for>>
for i in 1..regexp_count(v_list_of_sets, '[^|]+')-1
loop
--
v_set_2 := regexp_substr(v_list_of_sets, '[^|]+', 1, i+1);
v_list_of_sets := regexp_replace(v_list_of_sets, v_set_2, sort_set(v_set_2), 1, 1);
v_set_2 := sort_set(v_set_2);
v_pos_set_2 := regexp_instr(v_list_of_sets, '[^|]+', 1, i+1);
v_set_2_min := least(to_number(regexp_substr(v_set_2, '[^,]+', 1, 1)),to_number(regexp_substr(v_set_2, '[^,]+', 1, 2)));
v_set_2_max := greatest(to_number(regexp_substr(v_set_2, '[^,]+', 1, 1)),to_number(regexp_substr(v_set_2, '[^,]+', 1, 2)));
--
if greatest(v_set_1_min,v_set_2_min)-least(v_set_1_max,v_set_2_max) <= 0 then --overlapping
v_list_of_sets := regexp_replace(v_list_of_sets, v_set_1, ''||least(v_set_1_min,v_set_2_min)||','||greatest(v_set_1_max,v_set_2_max),v_pos_set_1,1);
v_list_of_sets := regexp_replace(v_list_of_sets, v_set_2, '', v_pos_set_2, 1);
continue loop_through_sets;
end if;
--
end loop loop_for;
--
v_output := ltrim(v_output||'|'||least(v_set_1_min,v_set_1_max)||', '||greatest(v_set_1_min,v_set_1_max),'|');
--
v_output := sort_output(v_output);
v_list_of_sets := regexp_replace(v_list_of_sets,v_set_1,'',1,1);
--
end loop loop_through_sets;
--
return '['||replace(v_output,'|','], [')||']';
end;
 
--Test
select lpad('[]',50) || ' ==> ' || range_consolidation('[]') as output from dual
union all
select lpad('[],[]',50) || ' ==> ' || range_consolidation('[],[]') as output from dual
union all
select lpad('[],[1,1]',50) || ' ==> ' || range_consolidation('[],[1,1]') as output from dual
union all
select lpad('[1.3]',50) || ' ==> ' || range_consolidation('[1.3]') as output from dual
union all
select lpad('[2,2],[1]',50) || ' ==> ' || range_consolidation('[2,2],[1]') as output from dual
union all
select lpad('[4,-1,0,1,5,7,7,7],[9,6,9,6,9]',50) || ' ==> ' || range_consolidation('[4,-1,0,1,5,7,7,7],[9,6,9,6,9]') as output from dual
union all
--Test RosettaCode
select '-- Test RosettaCode' as output from dual
union all
select lpad('[1.1, 2.2]',50) || ' ==> ' || range_consolidation('[1.1, 2.2]') as output from dual
union all
select lpad('[6.1, 7.2], [7.2, 8.3]',50) || ' ==> ' || range_consolidation('[6.1, 7.2], [7.2, 8.3]') as output from dual
union all
select lpad('[4, 3], [2, 1]',50) || ' ==> ' || range_consolidation('[4, 3], [2, 1]') as output from dual
union all
select lpad('[4, 3], [2, 1], [-1, -2], [3.9, 10]',50) || ' ==> ' || range_consolidation('[4, 3], [2, 1], [-1, -2], [3.9, 10]') as output from dual
union all
select lpad('[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]',50) || ' ==> ' || range_consolidation('[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]') as output from dual
union all
select lpad('1,3|-6,-1|-4,-5|8,2|-6,-6',50) || ' ==> ' || range_consolidation('1,3|-6,-1|-4,-5|8,2|-6,-6') as output from dual
/
;
/
</syntaxhighlight>
 
{{out}}
<pre>
[] ==> []
[],[] ==> []
[],[1,1] ==> [1, 1]
[1.3] ==> [1.3, 1.3]
[2,2],[1] ==> [1, 1], [2, 2]
[4,-1,0,1,5,7,7,7],[9,6,9,6,9] ==> [-1, 9]
-- Test RosettaCode
[1.1, 2.2] ==> [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] ==> [6.1, 8.3]
[4, 3], [2, 1] ==> [1, 2], [3, 4]
[4, 3], [2, 1], [-1, -2], [3.9, 10] ==> [-2, -1], [1, 2], [3, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] ==> [-6, -1], [1, 8]
1,3|-6,-1|-4,-5|8,2|-6,-6 ==> [-6, -1], [1, 8]
</pre>
 
=={{header|Wren}}==
As Wren already has a built-in Range class (which is not quite the same as what's required here), we create a Span class instead.
<syntaxhighlight lang="wren">class Span {
construct new(r) {
if (r.type != Range || !r.isInclusive) Fiber.abort("Argument must be an inclusive range.")
_low = r.from
_high = r.to
if (_low > _high) {
_low = r.to
_high = r.from
}
}
 
low { _low }
high { _high }
 
consolidate(r) {
if (r.type != Span) Fiber.abort("Argument must be a Span.")
if (_high < r.low) return [this, r]
if (r.high < _low) return [r, this]
return [Span.new(_low.min(r.low).._high.max(r.high))]
}
 
toString { "[%(_low), %(_high)]" }
}
 
var spanLists = [
[Span.new(1.1..2.2)],
[Span.new(6.1..7.2), Span.new(7.2..8.3)],
[Span.new(4..3), Span.new(2..1)],
[Span.new(4..3), Span.new(2..1), Span.new(-1..-2), Span.new(3.9..10)],
[Span.new(1..3), Span.new(-6..-1), Span.new(-4..-5), Span.new(8..2), Span.new(-6..-6)]
]
 
for (spanList in spanLists) {
if (spanList.count == 1) {
System.print(spanList.toString[1..-2])
} else if (spanList.count == 2) {
System.print(spanList[0].consolidate(spanList[1]).toString[1..-2])
} else {
var first = 0
while (first < spanList.count-1) {
var next = first + 1
while (next < spanList.count) {
var res = spanList[first].consolidate(spanList[next])
spanList[first] = res[0]
if (res.count == 2) {
spanList[next] = res[1]
next = next + 1
} else {
spanList.removeAt(next)
}
}
first = first + 1
}
System.print(spanList.toString[1..-2])
}
}</syntaxhighlight>
 
{{out}}
<pre>
[1.1, 2.2]
[6.1, 8.3]
[1, 2], [3, 4]
[-2, -1], [1, 2], [3, 10]
[-6, -1], [1, 8]
</pre>
 
=={{header|Yabasic}}==
<langsyntaxhighlight Yabasiclang="yabasic">sub sort(tabla())
local items, i, t1, t2, s
Line 1,777 ⟶ 2,678:
for i = 1 to items
if tabla(i, 1) <> void print tabla(i, 1), "..", tabla(i, 2);
next</langsyntaxhighlight>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn consolidate(rs){
(s:=List()).append(
normalize(rs).reduce('wrap(ab,cd){
Line 1,787 ⟶ 2,688:
}) )
}
fcn normalize(s){ s.apply("sort").sort(fcn(a,b){ a[0]<b[0] }) }</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">foreach rs in (L(
L(L(1.1, 2.2)), L(L(6.1, 7.2), L(7.2, 8.3)), L(L(4, 3), L(2, 1)),
L(L(4.0, 3.0), L(2.0, 1.0), L(-1.0, -2.0), L(3.9, 10.0)),
L(L(1, 3), L(-6, -1), L(-4, -5), L(8, 2), L(-6, -6)),
)){ println(ppp(rs),"--> ",ppp(consolidate(rs))) }
fcn ppp(ll){ ll.pump(String,fcn(list){ list.concat(", ", "[", "] ") }) }</langsyntaxhighlight>
{{out}}
<pre>
3,021

edits