Range extraction: Difference between revisions

m
(11 intermediate revisions by 7 users not shown)
Line 20:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F range_extract(lst)
[[Int]] r
V lenlst = lst.len
Line 46:
[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))</langsyntaxhighlight>
 
{{out}}
Line 55:
 
=={{header|Action!}}==
<langsyntaxhighlight Actionlang="action!">INT FUNC FindRange(INT ARRAY a INT len,start)
INT count
Line 121:
RangeToStr(b,20,res)
PrintE(res)
RETURN</langsyntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Range_extraction.png Screenshot from Atari 8-bit computer]
Line 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 185:
37, 38, 39
) ) );
end Range_Extraction;</langsyntaxhighlight>
 
 
Line 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 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 244:
=={{header|Aime}}==
 
<langsyntaxhighlight lang="aime">rp(list l)
{
integer a, i;
Line 269:
 
0;
}</langsyntaxhighlight>
 
{{out}}
Line 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 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 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 439:
REPR list c
))
END</langsyntaxhighlight>
 
{{out}}
Line 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 544:
);
 
OP (UNIRANGELISTS)UNIRANGELIST INITUNIRANGE = unirange list init; # alias #</langsyntaxhighlight>
{{out}}
<pre style="height:15ex;overflow:scroll">
Line 557:
===Functional===
{{Trans|JavaScript}}
<langsyntaxhighlight AppleScriptlang="applescript">--------------------- RANGE EXTRACTION ---------------------
 
-- rangeFormat :: [Int] -> String
Line 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 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 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 736 ⟶ 773:
}
return SubStr(ret (f!=p ? (p>f+1 ? "-" : ",") p : ""), 2)
}</langsyntaxhighlight>
{{out}}
<pre>---------------------------
Line 753 ⟶ 790:
by convention, separated from the expected ones by extra space.
 
<langsyntaxhighlight lang="awk">#!/usr/bin/awk -f
 
BEGIN {
Line 806 ⟶ 843:
sequence[s] = a[s]
}
}</langsyntaxhighlight>
 
{{out}}
Line 814 ⟶ 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 841 ⟶ 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 898 ⟶ 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 908 ⟶ 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 943 ⟶ 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 1,006 ⟶ 1,538:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,012 ⟶ 1,544:
 
===C#: Alternate Version===
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 1,047 ⟶ 1,579:
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,055 ⟶ 1,587:
=={{header|C++}}==
 
<langsyntaxhighlight lang="cpp">
#include <iostream>
#include <iterator>
Line 1,109 ⟶ 1,641:
std::cout << std::endl;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,116 ⟶ 1,648:
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">shared void run() {
value numbers = [
Line 1,159 ⟶ 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,165 ⟶ 1,697:
=={{header|Clojure}}==
{{libheader|org.flatland/useful}}
<langsyntaxhighlight lang="clojure">(use '[flatland.useful.seq :only (partition-between)])
 
(defn nonconsecutive? [[x y]]
Line 1,180 ⟶ 1,712:
(defn format-with-ranges [coll]
(println (clojure.string/join ","
(map string-ranges (partition-between nonconsecutive? coll)))))</langsyntaxhighlight>
 
{{out}}
Line 1,190 ⟶ 1,722:
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
<langsyntaxhighlight lang="cobol"> IDENTIFICATION DIVISION.
PROGRAM-ID. extract-range-task.
Line 1,369 ⟶ 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,385 ⟶ 1,917:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun format-with-ranges (list)
(unless list (return ""))
(with-output-to-string (s)
Line 1,411 ⟶ 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,443 ⟶ 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
Line 1,453 ⟶ 1,985:
 
=={{header|DWScript}}==
<langsyntaxhighlight lang="delphi">procedure ExtractRanges(const values : array of Integer);
begin
var i:=0;
Line 1,477 ⟶ 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,485 ⟶ 2,017:
{{trans|Go}}
 
<langsyntaxhighlight lang="dyalect">func rangeFormat(a) {
if a.Length() == 0 {
return ""
Line 1,523 ⟶ 2,055:
37, 38, 39
])
print("range format: \(rf)")</langsyntaxhighlight>
 
{{out}}
Line 1,533 ⟶ 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,549 ⟶ 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,557 ⟶ 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,585 ⟶ 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,661 ⟶ 2,223:
end
end
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 1,670 ⟶ 2,232:
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule RC do
def range_extract(list) do
max = Enum.max(list) + 2
Line 1,699 ⟶ 2,261:
37, 38, 39
]
IO.inspect RC.range_extract(list)</langsyntaxhighlight>
 
{{out}}
Line 1,709 ⟶ 2,271:
 
{{libheader|Gnus}}
<langsyntaxhighlight Lisplang="lisp">(require 'gnus-range)
 
(defun rangext (lst)
Line 1,725 ⟶ 2,287:
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>
 
Vanilla:
<langsyntaxhighlight Lisplang="lisp">(defun split-into-ranges (numbers)
(let* ((last-number (pop numbers))
(range (list last-number))
Line 1,758 ⟶ 2,320:
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>
 
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( range ).
 
Line 1,783 ⟶ 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,791 ⟶ 2,353:
 
=={{header|Euphoria}}==
<langsyntaxhighlight lang="euphoria">function extract_ranges(sequence s)
integer first
sequence out
Line 1,822 ⟶ 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,828 ⟶ 2,390:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let extractRanges = function
| [] -> Seq.empty
| x::xr ->
Line 1,851 ⟶ 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,858 ⟶ 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,875 ⟶ 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,882 ⟶ 2,444:
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">create values
here
0 , 1 , 2 , 4 , 6 , 7 , 8 , 11 , 12 , 14 ,
Line 1,908 ⟶ 2,470:
;
 
values /values .ranges</langsyntaxhighlight>
 
{{out}}
Line 1,920 ⟶ 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,978 ⟶ 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,151 ⟶ 2,599:
}
return strings.Join(parts, ","), nil
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,159 ⟶ 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,170 ⟶ 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,179 ⟶ 2,627:
37, 38, 39
'''
println (compressRanges(s))</langsyntaxhighlight>
 
{{out}}
Line 2,186 ⟶ 2,634:
=={{header|Haskell}}==
===direct recursion===
<langsyntaxhighlight lang="haskell">import Data.List (intercalate)
 
extractRange :: [Int] -> String
Line 2,198 ⟶ 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,207 ⟶ 2,655:
Delegating to splitBy allows a reasonably clean definition of range formatting:
 
<langsyntaxhighlight lang="haskell">import Data.List (intercalate)
import Data.Function (on)
 
Line 2,274 ⟶ 2,722:
, 38
, 39
]</langsyntaxhighlight>
{{Out}}
<pre>"0-2,4,6-8,11,12,14-25,27-33,35-39"</pre>
Line 2,281 ⟶ 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,309 ⟶ 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,346 ⟶ 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,356 ⟶ 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,411 ⟶ 2,859:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39,</pre>
Line 2,418 ⟶ 2,866:
===ES5===
====Imperative====
<langsyntaxhighlight lang="javascript">function rangeExtraction(list) {
var len = list.length;
var out = [];
Line 2,452 ⟶ 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,520 ⟶ 2,968:
33, 35, 36, 37, 38, 39
]);
})();</langsyntaxhighlight>
 
{{Out}}
Line 2,529 ⟶ 2,977:
{{Trans|Haskell}}
Defining the range format in terms of a reusable '''splitBy''' function:
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
Line 2,594 ⟶ 3,042:
// MAIN --
return main();
})();</langsyntaxhighlight>
{{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,650 ⟶ 3,098:
console.log(`expected output : '${expected}'.`);
console.log(`Correct? ${ actual === expected ? 'Yes' : 'No'}`);
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,658 ⟶ 3,106:
 
=={{header|jq}}==
<langsyntaxhighlight lang="kq"># Input should be an array
def extract:
reduce .[] as $i
Line 2,677 ⟶ 3,125:
then "\(.[0]),\(.[1])" # satisfy special requirement
else "\(.[0])-\(.[1])" end )
| join(",") ;</langsyntaxhighlight>
 
{{out|Command and output}}
Line 2,686 ⟶ 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,721 ⟶ 3,169:
 
puts(arr);
puts(rangeExtraction(arr));</langsyntaxhighlight>
 
{{out}}
Line 2,730 ⟶ 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,749 ⟶ 3,197:
println("Testing range-style formatting.")
println(" ", testa, "\n =>\n ", sprintfrange(testa))
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,759 ⟶ 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,768 ⟶ 3,216:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.0.6
 
fun extractRange(list: List<Int>): String {
Line 2,804 ⟶ 3,252:
37, 38, 39)
println(extractRange(list2))
}</langsyntaxhighlight>
 
{{out}}
Line 2,811 ⟶ 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,884 ⟶ 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,893 ⟶ 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,924 ⟶ 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,940 ⟶ 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}}==
<langsyntaxhighlight Mathematicalang="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}]</langsyntaxhighlight>
{{out}}
<pre>"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,975 ⟶ 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,981 ⟶ 3,389:
 
=={{header|Mercury}}==
<langsyntaxhighlight Mercurylang="mercury">:- module range_extraction.
:- interface.
 
Line 3,021 ⟶ 3,429:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39].
</syntaxhighlight>
</lang>
 
=={{header|MiniScript}}==
<langsyntaxhighlight MiniScriptlang="miniscript">extractRange = function(ints)
result = []
idx = 0
Line 3,045 ⟶ 3,453:
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}}
Line 3,051 ⟶ 3,459:
 
=={{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 3,067 ⟶ 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 3,076 ⟶ 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,112 ⟶ 3,520:
End
End
Say 'new='ol</langsyntaxhighlight>
{{out}}
<pre>
Line 3,122 ⟶ 3,530:
===NetRexx Ver. 2===
{{trans|Java}}
<langsyntaxhighlight NetRexxlang="netrexx">/* NetRexx */
options replace format comments java crossref symbols nobinary
 
Line 3,198 ⟶ 3,606:
end r_
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,212 ⟶ 3,620:
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import parseutils, re, strutils, sequtils
 
proc extractRange(input: string): string =
Line 3,241 ⟶ 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,248 ⟶ 3,656:
=={{header|Oberon-2}}==
Oxford Oberon-2
<langsyntaxhighlight lang="oberon2">
MODULE RangeExtraction;
IMPORT Out;
Line 3,341 ⟶ 3,749:
Range(seq1)
END RangeExtraction.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,350 ⟶ 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,396 ⟶ 3,804:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Objective-C}}==
Line 3,403 ⟶ 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,436 ⟶ 3,844:
}
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,443 ⟶ 3,851:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">let range_extract = function
| [] -> []
| x::xs ->
Line 3,463 ⟶ 3,871:
in
let rng = range_extract li in
print_endline(string_of_range rng)</langsyntaxhighlight>
 
{{out}}
Line 3,469 ⟶ 3,877:
 
=={{header|Ol}}==
<langsyntaxhighlight lang="scheme">
(define (extract ll)
(let loop ((head (car ll)) (tail (cdr ll)) (out #null))
Line 3,498 ⟶ 3,906:
(print "extracted ranges: " range)
(print "string representation: " (range->string range))
</syntaxhighlight>
</lang>
{{Out}}
<pre>$ ol range_extraction.scm
Line 3,508 ⟶ 3,916:
{{trans|NetRexx Ver. 2}}
{{trans|Java}}
<langsyntaxhighlight ooRexxlang="oorexx">/* Rexx */
 
parse arg userInput
Line 3,587 ⟶ 3,995:
end r_
return
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,599 ⟶ 4,007:
Compacted: -4--2,0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|OxygenBasic}}==
<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
</lang>
 
=={{header|Oz}}==
<langsyntaxhighlight lang="oz">declare
fun {Extract Xs}
{CommaSeparated
Line 3,698 ⟶ 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,708 ⟶ 4,065:
{{works with|Delphi}}
 
<langsyntaxhighlight Pascallang="pascal">program RangeExtractionApp;
 
 
Line 3,787 ⟶ 4,144:
37, 38, 39]);
{$IFNDEF UNIX}readln;{$ENDIF}
end.</langsyntaxhighlight>
 
{{out}}
Line 3,816 ⟶ 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,830 ⟶ 4,187:
25 27 28 29 30 31 32 33 35 36
37 38 39);
print rangext(@test), "\n";</langsyntaxhighlight>
 
{{out}}
Line 3,837 ⟶ 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}}==
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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>
Line 3,881 ⟶ 4,238:
<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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 3,888 ⟶ 4,245:
 
=={{header|Phixmonti}}==
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
( ) var res
Line 3,933 ⟶ 4,290:
clear
 
printRes</langsyntaxhighlight>
The same result in all examples.
{{out}}
Line 3,940 ⟶ 4,297:
A bit less ugly
 
<langsyntaxhighlight Phixmontilang="phixmonti">include ..\Utilitys.pmt
 
( 0 1 2 4 6 7 8 11 12 14
Line 3,978 ⟶ 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 4,012 ⟶ 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 4,055 ⟶ 4,412:
endfor
 
"," glue lprint</langsyntaxhighlight>
 
=={{header|Picat}}==
<langsyntaxhighlight Picatlang="picat">go =>
Lists = [
[-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9,
Line 4,105 ⟶ 4,462:
cond(R.length == 1,
R.first().to_string(),
min(R).to_string() ++ "-" ++ max(R).to_string()).</langsyntaxhighlight>
 
{{out}}
Line 4,125 ⟶ 4,482:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de rangeextract (Lst)
(glue ","
(make
Line 4,135 ⟶ 4,492:
((= N M) (link N))
((= (inc N) M) (link N M))
(T (link (list N '- M))) ) ) ) ) ) )</langsyntaxhighlight>
{{out}}
<pre>: (rangeextract
Line 4,144 ⟶ 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 4,191 ⟶ 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 4,203 ⟶ 4,560:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function range-extraction($arr) {
if($arr.Count -gt 2) {
Line 4,234 ⟶ 4,591:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39)
</syntaxhighlight>
</lang>
<b>Output:</b>
<pre>
Line 4,244 ⟶ 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,333 ⟶ 4,690:
 
run(Val,[Other|RRest], [Val, Val],[Other|RRest]).
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,340 ⟶ 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,447 ⟶ 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,461 ⟶ 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,509 ⟶ 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,518 ⟶ 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,553 ⟶ 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,566 ⟶ 4,847:
{{Trans|AppleScript}}
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">'''Range extraction'''
 
from functools import reduce
Line 4,654 ⟶ 4,935:
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>Range extraction:
Line 4,664 ⟶ 4,945:
 
=={{header|Qi}}==
<syntaxhighlight lang="qi">
<lang qi>
(define make-range
Start Start -> ["," Start]
Line 4,682 ⟶ 4,963:
25 27 28 29 30 31 32 33 35 36
37 38 39])
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,691 ⟶ 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,706 ⟶ 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,724 ⟶ 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,751 ⟶ 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,761 ⟶ 5,042:
===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*/
Line 4,776 ⟶ 5,057:
/*stick a fork in it, we're all done. */
new= substr(new, 2) /*elide the leading comma in the range.*/
say 'old:' old; say 'new:' new /*show the old and new range of numbers*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the (internal) default list of numbers:}}
<pre>
Line 4,786 ⟶ 5,067:
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.
<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); j= 0 /*number of integers in the number list*/
Line 4,801 ⟶ 5,082:
/*stick a fork in it, we're all done. */
new= substr(new, 2) /*elide the leading comma in the list. */
say 'old:' old; say 'new:' new /*show the old and new range of numbers*/</langsyntaxhighlight>
{{out|output|text=&nbsp; is the same as the 1<sup>st</sup> REXX version (1a).}}<br><br>
!-->
Line 4,807 ⟶ 5,088:
===version 2===
Somewhat simplified !?!
<langsyntaxhighlight lang="rexx">/*REXX program to test range extraction. ******************************
* 07.08.2012 Walter Pachl
**********************************************************************/
Line 4,838 ⟶ 5,119:
End
Say 'new='ol
</syntaxhighlight>
</lang>
Output is similar as above.
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Range extraction
 
Line 4,886 ⟶ 5,167:
see svect
see "]" + nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,893 ⟶ 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,927 ⟶ 5,208:
]
 
p rng = range_extract(lst)</langsyntaxhighlight>
 
{{out}}
Line 4,935 ⟶ 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,943 ⟶ 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,995 ⟶ 5,276:
}
println!("");
}</langsyntaxhighlight>
 
{{out}}
Line 5,003 ⟶ 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 5,041 ⟶ 5,322:
println(toRangeString(toRangeList(l)))
}
}</langsyntaxhighlight>
 
{{out}}
Line 5,048 ⟶ 5,329:
=={{header|Scheme}}==
{{trans|Qi}}
<langsyntaxhighlight lang="scheme">
(define (make-range start end)
(cond ((= start end)
Line 5,077 ⟶ 5,358:
25 27 28 29 30 31 32 33 35 36
37 38 39))
</syntaxhighlight>
</lang>
 
{{out}}
Line 5,085 ⟶ 5,366:
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func string: rangeExtraction (in array integer: numbers) is func
Line 5,116 ⟶ 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 5,131 ⟶ 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 5,152 ⟶ 5,433:
+ '37, 38, 39'
output = rangext(test)
end</langsyntaxhighlight>
 
{{out}}
Line 5,161 ⟶ 5,442:
This is not a particularly efficient solution, but it gets the job done.
 
<syntaxhighlight lang="sql">
<lang SQL>
/*
This code is an implementation of "Range extraction" in SQL ORACLE 19c
Line 5,272 ⟶ 5,553:
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>
</lang>
/
{{out}}
Line 5,295 ⟶ 5,576:
{{works with|Swift|3}}
 
<langsyntaxhighlight lang="swift">
import Darwin
 
Line 5,345 ⟶ 5,626:
print(description(from: ranges(from: ex)))
print(description(from: ranges(from: longer)))
</syntaxhighlight>
</lang>
 
{{out}}
Line 5,352 ⟶ 5,633:
 
=={{header|Tailspin}}==
<langsyntaxhighlight lang="tailspin">
templates extract
templates out
Line 5,371 ⟶ 5,652:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39] -> extract -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,378 ⟶ 5,659:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">proc rangeExtract list {
set result [lindex $list 0]
set first [set last [lindex $list 0]]
Line 5,406 ⟶ 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,425 ⟶ 5,706:
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs
</syntaxhighlight>
</lang>
Output:
<pre>
Line 5,432 ⟶ 5,713:
 
Solution without COMBINE
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
MODE DATA
Line 5,464 ⟶ 5,745:
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,472 ⟶ 5,753:
=={{header|TXR}}==
 
<langsyntaxhighlight lang="txrlisp">(defun range-extract (numbers)
`@{(mapcar [iff [callf > length (ret 2)]
(ret `@[@1 0]-@[@1 -1]`)
Line 5,480 ⟶ 5,761:
(op list @2 (- @2 @1))
(sort (uniq numbers))]
(op where [chain second (op < 1)])))) ","}`)</langsyntaxhighlight>
 
{{out|Run}}
Line 5,494 ⟶ 5,775:
=={{header|UNIX Shell}}==
{{works with|bash}}
<langsyntaxhighlight lang="bash">#!/usr/bin/bash
 
range_contract () (
Line 5,523 ⟶ 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,537 ⟶ 5,818:
#show+
 
t = <f x></langsyntaxhighlight>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
 
=={{header|VBA}}==
<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
</lang>
 
{{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}}==
<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")</lang>
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
Line 5,669 ⟶ 5,824:
=={{header|Wren}}==
{{trans|Kotlin}}
<langsyntaxhighlight ecmascriptlang="wren">var extractRange = Fn.new { |list|
if (list.isEmpty) return ""
var sb = ""
Line 5,705 ⟶ 5,860:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]
System.print(extractRange.call(list2))</langsyntaxhighlight>
 
{{out}}
Line 5,712 ⟶ 5,867:
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
 
=={{header|XPL0}}==
XPL0 does not provide much in the way of string handling features. In
this regard it's more like C than Basic. To overcome this limitation some
questionable techniques (or downright nasty tricks) are used here.
 
Ordinarily, RangeExtract would simply output the result to the console
and be done with it, but the task insists on having a string returned.
Thus, instead of outputting to the console, which is device 0, it outputs
to device 8, which is a buffer that can be written and read much like an
ordinary file. It is read into String to meet the requirement.
 
The zero-length String declaration works as long as there are no
variables declared after it that it can grow into. This must be true not
only in the RangeExtract function but also for any routines it calls. In
the case here all the routines called are "intrinsic" routines (such as
IntOut) that don't use the same memory space as XPL0 variables.
 
A safer possibility would have been to declare String globally with a
sufficiently large size, but that seemed less elegant.
 
Another limitation of XPL0 is that it is not able to determine the size
of an array, such as with a "sizeof List" command. Thus a sentinel (End)
is used. The -1>>1 provides the largest possible signed integer for both
the normal 32-bit integer versions of the language and for the older
16-bit versions.
 
An unusual feature of XPL0 is that it traditionally terminates strings by
setting the high bit of the last byte. The command "string 0" changes
this to terminate strings by appending a zero byte.
 
<syntaxhighlight lang "XPL0">
string 0;
def End = -1>>1;
 
func RangeExtract(List); \Return a string in the range format
int List, I, Lo, Hi;
char String(0);
[I:= 0;
loop [Lo:= List(I);
while List(I)+1 = List(I+1) do I:= I+1;
Hi:= List(I);
IntOut(8, Lo);
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>
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,723 ⟶ 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,738 ⟶ 5,960:
range(ns).println();
 
range([1..100]).println();</langsyntaxhighlight>
 
{{out}}
1,983

edits