Range expansion: Difference between revisions
m
→{{header|Wren}}: Changed to Wren S/H
m (→{{header|Wren}}: Changed to Wren S/H) |
|||
(34 intermediate revisions by 21 users not shown) | |||
Line 17:
=={{header|11l}}==
{{trans|Python}}
<
L(r) txt.split(‘,’)
I ‘-’ C r[1..]
Line 27:
R lst
print(rangeexpand(‘-6,-3--1,3-5,7-11,14,15,17-20’))</
=={{header|8th}}==
<
\ range, inclusive:
: n:gen-range \ low hi -- a
Line 90:
n:range-expand
\ print the expanded list:
. cr bye</
{{out}}
<pre>
[-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20]
</pre>
=={{header|Action!}}==
<syntaxhighlight lang="action!">BYTE FUNC Find(CHAR ARRAY text CHAR c BYTE start)
BYTE i
i=start
WHILE i<=text(0)
DO
IF text(i)=c THEN
RETURN (i)
FI
i==+1
OD
RETURN (0)
PROC ProcessItem(CHAR ARRAY text INT ARRAY res INT POINTER size)
BYTE pos
INT start,end,i
CHAR ARRAY tmp(200)
pos=Find(text,'-,2)
IF pos=0 THEN
res(size^)=ValI(text)
size^==+1
ELSE
SCopyS(tmp,text,1,pos-1)
start=ValI(tmp)
SCopyS(tmp,text,pos+1,text(0))
end=ValI(tmp)
FOR i=start TO end
DO
res(size^)=i
size^==+1
OD
FI
RETURN
PROC RangeExtraction(CHAR ARRAY text INT ARRAY res INT POINTER size)
BYTE i,pos
CHAR ARRAY tmp(200)
i=1 size^=0
WHILE i<=text(0)
DO
pos=Find(text,',,i)
IF pos=0 THEN
SCopyS(tmp,text,i,text(0))
i=text(0)+1
ELSE
SCopyS(tmp,text,i,pos-1)
i=pos+1
FI
ProcessItem(tmp,res,size)
OD
RETURN
PROC PrintArray(INT ARRAY a INT size)
INT i
Put('[)
FOR i=0 TO size-1
DO
IF i>0 THEN Put(' ) FI
PrintI(a(i))
OD
Put(']) PutE()
RETURN
PROC Main()
INT ARRAY res(100)
INT size
RangeExtraction("-6,-3--1,3-5,7-11,14,15,17-20",res,@size)
PrintArray(res,size)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Range_expansion.png Screenshot from Atari 8-bit computer]
<pre>
[-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20]
</pre>
=={{header|Ada}}==
The function Expand takes a string and returns a corresponding array of integers.
Upon syntax errors Constraint_Error is propagated:
<
procedure Test_Range_Expansion is
type Sequence is array (Positive range <>) of Integer;
Line 163 ⟶ 243:
begin
Put (Expand ("-6,-3--1,3-5,7-11,14,15,17-20"));
end Test_Range_Expansion;</
{{out}}
<pre>
Line 170 ⟶ 250:
=={{header|Aime}}==
{{incorrect|Aime|Needs "a comma separated list" without the trailing comma}}
<syntaxhighlight lang="aime">list l;
file().b_affix("-6,-3--1,3-5,7-11,14,15,17-20").news(l, 0, 0, ",");
Line 189 ⟶ 270:
}
o_("\n");</
or:
<
list l;
Line 204 ⟶ 285:
}
o_("\n");</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20,</pre>
Line 212 ⟶ 293:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny] - string parsing and formatting code tested with 2.6.win32}}
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d]}}
<
MODE RANGE = STRUCT(INT lwb, upb);
Line 381 ⟶ 462:
print( ( TOSTRING range expand( TORANGE "-6,-3--1,3-5,7-11,14,15,17-20" ), newline ) )
)
</syntaxhighlight>
{{out}}
<pre>
Line 387 ⟶ 468:
</pre>
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">range←{
aplnum←{⍎('¯',⎕D)[('-',⎕D)⍳⍵]}
∊{ 0::('Invalid range: ''',⍵,'''')⎕SIGNAL 11
n←aplnum¨(~<\(⊢≠∨\)⍵∊⎕D)⊆⍵
1=≢n:n
s e←n
(s+(⍳e-s-1))-1
}¨(⍵≠',')⊆⍵
}</syntaxhighlight>
{{out}}
<pre> range '-6,-3--1,3-5,7-11,14,15,17-20'
¯6 ¯3 ¯2 ¯1 3 4 5 7 8 9 10 11 14 15 17 18 19 20
range '-6,--3--1,3-5,7-11,14,15,17-20'
Invalid range: '--3--1'
range'-6,--3--1,3-5,7-11,14,15,17-20'
∧
range'-6,-3--1,3-5,11-7,14,15,17-20'
Invalid range: '11-7'
range'-6,-3--1,3-5,11-7,14,15,17-20'
∧</pre>
=={{header|AppleScript}}==
===Functional===
{{Trans|JavaScript}} (Functional ES5 version)
<
-- and these integer lists are concatenated together into a single list
---------------------- RANGE EXPANSION ---------------------
-- expansion :: String -> [Int]
Line 406 ⟶ 515:
-- signedIntegerAppended:: [Int] -> String -> Int -> [Int] -> [Int]
on signedIntegerAppended(
if strNum ≠ "" then
if iPosn > 1 then
else
set strSign to "+"
end if
acc & ((strSign & strNum) as integer)
else
end if
end signedIntegerAppended
Line 433 ⟶ 540:
on run
Line 442 ⟶ 549:
-- bool :: a -> a -> Bool -> a
on bool(tf, ff)
-- The evaluation of either tf or ff,
-- depending on a boolean value.
script
on |λ|(bln)
if bln then
set e to tf
else
set e to ff
end if
set c to class of e
if {script, handler} contains c then
|λ|() of mReturn(e)
else
e
end if
end |λ|
end script
end bool
-- concatMap :: (a -> [b]) -> [a] -> [b]
Line 522 ⟶ 651:
item 1 of tuple
end if
end tupleRange</
{{Out}}
<
----
===Idiomatic===
<syntaxhighlight lang="applescript">on rangeExpansion(rangeExpression)
-- Split the expression at the commas, if any.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
set theRanges to rangeExpression's text items
set integerList to {}
set AppleScript's text item delimiters to "-"
repeat with thisRange in theRanges
-- Split each range or integer text at its dash(es), if any.
set rangeParts to thisRange's text items
-- A minus before the first integer will make leading text item "".
-- If this happens, insert the negative first value at the beginning of the parts list.
-- (AppleScript automatically coerces numeric text to number when the context demands.)
if (rangeParts begins with "") then set beginning of rangeParts to -(item 2 of rangeParts)
-- A minus before the second (or only) integer will make the penultimate text item "".
-- In this case, insert the negative last value at the end of the parts list.
if (((count rangeParts) > 1) and (item -2 of rangeParts is "")) then set end of rangeParts to -(end of rangeParts)
-- Append all the integers implied by the range to the integer list.
repeat with i from (beginning of rangeParts) to (end of rangeParts)
set end of integerList to i
end repeat
end repeat
set AppleScript's text item delimiters to astid
return integerList
end rangeExpansion
-- Demo code:
set rangeExpression to "-6,-3--1,3-5,7-11,14,15,17-20"
return rangeExpansion(rangeExpression)</syntaxhighlight>
{{output}}
<syntaxhighlight lang="applescript">{-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20}</syntaxhighlight>
=={{header|Arturo}}==
<syntaxhighlight lang="rebol">expandRange: function [rng][
flatten @ to :block
join.with:" " map split.by:"," rng 'x ->
replace replace replace x
{/^\-(\d+)/} "(neg $1)" {/\-\-(\d+)/}
"-(neg $1)" "-" ".."
]
print expandRange {-6,-3--1,3-5,7-11,14,15,17-20}</syntaxhighlight>
{{out}}
<pre>-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</pre>
=={{header|AutoHotkey}}==
<
expand( range ) {
Line 535 ⟶ 718:
ret .= "," (A_Index-1) + f1
return SubStr(ret, 2)
}</
=={{header|AWK}}==
<
BEGIN { FS=","; }
Line 560 ⟶ 743:
}
return;
} </
<pre>
Line 569 ⟶ 752:
=={{header|BBC BASIC}}==
<
END
Line 591 ⟶ 774:
ENDIF
UNTIL i% = 0
= r$</
{{out}}
<pre>
Line 598 ⟶ 781:
=={{header|Bracmat}}==
<
= a b L
. @( !arg
Line 613 ⟶ 796:
)
& out$(str$(expandRanges$"-6,-3--1,3-5,7-11,14,15,17-20"))
</syntaxhighlight>
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
Line 619 ⟶ 802:
=={{header|C}}==
Recursive descent parser.
<
#include <stdlib.h>
#include <ctype.h>
Line 696 ⟶ 879:
return 0;
}</
{{out}}
<pre>-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20
Line 705 ⟶ 888:
=={{header|C sharp|C#}}==
{{works with|C sharp|3.0}}
<
using System.Collections.Generic;
using System.Linq;
Line 734 ⟶ 917:
Console.WriteLine(string.Join(", ", values));
}
}</
{{works with|C sharp|3.5+}}
<
using System.Collections.Generic;
using System.Linq;
Line 767 ⟶ 950:
}
}
}</
=={{header|C++}}==
<
#include <sstream>
#include <iterator>
Line 843 ⟶ 1,026:
else
std::cout << "an error occured.";
}</
{{out}}
-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20
Line 849 ⟶ 1,032:
=={{header|Clojure}}==
There is a split method in clojure.contrib, but I don't know if it is able to skip first character to so that <code>(split "-8--8") => (-8 -8)</code>.
<
(defn skipFirst [[x & xs :as s]]
(cond (empty? s) [nil nil]
Line 872 ⟶ 1,055:
> (rangeexpand "-6,-3--1,3-5,7-11,14,15,17-20")
(-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20)</
=={{header|COBOL}}==
{{works with|GNU Cobol|2.0}}
<
IDENTIFICATION DIVISION.
PROGRAM-ID. expand-range.
Line 968 ⟶ 1,151:
END-IF
.
END PROGRAM display-edited-num.</
Setup:
Line 982 ⟶ 1,165:
=={{header|Common Lisp}}==
<
(loop
with prevnum = nil
Line 1,004 ⟶ 1,187:
CL-USER> (expand-ranges "-6,-3--1,3-5,7-11,14,15,17-20")
(-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20)</
=={{header|Cowgol}}==
<syntaxhighlight lang="cowgol">include "cowgol.coh";
# Callback interface
interface RangeCb(n: int32);
# This will call `cb' for each number in the range, in ascending order.
# It will return NULL on success, or the location of an error if
# there is one.
sub Expand(ranges: [uint8], cb: RangeCb): (err: [uint8]) is
err := 0 as [uint8];
loop
# Grab first number
var n1: int32;
var next: [uint8];
(n1, next) := AToI(ranges);
if next == ranges then
# No number here!
err := ranges;
break;
elseif [next] == ',' or [next] == 0 then
# Only one number, not a range
cb(n1);
elseif [next] != '-' then
# No dash!
err := ranges;
break;
else
# Grab second number
ranges := @next next;
var n2: int32;
(n2, next) := AToI(ranges);
if next == ranges or n1 >= n2 then
# No second number, or first not before second
err := ranges;
break;
end if;
# We need all numbers from n1 to n2 inclusive
while n1 <= n2 loop
cb(n1);
n1 := n1 + 1;
end loop;
end if;
# stop if end reached
if [next] == 0 then break;
elseif [next] != ',' then
err := ranges;
break;
end if;
ranges := @next next;
end loop;
end sub;
# This function will use `Expand' above to expand a comma-separated
# range list, and reformat it as a comma-separated list of integers.
sub ExpandFmt(ranges: [uint8], buf: [uint8]): (err: [uint8]) is
# Format and add number to buffer
sub AddNum implements RangeCb is
buf := IToA(n, 10, buf);
[buf] := ',';
buf := @next buf;
end sub;
# Expand range, adding numbers to buffer
err := Expand(ranges, AddNum);
[@prev buf] := 0;
end sub;
# Expand and print, and/or give error
sub PrintExpansion(ranges: [uint8]) is
var buf: uint8[256];
var err := ExpandFmt(ranges, &buf[0]);
print(ranges);
print_nl();
print(" >> ");
if err == 0 as [uint8] then
# everything is OK
print(&buf[0]);
else
# error
print("error at: ");
print(err);
end if;
print_nl();
end sub;
# Try it on the given input
PrintExpansion("-6,-3--1,3-5,7-11,14,15,17-20");
# Try it on a couple of wrong ones
PrintExpansion("-6-3--1,3-5,7-11,14,15,17-20"); # misformatted range
PrintExpansion("-6,-3--1,5-3,7-11,14,15,17-20"); # numbers not in order</syntaxhighlight>
{{out}}
<pre>-6,-3--1,3-5,7-11,14,15,17-20
>> -6,-3,-2,-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
>> error at: 3--1,3-5,7-11,14,15,17-20
-6,-3--1,5-3,7-11,14,15,17-20
>> error at: 3,7-11,14,15,17-20</pre>
=={{header|Crystal}}==
{{trans|Ruby}}
<syntaxhighlight lang="crystal">def range_expand(range)
range.split(',').flat_map do |part|
match = /^(-?\d+)-(-?\d+)$/.match(part)
if match
(match[1].to_i .. match[2].to_i).to_a
else
part.to_i
end
end
end
puts range_expand("-6,-3--1,3-5,7-11,14,15,17-20")</syntaxhighlight>
{{out}}
<pre>[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]</pre>
=={{header|D}}==
<
enum rangeEx = (string s) /*pure*/ => s.matchAll(`(-?\d+)-?(-?\d+)?,?`)
Line 1,014 ⟶ 1,319:
void main() {
"-6,-3--1,3-5,7-11,14,15,17-20".rangeEx.writeln;
}</
{{out}}
<pre>[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program Range_expansion;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
const
input = '-6,-3--1,3-5,7-11,14,15,17-20';
var
r: TArray<Integer>;
last, i, n: Integer;
begin
for var part in input.Split([',']) do
begin
i := part.Substring(1).IndexOf('-');
if i = -1 then
begin
if not TryStrToInt(part, n) then
raise Exception.Create('Error: value invalid ' + part);
if Length(r) > 0 then
if last = n then
begin
raise Exception.Create('Error: Duplicate value:' + n.ToString);
end
else
begin
if last > n then
raise Exception.CreateFmt('Error: values not ordered: %s > %s', [last, n]);
end;
SetLength(r, Length(r) + 1);
r[High(r)] := n;
last := n;
end
else
begin
var n1 := 0;
var n2 := 0;
if not TryStrToInt(part.Substring(0, i + 1), n1) then
raise Exception.Create('Error: value invalid ' + part);
if not TryStrToInt(part.Substring(i + 2), n2) then
raise Exception.Create('Error: value invalid ' + part);
if n2 < n1 + 2 then
raise Exception.Create('Error: Invalid range' + part);
if Length(r) > 0 then
begin
if last = n1 then
raise Exception.Create('Error: Duplicate value: ' + n1.ToString);
if last > n1 then
raise Exception.CreateFmt('Error: Values not ordened: %d > %d', [last, n1]);
end;
for i := n1 to n2 do
begin
SetLength(r, Length(r) + 1);
r[High(r)] := i;
end;
last := n2;
end;
end;
write('expanded: ');
for var rr in r do
begin
write(rr, ',');
end;
readln;
end.</syntaxhighlight>
=={{header|DWScript}}==
<
function ExpandRanges(ranges : String) : array of Integer;
begin
Line 1,035 ⟶ 1,415:
var expanded := ExpandRanges('-6,-3--1,3-5,7-11,14,15,17-20');
PrintLn(JSON.Stringify(expanded));
</syntaxhighlight>
{{out}}
<pre>[-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20]</pre>
=={{header|Dyalect}}==
{{trans|Go}}
<syntaxhighlight lang="dyalect">func main() {
let input = "-6,-3--1,3-5,7-11,14,15,17-20"
print("range: \(input)")
var r = []
var last = 0
for part in input.Split(',') {
var i = part[1..].IndexOf('-')
if i == -1 {
var n = Integer(part)
if r.Length() > 0 {
return print("duplicate value: \(n)") when last == n
return print("values not ordered: \(last) > \(n)") when last > n
}
r.Add(n)
last = n
} else {
var n1 = Integer(part[..i])
var n2 = Integer(part[(i + 2)..])
return print("invalid range: \(part)") when n2 < n1 + 2
if r.Length() > 0 {
return print("duplicate value: \(n1)") when last == n1
return print("values not ordered: \(last) > \(n1)") when last > n1
}
for i in n1..n2 {
r.Add(i)
}
last = n2
}
}
print("expanded: \(r)")
}
main()</syntaxhighlight>
{{out}}
<pre>range: -6,-3--1,3-5,7-11,14,15,17-20
expanded: [-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]</pre>
=={{header|EchoLisp}}==
<
;; parsing [spaces][-]digit(s)-[-]digit(s)[spaces]
(define R (make-regexp "^ *(\-?\\d+)\-(\-?\\d+) *$" ))
Line 1,066 ⟶ 1,492:
(ranges task)
→ (-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20)
</syntaxhighlight>
=={{header|Elixir}}==
{{trans|Ruby}}
<
def expansion(range) do
Enum.flat_map(String.split(range, ","), fn part ->
Line 1,081 ⟶ 1,507:
end
IO.inspect RC.expansion("-6,-3--1,3-5,7-11,14,15,17-20")</
{{out}}
Line 1,089 ⟶ 1,515:
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
-module( range ).
Line 1,104 ⟶ 1,530:
expansion_individual( {ok, [N], []} ) -> N;
expansion_individual( {ok, [Start], "-" ++ Stop_string} ) -> lists:seq( Start, erlang:list_to_integer(Stop_string) ).
</syntaxhighlight>
{{out}}
Line 1,113 ⟶ 1,539:
=={{header|F_Sharp|F#}}==
<
// simplify regex matching with an active pattern
Line 1,135 ⟶ 1,561:
|> List.collect parseRange
printfn "%A" (expand "-6,-3--1,3-5,7-11,14,15,17-20")</
{{out}}
<pre>[-6; -3; -2; -1; 3; 4; 5; 7; 8; 9; 10; 11; 14; 15; 17; 18; 19; 20]</pre>
Line 1,141 ⟶ 1,567:
=={{header|Factor}}==
<code>R/ (?<=\d)-/ re-split</code> says: ''split only on hyphens immediately preceded by a digit.''
<
sequences sequences.extras splitting ;
Line 1,150 ⟶ 1,576:
] map-concat ;
"-6,-3--1,3-5,7-11,14,15,17-20" expand .</
{{out}}
<pre>
Line 1,157 ⟶ 1,583:
=={{header|Forth}}==
<
0. 2swap
over c@ [char] - = if
Line 1,181 ⟶ 1,607:
repeat 2drop ;
s" -6,-3--1,3-5,7-11,14,15,17-20" expand</
=={{header|Fortran}}==
Line 1,192 ⟶ 1,618:
A frustrating problem with many modern computer languages is the absence of a "shortcut" evaluation praxis for logical expressions; in Fortran's case the modern standard is that there is no standard. So a test <code>I<=LEN(TEXT) & TEXT(I:I)''etc.''</code> can't be relied upon to dodge out-of-bounds errors, and a flabby two-statement sequence is required instead. Similarly, few Fortran compilers allow for a function being evaluated via a WRITE statement to itself succeed in using a WRITE statement internally, though some do if one usage is free-format and the other formatted. If necessary, subroutine SPLOT could be re-written to convert an integer to a digit string without a WRITE statement, even for negative integers. And some compilers have difficulty with the use of the function name as a variable within the function so that it is safest to develop the result in an ordinary variable and then remember to assign its value to the function name just before exit.
A single number is made internally into a two-number range sequence, which values are used as the bounds for a DO-loop to generate the numbers for output. Despite the '''The range syntax is to be used only for, and for every range that expands to more than two values''', I see no reason for this restriction (say because otherwise some fancy method would be stymied, except I can think of no such fancier method) and I have no desire to interpose some sort of error message, a tedious business that requires a wider interface between a routine and its caller. Similarly, if a range of 40-30 were to appear, why not take it at face value? <
CONTAINS !The key function.
CHARACTER*200 FUNCTION ERANGE(TEXT) !Expands integer ranges in a list.
Line 1,291 ⟶ 1,717:
SOME = ERANGE(SOME)
WRITE (6,*) SOME !If ERANGE(SOME) then the function usually can't write output also.
END</
Output: <pre> -6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
Line 1,298 ⟶ 1,724:
=={{header|FreeBASIC}}==
<
Sub split (s As Const String, sepList As Const String, result() As String)
Line 1,372 ⟶ 1,798:
Print
Print "Press any key to quit"
Sleep</
{{out}}
Line 1,381 ⟶ 1,807:
=={{header|Go}}==
A version rather strict with input
<
import (
Line 1,444 ⟶ 1,870:
}
fmt.Println("expanded:", r)
}</
=={{header|Groovy}}==
Line 1,454 ⟶ 1,880:
# express as a string
# unwrap the list delimiters
<
Eval.me('['+compressed.replaceAll(~/(\d)-/, '$1..')+']').flatten().toString()[1..-2]
}</
Test:
<
println (expandRanges(s))</
{{out}}
<pre>-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20</pre>
Line 1,465 ⟶ 1,891:
=={{header|Haskell}}==
Given either of the below implementations of <code>expandRange</code>:
<
[-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20]</
===With conventional list processing===
<
expandRange = concatMap f . split ','
where f str@(c : cs) | '-' `elem` cs = [read (c : a) .. read b]
Line 1,477 ⟶ 1,903:
split delim [] = []
split delim l = a : split delim (dropWhile (== delim) b)
where (a, b) = break (== delim) l</
===With a parser===
<
import Text.Parsec
expandRange :: String -> Maybe [Int]
expandRange =
either
(const Nothing)
Just
. parse rangeParser ""
rangeParser ::
rangeParser = concat <$> (item `sepBy` char ',')
where
Line 1,496 ⟶ 1,925:
n2 <- option n1 (char '-' *> num)
return [n1 .. n2]
num =
read `dot` (<>) <$> option "" (string "-")
<*> many1 digit
dot = (.) . (.)
main :: IO ()
main = print $ expandRange "-6,-3--1,3-5,7-11,14,15,17-20"</
{{Out}}
<pre>Just [-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20]</pre>
=={{header|Icon}} and {{header|Unicon}}==
<
s := "-6,-3--1,3-5,7-11,14,15,17-20"
write("Input string := ",s)
Line 1,529 ⟶ 1,960:
every (s := "[ ") ||:= !L || " "
return s || "]"
end</
{{out}}
<pre>Input string := -6,-3--1,3-5,7-11,14,15,17-20
Line 1,535 ⟶ 1,966:
=={{header|J}}==
<
thru=: <. + i.@(+*)@-~
num=: _&".
normaliz=: rplc&(',-';',_';'--';'-_')@,~&','
subranges=:<@(thru/)@(num;._2)@,&'-';._1
rngexp=: ;@subranges@normaliz</
{{out|Example}}
<
_6 _3 _2 _1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</
Notes:
Line 1,560 ⟶ 1,991:
=={{header|Java}}==
<
class RangeExpander implements Iterator<Integer>, Iterable<Integer> {
Line 1,624 ⟶ 2,055:
}
}
}</
=={{header|JavaScript}}==
Line 1,630 ⟶ 2,061:
===Imperative (Spidermonkey)===
<
function main() {
Line 1,664 ⟶ 2,095:
main();
</syntaxhighlight>
{{out}}
Line 1,673 ⟶ 2,104:
====ES5====
<
'use strict';
Line 1,711 ⟶ 2,142:
return expansion(strTest);
})('-6,-3--1,3-5,7-11,14,15,17-20');</
{{Out}}
<
====ES6====
<syntaxhighlight lang="javascript">(() => {
"use strict";
// ----------------- RANGE EXPANSION -----------------
// rangeExpansion :: String -> [Int]
const rangeExpansion = rangeString =>
// A list of
// comma-delimited string which may include
// (rising) hyphenated ranges.
rangeString.split(",")
.flatMap(x => {
const ns = x.split("-")
.reduce((a, s, i, xs) =>
Boolean(s) ? (
0 < i ? a.concat(
parseInt(
xs[i - 1].length ? (
s
) : `-${s}`,
10
)
) : [Number(s)]
) : a,
[]
);
return 2 === ns.length ? (
) :
});
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () =>
rangeExpansion("-6,-3--1,3-5,7-11,14,15,17-20");
// --------------------- GENERIC ---------------------
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = m =>
}, (_, i) => m + i);
// uncurry :: (a -> b -> c) -> ((a, b) -> c)
const uncurry = f =>
// A function over a pair, derived
// from a curried function.
(...args) => {
const [x, y] = Boolean(args.length % 2) ? (
args[0]
) : args;
return
};
// MAIN ---
return JSON.stringify(main());
})();</syntaxhighlight>
{{Out}}
<
=={{header|jq}}==
{{works with|jq|with regex support}}
<
def number: "-?[0-9]+";
def expand: [range(.[0]; .[1] + 1)];
Line 1,773 ⟶ 2,229:
else sub( "(?<x>\(number))-(?<y>\(number))"; "\(.x):\(.y)")
| split(":") | map(tonumber) | expand
end));</
'''Example''':
<
{{out}}$ jq -c -n -f Range_expansion.jq
[-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20]
Line 1,781 ⟶ 2,237:
=={{header|Jsish}}==
{{trans|Javascript}}
<
"use strict";
Line 1,820 ⟶ 2,276:
rangeExpand('-6,-3--1,3-5,7-11,14,15,17-20') ==> [ -6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20 ]
=!EXPECTEND!=
*/</
{{out}}
Line 1,827 ⟶ 2,283:
=={{header|Julia}}==
<
conv(s)= colon(map(x->parse(Int,x),match(r"^(-?\d+)-(-?\d+)$", s).captures)...)
expand(s) = mapreduce(x -> isa(x,Number)? Int(x) : conv(x), vcat, slurp(s))</
{{out}}
<pre>julia> show(expand("-6,-3--1,3-5,7-11,14,15,17-20"))
Line 1,837 ⟶ 2,293:
=={{header|K}}==
<
pos : {:[3=l:#p:&"-"=x;0,p@1;2=l;p;0=*p;,0;0,p]}
conv: 0${(x;1_ y)}/'{(pos x)_ x}'
expd: {,/@[x;&2=#:'x;{(*x)+!1+,/-':x}]}
rnge: {expd@conv grp x}</
{{out|Example}}
<
-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</
=={{header|Kotlin}}==
<
fun expandRange(s: String): MutableList<Int> {
Line 1,881 ⟶ 2,337:
val s = "-6,-3--1,3-5,7-11,14,15,17-20"
println(expandRange(s))
}</
{{out}}
Line 1,889 ⟶ 2,345:
=={{header|Lasso}}==
<
local(parts) = regexp(`^(-?\d+)-(-?\d+)$`)
Line 1,901 ⟶ 2,357:
}
range_expand(`-6,-3--1,3-5,7-11,14,15,17-20`)</
{{out}}
<pre>-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20</pre>
=={{header|Liberty BASIC}}==
<
end
Line 1,930 ⟶ 2,385:
ItemCount = ItemCount + 1
wend
end function</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
=={{header|Lingo}}==
<
on expandRange (str)
res = ""
Line 1,955 ⟶ 2,410:
delete the last char of res
return res
end</
<
-- "-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20"</
=={{header|LiveCode}}==
<
local tRange, tBegin, tEnd, tstep
if stepping is empty or stepping is 0 then
Line 1,997 ⟶ 2,452:
end repeat
return z
end expandRange</
Test
<
-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20 </
=={{header|Lua}}==
<
local t = {}
for n = i, j, i<j and 1 or -1 do
Line 2,032 ⟶ 2,487:
local ranges = "-6,-3--1,3-5,7-11,14,15,17-20"
print(table.concat(expand_ranges(ranges), ', '))</
Due to the way Lua's <code>tonumber</code> function works and the way the string pattern to parse ranges is written, whitespace is allowed around commas and the dash separating the range start and end (but not between the plus/minus sign and the number).
Line 2,042 ⟶ 2,497:
=={{header|Maple}}==
<syntaxhighlight lang="maple">
ExpandRanges := proc( s :: string )
uses StringTools;
Line 2,080 ⟶ 2,535:
map( DoOne, map( Trim, Split( s, "," ) ) )
end proc:
</syntaxhighlight>
Running this on the example input we get the following.
<syntaxhighlight lang="maple">
> rng := "-6,-3--1,3-5,7-11,14,15,17-20":
> ExpandRanges( rng );
[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
</syntaxhighlight>
Here is an additional example which my first attempt got wrong.
<syntaxhighlight lang="maple">
> rng := "-6,-3-1,3-5,7-11,14,15,17-20":
> ExpandRanges( rng );
[-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
</syntaxhighlight>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
step1 = StringSplit[StringReplacePart[rng,"S",StringPosition[ rng,DigitCharacter~~"-"] /. {x_,y_} -> {y,y}],","];
Flatten@ToExpression/@Quiet@StringReplace[step1,x__~~"S"~~y__->"Range["<>x<>","<>y<>"]"] ]</
{{out|Example}}
<pre>rangeexpand["-6,-3--1,3-5,7-11,14,15,17-20"]
Line 2,103 ⟶ 2,558:
=={{header|MATLAB}} / {{header|Octave}}==
<
% Range expansion
if nargin < 1;
Line 2,115 ⟶ 2,570:
S(ixr)=':';
S=['[',S,']'];
L=eval(S);</
Usage:
<pre>
Line 2,123 ⟶ 2,578:
</pre>
=={{header|MiniScript}}==
<syntaxhighlight lang="miniscript">pullInt = function(chars)
numstr = chars.pull
while chars and chars[0] != "," and chars[0] != "-"
numstr = numstr + chars.pull
end while
return val(numstr)
end function
expandRange = function(s)
result = []
chars = s.split("")
while chars
num = pullInt(chars)
if not chars or chars.pull == "," then
result.push num
else
result = result + range(num, pullInt(chars))
chars.pull // skip "," after range
end if
end while
return result
end function
print expandRange("-6,-3--1,3-5,7-11,14,15,17-20")</syntaxhighlight>
{{out}}
<pre>[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]</pre>
=={{header|MUMPS}}==
<
NEW Y,I,J,X1,H SET Y=""
FOR I=1:1:$LENGTH(X,",") DO
Line 2,134 ⟶ 2,617:
.IF '(H<0) FOR J=+$EXTRACT(X1,1,(H-1)):1:+$EXTRACT(X1,(H+1),$LENGTH(X1)) SET Y=$SELECT($LENGTH(Y)=0:J,1:Y_","_J)
KILL I,J,X1,H
QUIT Y</
{{out|Example}}
<pre>USER>SET U="-6,-3--1,3-5,7-11,14,15,17-20"
Line 2,143 ⟶ 2,626:
=={{header|NetRexx}}==
Translation of: [[Range_expansion#Version_2_somewhat_simplified_.21.3F.21|Rexx Version 2]]
<
* 09.08.2012 Walter Pachl derived from my Rexx version
* Changes: translate(old,' ',',') -> old.translate(' ',',')
Line 2,177 ⟶ 2,660:
End
Say 'new='new /*show the expanded list */
</syntaxhighlight>
{{out}}
<pre>
Line 2,185 ⟶ 2,668:
=={{header|Nim}}==
<syntaxhighlight lang
proc expandRange(input: string): string =
var output: seq[string
for range in input.split(','):
var sep = range.find('-', 1)
Line 2,208 ⟶ 2,691:
return output.join(",")
echo("-6,-3--1,3-5,7-11,14,15,17-20".expandRange)</
{{out}}
Line 2,215 ⟶ 2,698:
=={{header|Oberon-2}}==
Oxford Oberon-2
<
MODULE LIVector;
IMPORT SYSTEM;
Line 2,452 ⟶ 2,935:
END ExpandRange.
</syntaxhighlight>
{{out}}
<pre>
Line 2,459 ⟶ 2,942:
=={{header|OCaml}}==
<
let range a b =
if b < a then invalid_arg "range";
let rec aux i acc =
if i = b then List.rev (i::acc)
else aux (succ i) (i::acc)
in
Line 2,481 ⟶ 2,964:
let exp = range_expand rng in
List.iter (Printf.printf " %d") exp;
print_newline ()</
=={{header|Oforth}}==
<
| i n |
s asInteger dup ifNotNull: [ res add return ] drop
Line 2,493 ⟶ 2,976:
: rangeExpand ( s -- [ n ] )
ArrayBuffer new s wordsWith( ',' ) apply( #[ over addRange ] ) ;</
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
list = '-6,-3--1,3-5,7-11,14,15,17-20'
expanded = expandRanges(list)
Line 2,527 ⟶ 3,010:
end
return expanded
</syntaxhighlight>
{{out}}
<pre>
Line 2,535 ⟶ 3,018:
=={{header|Oz}}==
<
fun {Expand RangeDesc}
{Flatten
Line 2,564 ⟶ 3,047:
in
{System.showInfo
{Value.toVirtualString {Expand "-6,-3--1,3-5,7-11,14,15,17-20"} 100 100}}</
{{out|Sample output}}
<
=={{header|Perl}}==
One-liner:
<
map { /^(.*\d)-(.+)$/ ? $1..$2 : $_ } split /,/, shift
}
# Test and display
print join(',', rangex('-6,-3--1,3-5,7-11,14,15,17-20')), "\n";</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
Alternative:
<
(my $range = shift) =~ s/(?<=\d)-/../g;
eval $range;
}</
=={{header|
<!--<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;">range_expansion</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">range</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: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range</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: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #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: #004080;">string</span> <span style="color: #000000;">si</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: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">si</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #000000;">si</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">startrange</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #000000;">si</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]),</span>
<span style="color: #000000;">endofrange</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_number</span><span style="color: #0000FF;">(</span><span style="color: #000000;">si</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$])</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">startrange</span> <span style="color: #008080;">to</span> <span style="color: #000000;">endofrange</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</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: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">range_expansion</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"-6,-3-1,3-5,7-11,14,15,17-20"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">range_expansion</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"-6,-3--1,3-5,7-11,14,15,17-20"</span><span style="color: #0000FF;">)</span>
<!--</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,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20}
</pre>
=={{header|Phixmonti}}==
Require Phixmonti 1.1
<syntaxhighlight lang="phixmonti">0 tolist var r
def append
r swap 0 put var r
enddef
"-6,-3--1,3-5,7-11,14,15,17-20" "," " " subst split
len for
get dup tonum dup
nan == if
drop
dup len 1 - 2 swap slice
"-" find dup 2 + rot drop
rot rot 1 swap slice tonum
rot rot len rot swap over - 1 + slice tonum
nip rot drop
2 tolist for append endfor
else
append drop
endif
endfor
r
pstack</syntaxhighlight>
Other solution
<syntaxhighlight lang="phixmonti">0 tolist var r
def append
r swap 0 put var r
enddef
"-6,-3--1,3-5,7-11,14,15,17-20" "," " " subst split
len for
get dup tonum dup
nan == if
drop
dup 32 1 set
"-" find nip
swap over 1 - 1 swap slice tonum
rot rot len rot swap over - swap 1 + swap slice tonum
nip 2 tolist for append endfor
else
append drop
endif
endfor
r
pstack</syntaxhighlight>
A bit more understandable
<syntaxhighlight lang="phixmonti">0 tolist var r
def append
r swap 0 put var r
enddef
def getSeparator /# s -- s n #/
dup 32 1 set
"-" find nip
enddef
def first /# s n -- s n #/
swap over 1 - 1
swap slice tonum
enddef
def last /# s n -- s n #/
swap len rot swap over - swap 1 +
swap slice tonum
enddef
"-6,-3--1,3-5,7-11,14,15,17-20" "," " " subst split
len for
get dup tonum dup
nan == if
drop
getSeparator
first
rot rot swap
last
nip 2 tolist for append endfor
else
append drop
endif
endfor
r
pstack</syntaxhighlight>
=={{header|PHP}}==
{{trans|Python}}
<
$lst = array();
foreach (explode(',', $str) as $e) {
Line 2,659 ⟶ 3,204:
}
return $lst;
}</
=={{header|PicoLisp}}==
<
(make
(for S (split (chop Str) ",")
Line 2,670 ⟶ 3,215:
(format (head @ S))
(format (tail (- -1 @) S)) ) )
(link (format S)) ) ) ) )</
{{out}}
<pre>: (rangeexpand "-6,-3--1,3-5,7-11,14,15,17-20")
Line 2,676 ⟶ 3,221:
=={{header|PL/I}}==
<
procedure options (main);
Line 2,726 ⟶ 3,271:
delimiter = ',';
end;
end range_expansion;</
{{out}}
<pre>
Line 2,733 ⟶ 3,278:
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
function range-expansion($array) {
function expansion($arr) {
Line 2,756 ⟶ 3,301:
}
range-expansion "-6,-3--1,3-5,7-11,14,15,17-20"
</syntaxhighlight>
<b>Output:</b>
<pre>
Line 2,764 ⟶ 3,309:
===Alternate Half-Assed Regex Version===
Ten times faster (only minimally tested).
<syntaxhighlight lang="powershell">
function Expand-Range
{
Line 2,807 ⟶ 3,352:
$output
}
</syntaxhighlight>
<syntaxhighlight lang="powershell">
(Expand-Range "-6,-3--1,3-5,7-11,14,15,17-20") -join ", "
</syntaxhighlight>
{{Out}}
<pre>
Line 2,821 ⟶ 3,366:
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 expansion''' and '''Range extraction''' work with the same predicates but in reverse order.
<
L = '-6,-3--1,3-5,7-11,14,15,17-20',
writeln(L),
Line 2,901 ⟶ 3,446:
run(Var1,LRest,[Deb, Fin], RRest).
run(Val,[Other|RRest], [Val, Val],[Other|RRest]).</
{{out}}
<pre> ?- range_expand.
Line 2,909 ⟶ 3,454:
=={{header|PureBasic}}==
<
Protected rangesCount = CountString(txt, ",") + 1
Protected subTxt.s, r, rangeMarker, rangeStart, rangeFinish, rangeIncrement, i
Line 2,954 ⟶ 3,499:
Input()
CloseConsole()
EndIf</
{{out}}
<pre>[ -6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20 ]</pre>
Line 2,960 ⟶ 3,505:
=={{header|Python}}==
===Procedural===
<
lst = []
for r in txt.split(','):
Line 2,970 ⟶ 3,515:
return lst
print(rangeexpand('-6,-3--1,3-5,7-11,14,15,17-20'))</
another variant, using [[regular expressions]] to parse the ranges,
<
def rangeexpand(txt):
Line 2,983 ⟶ 3,528:
else:
lst.append(int(start))
return lst</
===Functional===
As a fold/catamorphism:
{{Works with|Python|3.7}}
<
from functools import (reduce)
# ------------------- EXPANSION FUNCTION -------------------
# rangeExpansion :: String -> [Int]
Line 3,011 ⟶ 3,558:
#
def main():
'''Expansion test'''
Line 3,026 ⟶ 3,573:
#
# breakOn :: String -> String -> (String, String)
Line 3,045 ⟶ 3,592:
# enumFromTo ::
def enumFromTo(m):
'''
'''
return lambda n: list(range(m, 1 + n))
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a ->
def fTable(s):
'''Heading -> x display function ->
fx display function -> f ->
'''
def
fxShow(f(x))
)
return s + '\n' + '\n'.join(
map(arrowed, xs, ys)
)
return goxs
return gof
return gofx
return gox
# showList :: [a] -> String
def showList(xs):
'''Stringification of a list.
'''
return '[' + ','.join(str(x) for x in xs) + ']'
Line 3,079 ⟶ 3,634:
# MAIN ---
if __name__ == '__main__':
main()</
{{Out}}
<pre>Range expansion:
Line 3,088 ⟶ 3,643:
=={{header|R}}==
<syntaxhighlight lang="r">
rangeExpand <- function(text) {
lst <- gsub("(\\d)-", "\\1:", unlist(strsplit(text, ",")))
Line 3,096 ⟶ 3,651:
rangeExpand("-6,-3--1,3-5,7-11,14,15,17-20")
[1] -6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20
</syntaxhighlight>
=={{header|Racket}}==
<
#lang racket
Line 3,113 ⟶ 3,668:
(range-expand "-6,-3--1,3-5,7-11,14,15,17-20")
</syntaxhighlight>
{{out}}
<pre>
Line 3,124 ⟶ 3,679:
rather than 3 followed by - followed by -4,
a readtable is installed that makes - a delimiter.
<
#lang racket
Line 3,151 ⟶ 3,706:
(range-expand (open-input-string "-6,-3--1,3-5,7-11,14,15,17-20"))
</syntaxhighlight>
Note that one can use the full number syntax in this alternative version:
<pre>
Line 3,157 ⟶ 3,712:
'(1 2 30.0 31.0 32.0)
</pre>
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2016.07}}
<syntaxhighlight lang="raku" line>sub range-expand (Str $range-description) {
my token number { '-'? \d+ }
my token range { (<&number>) '-' (<&number>) }
$range-description
.split(',')
.map({ .match(&range) ?? $0..$1 !! +$_ })
.flat
}
say range-expand('-6,-3--1,3-5,7-11,14,15,17-20').join(', ');</syntaxhighlight>
{{out}}
<pre>-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20</pre>
<br>
Alternatively, using a grammar:
<syntaxhighlight lang="raku" line>grammar RangeList {
token TOP { <term>* % ',' { make $<term>.map(*.made) } }
token term { [<range>|<num>] { make ($<num> // $<range>).made } }
token range { <num> '-' <num> { make +$<num>[0] .. +$<num>[1] } }
token num { '-'? \d+ { make +$/ } }
}
say RangeList.parse('-6,-3--1,3-5,7-11,14,15,17-20').made.flat.join(', ');</syntaxhighlight>
{{out}}
<pre>-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20</pre>
=={{header|Raven}}==
Based loosely on Ruby
<
# "-22" split by "-" is [ "", "22" ] so check if
# first list item is "" -> a negative number
Line 3,192 ⟶ 3,781:
"\n" print
'-6,-3--1,3-5,7-11,14,15,17-20' range_expand</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
Line 3,199 ⟶ 3,788:
===version 1===
Extra imbedded blanks were added to the old list (which are ignored) to make the ''over/under'' comparison easier (in the output).
<
old= '-6,-3--1, 3-5, 7-11, 14,15,17-20'; a=translate(old,,',')
new= /*translate [↑] commas (,) ───► blanks*/
Line 3,211 ⟶ 3,800:
new=translate( strip(new), ',', " ") /*remove the first blank, add commas. */
say 'old list: ' old /*show the old list of numbers/ranges.*/
say 'new list: ' new /* " " new " " numbers. */</
'''output'''
<pre>
Line 3,219 ⟶ 3,808:
===Version 2 somewhat simplified !?!===
<
* 09.08.2012 Walter Pachl
**********************************************************************/
Line 3,247 ⟶ 3,836:
End
End
Say 'new='new /*show the expanded list */</
{{out}}
<pre>
Line 3,255 ⟶ 3,844:
=={{header|Ring}}==
<
# Project : Range expansion
Line 3,297 ⟶ 3,886:
see svect
see "]" + nl
</syntaxhighlight>
Output:
<pre>
Line 3,304 ⟶ 3,893:
=={{header|Ruby}}==
<
rng.split(',').flat_map do |part|
if part =~ /^(-?\d+)-(-?\d+)$/
Line 3,314 ⟶ 3,903:
end
p range_expand('-6,-3--1,3-5,7-11,14,15,17-20')</
{{out}}
<pre>[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]</pre>
=={{header|Run BASIC}}==
<
end
Line 3,343 ⟶ 3,932:
if i <> 0 then goto [loop]
rangeExpand$ = range$
end function</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
Line 3,350 ⟶ 3,939:
Rust doesn't have regex in standard library yet.
<
// Precondition: range doesn't contain multibyte UTF-8 characters
Line 3,376 ⟶ 3,965:
println!("{:?}", range_expand("-6,-3--1,3-5,7-11,14,15,17-20"));
}
</syntaxhighlight>
{{out}}
Line 3,384 ⟶ 3,973:
=={{header|S-lang}}==
<
foreach s (strchop(r_expres, ',', 0))
Line 3,402 ⟶ 3,991:
list_append(r_expan, s);
}
print(strjoin(list_to_array(r_expan), ", "));</
=={{header|Scala}}==
<
str split "," flatMap { (s) =>
val r = """(-?\d+)(?:-(-?\d+))?""".r
val r(a,b) = s
if (b == null) Seq(a.toInt) else a.toInt to b.toInt
}</
{{out}}
Line 3,419 ⟶ 4,008:
=={{header|Scheme}}==
<
(lambda (str char skip count)
(let ((len (string-length str)))
Line 3,453 ⟶ 4,042:
(display ","))))))
(split str #\, 0 0))
(newline)))</
{{out}}
<pre>
Line 3,463 ⟶ 4,052:
The library [http://seed7.sourceforge.net/libraries/scanstri.htm scanstri.s7i] defines the function [http://seed7.sourceforge.net/libraries/scanstri.htm#getInteger%28inout_string%29 getInteger] to extract substrings with integer literals (optional sign followed by a sequence of digits) from a string.
The integer literals are converted to the type [http://seed7.sourceforge.net/libraries/integer.htm integer] with the [http://seed7.sourceforge.net/libraries/integer.htm#%28attr_integer%29parse%28in_string%29 parse] operator.
<
include "scanstri.s7i";
Line 3,497 ⟶ 4,086:
end for;
writeln;
end func;</
{{out}}
<pre>
Line 3,504 ⟶ 4,093:
=={{header|Sidef}}==
<
str.split(',').map { |r|
var m = r.match(/^
Line 3,515 ⟶ 4,104:
}
say rangex('-6,-3--1,3-5,7-11,14,15,17-20').join(',')</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</pre>
=={{header|SNOBOL4}}==
<
define('range(n1,n2)') :(range_end)
range range = range n1 ','; n1 = lt(n1,n2) n1 + 1 :s(range)
Line 3,534 ⟶ 4,123:
* # Test and display
output = rangex('-6,-3--1,3-5,7-11,14,15,17-20')
end</
{{out}}
<pre>-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20</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 expansion" in SQL ORACLE 19c
p_list_of_sets -- input string
delimeter by default ","
*/
with
function range_expansion(p_list_of_sets in varchar2)
return varchar2 is
--
v_list_of_sets varchar2(32767) := p_list_of_sets;
v_output varchar2(32767) ;
v_set_1 varchar2(2000) ;
v_set_1_min pls_integer;
v_set_1_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 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 trim(both ',' from min(elem)||','||max(elem)) end
into v_out
from out_tab;
--
return v_out;
end;
--
function sort_output(p_in_str varchar2)
return varchar2 is
v_out varchar2(32767) := p_in_str;
begin
--
with out_tab as
(select 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 listagg(elem, ',') within group(order by elem) end
into v_out
from out_tab
where elem is not null;
--
return v_out;
end;
--
begin
--cleaning
v_list_of_sets := replace(v_list_of_sets, ' ', '') ;
v_list_of_sets := replace(v_list_of_sets, '+', '') ;
v_list_of_sets := replace(v_list_of_sets, ',', '|') ;
v_list_of_sets := regexp_replace(v_list_of_sets, '(\d{1,})-(\d{1,})', '\1,\2', 1, 0) ;
v_list_of_sets := regexp_replace(v_list_of_sets, '(\d{1,})--(\d{1,})', '\1,-\2', 1, 0) ;
--
<<loop_through_sets>>
while regexp_count(v_list_of_sets, '[^|]+') > 0
loop
v_set_1 := regexp_substr(v_list_of_sets, '[^|]+', 1, 1) ;
v_list_of_sets := regexp_replace(v_list_of_sets, v_set_1, sort_set(v_set_1), 1, 1) ;
v_set_1 := sort_set(v_set_1) ;
--
continue loop_through_sets when v_set_1 is null;
--
v_set_1_min := least(to_number(regexp_substr(v_set_1, '[^,]+', 1, 1))
,to_number(regexp_substr(v_set_1, '[^,]+', 1, 2))
) ;
v_set_1_max := greatest(to_number(regexp_substr(v_set_1, '[^,]+', 1, 1))
,to_number(regexp_substr(v_set_1, '[^,]+', 1, 2))
) ;
--
<<loop_for>>
for i in v_set_1_min..v_set_1_max
loop
--
v_output := v_output||','||i;
--
end loop loop_for;
--
v_list_of_sets := regexp_replace(v_list_of_sets,v_set_1,'',1,1);
--
end loop loop_through_sets;
--
v_output := sort_output(v_output);
--
return trim(v_output);
end;
--Test
select '-- Test ' as output from dual
union all
select lpad(' ', 65) || ' ==> ' || range_expansion(' ') as output from dual
union all
select lpad('-0,+0,-2 ,-1--2,3 ,-3, 2,-2', 65) || ' ==> ' || range_expansion('-0,+0,-2 ,-1--2,3 ,-3, 2,-2') as output from dual
union all
select lpad('0,-1,+2,-2', 65) || ' ==> ' || range_expansion('0,-1,2,-2') as output from dual
union all
select lpad('-D,-w23--1,+14q,15,17-20,3-5,7-11, +0, 2q, +4, 3,0 ,-0,-2 , -3', 65) || ' ==> ' || range_expansion('-D,-w23--1,+14q,15,17-20,3-5,7-11, +0, 2q, +4, 3,0 ,-0,-2 , -3') as output from dual
union all
select lpad('-6,-3--1,14,15,17-20,3-5,7-11', 65) || ' ==> ' || range_expansion('-6,-3--1,14,15,17-20,3-5,11-7') as output from dual
union all
--Test RosettaCode
select '-- Test RosettaCode' as output from dual
union all
select lpad('-6,-3--1,3-5,7-11,14,15,17-20', 65) || ' ==> ' || range_expansion('-6,-3--1,3-5,7-11,14,15,17-20') as output from dual
;
</syntaxhighlight>
{{out}}
<pre>
-- Test
==>
-0,+0,-2 ,-1--2,3 ,-3, 2,-2 ==> -3,-2,-1,0,2,3
0,-1,+2,-2 ==> -2,-1,0,2
-D,-w23--1,+14q,15,17-20,3-5,7-11, +0, 2q, +4, 3,0 ,-0,-2 , -3 ==> -3,-2,-1,0,3,4,5,7,8,9,10,11,15,17,18,19,20
-6,-3--1,14,15,17-20,3-5,7-11 ==> -6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20
-- Test RosettaCode
-6,-3--1,3-5,7-11,14,15,17-20 ==> -6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20
</pre>
=={{header|Tailspin}}==
<syntaxhighlight lang="tailspin">
composer expand
[<element>*]
rule element: <range|INT> (<','>?)
rule range: (def start: <INT>; <'-'>) <INT> -> $start..$
end expand
'-6,-3--1,3-5,7-11,14,15,17-20' -> expand -> !OUT::write
</syntaxhighlight>
{{out}}
<pre>
[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
</pre>
=={{header|Tcl}}==
<
set result {}
foreach term [split $desc ","] {
Line 3,552 ⟶ 4,290:
}
puts [rangeExpand "-6,-3--1,3-5,7-11,14,15,17-20"]</
{{out}}
<pre>-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</pre>
=={{header|TUSCRIPT}}==
<
rangednrs="-6,-3--1,3-5,7-11,14,15,17-20"
expandnrs=SPLIT (rangednrs,":,:")
Line 3,578 ⟶ 4,316:
expandnrs= JOIN (expandnrs,",")
PRINT expandnrs</
{{out}}
<pre>
Line 3,603 ⟶ 4,341:
Code:
<
@(define entry (e))@\
@(local n1 n2)@\
Line 3,645 ⟶ 4,383:
your junk: @{trailing-junk}
@(end)
@(end)</
{{out|Run}}
Line 3,669 ⟶ 4,407:
=={{header|UNIX Shell}}==
{{works with|bash}}
<
range_expand () (
Line 3,687 ⟶ 4,425:
)
range_expand "-6,-3--1,3-5,7-11,14,15,17-20"</
{{out}}
<pre>-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20</pre>
=={{header|Ursala}}==
<
#import int
Line 3,699 ⟶ 4,437:
#cast %zL
t = rex '-6,-3--1,3-5,7-11,14,15,17-20'</
{{out}}
<pre><-6,-3,-2,-1,3,4,5,7,8,9,10,11,14,15,17,18,19,20></pre>
=={{header|VBA}}==
<
' return a list with the numbers expressed in AString
Dim Splits() As String
Line 3,749 ⟶ 4,487:
Next
Debug.Print
End Sub</
{{out}}
<pre>
Line 3,757 ⟶ 4,495:
</pre>
=={{header|
{{trans|Kotlin}}
<syntaxhighlight lang="wren">var expandRange = Fn.new { |s|
var list = []
var items = s.split(",")
for (item in items) {
var count = item.count { |c| c == "-" }
if (count == 0 || (count == 1 && item[0] == "-")) {
list.add(Num.fromString(item))
} else {
var items2 = item.split("-")
var first
var last
if (count == 1) {
first = Num.fromString(items2[0])
last = Num.fromString(items2[1])
} else if (count == 2) {
first = Num.fromString(items2[1]) * -1
last = Num.fromString(items2[2])
} else {
first = Num.fromString(items2[1]) * -1
last = Num.fromString(items2[3]) * -1
}
for (i in first..last) list.add(i)
}
}
return list
}
var s = "-6,-3--1,3-5,7-11,14,15,17-20"
System.print(expandRange.call(s))</syntaxhighlight>
{{out}}
<pre>
[-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
</pre>
=={{header|XPL0}}==
See Range Extraction for explanations.
<syntaxhighlight lang "XPL0">proc Expand(Range);
char Range;
int Lo, Hi, N;
[Text(8, Range);
loop [Lo:= IntIn(8);
BackUp; \get what terminated number
^-: [Hi:= IntIn(8);
for N:= Lo to Hi do
[IntOut(0, N);
if N < Hi then Text(0, ", ");
];
BackUp;
if ChIn(8) = $1A \EOF\ then quit;
];
^,: IntOut(0, Lo)
other \EOF\ [IntOut(0, Lo); quit];
Text(0, ", ");
];
];
Expand("-6,-3--1,3-5,7-11,14,15,17-20")
</syntaxhighlight>
{{out}}
<pre>
-6, -3, -2, -1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20</pre>
=={{header|Yabasic}}==
<
sub RangeExpand$(s$)
Line 3,829 ⟶ 4,584:
return left$(r$, len(r$) - 1)
end sub
</syntaxhighlight>
=={{header|zkl}}==
<
fcn(s,re){
if (re.search(s)){
Line 3,842 ⟶ 4,597:
s.split(",").pump(List, _.fp1(RegExp(0'|(.*\d+)-(.*\d+)|)))
.flatten().concat(",");
}</
<
rangex(ns).println();
ns="-6,-3--1,3-5,7-11,14,15,17-20";
rangex(ns).println();</
{{out}}
|