Range extraction: Difference between revisions
m
→{{header|EasyLang}}
(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.
<
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;</
Line 79 ⟶ 192:
The recursive solution avoids the usage of unbounded strings.
<
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;</
{{out}}
Line 131 ⟶ 244:
=={{header|Aime}}==
<
{
integer a, i;
Line 156 ⟶ 269:
0;
}</
{{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'''
<
REQUIRES(MODE SCALAR, OP(SCALAR,SCALAR)BOOL =, OP(SCALAR,SCALAR)SCALAR +);
###
Line 223 ⟶ 336:
);
OP (UNIRANGELIST)STRING REPR = unirange list repr; # alias #</
<
REQUIRES(MODE SCALAR, OP(SCALAR,SCALAR)BOOL =, OP(SCALAR,SCALAR)SCALAR +);
###
Line 283 ⟶ 396:
out unirange list[:upb out unirange list]
);</
############################
# some simple test cases: #
Line 326 ⟶ 439:
REPR list c
))
END</
{{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'''
<
REQUIRES(MODE SCALAR, OP(SCALAR,SCALAR)BOOL =, OP(SCALAR,SCALAR)SCALAR +);
###
Line 431 ⟶ 544:
);
OP (UNIRANGELISTS)UNIRANGELIST INITUNIRANGE = unirange list init; # alias #</
{{out}}
<pre style="height:15ex;overflow:scroll">
Line 444 ⟶ 557:
===Functional===
{{Trans|JavaScript}}
<
-- rangeFormat :: [Int] -> String
Line 553 ⟶ 666:
item 1 of lstParts & {item 2 of lstParts}
end if
end splitBy</
{{Out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
Line 559 ⟶ 672:
===Straightforward===
<
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)</
{{output}}
<
=={{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}}==
<
extract( list ) {
Line 623 ⟶ 773:
}
return SubStr(ret (f!=p ? (p>f+1 ? "-" : ",") p : ""), 2)
}</
{{out}}
<pre>---------------------------
Line 640 ⟶ 790:
by convention, separated from the expected ones by extra space.
<
BEGIN {
Line 693 ⟶ 843:
sequence[s] = a[s]
}
}</
{{out}}
Line 701 ⟶ 851:
</pre>
=={{header|
==={{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}}
<
\ "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$)</
{{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}}==
<
= 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)</
{{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.
<
#include <stdlib.h>
Line 830 ⟶ 1,475:
return 0;
}</
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
=={{header|C sharp}}==
<
using System.Collections.Generic;
using System.Linq;
Line 893 ⟶ 1,538:
}
}
</syntaxhighlight>
{{out}}
Line 899 ⟶ 1,544:
===C#: Alternate Version===
<
using System.Collections.Generic;
using System.Linq;
Line 934 ⟶ 1,579:
}
}</
{{out}}
<pre>
Line 942 ⟶ 1,587:
=={{header|C++}}==
<
#include <iostream>
#include <iterator>
Line 996 ⟶ 1,641:
std::cout << std::endl;
}
</syntaxhighlight>
{{out}}
<pre>
Line 1,003 ⟶ 1,648:
=={{header|Ceylon}}==
<
value numbers = [
Line 1,046 ⟶ 1,691:
assert(rangeString == "0-2,4,6-8,11,12,14-25,27-33,35-39");
print(rangeString);
}</
{{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}}
<
(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)))))</
{{out}}
Line 1,077 ⟶ 1,722:
=={{header|COBOL}}==
{{works with|OpenCOBOL}}
<
PROGRAM-ID. extract-range-task.
Line 1,256 ⟶ 1,901:
END PROGRAM find-num-trailing-spaces.
END PROGRAM extract-range.</
nums-table.cpy:
<
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.</
{{out}}
Line 1,272 ⟶ 1,917:
=={{header|Common Lisp}}==
<
(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>
=={{header|D}}==
<
string rangeExtraction(in int[] items)
Line 1,330 ⟶ 1,975:
32, 33, 35, 36, 37, 38, 39]])
data.rangeExtraction.writeln;
}</
{{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}}==
<
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]);</
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
Line 1,369 ⟶ 2,017:
{{trans|Go}}
<
if a.
return ""
}
Line 1,377 ⟶ 2,025:
while true {
var n2 = n1 + 1
while n2 < a.
n2 += 1
}
var s = a[n1].
if n2 == n1+2 {
s += "," + a[n2-1]
Line 1,386 ⟶ 2,034:
s += "-" + a[n2-1]
}
parts.
if n2 == a.
break
}
Line 1,398 ⟶ 2,046:
n1 = n2
}
return String.
}
Line 1,407 ⟶ 2,055:
37, 38, 39
])
print("range format: \(rf)")</
{{out}}
Line 1,417 ⟶ 2,065:
and just formatting them ourselves.
<
var region := 0..!0
for n in numbers { region |= n..n }
Line 1,433 ⟶ 2,081:
}
return ",".rjoin(ranges)
}</
<
> 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>
=={{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}}==
<
(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>
=={{header|Eiffel}}==
<syntaxhighlight lang="eiffel">
class
RANGE
Line 1,545 ⟶ 2,223:
end
end
</syntaxhighlight>
{{Out}}
<pre>
Line 1,554 ⟶ 2,232:
=={{header|Elixir}}==
{{trans|Ruby}}
<
def range_extract(list) do
max = Enum.max(list) + 2
Line 1,583 ⟶ 2,261:
37, 38, 39
]
IO.inspect RC.range_extract(list)</
{{out}}
Line 1,591 ⟶ 2,269:
=={{header|Emacs Lisp}}==
{{libheader|Gnus}}
<syntaxhighlight lang="lisp">(require 'gnus-range)
(defun rangext (lst)
(mapconcat (lambda (item)
(if (consp item)
(if (= (+ 1 (car item)
(format "%d,%d" (car item) (cdr item)
(format "%d-%d" (car item) (cdr item)
(format "%d" item)))
(gnus-compress-sequence lst)
","))
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>
Vanilla:
<syntaxhighlight lang="lisp">(defun split-into-ranges (numbers)
(let* ((last-number (pop numbers))
(range (list last-number))
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)
(cond
((not range)
(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
(mapconcat #'format-range (split-into-ranges numbers) ","))
(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>
=={{header|Erlang}}==
<syntaxhighlight 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>
{{out}}
<pre>
Line 1,682 ⟶ 2,353:
=={{header|Euphoria}}==
<
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}))</
{{out}}
Line 1,719 ⟶ 2,390:
=={{header|F_Sharp|F#}}==
<
| [] -> 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 ])</
{{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.
<
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</
{{out}}
<pre>
Line 1,773 ⟶ 2,444:
=={{header|Forth}}==
<
here
0 , 1 , 2 , 4 , 6 , 7 , 8 , 11 , 12 , 14 ,
Line 1,799 ⟶ 2,470:
;
values /values .ranges</
{{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. <
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</
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|Go}}==
<
import (
Line 2,042 ⟶ 2,599:
}
return strings.Join(parts, ","), nil
}</
{{out}}
<pre>
Line 2,050 ⟶ 2,607:
=={{header|Groovy}}==
Ad Hoc Solution:
<
def compressList = { list ->
Line 2,061 ⟶ 2,618:
}
def compressRanges = { expanded -> compressList(Eval.me('[' + expanded + ']')) }</
Test:
<
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))</
{{out}}
Line 2,077 ⟶ 2,634:
=={{header|Haskell}}==
===direct recursion===
<
extractRange :: [Int] -> String
Line 2,089 ⟶ 2,646:
g a [] = (a - 1, [])
f (x : xs) = show x : f xs
f [] = []</
<
"0-2,4,6-8,11,12,14-25,27-33,35-39"</
===splitBy===
Line 2,098 ⟶ 2,655:
Delegating to splitBy allows a reasonably clean definition of range formatting:
<
import Data.Function (on)
-
rangeFormat :: [Int] -> String
rangeFormat = intercalate "," . fmap rangeString . splitBy ((/=) . succ)
Line 2,112 ⟶ 2,668:
ps@(x:t) = show <$> xs
--------------------- 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) =
where
go (x, prev) (active, acc)
| f x prev = ([x], current : acc)
| otherwise =
where
-
main :: IO ()
main =
Line 2,168 ⟶ 2,722:
, 38
, 39
]</
{{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'''.
<
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 ]</
{{Out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
=={{header|Icon}} and {{header|Unicon}}==
<
R := [ 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
Line 2,240 ⟶ 2,794:
every (s := "[ ") ||:= !L || " "
return s || "]"
end</
{{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>.
<
group=: <@fmt;.1~ 1 ~: 0 , 2 -~/\ ]
extractRange=: ',' joinstring group</
Example use:
<
0-2,4,6-8,11,12,14-25,27-33,35-39</
and
<
-6,-3-1,3-5,7-11,14,15,17-20</
Other examples:
<
0-100</
The first 101 non-negative integers
<syntaxhighlight 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</
Excluding those which are prime
<syntaxhighlight 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</
Also excluding the first two non-negative integers (which are neither prime nor the product of non-empty lists of primes).
=={{header|Java}}==
<
public static void main(String[] args) {
Line 2,305 ⟶ 2,859:
}
}
}</
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39,</pre>
Line 2,312 ⟶ 2,866:
===ES5===
====Imperative====
<
var len = list.length;
var out = [];
Line 2,346 ⟶ 2,900:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
]));</
====Functional====
{{Trans|ES6}}
{{Trans|Haskell}}
<
'use strict';
Line 2,414 ⟶ 2,968:
33, 35, 36, 37, 38, 39
]);
})();</
{{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">
function toRange(arr) {
const ranges = [];
Line 2,472 ⟶ 3,098:
console.log(`expected output : '${expected}'.`);
console.log(`Correct? ${ actual === expected ? 'Yes' : 'No'}`);
</syntaxhighlight>
{{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>
=={{header|jq}}==
<
def extract:
reduce .[] as $i
Line 2,560 ⟶ 3,125:
then "\(.[0]),\(.[1])" # satisfy special requirement
else "\(.[0])-\(.[1])" end )
| join(",") ;</
{{out|Command and output}}
Line 2,569 ⟶ 3,134:
=={{header|Jsish}}==
From Javascript ES5 Imperative solution.
<
function rangeExtraction(list) {
var len = list.length;
Line 2,604 ⟶ 3,169:
puts(arr);
puts(rangeExtraction(arr));</
{{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">
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>
{{out}}
Line 2,642 ⟶ 3,207:
=={{header|K}}==
<
fmt : {:[1=#s:$x;s;(*s),:[3>#s;",";"-"],*|s]}
erng: {{x,",",y}/,//'fmt'grp x}</
{{out|Example}}
Line 2,651 ⟶ 3,216:
=={{header|Kotlin}}==
<
fun extractRange(list: List<Int>): String {
Line 2,687 ⟶ 3,252:
37, 38, 39)
println(extractRange(list2))
}</
{{out}}
Line 2,694 ⟶ 3,259:
0-2,4,6-8,11,12,14-25,27-33,35-39
</pre>
=={{header|LiveCode}}==
Inefficient as it takes 2 passes
<
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>
Test
<
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</
Output: <
=={{header|Lua}}==
<
local rExpr, startVal = ""
for k, v in pairs(rList) do
Line 2,807 ⟶ 3,332:
37, 38, 39
}
print(extractRange(intList))</
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
=={{header|Maple}}==
<
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):</
{{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[
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}}
<pre>"0-2,4,6-8,11,12,14-25,27-33,35-39"</pre>
=={{header|MATLAB}} / {{header|Octave}}==
<
% 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]))</
{{Out|Output (Octave)}}
Line 2,872 ⟶ 3,389:
=={{header|Mercury}}==
<
:- interface.
Line 2,912 ⟶ 3,429:
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39].
</syntaxhighlight>
=={{header|MiniScript}}==
<syntaxhighlight 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)</
{{out}}
<pre>0-2,
=={{header|MUMPS}}==
<
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</
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===
<
* 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</
{{out}}
<pre>
Line 3,014 ⟶ 3,530:
===NetRexx Ver. 2===
{{trans|Java}}
<
options replace format comments java crossref symbols nobinary
Line 3,090 ⟶ 3,606:
end r_
return
</syntaxhighlight>
{{out}}
<pre>
Line 3,104 ⟶ 3,620:
=={{header|Nim}}==
<
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(
else: ranges.add("$1-$2".format(
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)</
{{out}}
Line 3,140 ⟶ 3,656:
=={{header|Oberon-2}}==
Oxford Oberon-2
<
MODULE RangeExtraction;
IMPORT Out;
Line 3,233 ⟶ 3,749:
Range(seq1)
END RangeExtraction.
</syntaxhighlight>
{{out}}
<pre>
Line 3,242 ⟶ 3,758:
=={{header|Objeck}}==
{{trans|Java}}
<
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>
=={{header|Objective-C}}==
Line 3,295 ⟶ 3,811:
{{works with|Mac OS X|10.7+}}
{{works with|iOS|5+}}
<
NSString *extractRanges(NSArray *nums) {
Line 3,328 ⟶ 3,844:
}
return 0;
}</
{{out}}
<pre>
Line 3,335 ⟶ 3,851:
=={{header|OCaml}}==
<
| [] -> []
| x::xs ->
Line 3,355 ⟶ 3,871:
in
let rng = range_extract li in
print_endline(string_of_range rng)</
{{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}}
<
parse arg userInput
Line 3,442 ⟶ 3,995:
end r_
return
</syntaxhighlight>
{{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|Oz}}==
<
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 ]}}</
{{out}}
Line 3,553 ⟶ 4,063:
{{works with|Free Pascal|2.6.2}}
{{works with|Delphi}}
<
{$IFDEF FPC}
{$mode objfpc}{$H+}
{$ENDIF}
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}
end.</syntaxhighlight>
{{out}}
Line 3,658 ⟶ 4,173:
Using regexes. Also handles +/- and negative integer ranges.
<
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";</
{{out}}
Line 3,679 ⟶ 4,194:
{{libheader|Set::IntSpan}}
<
sub rangext { return Set::IntSpan->new(@_) . '' } # stringized</
{{libheader|Set::IntSpan::Fast}}
<
sub rangext { return Set::IntSpan::Fast->new(@_)->as_string }</
<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)-->
<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>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span>
<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>
<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>
<span style="color: #008080;">else</span>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<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>
<span style="color: #004080;">integer</span> <span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">out</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<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>
<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>
<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>
<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>
<span style="color: #000000;">first</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">out</span>
<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}}==
<
( ) var res
Line 3,767 ⟶ 4,290:
clear
printRes</
The same result in all examples.
{{out}}
Line 3,774 ⟶ 4,297:
A bit less ugly
<
( 0 1 2 4 6 7 8 11 12 14
Line 3,812 ⟶ 4,335:
endif
endfor
8 tochar print " " print</
Short version
<
( 0 1 2 4 6 7 8 11 12 14
Line 3,846 ⟶ 4,369:
act inf == not
endwhile
8 tochar print " " print</
PicoLisp like version
<
def glue /# l o -- l #/
Line 3,858 ⟶ 4,381:
ob swap put
endfor
enddef
Line 3,893 ⟶ 4,412:
endfor
"," glue lprint</
=={{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}}==
<
(glue ","
(make
Line 3,906 ⟶ 4,492:
((= N M) (link N))
((= (inc N) M) (link N M))
(T (link (list N '- M))) ) ) ) ) ) )</
{{out}}
<pre>: (rangeextract
Line 3,915 ⟶ 4,501:
=={{header|PL/I}}==
<
/* least 3 items in a run. */
range_extraction: /* 17 August 2010 */
Line 3,962 ⟶ 4,548:
c, d = ',';
end;
end range_extraction;</
OUTPUT 17/8/2010:
<syntaxhighlight lang="text">
0-2,4,6-8,11-12,14-25,27-33,35-39
</syntaxhighlight>
{{out}}
<pre>
Line 3,974 ⟶ 4,560:
=={{header|PowerShell}}==
<syntaxhighlight 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>
<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.
<
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>
{{out}}
Line 4,111 ⟶ 4,697:
0-2,4,6-8,11,12,14-25,27-33,35-39
true</pre>
=={{header|Python}}==
===Procedural===
====Python: for ordered sequences====
<
'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))</
{{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]:
<
'''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))</
{{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>.
<
"Can push items back on iterable"
def __init__(self, it):
Line 4,324 ⟶ 4,834:
yield (hi,)
else:
yield (low,)</
{{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}}
<
from functools import reduce
Line 4,425 ⟶ 4,935:
# MAIN ---
if __name__ == '__main__':
main()</
{{Out}}
<pre>Range extraction:
Line 4,435 ⟶ 4,945:
=={{header|Qi}}==
<syntaxhighlight 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>
{{out}}
Line 4,462 ⟶ 4,972:
=={{header|R}}==
<
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)))</
=={{header|Racket}}==
<syntaxhighlight 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>
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku"
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;</
{{out}}
Line 4,531 ⟶ 5,041:
Note that the two numbers '''11''' and '''12''' are not considered a range.
===version 1===
This REXX version isn't limited to integers. It doesn't need a magic number to terminate the list.
<
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 #;
do k=j+1 to #; y= word(old, k) /*get the Kth number in the number list*/
if y\==
inc= inc + 1; g= y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=
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=
say 'old:' old; say 'new:'
{{out|output|text= when using the (internal) default 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 '''do''' loop's index ('''j''')
<br>and it also doesn't need a magic number to terminate the list.
<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;
do k=j+1 to #; y= word(old, k) /*get the Kth number in the number list*/
if y\==
inc= inc + 1; g= y /*increase the range, assign G (good).*/
end /*k*/
if k-1=j | g=
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=
say 'old:'
{{out|output|text= is the same as the 1<sup>st</sup> REXX version (1a).}}<br><br>
!-->
===version 2===
Somewhat simplified !?!
<
* 07.08.2012 Walter Pachl
**********************************************************************/
Line 4,611 ⟶ 5,119:
End
Say 'new='ol
</syntaxhighlight>
Output is
=={{header|Ring}}==
<
# Project : Range extraction
Line 4,659 ⟶ 5,167:
see svect
see "]" + nl
</syntaxhighlight>
Output:
<pre>
Line 4,666 ⟶ 5,174:
=={{header|Ruby}}==
<
# 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)</
{{out}}
Line 4,708 ⟶ 5,216:
{{works with|Ruby|2.2}}
Enumerable#slice_when method became usable.
<
puts ary.sort.slice_when{|i,j| i+1 != j}.map{|a| a.size<3 ? a : "#{a[0]}-#{a[-1]}"}.join(",")</
{{out}}
Line 4,716 ⟶ 5,224:
=={{header|Rust}}==
Iterators are very Rustic. This solution is generic for all numeric types.
<
struct RangeFinder<'a, T: 'a> {
Line 4,768 ⟶ 5,276:
}
println!("");
}</
{{out}}
Line 4,776 ⟶ 5,284:
Add this to the top of the file:
<
use std::num::One;</
Changing this line:
<
to this:
<
And this line:
<
to this:
<
=={{header|Scala}}==
<
def spanRange(ls:List[Int])={
var last=ls.head
Line 4,814 ⟶ 5,322:
println(toRangeString(toRangeList(l)))
}
}</
{{out}}
Line 4,821 ⟶ 5,329:
=={{header|Scheme}}==
{{trans|Qi}}
<
(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>
{{out}}
Line 4,858 ⟶ 5,366:
=={{header|Seed7}}==
<
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;</
{{out}}
Line 4,904 ⟶ 5,412:
Handles +/- and negative ranges.
<
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</
{{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}}
<
import Darwin
Line 4,983 ⟶ 5,626:
print(description(from: ranges(from: ex)))
print(description(from: ranges(from: longer)))
</syntaxhighlight>
{{out}}
Line 4,990 ⟶ 5,633:
=={{header|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>
{{out}}
<pre>
Line 5,016 ⟶ 5,659:
=={{header|Tcl}}==
<
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
}]</
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
=={{header|TUSCRIPT}}==
<
$$ MODE TUSCRIPT,{}
MODE DATA
Line 5,063 ⟶ 5,706:
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs
</syntaxhighlight>
Output:
<pre>
Line 5,070 ⟶ 5,713:
Solution without COMBINE
<
$$ MODE TUSCRIPT
MODE DATA
Line 5,102 ⟶ 5,745:
rangednrs=EXCHANGE (rangednrs,":':,:")
PRINT rangednrs
</syntaxhighlight>
{{out}}
<pre>
Line 5,110 ⟶ 5,753:
=={{header|TXR}}==
<
`@{(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)])))) ","}`)</
{{out|Run}}
Line 5,132 ⟶ 5,775:
=={{header|UNIX Shell}}==
{{works with|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</
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
=={{header|Ursala}}==
<
#import int
Line 5,175 ⟶ 5,818:
#show+
t = <f x></
{{out}}
<pre>0-2,4,6-8,11,12,14-25,27-33,35-39</pre>
=={{header|
{{trans|Kotlin}}
<syntaxhighlight lang="wren">var extractRange = Fn.new { |list|
if (list.isEmpty) return ""
var sb = ""
var first = list[0]
var prev = first
var append = Fn.new { |index|
if (first == prev) {
sb = sb + prev.toString
} else if (first == prev - 1) {
sb = sb + first.toString + "," + prev.toString
} else {
sb = sb + first.toString + "-" + prev.toString
if (index < list.count - 1) sb = sb + ","
}
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]
System.print(extractRange.call(list1))
var list2 = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
37, 38, 39]
System.print(extractRange.call(list2))</syntaxhighlight>
{{out}}
<pre>
-6,-3-1,3-5,7-11,14,15,17-20
</pre>
=={{header|
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;
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}}==
<
fcn(w){
if (w.atEnd) return(Void.Stop);
Line 5,315 ⟶ 5,945:
} :
(0).pump(*,List,_.fp(ns.walker().tweak(Void,Void))).concat(",");
}</
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.
<
range(ns).println();
Line 5,330 ⟶ 5,960:
range(ns).println();
range([1..100]).println();</
{{out}}
|