Range extraction: Difference between revisions

m
(39 intermediate revisions by 24 users not shown)
Line 16:
*   [[Range expansion]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F range_extract(lst)
[[Int]] r
V lenlst = lst.len
V i = 0
L i < lenlst
V low = lst[i]
L i < lenlst - 1 & lst[i] + 1 == lst[i + 1]
i++
V hi = lst[i]
I hi - low >= 2
r [+]= [low, hi]
E I hi - low == 1
r [+]= [low]
r [+]= [hi]
E
r [+]= [low]
i++
R r
 
F printr(ranges)
print(ranges.map(r -> (I r.len == 2 {r[0]‘-’r[1]} E String(r[0]))).join(‘,’))
 
L(lst) [[-8, -7, -6, -3, -2, -1, 0, 1, 3, 4, 5, 7,
8, 9, 10, 11, 14, 15, 17, 18, 19, 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]]
printr(range_extract(lst))</syntaxhighlight>
 
{{out}}
<pre>
-8--6,-3-1,3-5,7-11,14,15,17-20
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">INT FUNC FindRange(INT ARRAY a INT len,start)
INT count
count=1
WHILE start<len-1
DO
IF a(start)+1#a(start+1) THEN
EXIT
FI
start==+1
count==+1
OD
RETURN (count)
 
PROC Append(CHAR ARRAY text,suffix)
BYTE POINTER srcPtr,dstPtr
BYTE len
 
len=suffix(0)
IF text(0)+len>255 THEN
len=255-text(0)
FI
IF len THEN
srcPtr=suffix+1
dstPtr=text+text(0)+1
MoveBlock(dstPtr,srcPtr,len)
text(0)==+suffix(0)
FI
RETURN
 
PROC RangeToStr(INT ARRAY a INT len CHAR ARRAY res)
INT i,count
CHAR ARRAY tmp(10)
 
i=0
res(0)=0
WHILE i<len
DO
count=FindRange(a,len,i)
StrI(a(i),tmp) Append(res,tmp)
IF count=2 THEN
Append(res,",")
StrI(a(i+1),tmp) Append(res,tmp)
ELSEIF count>2 THEN
Append(res,"-")
StrI(a(i+count-1),tmp) Append(res,tmp)
FI
i==+count
IF i<len THEN
Append(res,",")
FI
OD
RETURN
 
PROC Main()
INT ARRAY a=[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]
INT ARRAY b=[65530 65533 65534 65535
0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20]
CHAR ARRAY res(256)
 
RangeToStr(a,33,res)
PrintE(res) PutE()
RangeToStr(b,20,res)
PrintE(res)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Range_extraction.png Screenshot from Atari 8-bit computer]
<pre>
0-2,4,6-8,11,12,14-25,27-33,35-39
 
-6,-3-1,3-5,7-11,14,15,17-20
</pre>
 
=={{header|Ada}}==
Line 27 ⟶ 140:
the iterative solution uses Unbounded_Strings.
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
Line 72 ⟶ 185:
37, 38, 39
) ) );
end Range_Extraction;</langsyntaxhighlight>
 
 
Line 79 ⟶ 192:
The recursive solution avoids the usage of unbounded strings.
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO, Ada.Strings.Fixed;
 
procedure Range_Extract is
Line 123 ⟶ 236:
17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29,
30, 31, 32, 33, 35, 36, 37, 38, 39) ));
end Range_Extract;</langsyntaxhighlight>
 
{{out}}
Line 131 ⟶ 244:
=={{header|Aime}}==
 
<langsyntaxhighlight lang="aime">rp(list l)
{
integer a, i;
Line 156 ⟶ 269:
 
0;
}</langsyntaxhighlight>
 
{{out}}
Line 170 ⟶ 283:
* The closest concept that ''Algol 68'' has to [[wp:duck typing|duck typing]] is the [[wp:tagged union|tagged union]]. This is used to define '''mode''' '''urange''' = '''union'''('''int''', '''struct'''('''int''' lwb, upb)). If ''duck typing'' was available it could reduced the size of the code specimen, but would have lost some of <i>Algol 68</i>'s strong type ''data security''.
'''File: Template_Range_extraction_Base.a68'''
<langsyntaxhighlight lang="algol68">###
REQUIRES(MODE SCALAR, OP(SCALAR,SCALAR)BOOL =, OP(SCALAR,SCALAR)SCALAR +);
###
Line 223 ⟶ 336:
);
 
OP (UNIRANGELIST)STRING REPR = unirange list repr; # alias #</langsyntaxhighlight>'''File: Template_Range_extraction_Iterative.a68'''
<langsyntaxhighlight lang="algol68">###
REQUIRES(MODE SCALAR, OP(SCALAR,SCALAR)BOOL =, OP(SCALAR,SCALAR)SCALAR +);
###
Line 283 ⟶ 396:
 
out unirange list[:upb out unirange list]
);</langsyntaxhighlight>'''File: test_Range_extraction_Integer.a68'''<langsyntaxhighlight lang="algol68">#!/usr/local/bin/a68g --script #
############################
# some simple test cases: #
Line 326 ⟶ 439:
REPR list c
))
END</langsyntaxhighlight>
 
{{out}}
Line 349 ⟶ 462:
# Finally iterate with ''unirange list init'' '''exiting''' with an array of '''union''' of '''int''' and '''range'''.
'''File: Template_Range_extraction_Generative.a68'''
<langsyntaxhighlight lang="algol68">###
REQUIRES(MODE SCALAR, OP(SCALAR,SCALAR)BOOL =, OP(SCALAR,SCALAR)SCALAR +);
###
Line 431 ⟶ 544:
);
 
OP (UNIRANGELISTS)UNIRANGELIST INITUNIRANGE = unirange list init; # alias #</langsyntaxhighlight>
{{out}}
<pre style="height:15ex;overflow:scroll">
Line 444 ⟶ 557:
===Functional===
{{Trans|JavaScript}}
<langsyntaxhighlight AppleScriptlang="applescript">--------------------- RANGE EXTRACTION ---------------------
 
-- rangeFormat :: [Int] -> String
Line 553 ⟶ 666:
item 1 of lstParts & {item 2 of lstParts}
end if
end splitBy</langsyntaxhighlight>
{{Out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
Line 559 ⟶ 672:
===Straightforward===
 
<langsyntaxhighlight lang="applescript">(*
The task description doesn't explicitly state that the integers are unique or what to do if they're not.
This script treats runs of equal integers as single instances of those integers.
Line 607 ⟶ 720:
-- Test code:
set listOfIntegers to {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}
return rangeDescription(listOfIntegers)</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">"0-2,4,6-8,11,12,14-25,27-33,35-39"</langsyntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="arturo">extractRange: function [inp][
items: map split.by:"," join split.lines strip inp 'x -> to :integer strip x
ranges: []
 
i: 0
while [i < size items][
fst: items\[i]
offset: i
while [true][
if (i + 1) >= size items -> break
if (fst - offset) <> items\[i+1] - (i+1) -> break
i: i + 1
]
lst: items\[i]
case [(lst-fst)=]
when? -> 0 -> 'ranges ++ ~"|fst|"
when? -> 1 -> 'ranges ++ ~"|fst|, |lst|"
else -> 'ranges ++ ~"|fst|-|lst|"
i: i + 1
]
 
return join.with:", " ranges
]
 
print extractRange {
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
}</syntaxhighlight>
 
{{out}}
 
<pre>0-2, 4, 6-8, 11, 12, 14-25, 27-33, 35-39</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">msgbox % extract("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")
 
extract( list ) {
Line 623 ⟶ 773:
}
return SubStr(ret (f!=p ? (p>f+1 ? "-" : ",") p : ""), 2)
}</langsyntaxhighlight>
{{out}}
<pre>---------------------------
Line 640 ⟶ 790:
by convention, separated from the expected ones by extra space.
 
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
 
BEGIN {
Line 693 ⟶ 843:
sequence[s] = a[s]
}
}</langsyntaxhighlight>
 
{{out}}
Line 701 ⟶ 851:
</pre>
 
=={{header|BBC BASIC}}==
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="basic">arraybase 1
dim a = {-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}
print formatRange(a)
print
 
dim b = {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}
print formatRange(b)
end
 
function formatRange (a)
lb = a[?,]: ub = a[?]
if ub = - 1 then return ""
if lb = ub then return string(a[lb])
rangeCount = 1
range = string(a[lb])
for i = lb + 1 to ub
if a[i] = a[i - 1] + 1 then
rangeCount += 1
else
if rangeCount = 1 then
range += "," + string(a[i])
else
if rangeCount = 2 then
rangeCount = 1
range += "," + string(a[i-1]) + "," + string(a[i])
else
rangeCount = 1
range += "-" + string(a[i-1]) + "," + string(a[i])
end if
end if
end if
next
if rangeCount = 2 then
range += "," + string(a[ub])
else
if rangeCount > 2 then range += "-" + string(a[ub])
end if
return range
end function</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> range$ = " 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, " + \
Line 728 ⟶ 923:
ENDIF
UNTIL i% = 0
= LEFT$(t$)</langsyntaxhighlight>
{{out}}
<pre>
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
==={{header|FreeBASIC}}===
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
Function formatRange (a() As Integer) As String
Dim lb As Integer = LBound(a)
Dim ub As Integer = UBound(a)
If ub = - 1 Then Return ""
If lb = ub Then Return Str(a(lb))
Dim rangeCount As Integer = 1
Dim range As String = Str(a(lb))
For i As Integer = lb + 1 To ub
If a(i) = a(i - 1) + 1 Then
rangeCount += 1
ElseIf rangeCount = 1 Then
range += "," + Str(a(i))
ElseIf rangeCount = 2 Then
rangeCount = 1
range += "," + Str(a(i-1)) + "," + Str(a(i))
Else
rangeCount = 1
range += "-" + Str(a(i-1)) + "," + Str(a(i))
End If
Next
If rangeCount = 2 Then
range += "," + Str(a(ub))
ElseIf rangeCount > 2 Then
range += "-" + Str(a(ub))
End If
Return range
End Function
 
Dim a(1 To 20) As Integer = {-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}
Print formatRange(a())
Print
 
Dim b(1 To 33) As Integer => _
{ _
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 _
}
 
Print formatRange(b())
Print
Print "Press any key to continue"
Sleep</syntaxhighlight>
 
{{out}}
<pre>
-6,-3-1,3-5,7-11,14,15,17-20
 
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
==={{header|Gambas}}===
'''[https://gambas-playground.proko.eu/?gist=49f362e3de9725fbf3c56f2381abf8a4 Click this link to run this code]'''
<syntaxhighlight lang="gambas">siInput As New Short[]
siInput1 As Short[] = [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]
siInput2 As Short[] = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
sOutput As New String[]
siCount As Short
siNum As Short
'__________________
Public Sub Main()
Dim siLoop As Short
 
For siLoop = 0 To 1
If siLoop = 0 Then siInput = siInput1.Copy() Else siInput = siInput2.Copy()
siCount = 0
siNum = 0
Repeat
If siInput[siCount + 1] = siInput[siCount] + 1 Then
Inc siCount
Else
GetOutput
Endif
Until siCount = siInput.Max
GetOutput
Print sOutput.join(", ")
sOutput.clear
Next
 
End
'__________________
Public Sub GetOutput()
 
If siNum = siCount Then
sOutput.add(siInput[siNum])
Inc siCount
siNum = siCount
End If
 
If siNum <> siCount Then
If siNum = siCount - 1 Then
sOutput.add(siInput[siNum])
sOutput.add(siInput[siNum + 1])
siCount += 2
siNum += 2
Return
End If
sOutput.Add(siInput[siNum] & "-" & siInput[siCount])
Inc siCount
siNum = siCount
End If
 
End</syntaxhighlight>
Output:
<pre>
0-2, 4, 6-8, 11, 12, 14-25, 27-33, 35-39
-6, -3-1, 3-5, 7-11, 14, 15, 17-20
</pre>
 
==={{header|Liberty BASIC}}===
{{works with|Just BASIC}}
{{works with|Run BASIC}}
<syntaxhighlight lang="lb">
s$ = "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"
print ExtractRange$( s$)
end
 
function ExtractRange$( range$)
n = 1
count = ItemCount( range$, ",")
while n <= count
startValue = val( word$( range$, n, ","))
m = n + 1
while m <= count
nextValue = val( word$( range$, m, ","))
if nextValue - startValue <> m - n then exit while
m = m + 1
wend
if m - n > 2 then
ExtractRange$ = ExtractRange$ + str$( startValue) + "-" + str$( startValue + m - n - 1) + ","
else
for i = n to m - 1
ExtractRange$ = ExtractRange$ + str$( startValue + i - n) + ","
next i
end if
n = m
wend
ExtractRange$ = left$( ExtractRange$, len( ExtractRange$) - 1)
end function
 
function ItemCount( list$, separator$)
while word$( list$, ItemCount + 1, separator$) <> ""
ItemCount = ItemCount + 1
wend
end function
</syntaxhighlight>
{{out}}
<pre> 0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
==={{header|OxygenBasic}}===
<syntaxhighlight lang="oxygenbasic">
int ints(100)
 
ints={
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
}
 
 
' RESULT:
' 0-2, 4, 6-8, 11, 12, 14-25, 27-33, 35-39
 
 
function Ranges(int*i) as string
'===============================
string pr=""
int n=0
int e=0
int j=0
int k=0
int f=1
do
j++
n=i(j)
e=i(j+1)
if e<j
exit do
endif
if e=n+1 and i(j+2)=n+2 then 'LOOKAHEAD
if f then k=n : f=0
else
if f=0 then
pr+=k "-" i(j+1) ", " 'RANGE OF VALUES
j++
f=1
else
pr+=n ", " 'SINGLE VALUES
end if
end if
loop
return left pr, len(pr)-2
end function
print Ranges ints
</syntaxhighlight>
 
==={{header|PureBasic}}===
Even though the example integer list only includes ascending ranges
this code will also handles descending ranges.
<syntaxhighlight lang="purebasic">DataSection
Data.i 33 ;count of elements to be read
Data.i 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
Data.i 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39
EndDataSection
 
NewList values()
;setup list
Define elementCount, i
Read.i elementCount
For i = 1 To elementCount
AddElement(values()): Read.i values()
Next
Procedure.s rangeExtract(List values())
Protected listSize = ListSize(values()) - 1
Protected rangeMarker, rangeStart, rangeIncrement, retraceSteps, rangeSize, endOfRange, output.s, sub.s
ForEach values()
rangeStart = values():
sub = Str(rangeStart)
If NextElement(values())
retraceSteps = 1
rangeIncrement = values() - rangeStart
If rangeIncrement = 1 Or rangeIncrement = -1
;found start of possible range
If ListIndex(values()) <> listSize
retraceSteps = 2
rangeSize = 2
endOfRange = #False
rangeMarker = values()
While NextElement(values())
If values() - rangeMarker <> rangeIncrement
endOfRange = #True
Break
EndIf
rangeSize + 1
rangeMarker = values()
Wend
If rangeSize > 2
sub = Str(rangeStart) + "-" + Str(rangeMarker)
If Not endOfRange
retraceSteps = 0 ;at end of list
Else
retraceSteps = 1
EndIf
EndIf
EndIf
EndIf
;return to the value before look-aheads
While retraceSteps > 0
PreviousElement(values()): retraceSteps - 1
Wend
EndIf
output + sub + ","
Next
ProcedureReturn RTrim(output, ",")
EndProcedure
 
If OpenConsole()
PrintN(rangeExtract(values()))
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf</syntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
==={{header|QuickBASIC}}===
For negative numbers the results look rather strange, but they satisfy the requirements.
{{trans|BBC BASIC}}
<syntaxhighlight lang="qbasic">
REM Range extraction
DECLARE FUNCTION RangeExtract$ (RS$)
 
Range$ = " 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, "
Range$ = Range$ + "15, 16, 17, 18, 19, 20, 21, 22, 23, 24, "
Range$ = Range$ + "25, 27, 28, 29, 30, 31, 32, 33, 35, 36, "
Range$ = Range$ + "37, 38, 39"
PRINT RangeExtract$(Range$)
END
 
FUNCTION RangeExtract$ (RS$)
TS$ = "": I% = 0
F% = VAL(RS$)
DO
I% = INSTR(I% + 1, RS$, ",")
T% = VAL(MID$(RS$, I% + 1))
IF T% = F% + R% + 1 THEN
R% = R% + 1
ELSE
SELECT CASE R%
CASE 0
TS$ = TS$ + LTRIM$(STR$(F%)) + ","
CASE 1
TS$ = TS$ + LTRIM$(STR$(F%)) + "," + LTRIM$(STR$(F% + R%)) + ","
CASE ELSE
TS$ = TS$ + LTRIM$(STR$(F%)) + "-" + LTRIM$(STR$(F% + R%)) + ","
END SELECT
R% = 0: F% = T%
END IF
LOOP WHILE I% <> 0
RangeExtract$ = LEFT$(TS$, LEN(TS$) - 1)
END FUNCTION
</syntaxhighlight>
{{out}}
<pre>
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
==={{header|VBA}}===
<syntaxhighlight lang="vb">
Public Function RangeExtraction(AList) As String
'AList is a variant that is an array, assumed filled with numbers in ascending order
Const RangeDelim = "-" 'range delimiter
Dim result As String
Dim InRange As Boolean
Dim Posn, ub, lb, rangestart, rangelen As Integer
 
result = ""
'find dimensions of AList
ub = UBound(AList)
lb = LBound(AList)
Posn = lb
While Posn < ub
rangestart = Posn
rangelen = 0
InRange = True
'try to extend the range
While InRange
rangelen = rangelen + 1
If Posn = ub Then
InRange = False
Else
InRange = (AList(Posn + 1) = AList(Posn) + 1)
Posn = Posn + 1
End If
Wend
If rangelen > 2 Then 'output the range if it has more than 2 elements
result = result & "," & Format$(AList(rangestart)) & RangeDelim & Format$(AList(rangestart + rangelen - 1))
Else 'output the separate elements
For i = rangestart To rangestart + rangelen - 1
result = result & "," & Format$(AList(i))
Next
End If
Posn = rangestart + rangelen
Wend
RangeExtraction = Mid$(result, 2) 'get rid of first comma!
End Function
 
 
Public Sub RangeTest()
'test function RangeExtraction
'first test with a Variant array
Dim MyList As Variant
MyList = Array(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)
Debug.Print "a) "; RangeExtraction(MyList)
 
'next test with an array of integers
Dim MyOtherList(1 To 20) As Integer
MyOtherList(1) = -6
MyOtherList(2) = -3
MyOtherList(3) = -2
MyOtherList(4) = -1
MyOtherList(5) = 0
MyOtherList(6) = 1
MyOtherList(7) = 3
MyOtherList(8) = 4
MyOtherList(9) = 5
MyOtherList(10) = 7
MyOtherList(11) = 8
MyOtherList(12) = 9
MyOtherList(13) = 10
MyOtherList(14) = 11
MyOtherList(15) = 14
MyOtherList(16) = 15
MyOtherList(17) = 17
MyOtherList(18) = 18
MyOtherList(19) = 19
MyOtherList(20) = 20
Debug.Print "b) "; RangeExtraction(MyOtherList)
End Sub
</syntaxhighlight>
{{out}}
<pre>
RangeTest
a) 0-2,4,6-8,11,12,14-25,27-33,35-39
b) -6,-3-1,3-5,7-11,14,15,17-20
</pre>
 
==={{header|VBScript}}===
<syntaxhighlight lang="vb">Function Range_Extraction(list)
num = Split(list,",")
For i = 0 To UBound(num)
startnum = CInt(num(i))
sum = startnum
Do While i <= UBound(num)
If sum = CInt(num(i)) Then
If i = UBound(num) Then
If startnum <> CInt(num(i)) Then
If startnum + 1 = CInt(num(i)) Then
Range_Extraction = Range_Extraction & startnum & "," & num(i) & ","
Else
Range_Extraction = Range_Extraction & startnum & "-" & num(i) & ","
End If
Else
Range_Extraction = Range_Extraction & startnum & ","
End If
Exit Do
Else
i = i + 1
sum = sum + 1
End If
Else
If startnum = CInt(num(i-1)) Then
Range_Extraction = Range_Extraction & startnum & ","
Else
If startnum + 1 = CInt(num(i-1)) Then
Range_Extraction = Range_Extraction & startnum & "," & num(i-1) & ","
Else
Range_Extraction = Range_Extraction & startnum & "-" & num(i-1) & ","
End If
End If
i = i - 1
Exit Do
End If
Loop
Next
Range_Extraction = Left(Range_Extraction,Len(Range_Extraction)-1)
End Function
WScript.StdOut.Write 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")</syntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat"> ( rangeExtract
= accumulator firstInRange nextInRange
, accumulate fasten rangePattern
Line 785 ⟶ 1,430:
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39)</langsyntaxhighlight>
{{out}}
<pre>(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) ==>
Line 795 ⟶ 1,440:
but always returns the output length sans the terminating null,
so caller can allocate buffer.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
 
Line 830 ⟶ 1,475:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|C sharp}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 893 ⟶ 1,538:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 899 ⟶ 1,544:
 
===C#: Alternate Version===
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 934 ⟶ 1,579:
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 942 ⟶ 1,587:
=={{header|C++}}==
 
<langsyntaxhighlight lang="cpp">
#include <iostream>
#include <iterator>
Line 996 ⟶ 1,641:
std::cout << std::endl;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,003 ⟶ 1,648:
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">shared void run() {
value numbers = [
Line 1,046 ⟶ 1,691:
assert(rangeString == "0-2,4,6-8,11,12,14-25,27-33,35-39");
print(rangeString);
}</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
Line 1,052 ⟶ 1,697:
=={{header|Clojure}}==
{{libheader|org.flatland/useful}}
<langsyntaxhighlight lang="clojure">(use '[flatland.useful.seq :only (partition-between)])
 
(defn nonconsecutive? [[x y]]
Line 1,067 ⟶ 1,712:
(defn format-with-ranges [coll]
(println (clojure.string/join ","
(map string-ranges (partition-between nonconsecutive? coll)))))</langsyntaxhighlight>
 
{{out}}
Line 1,077 ⟶ 1,722:
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
<langsyntaxhighlight lang="cobol"> IDENTIFICATION DIVISION.
PROGRAM-ID. extract-range-task.
Line 1,256 ⟶ 1,901:
END PROGRAM find-num-trailing-spaces.
END PROGRAM extract-range.</langsyntaxhighlight>
 
nums-table.cpy:
<langsyntaxhighlight lang="cobol"> 01 nums-table.
03 num-nums PIC 999.
03 nums-area.
05 nums PIC S999 OCCURS 1 TO 100 TIMES
DEPENDING ON num-nums
INDEXED BY nums-idx.</langsyntaxhighlight>
 
{{out}}
Line 1,272 ⟶ 1,917:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun format-with-ranges (list)
(unless list (return ""))
(with-output-to-string (s)
Line 1,298 ⟶ 1,943:
37 38 39))
"0-2,4,6-8,11,12,14-25,27-33,35-39"
</syntaxhighlight>
</lang>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.conv, std.string, std.algorithm, std.range;
 
string rangeExtraction(in int[] items)
Line 1,330 ⟶ 1,975:
32, 33, 35, 36, 37, 38, 39]])
data.rangeExtraction.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>-8--6,-3-1,3-5,7-11,14,15,17-20
0,0,0,1,1
0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Delphi}}==
See [https://rosettacode.org/wiki/Range_extraction#Pascal Pascal].
 
=={{header|DWScript}}==
<langsyntaxhighlight lang="delphi">procedure ExtractRanges(const values : array of Integer);
begin
var i:=0;
Line 1,361 ⟶ 2,009:
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]);</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
Line 1,369 ⟶ 2,017:
{{trans|Go}}
 
<langsyntaxhighlight lang="dyalect">func rangeFormat(a) {
if a.lenLength() == 0 {
return ""
}
Line 1,377 ⟶ 2,025:
while true {
var n2 = n1 + 1
while n2 < a.lenLength() && a[n2] == a[n2-1]+1 {
n2 += 1
}
var s = a[n1].toStringToString()
if n2 == n1+2 {
s += "," + a[n2-1]
Line 1,386 ⟶ 2,034:
s += "-" + a[n2-1]
}
parts.addAdd(s)
if n2 == a.lenLength() {
break
}
Line 1,398 ⟶ 2,046:
n1 = n2
}
return String.joinJoin(values =: parts)
}
Line 1,407 ⟶ 2,055:
37, 38, 39
])
print("range format: \(rf)")</langsyntaxhighlight>
 
{{out}}
Line 1,417 ⟶ 2,065:
and just formatting them ourselves.
 
<langsyntaxhighlight lang="e">def rex(numbers :List[int]) {
var region := 0..!0
for n in numbers { region |= n..n }
Line 1,433 ⟶ 2,081:
}
return ",".rjoin(ranges)
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="e">? rex([
> 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
> 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
Line 1,441 ⟶ 2,089:
> 37, 38, 39])
# value: "0-2,4,6-8,11,12,14-25,27-33,35-39"
</syntaxhighlight>
</lang>
 
=={{header|EasyLang}}==
{{trans|Java}}
<syntaxhighlight>
func$ mkrange arr[] .
idx = 1
idx2 = 1
while idx <= len arr[]
repeat
idx2 += 1
until idx2 > len arr[] or arr[idx2] - arr[idx2 - 1] <> 1
.
if idx2 - idx > 2
r$ &= arr[idx] & "-" & arr[idx2 - 1] & ","
idx = idx2
else
while idx < idx2
r$ &= arr[idx] & ","
idx += 1
.
.
.
return substr r$ 1 (len r$ - 1)
.
print mkrange [ 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 ]
</syntaxhighlight>
{{out}}
<pre>
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
(define task '(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))
 
Line 1,469 ⟶ 2,147:
(string-join (map range->string (reverse (foldl group-range () task))) ",")
→ "0-2 ,4 ,6-8 ,11, 12 ,14-25 ,27-33 ,35-39 "
</syntaxhighlight>
</lang>
 
=={{header|Eiffel}}==
<syntaxhighlight lang="eiffel">
<lang Eiffel>
class
RANGE
Line 1,545 ⟶ 2,223:
end
end
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 1,554 ⟶ 2,232:
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule RC do
def range_extract(list) do
max = Enum.max(list) + 2
Line 1,583 ⟶ 2,261:
37, 38, 39
]
IO.inspect RC.range_extract(list)</langsyntaxhighlight>
 
{{out}}
Line 1,591 ⟶ 2,269:
 
=={{header|Emacs Lisp}}==
 
===version 1===
{{libheader|Gnus}}
<lang Emacs Lisp}>
<syntaxhighlight lang="lisp">(require 'gnus-range)
 
(defun rangext (lst)
(mapconcat (lambda (item)
(if (consp item)
(if (= (+ 1 (car item) ) (cdr item) )
(format "%d,%d" (car item) (cdr item) )
(format "%d-%d" (car item) (cdr item) ))
(format "%d" item)))
(gnus-compress-sequence lst)
","))
 
(insert (rangext '(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"</syntaxhighlight>
</lang>
 
Vanilla:
<b>Output:</b>
<syntaxhighlight lang="lisp">(defun split-into-ranges (numbers)
<pre>
(let* ((last-number (pop numbers))
0-2,4,6-8,11,12,14-25,27-33,35-39
(range (list last-number))
</pre>
ranges)
(dolist (n numbers)
(if (= n (1+ last-number))
(push n range)
(push (nreverse range) ranges)
(setq range (list n)))
(setq last-number n))
(nreverse (cons (nreverse range) ranges))))
 
(defun format-range (range)
===version 2===
(cond
<lang Emacs Lisp}>
((not range)
(setq max-lisp-eval-depth 10000)
(error "invalid range"))
((= (length range) 1)
(number-to-string (car range)))
((= (length range) 2)
(format "%d,%d" (car range) (cadr range)))
(t
(format "%d-%d" (car range) (car (last range))))))
 
(defun abrangext (a lsnumbers)
(mapconcat #'format-range (split-into-ranges numbers) ","))
(if ls (if (= (+ a 1) (car ls) )
(abc a (car ls) (cdr ls) )
(format "%d,%s" a (ab (car ls) (cdr ls) )))
(format "%d" a) ))
 
(rangext '(0 1 2 4 6 7 8 11 12 14
(defun abc (a b ls)
(if ls (if (= (+ b 1) (car ls) )
(abcd a (car ls) (cdr ls) )
(format "%d,%d,%s" a b (ab (car ls) (cdr ls) )))
(format "%d,%d" a b) ))
 
(defun abcd (a c ls)
(if ls (if (= (+ c 1) (car ls) )
(abcd a (car ls) (cdr ls) )
(format "%d-%d,%s" a c (ab (car ls) (cdr ls) )))
(format "%d-%d" a c) ))
 
(defun rangext (ls)
(if ls (ab (car ls) (cdr ls) ) ""))
 
(insert (rangext '(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"</syntaxhighlight>
</lang>
 
<b>Output:</b>
<pre>
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( range ).
 
Line 1,674 ⟶ 2,345:
extraction_acc( {Start, Stop, Acc} ) when Stop > Start + 1 -> [erlang:integer_to_list(Start) ++ "-" ++ erlang:integer_to_list(Stop) | Acc];
extraction_acc( {Start, Stop, Acc} ) -> [erlang:integer_to_list(Stop), erlang:integer_to_list(Start) | Acc]. % Reversed
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,682 ⟶ 2,353:
 
=={{header|Euphoria}}==
<langsyntaxhighlight lang="euphoria">function extract_ranges(sequence s)
integer first
sequence out
Line 1,713 ⟶ 2,384:
 
puts(1, extract_ranges({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}))</langsyntaxhighlight>
 
{{out}}
Line 1,719 ⟶ 2,390:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let extractRanges = function
| [] -> Seq.empty
| x::xr ->
Line 1,742 ⟶ 2,413:
 
printfn "%s" (extract [ 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 ])</langsyntaxhighlight>
 
{{out}}
Line 1,749 ⟶ 2,420:
=={{header|Factor}}==
The <code>monotonic-split</code> word enables us to split the input sequence into sub-sequences of contiguous integers. From there, we make ranges out of sequences greater than 2 in length and list members of sequences less than or equal to 2 in length.
<langsyntaxhighlight lang="factor">USING: formatting io kernel math math.parser sequences
splitting.monotonic ;
IN: rosetta-code.range-extraction
Line 1,766 ⟶ 2,437:
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
} extract-range print</langsyntaxhighlight>
{{out}}
<pre>
Line 1,773 ⟶ 2,444:
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">create values
here
0 , 1 , 2 , 4 , 6 , 7 , 8 , 11 , 12 , 14 ,
Line 1,799 ⟶ 2,470:
;
 
values /values .ranges</langsyntaxhighlight>
 
{{out}}
Line 1,811 ⟶ 2,482:
Although Pascal offers a Str procedure for converting a variable to a text string, maddeningly, it is a procedure not a function and so cannot be used within a compound statement. Fortran could offer access to the FORMAT facility via something like a function FMT(x) which returns the text representation of variable x with no leading or trailing spaces (whereby FMT(-6) would return "-6" and so forth) but alas, does not. Such a function cannot be written in ordinary Fortran until such time as it is possible to return varying-sized character results. The I0 format code standardised in F90 comes close but of course it must be used in a complex environment. All in all, it is easier to devise a subroutine SPLOT(n) to write the value of an integer (with possible leading hyphen if negative) to a scratchpad and then EMIT its text character by character to the output variable character until stopped by a space. Subroutines EMIT and SPLOT could be normal separate subroutines, but as servants of IRANGE it is easier to take advantage of the F90 facility whereby they can be "contained" inside IRANGE and thereby gain access to its internal context. Otherwise, there would have to be additional parameters or usage of COMMON variables for such communication.
 
The method grinds through the list of values, looking ahead for consecutive continuations (relying on the value of a DO-loop's index variable being available on exit from the loop) and thereby placing in its output string either a range of numbers or a single number. This could be done by using WRITE with suitable FORMAT statements to appropriate portions of the output string via careful counting of positions, but using EMIT and SPLOT avoids the requisite cogitations. A fancier method would be to devise a list of numbers to be output along with a suitable FORMAT statement that would supply the commas and hyphens as appropriate. Of course, one would again face the question "how long is a FORMAT string?", so, grinding stepwise it is. <langsyntaxhighlight Fortranlang="fortran"> SUBROUTINE IRANGE(TEXT) !Identifies integer ranges in a list of integers.
Could make this a function, but then a maximum text length returned would have to be specified.
CHARACTER*(*) TEXT !The list on input, the list with ranges on output.
Line 1,869 ⟶ 2,540:
CALL IRANGE(SOME)
WRITE (6,*) SOME
END</langsyntaxhighlight>
 
Output: spaces after the commas could be added easily enough.<pre> 0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|FreeBASIC}}==
<lang freebasic>' FB 1.05.0 Win64
 
Function formatRange (a() As Integer) As String
Dim lb As Integer = LBound(a)
Dim ub As Integer = UBound(a)
If ub = - 1 Then Return ""
If lb = ub Then Return Str(a(lb))
Dim rangeCount As Integer = 1
Dim range As String = Str(a(lb))
For i As Integer = lb + 1 To ub
If a(i) = a(i - 1) + 1 Then
rangeCount += 1
ElseIf rangeCount = 1 Then
range += "," + Str(a(i))
ElseIf rangeCount = 2 Then
rangeCount = 1
range += "," + Str(a(i-1)) + "," + Str(a(i))
Else
rangeCount = 1
range += "-" + Str(a(i-1)) + "," + Str(a(i))
End If
Next
If rangeCount = 2 Then
range += "," + Str(a(ub))
ElseIf rangeCount > 2 Then
range += "-" + Str(a(ub))
End If
Return range
End Function
 
Dim a(1 To 20) As Integer = {-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}
Print formatRange(a())
Print
 
Dim b(1 To 33) As Integer => _
{ _
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 _
}
 
Print formatRange(b())
Print
Print "Press any key to continue"
Sleep</lang>
 
{{out}}
<pre>
-6,-3-1,3-5,7-11,14,15,17-20
 
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|Gambas}}==
'''[https://gambas-playground.proko.eu/?gist=49f362e3de9725fbf3c56f2381abf8a4 Click this link to run this code]'''
<lang gambas>siInput As New Short[]
siInput1 As Short[] = [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]
siInput2 As Short[] = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
sOutput As New String[]
siCount As Short
siNum As Short
'__________________
Public Sub Main()
Dim siLoop As Short
 
For siLoop = 0 To 1
If siLoop = 0 Then siInput = siInput1.Copy() Else siInput = siInput2.Copy()
siCount = 0
siNum = 0
Repeat
If siInput[siCount + 1] = siInput[siCount] + 1 Then
Inc siCount
Else
GetOutput
Endif
Until siCount = siInput.Max
GetOutput
Print sOutput.join(", ")
sOutput.clear
Next
 
End
'__________________
Public Sub GetOutput()
 
If siNum = siCount Then
sOutput.add(siInput[siNum])
Inc siCount
siNum = siCount
End If
 
If siNum <> siCount Then
If siNum = siCount - 1 Then
sOutput.add(siInput[siNum])
sOutput.add(siInput[siNum + 1])
siCount += 2
siNum += 2
Return
End If
sOutput.Add(siInput[siNum] & "-" & siInput[siCount])
Inc siCount
siNum = siCount
End If
 
End</lang>
Output:
<pre>
0-2, 4, 6-8, 11, 12, 14-25, 27-33, 35-39
-6, -3-1, 3-5, 7-11, 14, 15, 17-20
</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,042 ⟶ 2,599:
}
return strings.Join(parts, ","), nil
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,050 ⟶ 2,607:
=={{header|Groovy}}==
Ad Hoc Solution:
<langsyntaxhighlight lang="groovy">def range = { s, e -> s == e ? "${s}," : s == e - 1 ? "${s},${e}," : "${s}-${e}," }
 
def compressList = { list ->
Line 2,061 ⟶ 2,618:
}
 
def compressRanges = { expanded -> compressList(Eval.me('[' + expanded + ']')) }</langsyntaxhighlight>
 
Test:
<langsyntaxhighlight lang="groovy">def s = '''
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
Line 2,070 ⟶ 2,627:
37, 38, 39
'''
println (compressRanges(s))</langsyntaxhighlight>
 
{{out}}
Line 2,077 ⟶ 2,634:
=={{header|Haskell}}==
===direct recursion===
<langsyntaxhighlight lang="haskell">import Data.List (intercalate)
 
extractRange :: [Int] -> String
Line 2,089 ⟶ 2,646:
g a [] = (a - 1, [])
f (x : xs) = show x : f xs
f [] = []</langsyntaxhighlight>
 
<langsyntaxhighlight lang="text">> extractRange $ [0..2] ++ 4 : [6..8] ++ 11 : 12 : [14..25] ++ [27..33] ++ [35..39]
"0-2,4,6-8,11,12,14-25,27-33,35-39"</langsyntaxhighlight>
 
===splitBy===
Line 2,098 ⟶ 2,655:
Delegating to splitBy allows a reasonably clean definition of range formatting:
 
<langsyntaxhighlight lang="haskell">import Data.List (intercalate)
import Data.Function (on)
import Data.Bool (bool)
 
-- RANGE FORMAT ---------------------- RANGE FORMAT ---------------------
rangeFormat :: [Int] -> String
rangeFormat = intercalate "," . fmap rangeString . splitBy ((/=) . succ)
Line 2,112 ⟶ 2,668:
ps@(x:t) = show <$> xs
 
--------------------- GENERIC FUNCTION -------------------
 
-- GENERIC FUNCTION ---------------------------------------
 
-- Split wherever a supplied predicate matches the
-- relationship between two consecutive items.
Line 2,120 ⟶ 2,674:
splitBy _ [] = []
splitBy _ [x] = [[x]]
splitBy f xs@(_:t) = activeuncurry (:) acc$ foldr go ([], []) (zip xs t)
where
go (x, prev) (active, acc) =
| f x prev = ([x], current : acc)
foldr
| otherwise = (\(x, prev): (activecurrent, acc) ->
where
let current = bool active [prev] (null active)
in bool (x : current, acc) ([x], current : acc) (f x prev))
([], | null active = [prev])
(zip xs t)| otherwise = active
 
-- TEST -------------------------- TEST -------------------------
main :: IO ()
main =
Line 2,168 ⟶ 2,722:
, 38
, 39
]</langsyntaxhighlight>
{{Out}}
<pre>"0-2,4,6-8,11,12,14-25,27-33,35-39"</pre>
Line 2,175 ⟶ 2,729:
Or, we can pass a span-chopping function to Data.List.Split '''chop'''.
 
<langsyntaxhighlight lang="haskell">import Data.List (intercalate, groupBy, isPrefixOf)
import Data.List.Split (chop)
import Data.Bool (bool)
Line 2,203 ⟶ 2,757:
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39 ]</langsyntaxhighlight>
{{Out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main()
 
R := [ 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
Line 2,240 ⟶ 2,794:
every (s := "[ ") ||:= !L || " "
return s || "]"
end</langsyntaxhighlight>
{{out}}
<pre>Input list := [ 0 1 2 4 6 7 8 11 12 14 15 16 17 18 19 20 21 22 23 24 25 27
Line 2,250 ⟶ 2,804:
Older versions of J will also need <code> require 'strings'</code>.
 
<langsyntaxhighlight lang="j">fmt=: [: ;@(8!:0) [`]`({. ; (',-' {~ 2 < #) ; {:)@.(2 <. #)
group=: <@fmt;.1~ 1 ~: 0 , 2 -~/\ ]
extractRange=: ',' joinstring group</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight lang="j"> extractRange 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</langsyntaxhighlight>
 
and
 
<langsyntaxhighlight lang="j"> extractRange (-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</langsyntaxhighlight>
 
Other examples:
 
<langsyntaxhighlight Jlang="j"> extractRange i.101
0-100</langsyntaxhighlight>
 
The first 101 non-negative integers
 
<syntaxhighlight lang="j">
<lang J>
extractRange (-. p:) i.101
0,1,4,6,8-10,12,14-16,18,20-22,24-28,30,32-36,38-40,42,44-46,48-52,54-58,60,62-66,68-70,72,74-78,80-82,84-88,90-96,98-100</langsyntaxhighlight>
 
Excluding those which are prime
 
<syntaxhighlight lang="j">
<lang J>
extractRange 2}. (-. p:) i.101
4,6,8-10,12,14-16,18,20-22,24-28,30,32-36,38-40,42,44-46,48-52,54-58,60,62-66,68-70,72,74-78,80-82,84-88,90-96,98-100</langsyntaxhighlight>
 
Also excluding the first two non-negative integers (which are neither prime nor the product of non-empty lists of primes).
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">public class RangeExtraction {
 
public static void main(String[] args) {
Line 2,305 ⟶ 2,859:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39,</pre>
Line 2,312 ⟶ 2,866:
===ES5===
====Imperative====
<langsyntaxhighlight lang="javascript">function rangeExtraction(list) {
var len = list.length;
var out = [];
Line 2,346 ⟶ 2,900:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
]));</langsyntaxhighlight>
 
====Functional====
{{Trans|ES6}}
{{Trans|Haskell}}
<langsyntaxhighlight JavaScriptlang="javascript">(function () {
'use strict';
 
Line 2,414 ⟶ 2,968:
33, 35, 36, 37, 38, 39
]);
})();</langsyntaxhighlight>
 
{{Out}}
Line 2,420 ⟶ 2,974:
 
===ES6===
====Composition of pure functions====
{{Trans|Haskell}}
Defining the range format in terms of a reusable '''splitBy''' function:
<syntaxhighlight lang="javascript">(() => {
'use strict';
 
// ---------------- RANGE EXTRACTION -----------------
 
// rangeFormat :: [Int] -> String
const rangeFormat = xs =>
splitBy((a, b) => b - a > 1, xs)
.map(rangeString)
.join(',');
 
// rangeString :: [Int] -> String
const rangeString = xs =>
xs.length > 2 ? (
[xs[0], last(xs)].map(show)
.join('-')
) : xs.join(',')
 
 
// ---------------------- TEST -----------------------
const main = () =>
rangeFormat([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
]);
 
 
// ---------------- GENERIC FUNCTIONS ----------------
 
// Splitting not on a delimiter, but whenever the
// relationship between two consecutive items matches
// a supplied predicate function
 
// splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
const splitBy = (f, xs) => {
if (xs.length < 2) return [xs];
const
h = xs[0],
lstParts = xs.slice(1)
.reduce(([acc, active, prev], x) =>
f(prev, x) ? (
[acc.concat([active]), [x], x]
) : [acc, active.concat(x), x], [
[],
[h],
h
]);
return lstParts[0].concat([lstParts[1]]);
};
 
// last :: [a] -> a
const last = xs => (
// The last item of a list.
ys => 0 < ys.length ? (
ys.slice(-1)[0]
) : undefined
)(xs);
 
// show :: a -> String
const show = x =>
JSON.stringify(x);
 
// MAIN --
return main();
})();</syntaxhighlight>
{{Out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
====Idiomatic====
<syntaxhighlight lang="javascript">
<lang JavaScript>
function toRange(arr) {
const ranges = [];
Line 2,472 ⟶ 3,098:
console.log(`expected output : '${expected}'.`);
console.log(`Correct? ${ actual === expected ? 'Yes' : 'No'}`);
</syntaxhighlight>
</lang>
{{Out}}
<pre>
actual output : '0-2,4,6-8,11,12,14-25,27-33,35-39'.
expected output : '0-2,4,6-8,11,12,14-25,27-33,35-39'.
Correct? Yes</pre>
</pre>
====From Haskell====
{{Trans|Haskell}}
Defining the range format in terms of a reusable '''splitBy''' function:
<lang JavaScript>(() => {
'use strict';
 
// rangeFormat :: [Int] -> String
const rangeFormat = xs =>
splitBy((a, b) => b - a > 1, xs)
.map(rangeString)
.join(',');
 
// rangeString :: [Int] -> String
const rangeString = xs =>
xs.length > 2 ? (
[head(xs), last(xs)].map(show)
.join('-')
) : xs.join(',')
 
 
// GENERIC FUNCTIONS
 
// Splitting not on a delimiter, but whenever the relationship between
// two consecutive items matches a supplied predicate function
 
// splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
const splitBy = (f, xs) => {
if (xs.length < 2) return [xs];
const
h = head(xs),
lstParts = xs.slice(1)
.reduce(([acc, active, prev], x) =>
f(prev, x) ? (
[acc.concat([active]), [x], x]
) : [acc, active.concat(x), x], [
[],
[h],
h
]);
return lstParts[0].concat([lstParts[1]]);
};
 
// head :: [a] -> a
const head = xs => xs.length ? xs[0] : undefined;
 
// last :: [a] -> a
const last = xs => xs.length ? xs.slice(-1)[0] : undefined;
 
// show :: a -> String
const show = x => JSON.stringify(x);
 
// TEST
return rangeFormat([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
]);
})();</lang>
{{Out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|jq}}==
<langsyntaxhighlight lang="kq"># Input should be an array
def extract:
reduce .[] as $i
Line 2,560 ⟶ 3,125:
then "\(.[0]),\(.[1])" # satisfy special requirement
else "\(.[0])-\(.[1])" end )
| join(",") ;</langsyntaxhighlight>
 
{{out|Command and output}}
Line 2,569 ⟶ 3,134:
=={{header|Jsish}}==
From Javascript ES5 Imperative solution.
<langsyntaxhighlight lang="javascript">/* Range Extraction, in Jsish */
function rangeExtraction(list) {
var len = list.length;
Line 2,604 ⟶ 3,169:
 
puts(arr);
puts(rangeExtraction(arr));</langsyntaxhighlight>
 
{{out}}
Line 2,613 ⟶ 3,178:
=={{header|Julia}}==
This is perhaps an idiosyncratic solution. Numbers inside of runs are replaced with Xs, the list is converted into a comma separated string, and then Xs and extra commas are replaced with the range character via a regular expression.
<syntaxhighlight lang="julia">
<lang Julia>
function sprintfrange{T<:Integer}(a::Array{T,1})
len = length(a)
Line 2,632 ⟶ 3,197:
println("Testing range-style formatting.")
println(" ", testa, "\n =>\n ", sprintfrange(testa))
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,642 ⟶ 3,207:
 
=={{header|K}}==
<langsyntaxhighlight lang="k">grp : {(&~1=0,-':x)_ x}
fmt : {:[1=#s:$x;s;(*s),:[3>#s;",";"-"],*|s]}
erng: {{x,",",y}/,//'fmt'grp x}</langsyntaxhighlight>
 
{{out|Example}}
Line 2,651 ⟶ 3,216:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.0.6
 
fun extractRange(list: List<Int>): String {
Line 2,687 ⟶ 3,252:
37, 38, 39)
println(extractRange(list2))
}</langsyntaxhighlight>
 
{{out}}
Line 2,694 ⟶ 3,259:
 
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|Liberty BASIC}}==
<lang lb>
s$ = "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"
print ExtractRange$( s$)
end
 
function ExtractRange$( range$)
n = 1
count = ItemCount( range$, ",")
while n <= count
startValue = val( word$( range$, n, ","))
m = n + 1
while m <= count
nextValue = val( word$( range$, m, ","))
if nextValue - startValue <> m - n then exit while
m = m + 1
wend
if m - n > 2 then
ExtractRange$ = ExtractRange$ + str$( startValue) + "-" + str$( startValue + m - n - 1) + ","
else
for i = n to m - 1
ExtractRange$ = ExtractRange$ + str$( startValue + i - n) + ","
next i
end if
n = m
wend
ExtractRange$ = left$( ExtractRange$, len( ExtractRange$) - 1)
end function
 
function ItemCount( list$, separator$)
while word$( list$, ItemCount + 1, separator$) <> ""
ItemCount = ItemCount + 1
wend
end function
</lang>
{{out}}
<pre> 0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|LiveCode}}==
Inefficient as it takes 2 passes
<langsyntaxhighlight LiveCodelang="livecode">function rangeExtract nums
local prevNum, znums, rangedNums
set itemDelimiter to ", "
Line 2,767 ⟶ 3,292:
return char 1 to -2 of rangedNums --strip off trailing comma
end rangeExtract
</syntaxhighlight>
</lang>
Test
<langsyntaxhighlight LiveCodelang="livecode">command testRangeExtract
local numbers
put "0, 1, 2, 4, 6, 7, 8, 11, 12, 14," \
Line 2,776 ⟶ 3,301:
&& "37, 38, 39" into numbers
put rangeExtract(numbers)
end testRangeExtract</langsyntaxhighlight>
Output: <langsyntaxhighlight LiveCodelang="livecode">0-2,4,6-8,11,12,14-25,27-33,35-39</langsyntaxhighlight>
 
=={{header|Lua}}==
<langsyntaxhighlight Lualang="lua">function extractRange (rList)
local rExpr, startVal = ""
for k, v in pairs(rList) do
Line 2,807 ⟶ 3,332:
37, 38, 39
}
print(extractRange(intList))</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Maple}}==
<langsyntaxhighlight Maplelang="maple">lst := [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]:
r1,r2:= lst[1],lst[1]:
Line 2,823 ⟶ 3,348:
fi:
od:
printf(piecewise(r2-r1=1, "%d,%d", r2-r1>1,"%d-%d", "%d"), r1, r2):</langsyntaxhighlight>
{{Out|Output}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">rangeExtract[data_List] := ToString[Row[Riffle[
<lang Mathematica>
rangeExtract[data_List] := ToString[Row[
Riffle[
Flatten[Split[Sort[data], #2 - #1 == 1 &] /. {a_Integer, __, b_} :> Row[{a, "-", b}]],
","]]];
rangeExtract[{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}]</syntaxhighlight>
]];
{{out}}
</lang>
<pre>"0-2,4,6-8,11,12,14-25,27-33,35-39"</pre>
 
Example:
<pre>
rangeExtract[{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|MATLAB}} / {{header|Octave}}==
<langsyntaxhighlight MATLABlang="matlab">function S=range_extraction(L)
% Range extraction
L(end+1) = NaN;
Line 2,866 ⟶ 3,383:
disp(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]))</langsyntaxhighlight>
 
{{Out|Output (Octave)}}
Line 2,872 ⟶ 3,389:
 
=={{header|Mercury}}==
<langsyntaxhighlight Mercurylang="mercury">:- module range_extraction.
:- interface.
 
Line 2,912 ⟶ 3,429:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39].
</syntaxhighlight>
</lang>
 
=={{header|MiniScript}}==
<syntaxhighlight lang="miniscript">extractRange = function(ints)
{{incorrect|MiniScript|Extra spaces in output}}
<lang MiniScript>extractRange = function(ints)
result = []
idx = 0
Line 2,932 ⟶ 3,448:
end if
end while
return join(result, ", ")
end function
 
test = [ 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]
print extractRange(test)</langsyntaxhighlight>
 
{{out}}
<pre>0-2, 4, 6-8, 11, 12, 14-25, 27-33, 35-39</pre>
 
=={{header|MUMPS}}==
<langsyntaxhighlight MUMPSlang="mumps">RANGCONT(X) ;Integer range contraction
NEW Y,I,CONT,NOTFIRST,CURR,PREV,NEXT,SEQ SET Y="",SEQ=0,PREV="",CONT=0
FOR I=1:1:$LENGTH(X,",") DO
Line 2,959 ⟶ 3,475:
IF CONT SET Y=Y_PREV
K I,CONT,NOTFIRST,CURR,PREV,NEXT,SEQ
QUIT Y</langsyntaxhighlight>
Example:
<pre>USER>SET S="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"
Line 2,968 ⟶ 3,484:
=={{header|NetRexx}}==
===NetRexx Ver. 1===
<langsyntaxhighlight lang="netrexx">/*NetRexx program to test range extraction. ***************************
* 07.08.2012 Walter Pachl derived from my Rexx Version
* Changes: line continuation in aaa assignment changed
Line 3,004 ⟶ 3,520:
End
End
Say 'new='ol</langsyntaxhighlight>
{{out}}
<pre>
Line 3,014 ⟶ 3,530:
===NetRexx Ver. 2===
{{trans|Java}}
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 3,090 ⟶ 3,606:
end r_
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,104 ⟶ 3,620:
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import parseutils, re, strutils, sequtils
 
proc extractRange(input: string): string =
var list = input.replace(re"\s+").split(',').map(parseInt)
var ranges: seq[string] = @[]
var i = 0
while i < list.len:
Line 3,124 ⟶ 3,640:
case last - first
of 0: ranges.add($first)
of 1: ranges.add("$1,$2".format([$first, $last]))
else: ranges.add("$1-$2".format([$first, $last]))
i.inc
return ranges.join(",")
Line 3,133 ⟶ 3,649:
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39""".extractRange)</langsyntaxhighlight>
 
{{out}}
Line 3,140 ⟶ 3,656:
=={{header|Oberon-2}}==
Oxford Oberon-2
<langsyntaxhighlight lang="oberon2">
MODULE RangeExtraction;
IMPORT Out;
Line 3,233 ⟶ 3,749:
Range(seq1)
END RangeExtraction.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,242 ⟶ 3,758:
=={{header|Objeck}}==
{{trans|Java}}
<langsyntaxhighlight lang="objeck">class IdentityMatrix {
function : Main(args : String[]) ~ Nil {
Compress2Range("-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20")->PrintLine();
Line 3,288 ⟶ 3,804:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Objective-C}}==
Line 3,295 ⟶ 3,811:
{{works with|Mac OS X|10.7+}}
{{works with|iOS|5+}}
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
 
NSString *extractRanges(NSArray *nums) {
Line 3,328 ⟶ 3,844:
}
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,335 ⟶ 3,851:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let range_extract = function
| [] -> []
| x::xs ->
Line 3,355 ⟶ 3,871:
in
let rng = range_extract li in
print_endline(string_of_range rng)</langsyntaxhighlight>
 
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Ol}}==
<syntaxhighlight lang="scheme">
(define (extract ll)
(let loop ((head (car ll)) (tail (cdr ll)) (out #null))
(if (null? tail)
(reverse (cons head out))
else
(cond
((eq? head (- (car tail) 1))
(loop (list (car tail) head) (cdr tail) out))
((and (pair? head) (eq? (car head) (- (car tail) 1)))
(loop (cons (car tail) head) (cdr tail) out))
(else
(loop (car tail) (cdr tail) (cons head out)))))))
 
(define (range->string range)
(fold (lambda (f v)
(string-append (if f (string-append f ",") "")
(if (pair? v)
(string-append (string-append (number->string (last v #f)) "-")(number->string (car v)))
(number->string v))))
#false
range))
 
; let's test
(define data '(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))
(define range (extract data))
 
(print "extracted ranges: " range)
(print "string representation: " (range->string range))
</syntaxhighlight>
{{Out}}
<pre>$ ol range_extraction.scm
extracted ranges: ((2 1 0) 4 (8 7 6) (12 11) (25 24 23 22 21 20 19 18 17 16 15 14) (33 32 31 30 29 28 27) (39 38 37 36 35))
string representation: 0-2,4,6-8,11-12,14-25,27-33,35-39
</pre>
 
=={{header|ooRexx}}==
{{trans|NetRexx Ver. 2}}
{{trans|Java}}
<langsyntaxhighlight ooRexxlang="oorexx">/* Rexx */
 
parse arg userInput
Line 3,442 ⟶ 3,995:
end r_
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,454 ⟶ 4,007:
Compacted: -4--2,0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|OxygenBasic}}==
{{output?|OxygenBasic}}
<lang oxygenbasic>
dim sys ints(100)
ints=>
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
 
function ShowRange(sys*i) as string
'==================================
pr=""
n=0
e=0
j=0
k=-1
do
j++
n=i(j)
e=i(j+1)
if e<j then
exit do
end if
if e=n+1 and i(j+2)=n+2 then 'LOOKAHEAD
if k=-1 then k=n
else
if k>=0 then
pr+=k "-" i(j+1) ", " 'RANGE OF VALUES
j++
k=-1
else
pr+=n ", " 'SINGLE VALUES
end if
end if
end do
return left pr, len(pr)-2
end function
 
 
print ShowRange ints
</lang>
 
=={{header|Oz}}==
<langsyntaxhighlight lang="oz">declare
fun {Extract Xs}
{CommaSeparated
Line 3,545 ⟶ 4,055:
15 16 17 18 19 20 21 22 23 24
25 27 28 29 30 31 32 33 35 36
37 38 39 ]}}</langsyntaxhighlight>
 
{{out}}
Line 3,553 ⟶ 4,063:
 
{{works with|Free Pascal|2.6.2}}
{{works with|Delphi}}
 
<langsyntaxhighlight Pascallang="pascal">program RangeExtractionRangeExtractionApp;
 
 
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$ENDIF}
 
{$mode objfpc}{$H+}
 
uses
Line 3,563 ⟶ 4,078:
{$ENDIF}{$ENDIF}
SysUtils;
 
function RangeExtraction(const Seq: array of integer): String;
const
Line 3,569 ⟶ 4,084:
var
i, j: Integer;
Separator: string = '';
begin
Separator:= '';
Result := '';
i := Low(Seq);
Line 3,598 ⟶ 4,114:
end;
End;
 
procedure DisplayRange(const Seq: array of integer);
var
Line 3,609 ⟶ 4,125:
WriteLn;
End;
 
begin
DisplayRange([0]);
Line 3,621 ⟶ 4,137:
DisplayRange([0,1,2,3,4,5,6,7,9]);
DisplayRange([0,1,2,3,4,6,9,10,11,12]);
 
DisplayRange([
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
Line 3,627 ⟶ 4,143:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]);
{$IFNDEF UNIX}readln;{$ENDIF}
ReadLn;
end.</syntaxhighlight>
end.
</lang>
 
{{out}}
Line 3,658 ⟶ 4,173:
Using regexes. Also handles +/- and negative integer ranges.
 
<langsyntaxhighlight Perllang="perl">sub rangext {
my $str = join ' ', @_;
1 while $str =~ s{([+-]?\d+) ([+-]?\d+)}
Line 3,672 ⟶ 4,187:
25 27 28 29 30 31 32 33 35 36
37 38 39);
print rangext(@test), "\n";</langsyntaxhighlight>
 
{{out}}
Line 3,679 ⟶ 4,194:
{{libheader|Set&#58;&#58;IntSpan}}
 
<langsyntaxhighlight Perllang="perl">use Set::IntSpan;
sub rangext { return Set::IntSpan->new(@_) . '' } # stringized</langsyntaxhighlight>
 
{{libheader|Set&#58;&#58;IntSpan&#58;&#58;Fast}}
 
<langsyntaxhighlight Perllang="perl">use Set::IntSpan::Fast;
sub rangext { return Set::IntSpan::Fast->new(@_)->as_string }</langsyntaxhighlight>
 
<code>Set::IntSpan</code> and <code>Set::IntSpan::Fast</code> are similar. "Fast" does a binary search for member testing (not part of the task here). Both accept negatives.
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function spout(integer first, integer this, sequence s)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
string res
<span style="color: #008080;">function</span> <span style="color: #000000;">spout</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">first</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">curr</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
if first=this-1 then
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span>
res = sprintf("%d",s[first])
<span style="color: #008080;">if</span> <span style="color: #000000;">first</span><span style="color: #0000FF;">=</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">first</span><span style="color: #0000FF;">])</span>
res = sprintf("%d%s%d",{s[first],iff(first=this-2?',':'-'),s[this-1]})
<span style="color: #008080;">else</span>
end if
<span style="color: #004080;">integer</span> <span style="color: #000000;">sep</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">first</span><span style="color: #0000FF;">=</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">?</span><span style="color: #008000;">','</span><span style="color: #0000FF;">:</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">)</span>
return res
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d%s%d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">first</span><span style="color: #0000FF;">],</span><span style="color: #000000;">sep</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">curr</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]})</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
function extract_ranges(sequence s)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
integer first = 1
string out = ""
<span style="color: #008080;">function</span> <span style="color: #000000;">extract_ranges</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
if length(s)!=0 then
<span style="color: #004080;">integer</span> <span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
for i=2 to length(s) do
<span style="color: #004080;">string</span> <span style="color: #000000;">out</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
if s[i]!=s[i-1]+1 then
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
out &= spout(first,i,s)&','
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
first = i
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</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: #008080;">then</span>
end if
<span style="color: #000000;">out</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">spout</span><span style="color: #0000FF;">(</span><span style="color: #000000;">first</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">','</span>
end for
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
out &= spout(first,length(s)+1,s)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return out
<span style="color: #000000;">out</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">spout</span><span style="color: #0000FF;">(</span><span style="color: #000000;">first</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #008080;">return</span> <span style="color: #000000;">out</span>
puts(1,extract_ranges({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}))</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0</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;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">22</span><span style="color: #0000FF;">,</span><span style="color: #000000;">23</span><span style="color: #0000FF;">,</span><span style="color: #000000;">24</span><span style="color: #0000FF;">,</span><span style="color: #000000;">25</span><span style="color: #0000FF;">,</span><span style="color: #000000;">27</span><span style="color: #0000FF;">,</span><span style="color: #000000;">28</span><span style="color: #0000FF;">,</span><span style="color: #000000;">29</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">30</span><span style="color: #0000FF;">,</span><span style="color: #000000;">31</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">,</span><span style="color: #000000;">33</span><span style="color: #0000FF;">,</span><span style="color: #000000;">35</span><span style="color: #0000FF;">,</span><span style="color: #000000;">36</span><span style="color: #0000FF;">,</span><span style="color: #000000;">37</span><span style="color: #0000FF;">,</span><span style="color: #000000;">38</span><span style="color: #0000FF;">,</span><span style="color: #000000;">39</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;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">extract_ranges</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 3,722 ⟶ 4,245:
 
=={{header|Phixmonti}}==
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
( ) var res
Line 3,767 ⟶ 4,290:
clear
 
printRes</langsyntaxhighlight>
The same result in all examples.
{{out}}
Line 3,774 ⟶ 4,297:
A bit less ugly
 
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
( 0 1 2 4 6 7 8 11 12 14
Line 3,812 ⟶ 4,335:
endif
endfor
8 tochar print " " print</langsyntaxhighlight>
 
Short version
 
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
( 0 1 2 4 6 7 8 11 12 14
Line 3,846 ⟶ 4,369:
act inf == not
endwhile
8 tochar print " " print</langsyntaxhighlight>
 
 
PicoLisp like version
 
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
def glue /# l o -- l #/
Line 3,858 ⟶ 4,381:
ob swap put
endfor
enddef
 
def pop /# l -- h t #/
head swap tail nip
enddef
 
Line 3,893 ⟶ 4,412:
endfor
 
"," glue lprint</langsyntaxhighlight>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">go =>
Lists = [
[-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9,
10, 11, 14, 15, 17, 18, 19, 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],
1..20,
[13],
[11,12,13,15]
].
foreach(List in Lists)
println(List),
println(make_ranges(List)),
nl
end,
nl.
 
 
make_ranges(L) = Res =>
Ranges = [],
Range = [L[1]],
 
% Identify the range
foreach(I in 2..L.length)
Li1 = L[I-1],
Li = L[I],
if Li == Li1+1 then
Range := Range ++ [Li]
else
if length(Range) > 0 then
Ranges := Ranges ++ [Range]
end,
Range := [] ++ [Li]
end
end,
% pickup the last range
if length(Range) > 0 then
Ranges := Ranges ++ [Range]
end,
Res := join([get_range(R) : R in Ranges], ",").
 
 
% Convert to range representation
get_range(R) =
cond(R.length == 1,
R.first().to_string(),
min(R).to_string() ++ "-" ++ max(R).to_string()).</syntaxhighlight>
 
{{out}}
<pre>[-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
 
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
1-20
 
[13]
13
 
[11,12,13,15]
11-13,15</pre>
 
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de rangeextract (Lst)
(glue ","
(make
Line 3,906 ⟶ 4,492:
((= N M) (link N))
((= (inc N) M) (link N M))
(T (link (list N '- M))) ) ) ) ) ) )</langsyntaxhighlight>
{{out}}
<pre>: (rangeextract
Line 3,915 ⟶ 4,501:
 
=={{header|PL/I}}==
<langsyntaxhighlight lang="pli">/* Modified 19 November 2011 to meet requirement that there be at */
/* least 3 items in a run. */
range_extraction: /* 17 August 2010 */
Line 3,962 ⟶ 4,548:
c, d = ',';
end;
end range_extraction;</langsyntaxhighlight>
 
OUTPUT 17/8/2010:
<syntaxhighlight lang="text">
0-2,4,6-8,11-12,14-25,27-33,35-39
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,974 ⟶ 4,560:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function range-extraction($arr) {
if($arr.Count -gt 2) {
Line 4,005 ⟶ 4,591:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39)
</syntaxhighlight>
</lang>
<b>Output:</b>
<pre>
Line 4,015 ⟶ 4,601:
The code uses three predicates '''extract_Range/2''', '''study_Range/2''' and '''pack_Range/2'''.<BR>
Every predicate works in both directions arg1 towards arg2 and arg2 towards arg1, so that '''Range extraction''' and '''Range expansion''' work with the same predicates but in reverse order.
<langsyntaxhighlight Prologlang="prolog">range_extract :-
L = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
Line 4,104 ⟶ 4,690:
 
run(Val,[Other|RRest], [Val, Val],[Other|RRest]).
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,111 ⟶ 4,697:
0-2,4,6-8,11,12,14-25,27-33,35-39
true</pre>
 
=={{header|PureBasic}}==
Even though the example integer list only includes ascending ranges
this code will also handles descending ranges.
<lang PureBasic>DataSection
Data.i 33 ;count of elements to be read
Data.i 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
Data.i 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39
EndDataSection
 
NewList values()
;setup list
Define elementCount, i
Read.i elementCount
For i = 1 To elementCount
AddElement(values()): Read.i values()
Next
Procedure.s rangeExtract(List values())
Protected listSize = ListSize(values()) - 1
Protected rangeMarker, rangeStart, rangeIncrement, retraceSteps, rangeSize, endOfRange, output.s, sub.s
ForEach values()
rangeStart = values():
sub = Str(rangeStart)
If NextElement(values())
retraceSteps = 1
rangeIncrement = values() - rangeStart
If rangeIncrement = 1 Or rangeIncrement = -1
;found start of possible range
If ListIndex(values()) <> listSize
retraceSteps = 2
rangeSize = 2
endOfRange = #False
rangeMarker = values()
While NextElement(values())
If values() - rangeMarker <> rangeIncrement
endOfRange = #True
Break
EndIf
rangeSize + 1
rangeMarker = values()
Wend
If rangeSize > 2
sub = Str(rangeStart) + "-" + Str(rangeMarker)
If Not endOfRange
retraceSteps = 0 ;at end of list
Else
retraceSteps = 1
EndIf
EndIf
EndIf
EndIf
;return to the value before look-aheads
While retraceSteps > 0
PreviousElement(values()): retraceSteps - 1
Wend
EndIf
output + sub + ","
Next
ProcedureReturn RTrim(output, ",")
EndProcedure
 
If OpenConsole()
PrintN(rangeExtract(values()))
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf</lang>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Python}}==
===Procedural===
====Python: for ordered sequences====
<langsyntaxhighlight lang="python">def range_extract(lst):
'Yield 2-tuple ranges or 1-tuple single elements from list of increasing ints'
lenlst = len(lst)
Line 4,218 ⟶ 4,728:
23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39]]:
#print(list(range_extract(lst)))
printr(range_extract(lst))</langsyntaxhighlight>
 
{{out}}
Line 4,232 ⟶ 4,742:
A more general method that works on any sequential [https://docs.python.org/3/library/collections.abc.html?highlight=iterable#collections.abc.Iterable Iterable] of integers, not only [https://docs.python.org/3/library/collections.abc.html?highlight=iterable#collections.abc.Sequence Sequences]:
 
<langsyntaxhighlight lang="python">def range_extract(iterable):
'''Assumes iterable is sorted sequentially. Returns iterator of range tuples.'''
it = iter(iterable)
Line 4,280 ⟶ 4,790:
23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39]]:
#print(list(range_extract(lst)))
printr(range_extract(lst))</langsyntaxhighlight>
 
{{out}}
Line 4,289 ⟶ 4,799:
Note that for an iterable yielding <code>1,2,3,6,7,8</code> the only way to determine the end of the first section of incremented numbers, <code>1,2,3</code> is to read the next number <code>6</code>, This next example defines an iterator where the <code>6</code> can be pushed back and so more cleanly made available for inclusion in detrmining the next sub-sequence of <code>6,7,8</code>.
 
<langsyntaxhighlight lang="python">class PushableIter():
"Can push items back on iterable"
def __init__(self, it):
Line 4,324 ⟶ 4,834:
yield (hi,)
else:
yield (low,)</langsyntaxhighlight>
{{out}}
When substituted for function <code>range_extract</code> in the first Python example it gives the same results.
Line 4,337 ⟶ 4,847:
{{Trans|AppleScript}}
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Range extraction'''
 
from functools import reduce
Line 4,425 ⟶ 4,935:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Range extraction:
Line 4,435 ⟶ 4,945:
 
=={{header|Qi}}==
<syntaxhighlight lang="qi">
<lang qi>
(define make-range
Start Start -> ["," Start]
Line 4,453 ⟶ 4,963:
25 27 28 29 30 31 32 33 35 36
37 38 39])
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,462 ⟶ 4,972:
=={{header|R}}==
 
<langsyntaxhighlight lang="rsplus">extract.range = function(v) {
r <- c(1, which(diff(v) != 1) + 1, length(v) + 1)
paste0(collapse=",",
Line 4,477 ⟶ 4,987:
print(extract.range(c(
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)))</langsyntaxhighlight>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 4,495 ⟶ 5,005:
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"
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line>sub range-extraction (*@ints) {
my $prev = NaN;
my @ranges;
Line 4,522 ⟶ 5,032:
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39;</langsyntaxhighlight>
 
{{out}}
Line 4,531 ⟶ 5,041:
Note that the two numbers &nbsp; '''11''' &nbsp; and &nbsp; '''12''' &nbsp; are not considered a range.
===version 1===
This REXX version isn't limited to integers. &nbsp; It doesn't need a magic number to terminate the list.
<langsyntaxhighlight lang="rexx">/*REXX program creates a range extraction from a list of numbers (can be negative.) */
old=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
#= words(old) /*number of integers in the number list*/
new= /*the new list, possibly with ranges. */
do j=1 to #; xz= word(old, j) /*obtain Jth number in the old list. */
newinc= new',' x 1; new= new','z /*append " " to " new " */
inc= 1 /*start with an increment of one (1). */
do k=j+1 to #; y= word(old, k) /*get the Kth number in the number list*/
if y\==xz+inc then leave /*is this number not > previous by inc?*/
inc= inc + 1; g= y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=xz+1 then iterate /*Is the range=0│1? Then keep truckin'*/
new= new'-'g; j= k - 1 /*indicate a range of #s; change index*/
end /*j*/
/*stick a fork in it, we're all done. */
new= space( substr(new, 2), 0) /*elide the leading comma, alsoin allthe blanksrange.*/
say 'old:' old; say 'new:' new /*displayshow the old and new range of numbers. */</syntaxhighlight>
{{out|output|text=&nbsp; when using the (internal) default list of numbers:}}
say 'new:' new /* " " new list " " */</lang>
'''output''' &nbsp; when using the (internal) list of numbers:
<pre>
old: 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
new: 0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
<!-- elided version 1a as it was slower and less idiomatic.
 
===version 1a===
The REXX version is the same as above, but doesn't modify a &nbsp; '''do''' &nbsp; loop's index &nbsp; ('''j''').,
<br>and it also doesn't need a magic number to terminate the list.
<lang rexx>/*REXX program creates a range extraction from a list of numbers (can be negative.) */
<syntaxhighlight lang="rexx">/*REXX program creates a range extraction from a list of numbers (can be negative.) */
old=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
#= words(old); j= 0 /*number of integers in the number list*/
new= /*the new list, possibly with ranges. */
do while j<#; j= j + 1; xz= word(old, j) /*get the Jth number in the number list*/
newinc=new',' x 1; new= new','z /*append " " to " new " */
inc=1 /*start with an increment of one (1). */
do k=j+1 to #; y= word(old, k) /*get the Kth number in the number list*/
if y\==xz+inc then leave /*is this number not > previous by inc?*/
inc= inc + 1; g= y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=xz+1 then iterate /*Is the range=0│1? Then keep truckin'*/
new= new'-'g; j= k - 1 /*indicate a range of numbers; change J*/
end /*while*/
/*stick a fork in it, we're all done. */
new= space( substr(new, 2), 0) /*elide the leading comma, alsoin allthe blankslist. */
say 'old:' old; say 'new:' new /*displayshow the old and new range of numbers. */</syntaxhighlight>
{{out|output|text=&nbsp; is the same as the 1<sup>st</sup> REXX version (1a).}}<br><br>
say 'new:' new /* " " new list " " */</lang>
!-->
'''output''' &nbsp; is the same as the 1<sup>st</sup> REXX version.<br><br>
 
===version 2===
Somewhat simplified !?!
<langsyntaxhighlight lang="rexx">/*REXX program to test range extraction. ******************************
* 07.08.2012 Walter Pachl
**********************************************************************/
Line 4,611 ⟶ 5,119:
End
Say 'new='ol
</syntaxhighlight>
</lang>
Output is the samesimilar as above.
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Range extraction
 
Line 4,659 ⟶ 5,167:
see svect
see "]" + nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,666 ⟶ 5,174:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">def range_extract(l)
# pad the list with a big value, so that the last loop iteration will
# append something to the range
Line 4,700 ⟶ 5,208:
]
 
p rng = range_extract(lst)</langsyntaxhighlight>
 
{{out}}
Line 4,708 ⟶ 5,216:
{{works with|Ruby|2.2}}
Enumerable#slice_when method became usable.
<langsyntaxhighlight lang="ruby">ary = [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]
puts ary.sort.slice_when{|i,j| i+1 != j}.map{|a| a.size<3 ? a : "#{a[0]}-#{a[-1]}"}.join(",")</langsyntaxhighlight>
 
{{out}}
Line 4,716 ⟶ 5,224:
=={{header|Rust}}==
Iterators are very Rustic. This solution is generic for all numeric types.
<langsyntaxhighlight lang="rust">use std::ops::Add;
struct RangeFinder<'a, T: 'a> {
Line 4,768 ⟶ 5,276:
}
println!("");
}</langsyntaxhighlight>
 
{{out}}
Line 4,776 ⟶ 5,284:
 
Add this to the top of the file:
<langsyntaxhighlight lang="rust">#![feature(zero_one)]
use std::num::One;</langsyntaxhighlight>
 
Changing this line:
<langsyntaxhighlight lang="rust"> impl<'a, T> Iterator for RangeFinder<'a, T> where T: PartialEq + Add<i8, Output=T> + Copy {</langsyntaxhighlight>
to this:
<langsyntaxhighlight lang="rust">impl<'a, T> Iterator for RangeFinder<'a, T> where T: PartialEq + Add<T, Output=T> + Copy + One {</langsyntaxhighlight>
 
And this line:
<langsyntaxhighlight lang="rust"> while self.index < self.length - 1 && self.arr[self.index + 1] == self.arr[self.index] + 1 {</langsyntaxhighlight>
to this:
<langsyntaxhighlight lang="rust"> while self.index < self.length - 1 && self.arr[self.index + 1] == self.arr[self.index] + T::one() {</langsyntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">object Range {
def spanRange(ls:List[Int])={
var last=ls.head
Line 4,814 ⟶ 5,322:
println(toRangeString(toRangeList(l)))
}
}</langsyntaxhighlight>
 
{{out}}
Line 4,821 ⟶ 5,329:
=={{header|Scheme}}==
{{trans|Qi}}
<langsyntaxhighlight lang="scheme">
(define (make-range start end)
(cond ((= start end)
Line 4,850 ⟶ 5,358:
25 27 28 29 30 31 32 33 35 36
37 38 39))
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,858 ⟶ 5,366:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func string: rangeExtraction (in array integer: numbers) is func
Line 4,889 ⟶ 5,397:
writeln(rangeExtraction([] (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)));
end func;</langsyntaxhighlight>
 
{{out}}
Line 4,904 ⟶ 5,412:
Handles +/- and negative ranges.
 
<langsyntaxhighlight SNOBOL4lang="snobol4">* # Absolute value
define('abs(n)') :(abs_end)
abs abs = ~(abs = lt(n,0) -n) n :(return)
Line 4,925 ⟶ 5,433:
+ '37, 38, 39'
output = rangext(test)
end</langsyntaxhighlight>
 
{{out}}
<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.
 
<syntaxhighlight 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
;
</syntaxhighlight>
/
{{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}}==
{{works with|Swift|3}}
 
<langsyntaxhighlight lang="swift">
import Darwin
 
Line 4,983 ⟶ 5,626:
print(description(from: ranges(from: ex)))
print(description(from: ranges(from: longer)))
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,990 ⟶ 5,633:
 
=={{header|Tailspin}}==
<langsyntaxhighlight lang="tailspin">
templates extract
templates out
when <{start: <=$.end::raw>}> do '$.start;' !
when <{end: <=$.start::raw+1>}> do '$.start;,$.end;' !
otherwise '$.start;-$.end;' !
end out
@: {start: $(1), end: $(1)};
[ $(2..last)... -> #, $@ -> out ] -> '$...;' !
when <=$@.end::raw+1> do @.end: $;
otherwise $@ -> out !
',' !
Line 5,009 ⟶ 5,652:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39] -> extract -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,016 ⟶ 5,659:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc rangeExtract list {
set result [lindex $list 0]
set first [set last [lindex $list 0]]
Line 5,044 ⟶ 5,687:
25 27 28 29 30 31 32 33 35 36
37 38 39
}]</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT,{}
MODE DATA
Line 5,063 ⟶ 5,706:
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs
</syntaxhighlight>
</lang>
Output:
<pre>
Line 5,070 ⟶ 5,713:
 
Solution without COMBINE
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
MODE DATA
Line 5,102 ⟶ 5,745:
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,110 ⟶ 5,753:
=={{header|TXR}}==
 
<langsyntaxhighlight lang="txrlisp">(defun range-extract (numbers)
`@{(mapcar [iff [callf > length (ret 2)]
(ret `@[@1 0]-@[@1 -1]`)
Line 5,118 ⟶ 5,761:
(op list @2 (- @2 @1))
(sort (uniq numbers))]
(op where [chain second (op < 1)])))) ","}`)</langsyntaxhighlight>
 
{{out|Run}}
Line 5,132 ⟶ 5,775:
=={{header|UNIX Shell}}==
{{works with|bash}}
<langsyntaxhighlight lang="bash">#!/usr/bin/bash
 
range_contract () (
Line 5,161 ⟶ 5,804:
)
 
range_contract 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</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|Ursala}}==
<langsyntaxhighlight Ursalalang="ursala">#import std
#import int
 
Line 5,175 ⟶ 5,818:
#show+
 
t = <f x></langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|VBAWren}}==
{{trans|Kotlin}}
<lang vb>
<syntaxhighlight lang="wren">var extractRange = Fn.new { |list|
Public Function RangeExtraction(AList) As String
if (list.isEmpty) return ""
'AList is a variant that is an array, assumed filled with numbers in ascending order
var sb = ""
Const RangeDelim = "-" 'range delimiter
var first = list[0]
Dim result As String
var prev = first
Dim InRange As Boolean
Dim Posn, ub, lb, rangestart, rangelen As Integer
 
var append = Fn.new { |index|
result = ""
if (first == prev) {
'find dimensions of AList
sb = sb + prev.toString
ub = UBound(AList)
} else if (first == prev - 1) {
lb = LBound(AList)
sb = sb + first.toString + "," + prev.toString
Posn = lb
} else {
While Posn < ub
sb = sb + first.toString + "-" + prev.toString
rangestart = Posn
rangelen = 0 }
if (index < list.count - 1) sb = sb + ","
InRange = True
}
'try to extend the range
While InRange
rangelen = rangelen + 1
If Posn = ub Then
InRange = False
Else
InRange = (AList(Posn + 1) = AList(Posn) + 1)
Posn = Posn + 1
End If
Wend
If rangelen > 2 Then 'output the range if it has more than 2 elements
result = result & "," & Format$(AList(rangestart)) & RangeDelim & Format$(AList(rangestart + rangelen - 1))
Else 'output the separate elements
For i = rangestart To rangestart + rangelen - 1
result = result & "," & Format$(AList(i))
Next
End If
Posn = rangestart + rangelen
Wend
RangeExtraction = Mid$(result, 2) 'get rid of first comma!
End Function
 
for (i in 1...list.count) {
if (list[i] == prev + 1) {
prev = prev + 1
} else {
append.call(i)
first = list[i]
prev = first
}
}
append.call(list.count - 1)
return sb
}
 
var list1 = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
Public Sub RangeTest()
System.print(extractRange.call(list1))
'test function RangeExtraction
var list2 = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
'first test with a Variant array
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
Dim MyList As Variant
MyList = Array(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)
37, 38, 39]
Debug.Print "a) "; RangeExtraction(MyList)
System.print(extractRange.call(list2))</syntaxhighlight>
 
'next test with an array of integers
Dim MyOtherList(1 To 20) As Integer
MyOtherList(1) = -6
MyOtherList(2) = -3
MyOtherList(3) = -2
MyOtherList(4) = -1
MyOtherList(5) = 0
MyOtherList(6) = 1
MyOtherList(7) = 3
MyOtherList(8) = 4
MyOtherList(9) = 5
MyOtherList(10) = 7
MyOtherList(11) = 8
MyOtherList(12) = 9
MyOtherList(13) = 10
MyOtherList(14) = 11
MyOtherList(15) = 14
MyOtherList(16) = 15
MyOtherList(17) = 17
MyOtherList(18) = 18
MyOtherList(19) = 19
MyOtherList(20) = 20
Debug.Print "b) "; RangeExtraction(MyOtherList)
End Sub
</lang>
 
{{out}}
<pre>
-6,-3-1,3-5,7-11,14,15,17-20
RangeTest
a) 0-2,4,6-8,11,12,14-25,27-33,35-39
b) -6,-3-1,3-5,7-11,14,15,17-20
</pre>
 
=={{header|VBScriptXPL0}}==
XPL0 does not provide much in the way of string handling features. In
<lang vb>Function Range_Extraction(list)
this regard it's more like C than Basic. To overcome this limitation some
num = Split(list,",")
questionable techniques (or downright nasty tricks) are used here.
For i = 0 To UBound(num)
 
startnum = CInt(num(i))
Ordinarily, RangeExtract would simply output the result to the console
sum = startnum
and be done with it, but the task insists on having a string returned.
Do While i <= UBound(num)
Thus, instead of outputting to the console, which is device 0, it outputs
If sum = CInt(num(i)) Then
to device 8, which is a buffer that can be written and read much like an
If i = UBound(num) Then
ordinary file. It is read into String to meet the requirement.
If startnum <> CInt(num(i)) Then
 
If startnum + 1 = CInt(num(i)) Then
The zero-length String declaration works as long as there are no
Range_Extraction = Range_Extraction & startnum & "," & num(i) & ","
variables declared after it that it can grow into. This must be true not
Else
only in the RangeExtract function but also for any routines it calls. In
Range_Extraction = Range_Extraction & startnum & "-" & num(i) & ","
the case here all the routines called are "intrinsic" routines (such as
End If
IntOut) that don't use the same memory space as XPL0 variables.
Else
 
Range_Extraction = Range_Extraction & startnum & ","
A safer possibility would have been to declare String globally with a
End If
sufficiently large size, but that seemed less elegant.
Exit Do
 
Else
Another limitation of XPL0 is that it is not able to determine the size
i = i + 1
of an array, such as with a "sizeof List" command. Thus a sentinel (End)
sum = sum + 1
is used. The -1>>1 provides the largest possible signed integer for both
End If
the normal 32-bit integer versions of the language and for the older
Else
16-bit versions.
If startnum = CInt(num(i-1)) Then
 
Range_Extraction = Range_Extraction & startnum & ","
An unusual feature of XPL0 is that it traditionally terminates strings by
Else
setting the high bit of the last byte. The command "string 0" changes
If startnum + 1 = CInt(num(i-1)) Then
this to terminate strings by appending a zero byte.
Range_Extraction = Range_Extraction & startnum & "," & num(i-1) & ","
 
Else
<syntaxhighlight lang "XPL0">
Range_Extraction = Range_Extraction & startnum & "-" & num(i-1) & ","
string 0;
End If
def End If= -1>>1;
 
i = i - 1
func RangeExtract(List); \Return a string in the range format
Exit Do
int List, I, Lo, Hi;
End If
char String(0);
Loop
[I:= 0;
Next
loop [Lo:= List(I);
Range_Extraction = Left(Range_Extraction,Len(Range_Extraction)-1)
while List(I)+1 = List(I+1) do I:= I+1;
End Function
Hi:= List(I);
IntOut(8, Lo);
WScript.StdOut.Write 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")</lang>
if Hi-Lo >= 2 then
[ChOut(8, ^-); IntOut(8, Hi)]
else if Hi-Lo = 1 then
[ChOut(8, ^,); IntOut(8, Hi)];
I:= I+1;
if List(I) = End then quit;
ChOut(8, ^,);
];
ChOut(8, 0);
I:= 0;
loop [String(I):= ChIn(8);
if String(I) = 0 then return String;
I:= I+1;
];
];
 
Text(0, RangeExtract(
[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, End]) )</syntaxhighlight>
{{out}}
<pre>
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn range(ns){
fcn(w){
if (w.atEnd) return(Void.Stop);
Line 5,315 ⟶ 5,945:
} :
(0).pump(*,List,_.fp(ns.walker().tweak(Void,Void))).concat(",");
}</langsyntaxhighlight>
The trick here is to use a modified iterator,
one that can look past the end of the sequence without puking.
The function gathers three or more successive ints (saved as a "a-b" string list element) or just returns the first one (as a number) if it can't.
The resulting list is converted to strings separated by commas.
<langsyntaxhighlight lang="zkl">var ns=T(-6,-3,-2,-1,0,1,3,4,5,7,8,9,10,11,14,15,17,18,19,20);
range(ns).println();
 
Line 5,330 ⟶ 5,960:
range(ns).println();
 
range([1..100]).println();</langsyntaxhighlight>
 
{{out}}
1,983

edits