Brace expansion using ranges: Difference between revisions

→‎{{header|jq}}: right-most-first
(Added a Python implementation)
(→‎{{header|jq}}: right-most-first)
 
(24 intermediate revisions by 10 users not shown)
Line 1:
{{draft task}}{{clarified-review}}
 
;Task
{{task heading}}
 
Write and test a function which expands one or more Unix-style '''numeric and alphabetic range braces''' embedded in a larger string.<br><br>
Line 54:
{{task heading|Tests}}
 
Generate and display here the expansion of (at least) each of the nineten example lines shown abovebelow.
 
The JavaScript implementation below uses parser combinators, aiming to encode a more or less full and legible description of the <pre><PREAMBLE><AMBLE><POSTSCRIPT></pre> range brace grammar, but you should use any resource that suggests itself in your language, including parser libraries.
Line 60:
(The grammar of range expansion, unlike that of nested list expansion, is not recursive, so even regular expressions should prove serviceable here).
 
The output of the JS implementation, which aims to match the brace expansion behaviour of the default '''zsh''' shell on macOScurrent Catalinaversions isof macOS:
 
<pre>simpleNumberRising{1..3}.txt ->
Line 81:
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
reverseSteppedNumberRising{1..6..-2}.txt ->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
 
combined-{Q..P}{2..1}.txt ->
Line 106 ⟶ 111:
* &nbsp; [[Range_expansion|range expansion]]
<br><br>
=={{header|11l}}==
{{trans|Nim}}
 
<syntaxhighlight lang="11l">F intFromString(s) -> Int?
X.try
R Int(s)
X.catch ValueError
R N
 
F parseRange(r)
I r.empty {R [‘{}’]}
V sp = r.split(‘..’)
I sp.len == 1 {R [‘{’r‘}’]}
V first = sp[0]
V last = sp[1]
V incr = I sp.len == 2 {‘1’} E sp[2]
 
Int? val1 = intFromString(first)
Int? val2 = intFromString(last)
Int? val3 = intFromString(incr)
 
I val3 == N {R [‘{’r‘}’]}
V n3 = val3
V numeric = val1 != N & val2 != N
 
Int n1
Int n2
I numeric
n1 = val1
n2 = val2
E
I (val1 != N & val2 == N) | (val1 == N & val2 != N)
R [‘{’r‘}’]
I first.len != 1 | last.len != 1
R [‘{’r‘}’]
n1 = first[0].code
n2 = last[0].code
 
V width = 1
I numeric
width = max(first.len, last.len)
 
I n3 == 0
R I numeric {[String(n1).zfill(width)]} E [first]
 
V asc = n1 < n2
I n3 < 0
asc = !asc
swap(&n1, &n2)
n3 = -n3
 
[String] result
V i = n1
I asc
L i <= n2
result.append(I numeric {String(i).zfill(width)} E Char(code' i))
i += n3
E
L i >= n2
result.append(I numeric {String(i).zfill(width)} E Char(code' i))
i -= n3
R result
 
F rangeExpand(s)
V result = [‘’]
V rng = ‘’
V inRng = 0B
 
L(c) s
I c == ‘{’ & !inRng
inRng = 1B
rng = ‘’
E I c == ‘}’ & inRng
V rngRes = parseRange(rng)
[String] res
L(r) result
L(rr) rngRes
res.append(r‘’rr)
result = move(res)
inRng = 0B
E I inRng
rng ‘’= c
E
L(&s) result
s ‘’= c
 
I inRng
L(&s) result
s ‘’= ‘{’rng
R result
 
-V examples = [‘simpleNumberRising{1..3}.txt’,
‘simpleAlphaDescending-{Z..X}.txt’,
‘steppedDownAndPadded-{10..00..5}.txt’,
‘minusSignFlipsSequence {030..20..-5}.txt’,
‘combined-{Q..P}{2..1}.txt’,
‘li{teral’,
‘rangeless{}empty’,
‘rangeless{random}string’,
‘mixedNumberAlpha{5..k}’,
‘steppedAlphaRising{P..Z..2}.txt’,
‘stops after endpoint-{02..10..3}.txt’]
 
L(s) examples
print(s" ->\n ", end' ‘’)
V res = rangeExpand(s)
print(res.join("\n "))
print()</syntaxhighlight>
 
{{out}}
<pre>
simpleNumberRising{1..3}.txt ->
simpleNumberRising1.txt
simpleNumberRising2.txt
simpleNumberRising3.txt
 
simpleAlphaDescending-{Z..X}.txt ->
simpleAlphaDescending-Z.txt
simpleAlphaDescending-Y.txt
simpleAlphaDescending-X.txt
 
steppedDownAndPadded-{10..00..5}.txt ->
steppedDownAndPadded-10.txt
steppedDownAndPadded-05.txt
steppedDownAndPadded-00.txt
 
minusSignFlipsSequence {030..20..-5}.txt ->
minusSignFlipsSequence 020.txt
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
combined-{Q..P}{2..1}.txt ->
combined-Q2.txt
combined-Q1.txt
combined-P2.txt
combined-P1.txt
 
li{teral ->
li{teral
 
rangeless{}empty ->
rangeless{}empty
 
rangeless{random}string ->
rangeless{random}string
 
mixedNumberAlpha{5..k} ->
mixedNumberAlpha{5..k}
 
steppedAlphaRising{P..Z..2}.txt ->
steppedAlphaRisingP.txt
steppedAlphaRisingR.txt
steppedAlphaRisingT.txt
steppedAlphaRisingV.txt
steppedAlphaRisingX.txt
steppedAlphaRisingZ.txt
 
stops after endpoint-{02..10..3}.txt ->
stops after endpoint-02.txt
stops after endpoint-05.txt
stops after endpoint-08.txt
 
</pre>
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">Brace_expansion_using_ranges(line){
needle := "^.*\K{(?P<Start>[^{}]+?)\..(?P<End>[^{}]+?)(?:\..(?P<Incr>[^{}]+?))?}"
while true
{
while pos := RegExMatch(line, needle, m, A_Index=1?1:pos+StrLen(m))
{
char := false, step := "", output := ""
reverse := InStr(mIncr, "-") ? true : false
if mStart is number
pad1 := pad(mStart), pad2 := pad(mEnd), pad := StrLen(pad1)>=StrLen(pad2) ? pad1 : pad2
else
mStart := Ord(mStart), mEnd := Ord(mEnd), char := true
mIncr := (mIncr?Abs(mIncr):1) * (mStart>mEnd?-1:1)
loop % Abs((mStart-mEnd)/mIncr) + 1
{
step := mStart + (A_Index-1) * mIncr
step := pad <> "" ? SubStr(pad . step, 1-StrLen(pad)) : step
step := char ? Chr(step) : step
Rep := StrReplace(line, m, step)
output := reverse ? rep "`n" output : output .= Rep "`n"
}
output := Trim(Output, "`n")
}
if RegExMatch(output, needle)
line := output
else
break
}
return output ? output : line
}
pad(num){
if RegExMatch(num, "`am)^(0+)(?=[1-9]|0$)", m)
loop % StrLen(num)
pad .= "0"
return pad
}</syntaxhighlight>
Examples:<syntaxhighlight lang="autohotkey">data=
(
simpleNumberRising{1..3}.txt
simpleAlphaDescending-{Z..X}.txt
steppedDownAndPadded-{10..00..5}.txt
minusSignFlipsSequence {030..20..-5}.txt
reverseSteppedNumberRising{1..6..-2}.txt
combined-{Q..P}{2..1}.txt
emoji{🌵..🌶}{🌽..🌾}etc
li{teral
rangeless{}empty
rangeless{random}string
)
for i, line in StrSplit(data, "`n", "`r")
result .= line " ->`n" RegExReplace(Brace_expansion_using_ranges(line), "`am)^", "`t") "`n`n"
 
MsgBox, 262144, , % result
return</syntaxhighlight>
{{out}}
<pre>simpleNumberRising{1..3}.txt ->
simpleNumberRising1.txt
simpleNumberRising2.txt
simpleNumberRising3.txt
 
simpleAlphaDescending-{Z..X}.txt ->
simpleAlphaDescending-Z.txt
simpleAlphaDescending-Y.txt
simpleAlphaDescending-X.txt
 
steppedDownAndPadded-{10..00..5}.txt ->
steppedDownAndPadded-10.txt
steppedDownAndPadded-05.txt
steppedDownAndPadded-00.txt
 
minusSignFlipsSequence {030..20..-5}.txt ->
minusSignFlipsSequence 020.txt
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
reverseSteppedNumberRising{1..6..-2}.txt ->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
 
combined-{Q..P}{2..1}.txt ->
combined-Q2.txt
combined-Q1.txt
combined-P2.txt
combined-P1.txt
 
emoji{🌵..🌶}{🌽..🌾}etc ->
emoji🌵🌽etc
emoji🌵🌾etc
emoji🌶🌽etc
emoji🌶🌾etc
 
li{teral ->
li{teral
 
rangeless{}empty ->
rangeless{}empty
 
rangeless{random}string ->
rangeless{random}string</pre>
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Brace expansion using ranges. Nigel Galloway: October 6th., 2021
let fUC, fUR=System.Text.Rune.GetUnicodeCategory,(fun n->System.Text.Rune.GetRuneAt(n,0))
let fV(n,i,g,e,l,s)=let l=if l="" then 1 else int l in match l with 0->None |_->Some(n,i,g,e,int l,s)
let(|Valid|_|)(n:System.Text.RegularExpressions.Match)=let fN(g:string)=n.Groups.[g].Value in if n.Success then fV(fN "n",fN "i",fN "g",fN "e",fN "l",fN "s") else None
let fN(g:string)=let mutable g=g.EnumerateRunes() in if g.MoveNext() && not(g.MoveNext()) then true else false
let(|I|_|)(n,g)=if fN n && fN g then (let n,g=fUR n,fUR g in if fUC n=fUC g then Some(n,g) else None) else None
let(|G|_|)(n:string,g:string)=try let n,g=(int n,int g) in Some(n,g) with _->None
let(|E|_|)(n:string,g:string)=if n.[0]='0' || g.[0]='0' then match (n,g) with G(e,l)->Some(e,l,max n.Length g.Length) |_->None else None
let fL n=let fN i g e l=let n=[i..(if i>g then -l else l)..g] in if e="-" then List.rev n else n
let fG n g=let n,buf=string n, System.Text.StringBuilder() in (for _ in 1..g-n.Length do buf.Append 0); buf.Append n; buf.ToString()
match System.Text.RegularExpressions.Regex.Match(n,@"^(?<n>.*?){(?<i>.*?)\.\.(?<g>.*?)(\.\.(?<e>[-]+)?(?<l>[0-9]*?))?}(?<s>.*)$") with
Valid(n,i,g,e,l,s)->match (i,g) with I(i,g)->Some(fN i.Value g.Value e l|>Seq.map(fun g->sprintf "%s%A%s" n (System.Text.Rune(g)) s))
|E(i,g,z)->Some(fN i g e l|>Seq.map(fun g->sprintf "%s%s%s" n (fG g z) s))
|G(i,g)->Some(fN i g e l|>Seq.map(fun g->sprintf "%s%A%s" n (string g) s)) |_->None
|_->None
let rec expBraces n=seq{match fL n with Some n->yield!(n|>Seq.collect(expBraces)) |_->yield n}
let tests=["simpleNumberRising{1..3}.txt";"steppedNumberRising{1..6..2}.txt";"reverseSteppedNumberRising{1..6..-2}.txt";"steppedNumberDescending{20..9..2}.txt";"simpleAlphaDescending-{Z..X}.txt";"steppedDownAndPadded-{10..00..5}.txt";"minusSignFlipsSequence {030..20..-5}.txt";"combined-{Q..P}{2..1}.txt";"emoji{🌵..🌶}{🌽..🌾}etc";"li{teral";"rangeless{random}string";"rangeless{}empty";"steppedAlphaDescending-{Z..M..2}.txt";"reversedSteppedAlphaDescending-{Z..M..-2}.txt"]
tests|>List.iter(fun g->printfn $"%s{g}->"; for n in expBraces g do printfn $" %s{n}")
</syntaxhighlight>
{{out}}
<pre>
simpleNumberRising{1..3}.txt->
simpleNumberRising1.txt
simpleNumberRising2.txt
simpleNumberRising3.txt
steppedNumberRising{1..6..2}.txt->
steppedNumberRising1.txt
steppedNumberRising3.txt
steppedNumberRising5.txt
reverseSteppedNumberRising{1..6..-2}.txt->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
steppedNumberDescending{20..9..2}.txt->
steppedNumberDescending"20".txt
steppedNumberDescending"18".txt
steppedNumberDescending"16".txt
steppedNumberDescending"14".txt
steppedNumberDescending"12".txt
steppedNumberDescending"10".txt
simpleAlphaDescending-{Z..X}.txt->
simpleAlphaDescending-Z.txt
simpleAlphaDescending-Y.txt
simpleAlphaDescending-X.txt
steppedDownAndPadded-{10..00..5}.txt->
steppedDownAndPadded-10.txt
steppedDownAndPadded-05.txt
steppedDownAndPadded-00.txt
minusSignFlipsSequence {030..20..-5}.txt->
minusSignFlipsSequence 020.txt
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
combined-{Q..P}{2..1}.txt->
combined-Q2.txt
combined-Q1.txt
combined-P2.txt
combined-P1.txt
emoji{🌵..🌶}{🌽..🌾}etc->
emoji🌵🌽etc
emoji🌵🌾etc
emoji🌶🌽etc
emoji🌶🌾etc
li{teral->
li{teral
rangeless{random}string->
rangeless{random}string
rangeless{}empty->
rangeless{}empty
steppedAlphaDescending-{Z..M..2}.txt->
steppedAlphaDescending-Z.txt
steppedAlphaDescending-X.txt
steppedAlphaDescending-V.txt
steppedAlphaDescending-T.txt
steppedAlphaDescending-R.txt
steppedAlphaDescending-P.txt
steppedAlphaDescending-N.txt
reversedSteppedAlphaDescending-{Z..M..-2}.txt->
reversedSteppedAlphaDescending-N.txt
reversedSteppedAlphaDescending-P.txt
reversedSteppedAlphaDescending-R.txt
reversedSteppedAlphaDescending-T.txt
reversedSteppedAlphaDescending-V.txt
reversedSteppedAlphaDescending-X.txt
reversedSteppedAlphaDescending-Z.txt
</pre>
=={{header|Go}}==
{{trans|Wren}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 117 ⟶ 474:
"unicode/utf8"
)
 
func sign(n int) int {
switch {
case n < 0:
return -1
case n > 0:
return 1
}
return 0
}
 
func abs(n int) int {
if n < 0 {
return -n
}
return n
}
 
func parseRange(r string) []string {
Line 168 ⟶ 542:
if n3 < 0 {
asc = !asc
n1, n2t := n2, n1
d := abs(n1-n2) % (-n3)
n1 = n2 - d*sign(n2-n1)
n2 = t
n3 = -n3
}
Line 233 ⟶ 610:
"steppedDownAndPadded-{10..00..5}.txt",
"minusSignFlipsSequence {030..20..-5}.txt",
"reverseSteppedNumberRising{1..6..-2}.txt",
"combined-{Q..P}{2..1}.txt",
"emoji{🌵..🌶}{🌽..🌾}etc",
Line 241 ⟶ 619:
"steppedAlphaRising{P..Z..2}.txt",
"stops after endpoint-{02..10..3}.txt",
"steppedNumberRising{1..6..2}.txt",
"steppedNumberDescending{20..9..2}",
"steppedAlphaDescending-{Z..M..2}.txt",
"reversedSteppedAlphaDescending-{Z..M..-2}.txt",
}
for _, s := range examples {
Line 248 ⟶ 630:
fmt.Println()
}
}</langsyntaxhighlight>
 
{{out}}
Line 254 ⟶ 636:
Same as Wren entry.
</pre>
 
=={{header|JavaScript}}==
<langsyntaxhighlight lang="javascript">(() => {
'"use strict'";
 
// --------------- BRACE-RANGE EXPANSION ---------------
 
// braceExpandWithRange :: String -> [String]
Line 269 ⟶ 650:
braceRangeExpansion()
))(s);
 
return 0 < expansions.length ? (() => {
const [parsed, residue] = Array.from(expansions[0];
 
expansions[0]
);
return suffixAdd(
parsed.reduce(
uncurry(suffixMultiply),
[''""]
)
)([residue.join(''"")]);
})() : [s];
};
 
 
// ----------- BRACE-RANGE EXPANSION PARSER ------------
 
// braceRangeExpansion :: [String]
Line 298 ⟶ 679:
affixLeaf(),
fmapP(xs => [xs])(
between(char('"{'"))(char('"}'"))(
altP(
numericSequence()
Line 310 ⟶ 691:
 
 
// ----------------------- TESTS -----------------------
// main :: IO ()
const main = () => {
const tests = [
'"simpleNumberRising{1..3}.txt'",
'"simpleAlphaDescending-{Z..X}.txt'",
'"steppedDownAndPadded-{10..00..5}.txt'",
'"minusSignFlipsSequence {030..20..-5}.txt'",
'combined-"reverseSteppedNumberRising{Q1..P}{26..1-2}.txt'",
'emoji"combined-{🌵Q..🌶P}{🌽2..🌾1}etc'.txt",
'li"emoji{teral'🌵..🌶}{🌽..🌾}etc",
'rangeless"li{}empty'teral",
'"rangeless{random}string'empty",
"rangeless{random}string"
];
 
return tests.map(s => {
s => s + ' -> ' + '\n\t' + (const
expanded = braceExpandWithRange(s).join('\n\t')
.join("\n\t");
 
).join('\n\n');
return `${s} -> \n\t${expanded}`;
})
.join("\n\n");
};
 
 
// ----------- BRACE-RANGE COMPONENT PARSERS -----------
 
// affixLeaf :: () -> Parser String
Line 340 ⟶ 725:
// characters before or after a pair of braces.
fmapP(cs => [
[cs.join(''"")]
])(
many(choice([noneOf('"{\\'"), escape()]))
);
 
Line 352 ⟶ 737:
fmapP(ab => {
const [from, to] = ab;
 
return from !== to ? (
enumFromThenToChar(from)(
Line 359 ⟶ 745:
})(
ordinalRange(satisfy(
c => !'"0123456789'".includes(c)
))
);
Line 375 ⟶ 761:
[from, to, by] = triple.map(
sn => (sn[0] ? negate : identity)(
parseInt(sn[1], 10)
)
);
 
return map(
compose(justifyRight(w)('"0'"), str)
)(
0 > by ? (
enumFromThenTo(to)(to0 -> by) ? (from)
) : enumFromThenTo(from)( reverse
from + (to >= from ? by) : -by)identity
)(to)
enumFromThenTo(from)(
from + (
to < from ? (
-abs(by)
) : abs(by)
)
)(to)
)
);
};
Line 396 ⟶ 791:
// The String component contains the digits.
bindP(
option(''"")(char('"-'"))
)(sign => bindP(
some(digit())
Line 422 ⟶ 817:
option(Tuple(false)(1))(
bindP(
string('"..'")
)(_() => bindP(
numericPart()
)(pureP))
Line 438 ⟶ 833:
p
)(from => bindP(
string('"..'")
)(_() => bindP(
p
)(compose(pureP, append([from])))));
Line 452 ⟶ 847:
(a, x) => (0 < a) || (1 > x.length) ? (
a
) : '"0'" !== x[0] ? a : x.length,
0
);
Line 469 ⟶ 864:
 
 
// ------------ GENERIC PARSER COMBINATORS -------------
 
// Parser :: String -> [(a, String)] -> Parser a
Line 475 ⟶ 870:
// A function lifted into a Parser object.
({
type: '"Parser'",
parser: f
});
Line 485 ⟶ 880:
q => Parser(s => {
const xs = parse(p)(s);
 
return 0 < xs.length ? (
xs
Line 498 ⟶ 894:
p => Parser(
s => parse(pf)(s).flatMap(
vr([v, r]) => parse(
fmapP(vr[0]v)(p)
)(vr[1]r)
)
);
Line 512 ⟶ 908:
pClose => p => bindP(
pOpen
)(_() => bindP(
p
)(x => bindP(
pClose
)(_() => pureP(x))));
 
 
Line 529 ⟶ 925:
f => Parser(
s => parse(p)(s).flatMap(
tpl([x, r]) => parse(f(tpl[0]x))(tpl[1]r)
)
);
Line 537 ⟶ 933:
const char = x =>
// A particular single character.
satisfy(c => x === c);
 
 
Line 556 ⟶ 952:
const emptyP = () =>
// The empty list.
Parser(_() => []);
 
 
// escape :: Parser String
const escape = () =>
fmapP(xs => xs.join(''""))(
sequenceP([char('"\\'"), item()])
);
 
Line 572 ⟶ 968:
p => Parser(
s => parse(p)(s).flatMap(
vr => Tuplefirst(f(vr[0]))(vr[1])
)
);
Line 580 ⟶ 976:
const item = () =>
// A single character.
Parser(s => {
sconst =>[h, 0...t] <= s.length ? [;
 
Tuple(s[0])(
return Boolean(h) ? s.slice(1)[
Tuple(h)(t)
] : [];
});
 
 
Line 602 ⟶ 998:
// Lifts a parser for a simple type of value
// to a parser for a list of such values.
const some_psomeP = pq =>
liftA2P(
x => xs => [x].concat(xs)
)(pq)(many(pq));
 
return Parser(
s => parse(
0 < s.length ? (
altP(some_psomeP(p))(pureP([]))
) : pureP([])
)(s)
Line 632 ⟶ 1,029:
const parse = p =>
// The result of parsing s with p.
s => {p.parser([...s]);
//showLog('s', s)
return p.parser([...s]);
};
 
 
Line 649 ⟶ 1,043:
// Any character for which the
// given predicate returns true.
Parser(s => {
sconst =>[h, 0...t] <= s.length ? (;
 
test(s[0]) ? [
return Boolean(h) ? Tuple(s[0])(s.slice(1))
test(h) ? [
Tuple(h)(t)
] : []
) : [];
});
 
 
// sepBy1 :: Parser a -> Parser b -> Parser [a]
const sepBy1 = p =>
// One or more occurrences of p, as
// separated by (discarded) instances of sep.
sep => bindP(
p
)(x => bindP(
many(bindP(
sep
)(_ => bindP(
p
)(pureP))))(
xs => pureP([x].concat(xs))));
 
 
// sequenceP :: [Parser a] -> Parser [a]
Line 680 ⟶ 1,060:
s => ps.reduce(
(a, q) => a.flatMap(
vr([v, r]) => parse(q)(snd(vr)r).flatMap(
first(xs => fst(vr)v.concat(xs))
)
),
Line 694 ⟶ 1,074:
// Lifts a parser for a simple type of value
// to a parser for a list of such values.
const many_pmanyP = pq =>
altP(some(pq))(pureP([]));
 
return Parser(
s => parse(
liftA2P(
x => xs => [x].concat(xs)
)(p)(many_pmanyP(p))
)(s)
);
Line 709 ⟶ 1,090:
const string = s =>
// A particular string.
fmapP(cs => cs.join(''""))(
sequenceP([...s].map(char))
);
 
 
// ----------------- GENERAL FUNCTIONS -----------------
 
// Tuple (,) :: a -> b -> (a, b)
const Tuple = a =>
b => ({
type: '"Tuple'",
'"0'": a,
'"1'": b,
length: 2,
*[Symbol.iterator]() {
for (const k in this) {
if (!isNaN(k)) {
yield this[k];
}
}
}
});
 
 
// abs :: Num -> Num
const abs =
// Absolute value of a given number
// without the sign.
x => 0 > x ? (
-x
) : x;
 
 
Line 753 ⟶ 1,150:
 
// concat :: [[a]] -> [a]
//const concat ::= [String]xs -=> String
const concat = xs => .flat(1);
ys => 0 < ys.length ? (
ys.every(Array.isArray) ? (
[]
) : ''
).concat(...ys) : ys
)(list(xs));
 
 
// enumFromThenTo :: Int -> Int -> Int -> [Int]
const enumFromThenTo = x1m =>
x2// =>Integer yvalues =>enumerated {from m to n
// with a step constdefined dby = x2(nxt - x1;m).
nxt => n => {
const d = nxt - m;
 
return Array.from({
length: (Math.floor(yn - x2nxt) / d) + 2
}, (_, i) => x1m + (d * i));
};
 
Line 779 ⟶ 1,173:
.map(x => x.codePointAt(0)),
d = i2 - i1;
 
return Array.from({
length: (Math.floor(iY - i2) / d) + 2
Line 789 ⟶ 1,184:
// A simple function lifted to one which applies
// to a tuple, transforming only its first item.
xy([x, y]) => Tuple(f(xy[0]x))(y);
xy[1]
);
 
 
// flip :: (a -> b -> c) -> b -> a -> c
const flip = op =>
// The binary function op with
// its arguments reversed.
1 < op.length ? (
(a, b) => op(b, a)
) : (x => y => op(y)(x));
 
 
// fst :: (a, b) -> a
const fst = tpl =>
// First member of a pair.
tpl[0];
 
 
// fromEnum :: Enum a => a -> Int
const fromEnum = x =>
typeof x !== '"string'" ? (
x.constructor === Object ? (
x.value
) : parseInt(Number(x), 10)
) : x.codePointAt(0);
 
Line 822 ⟶ 1,209:
// The identity function. (`id`, in Haskell)
x;
 
 
// isAlpha :: Char -> Bool
const isAlpha = c =>
/[A-Za-z\u00C0-\u00FF]/.test(c);
 
 
Line 832 ⟶ 1,214:
const isDigit = c => {
const n = c.codePointAt(0);
 
return 48 <= n && 57 >= n;
};
Line 843 ⟶ 1,226:
s.padStart(n, c)
) : s;
 
 
// list :: StringOrArrayLike b => b -> [a]
const list = xs =>
// xs itself, if it is an Array,
// or an Array derived from xs.
Array.isArray(xs) ? (
xs
) : Array.from(xs || []);
 
 
Line 865 ⟶ 1,239:
const maxBound = x => {
const e = x.enum;
 
return Boolean(e) ? (
e[e[x.max]]
) : {
'"number'": Number.MAX_SAFE_INTEGER,
'"string'": String.fromCodePoint(0x10FFFF),
'"boolean'": true
} [typeof x];
};
Line 877 ⟶ 1,252:
const minBound = x => {
const e = x.enum;
 
return Boolean(e) ? (
e[e[0]]
) : {
'"number'": Number.MIN_SAFE_INTEGER,
'"string'": String.fromCodePoint(0),
'"boolean'": false
} [typeof x];
};
Line 895 ⟶ 1,271:
const pred = x => {
const t = typeof x;
 
return 'number' !== t ? (() => {
return "number" !== t ? (() => {
const [i, mn] = [x, minBound(x)].map(fromEnum);
 
return i > mn ? (
toEnum(x)(i - 1)
) : Error('"succ :: enum out of range.'");
})() : x > Number.MIN_SAFE_INTEGER ? (
x - 1
) : Error('"succ :: Num out of range.'");
};
 
 
// showLogreverse :: [a] -> IO ()[a]
const showLogreverse = (...args)xs =>
consolexs.logslice(0).reverse();
args
.map(JSON.stringify)
.join(' -> ')
);
 
 
// snd :: (a, b) -> b
const snd = tpl =>
// Second member of a pair.
tpl[1];
 
 
Line 924 ⟶ 1,292:
const str = x =>
Array.isArray(x) && x.every(
v => ('"string'" === typeof v) && (1 === v.length)
) ? (
x.join(''"")
) : x.toString();
 
Line 933 ⟶ 1,301:
const succ = x => {
const t = typeof x;
 
return 'number' !== t ? (() => {
return "number" !== t ? (
const [i, mx] = [x, maxBound(x)].map(fromEnum);
return(() i=> < mx ? ({
toEnumconst [i, mx] = [x, maxBound(x)].map(1 + i)
) : Error('succ :: enum out of range.') fromEnum
})() : x < Number.MAX_SAFE_INTEGER ? ( );
 
return i < mx ? (
toEnum(x)(1 + i)
) : Error("succ :: enum out of range.");
})()
) : x < Number.MAX_SAFE_INTEGER ? (
1 + x
) : Error('"succ :: Num out of range.'");
};
 
Line 949 ⟶ 1,323:
// allowing the function to make the right mapping
x => ({
'"number'": Number,
'"string'": String.fromCodePoint,
'"boolean'": Boolean,
'"object'": v => e.min + v
} [typeof e])(x);
 
Line 960 ⟶ 1,334:
// A function over a pair, derived
// from a curried function.
function (...args) => {
const
args = arguments,
xy = Boolean(args.length % 2) ? (
args[0]
) : args;
 
return f(xy[0])(xy[1]);
};
Line 971 ⟶ 1,345:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>simpleNumberRising{1..3}.txt ->
Line 992 ⟶ 1,366:
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
reverseSteppedNumberRising{1..6..-2}.txt ->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
 
combined-{Q..P}{2..1}.txt ->
Line 1,013 ⟶ 1,392:
rangeless{random}string ->
rangeless{random}string</pre>
=={{header|jq}}==
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
 
This implementation relies on "reluctant" regex parsing.
 
Range expressions of the form {x..y}, where x and y are single
characters, are allowed, even if exactly one of them is a digit.
 
When expanding an expression with more than one range, the program
as given below produces an ordering
based on expansion of the left-most range first.
A trivial change in two places is sufficient to produce the alternative ordering.
<syntaxhighlight lang="jq">
# Left-pad with 0s
def lpad($len): tostring | ($len - length) as $l | ("0" * $l) + .;
 
def expand:
# The key to success here is reluctance (".*?")
def cap:
capture("(?<head>^.*?)[{](?<from>[0-9]+|.)[.][.](?<to>[0-9]+|.)"
+ "([.][.](?<sign>-)?(?<increment>[0-9]))?[}](?<tail>.*)$");
 
def ton: if . == null then . else tonumber end;
 
# Produce a stream of integers, handling implicit descent.
# $i and $j should be integers.
# If $i and $j are distinct, then expand($i;$j;null;null) will include both,
# otherwise just $i.
def expand($i; $j; $sign; $increment):
(if $increment == null then 1 else $increment end) as $inc
| if $sign == null
then if $i <= $j
then range($i; $j + 1; $inc)
else range($i; $j - 1; - $inc)
end
else [expand($i; $j; null; $increment)] | reverse[]
end ;
 
# Produce a stream of single characters, handling implicit descent
def explode($x; $y; $sign; $increment):
($x|explode[0]) as $x
| ($y|explode[0]) as $y
| expand($x; $y; $sign; $increment)
| [.] | implode;
 
# The number of leading 0s of the input string
def leadingZeros: match("^0*") | .string | length;
def padding($x; $y):
($x | leadingZeros) as $a
| ($y | leadingZeros) as $b
| [if $a > 0 then ($x|length) else 0 end,
if $b > 0 then ($y|length) else 0 end]
| max;
( cap as $c
| if ($c.from|test("[0-9]+")) and ($c.to|test("[0-9]+"))
then padding($c.from; $c.to) as $padding
| $c.head
+ ( expand($c.from|tonumber;
$c.to|tonumber;
$c.sign;
$c.increment | ton) | lpad($padding))
+ ($c.tail | expand)
elif ($c.from|length == 1) and ($c.to|length == 1)
then $c.head + explode($c.from; $c.to; $c.sign; $c.increment|ton)
+ ($c.tail | expand)
else ""
end )
// . ;
 
def examples:
"simpleNumberRising{1..3}.txt",
"simpleAlphaDescending-{Z..X}.txt",
"steppedDownAndPadded-{10..00..5}.txt",
"minusSignFlipsSequence {030..20..-5}.txt",
"reverseSteppedNumberRising{1..6..-2}.txt",
"combined-{Q..P}{2..1}.txt",
"emoji{🌵..🌶}{🌽..🌾}etc",
"li{teral",
"rangeless{}empty",
"rangeless{random}string",
"mixedNumberAlpha{5..k}",
"steppedAlphaRising{P..Z..2}.txt",
"stops after endpoint-{02..10..3}.txt",
"steppedNumberRising{1..6..2}.txt",
"steppedNumberDescending{20..9..2}",
"steppedAlphaDescending-{Z..M..2}.txt",
"reversedSteppedAlphaDescending-{Z..M..-2}.txt"
;
 
examples
| "\(.) ->",
" \(expand)", ""
</syntaxhighlight>
{{output}}
<pre style="height:20lh;overflow:auto>
simpleNumberRising{1..3}.txt ->
simpleNumberRising1.txt
simpleNumberRising2.txt
simpleNumberRising3.txt
 
simpleAlphaDescending-{Z..X}.txt ->
simpleAlphaDescending-Z.txt
simpleAlphaDescending-Y.txt
simpleAlphaDescending-X.txt
 
steppedDownAndPadded-{10..00..5}.txt ->
steppedDownAndPadded-10.txt
steppedDownAndPadded-05.txt
steppedDownAndPadded-00.txt
 
minusSignFlipsSequence {030..20..-5}.txt ->
minusSignFlipsSequence 020.txt
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
reverseSteppedNumberRising{1..6..-2}.txt ->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
 
combined-{Q..P}{2..1}.txt ->
combined-Q2.txt
combined-P2.txt
combined-Q1.txt
combined-P1.txt
 
emoji{🌵..🌶}{🌽..🌾}etc ->
emoji🌵🌽etc
emoji🌶🌽etc
emoji🌵🌾etc
emoji🌶🌾etc
 
li{teral ->
li{teral
 
rangeless{}empty ->
rangeless{}empty
 
rangeless{random}string ->
rangeless{random}string
 
mixedNumberAlpha{5..k} ->
mixedNumberAlpha5
mixedNumberAlpha6
mixedNumberAlpha7
mixedNumberAlpha8
mixedNumberAlpha9
mixedNumberAlpha:
mixedNumberAlpha;
mixedNumberAlpha<
mixedNumberAlpha=
mixedNumberAlpha>
mixedNumberAlpha?
mixedNumberAlpha@
mixedNumberAlphaA
mixedNumberAlphaB
mixedNumberAlphaC
mixedNumberAlphaD
mixedNumberAlphaE
mixedNumberAlphaF
mixedNumberAlphaG
mixedNumberAlphaH
mixedNumberAlphaI
mixedNumberAlphaJ
mixedNumberAlphaK
mixedNumberAlphaL
mixedNumberAlphaM
mixedNumberAlphaN
mixedNumberAlphaO
mixedNumberAlphaP
mixedNumberAlphaQ
mixedNumberAlphaR
mixedNumberAlphaS
mixedNumberAlphaT
mixedNumberAlphaU
mixedNumberAlphaV
mixedNumberAlphaW
mixedNumberAlphaX
mixedNumberAlphaY
mixedNumberAlphaZ
mixedNumberAlpha[
mixedNumberAlpha\
mixedNumberAlpha]
mixedNumberAlpha^
mixedNumberAlpha_
mixedNumberAlpha`
mixedNumberAlphaa
mixedNumberAlphab
mixedNumberAlphac
mixedNumberAlphad
mixedNumberAlphae
mixedNumberAlphaf
mixedNumberAlphag
mixedNumberAlphah
mixedNumberAlphai
mixedNumberAlphaj
mixedNumberAlphak
 
steppedAlphaRising{P..Z..2}.txt ->
steppedAlphaRisingP.txt
steppedAlphaRisingR.txt
steppedAlphaRisingT.txt
steppedAlphaRisingV.txt
steppedAlphaRisingX.txt
steppedAlphaRisingZ.txt
 
stops after endpoint-{02..10..3}.txt ->
stops after endpoint-02.txt
stops after endpoint-05.txt
stops after endpoint-08.txt
 
steppedNumberRising{1..6..2}.txt ->
steppedNumberRising1.txt
steppedNumberRising3.txt
steppedNumberRising5.txt
 
steppedNumberDescending{20..9..2} ->
steppedNumberDescending20
steppedNumberDescending18
steppedNumberDescending16
steppedNumberDescending14
steppedNumberDescending12
steppedNumberDescending10
 
steppedAlphaDescending-{Z..M..2}.txt ->
steppedAlphaDescending-Z.txt
steppedAlphaDescending-X.txt
steppedAlphaDescending-V.txt
steppedAlphaDescending-T.txt
steppedAlphaDescending-R.txt
steppedAlphaDescending-P.txt
steppedAlphaDescending-N.txt
 
reversedSteppedAlphaDescending-{Z..M..-2}.txt ->
reversedSteppedAlphaDescending-N.txt
reversedSteppedAlphaDescending-P.txt
reversedSteppedAlphaDescending-R.txt
reversedSteppedAlphaDescending-T.txt
reversedSteppedAlphaDescending-V.txt
reversedSteppedAlphaDescending-X.txt
reversedSteppedAlphaDescending-Z.txt
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">padzeros(str) = (len = length(str)) > 1 && str[1] == '0' ? len : 0
 
function ranged(str)
Line 1,056 ⟶ 1,681:
println(test, "->\n", [" " * x * "\n" for x in splatrange(test)]...)
end
</langsyntaxhighlight>{{out}}
<pre>
simpleNumberRising{1..3}.txt->
Line 1,116 ⟶ 1,741:
</pre>
 
=={{header|PhixNim}}==
{{trans|Wren}}
<syntaxhighlight lang="nim">import options, strutils, unicode
<lang Phix>requires("0.8.2") -- (is_integer() is new, plus "==sign(inc)" found me a long-buried compiler bug)
 
 
function parse_range(string r)
func intFromString(s: string): Option[int] =
sequence sp = split(r,"..")&{"1"},
## Try to parse an int. Return some(int) if parsing
res = {}
## was successful, return none(int) if it failed.
if length(sp)>=3 then
try:
string {strange,ending,step} = sp
let integer incn = to_integers.parseInt(step)
result if inc!=0 thensome(n)
except ValueError:
bool ns = is_integer(strange),
neresult = is_integernone(endingint)
 
if ns=ne then
 
if ns then
func parseRange(r: string): seq[string] =
integer s = to_integer(strange),
 
e = to_integer(ending),
if r.len == 0: return @["{}"] # rangeless, empty.
w = max(length(strange),length(ending))
let sp = r.split("..")
if inc<0 then {s,e,inc} = {e,s,-inc} end if
if sp.len == 1: return @['{' & r & '}']
if s>e then inc *= -1 end if
let first = sp[0]
integer zfill = (length(strange)>1 and strange[1]='0') or
let last = sp[1]
(length(ending)>1 and ending[1]='0')
let incr = if sp.len == 2: "1" else: sp[2]
string fmt = iff(zfill?sprintf("%%0%dd",{w}):"%d")
 
for k=s to e by inc do
let val1 = intFromString(first)
res = append(res,sprintf(fmt,k))
let val2 = intFromString(last)
end for
let val3 = intFromString(incr)
return res
 
elsif length(strange)=length(ending) then
if val3.isNone(): return @['{' & r & '}'] # increment isn't a number.
bool ok = (length(strange)=1)
var n3 = val3.get()
if not ok then
let numeric = val1.isSome and val2.isSome
object s32 = utf8_to_utf32(strange,-1),
 
e32 = utf8_to_utf32(ending,-1)
var n1, n2: int
if sequence(s32) and length(s32)=1
if numeric:
and sequence(e32) and length(e32)=1 then
n1 = val1.get()
ok = true
n2 = val2.get()
end if
else:
end if
if val1.isSome and val2.isNone or val1.isNone and val2.isSome:
if ok then
return @['{' & r & '}'] # mixed numeric/alpha not expanded.
if strange>ending then inc *= -1 end if
if first.runeLen != 1 or last.runeLen != 1:
while true do
return @['{' & r & '}'] # start/end are not both single res = append(res,strange)alpha.
n1 = first.toRunes[0].int
integer sdx = length(strange)
n2 = last.toRunes[0].int
while true do
 
integer ch = strange[sdx]+inc
var width = 1
if ch<=#FF and ch>=#00 then
if numeric:
strange[sdx] = ch
width = if first.len < last.len: last.len else: first.len
exit
 
end if
if n3 == 0:
strange[sdx] = iff(inc<0?#FF:#00)
# Zero increment.
sdx -= 1
return if numeric: @[n1.intToStr(width)] else: @[first]
end while
 
if compare(strange,ending)==sign(inc) then exit end if
var asc = n1 < n2
if length(res)>10 then ?9/0 end if -- (sanity check)
if n3 < 0:
end while
asc = not asc
return res
swap n1, n2
end if -- ([utf8] strings not single char)
n3 = -n3
end if -- (neither numeric nor same-length alpha)
 
end if -- (mixed numeric/alpha)
var i = n1
end if -- (non-numeric increment)
if asc:
end if -- (rangeless)
returnwhile {"{"&r&"}"}i <= n2:
result.add if numeric: i.intToStr(width) else: $Rune(i)
end function
inc i, n3
else:
function range_expand(string s)
sequencewhile resi >= {""}n2:
result.add if numeric: i.intToStr(width) else: $Rune(i)
string range = ""
bool in_range =dec falsei, n3
 
for k=1 to length(s) do
 
integer c = s[k]
func rangeExpand(s: string): seq[string] =
if c == '{' and not in_range then
in_range = true
rangeresult = @[""]
var rng = ""
elsif c == '}' and in_range then
var inRng = false
sequence range_res = parse_range(range),
 
prev_res = res
for c in s:
res = {}
if c == '{' and not inRng:
for i=1 to length(prev_res) do
inRng = true
for j=1 to length(range_res) do
rng = ""
res = append(res, prev_res[i] & range_res[j])
elif c == '}' and end forinRng:
let rngRes = end forrng.parseRange()
var res: in_range = falseseq[string]
for i elsifin in_range then0..result.high:
for j in range &= c0..rngRes.high:
else res.add result[i] & rngRes[j]
result for i=1 to lengthmove(res) do
inRng res[i] &= cfalse
elif end forinRng:
rng.add end ifc
end forelse:
for s in result.mitems: s.add c
if in_range then
 
for i=1 to length(res) do
if inRng:
res[i] &= "{" & range // unmatched braces
for s in result.mitems: s.add '{' & rng # unmatched braces.
end for
 
end if
 
return res
when isMainModule:
end function
 
const Examples = ["simpleNumberRising{1..3}.txt",
constant examples = {
"simpleNumberRisingsimpleAlphaDescending-{1Z..3X}.txt",
"simpleAlphaDescendingsteppedDownAndPadded-{Z10..X00..5}.txt",
"steppedDownAndPadded-minusSignFlipsSequence {10030..0020..-5}.txt",
"minusSignFlipsSequence "combined-{030Q..20P}{2..-51}.txt",
"combined-emoji{Q🌵..P🌶}{2🌽..1🌾}.txtetc",
"li{teral",
"emoji{🌵..🌶}{🌽..🌾}etc",
"rangeless{}empty",
"multi char emoji ranges fail {🌵🌵..🌵🌶}",
"rangeless{random}string",
"li{teral",
"mixedNumberAlpha{5..k}",
"rangeless{}empty",
"steppedAlphaRising{P..Z..2}.txt",
"rangeless{random}string",
"stops after endpoint-{02..10..3}.txt"]
"mixedNumberAlpha{5..k}",
 
"steppedAlphaRising{P..Z..2}.txt",
for s in Examples:
"stops after endpoint-{02..10..3}.txt"
stdout.write s, " →\n "
}
let res = rangeExpand(s)
stdout.write res.join("\n ")
for i=1 to length(examples) do
echo '\n'
string s = examples[i]
</syntaxhighlight>
printf(1,"%s ->\n %s\n",{s,join(range_expand(s),"\n ")})
 
end for</lang>
{{out}}
<pre>simpleNumberRising{1..3}.txt →
simpleNumberRising1.txt
simpleNumberRising2.txt
simpleNumberRising3.txt
 
simpleAlphaDescending-{Z..X}.txt →
simpleAlphaDescending-Z.txt
simpleAlphaDescending-Y.txt
simpleAlphaDescending-X.txt
 
steppedDownAndPadded-{10..00..5}.txt →
steppedDownAndPadded-10.txt
steppedDownAndPadded-05.txt
steppedDownAndPadded-00.txt
 
minusSignFlipsSequence {030..20..-5}.txt →
minusSignFlipsSequence 020.txt
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
combined-{Q..P}{2..1}.txt →
combined-Q2.txt
combined-Q1.txt
combined-P2.txt
combined-P1.txt
 
emoji{🌵..🌶}{🌽..🌾}etc →
emoji🌵🌽etc
emoji🌵🌾etc
emoji🌶🌽etc
emoji🌶🌾etc
 
li{teral →
li{teral
 
rangeless{}empty →
rangeless{}empty
 
rangeless{random}string →
rangeless{random}string
 
mixedNumberAlpha{5..k} →
mixedNumberAlpha{5..k}
 
steppedAlphaRising{P..Z..2}.txt →
steppedAlphaRisingP.txt
steppedAlphaRisingR.txt
steppedAlphaRisingT.txt
steppedAlphaRisingV.txt
steppedAlphaRisingX.txt
steppedAlphaRisingZ.txt
 
stops after endpoint-{02..10..3}.txt →
stops after endpoint-02.txt
stops after endpoint-05.txt
stops after endpoint-08.txt
</pre>
=={{header|Phix}}==
{{trans|Wren}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0.8.2"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (is_integer() is new, plus "==sign(inc)" found me a long-buried compiler bug)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">parse_range</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">sp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #008000;">".."</span><span style="color: #0000FF;">)&{</span><span style="color: #008000;">"1"</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;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sp</span><span style="color: #0000FF;">)>=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">,</span><span style="color: #000000;">step</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sp</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">inc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">step</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">inc</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">ns</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">is_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ne</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">is_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ns</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ne</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ns</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">to_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">inc</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">></span><span style="color: #000000;">e</span> <span style="color: #008080;">then</span> <span style="color: #000000;">inc</span> <span style="color: #0000FF;">*=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">zfill</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">strange</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span>
<span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ending</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">zfill</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%%0%dd"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">}):</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">s</span> <span style="color: #008080;">to</span> <span style="color: #000000;">e</span> <span style="color: #008080;">by</span> <span style="color: #000000;">inc</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: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">))</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;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">)=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">s32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">utf8_to_utf32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">e32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">utf8_to_utf32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s32</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s32</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span>
<span style="color: #008080;">and</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e32</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e32</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">strange</span><span style="color: #0000FF;">></span><span style="color: #000000;">ending</span> <span style="color: #008080;">then</span> <span style="color: #000000;">inc</span> <span style="color: #0000FF;">*=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</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;">strange</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">sdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strange</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">inc</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">#FF</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">#00</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">strange</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">strange</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inc</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">:</span><span style="color: #000000;">#00</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">sdx</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strange</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ending</span><span style="color: #0000FF;">)==</span><span style="color: #7060A8;">sign</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)></span><span style="color: #000000;">10</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (sanity check)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- ([utf8] strings not single char)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (neither numeric nor same-length alpha)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (mixed numeric/alpha)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (non-numeric increment)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (rangeless)</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"{"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">r</span><span style="color: #0000FF;">&</span><span style="color: #008000;">"}"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">range_expand</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">""</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: #008000;">""</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">in_range</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</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;">integer</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">'{'</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</span> <span style="color: #000000;">in_range</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">in_range</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #000000;">range</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">==</span> <span style="color: #008000;">'}'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">in_range</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">range_res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">parse_range</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">prev_res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</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;">prev_res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</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;">range_res</span><span style="color: #0000FF;">)</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;">prev_res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">range_res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</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;">for</span>
<span style="color: #000000;">in_range</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">in_range</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">range</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">c</span>
<span style="color: #008080;">else</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;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">c</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;">if</span> <span style="color: #000000;">in_range</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;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"{"</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">range</span> <span style="color: #000080;font-style:italic;">// unmatched braces</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;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">examples</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
<span style="color: #008000;">"simpleNumberRising{1..3}.txt"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"simpleAlphaDescending-{Z..X}.txt"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"steppedDownAndPadded-{10..00..5}.txt"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"minusSignFlipsSequence {030..20..-5}.txt"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"combined-{Q..P}{2..1}.txt"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"emoji{🌵..🌶}{🌽..🌾}etc"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"multi char emoji ranges fail {🌵🌵..🌵🌶}"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"li{teral"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"rangeless{}empty"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"rangeless{random}string"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"mixedNumberAlpha{5..k}"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"steppedAlphaRising{P..Z..2}.txt"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"stops after endpoint-{02..10..3}.txt"</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;">examples</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">examples</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</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 -&gt;\n %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">range_expand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"\n "</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
Note that, as usual, unicode output does not look good on a windows console for tests 6 & 7 (linux output shown)
Line 1,285 ⟶ 2,088:
stops after endpoint-08.txt
</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">"""Brace expansion using ranges. Requires Python >= 3.6.
<lang python>
"""Brace range expansion. Requires Python >=3.6.
 
Here we use regular expressions for parsing and take an object orientated approach
to expansion of range expressions.
 
This implementation supports stepped ordinal range expressions.
NOTE: With my current version of bash (GNU bash, version 5.0.3(1)-release), a ``-``
or ``+`` character in front of a `step` has no effect. This implementation reverses
the range if a ``-`` immediately precedes a step, and does not recognize range
expressions that use a ``+``.
 
NOTE: This implementation supports stepped ordinal range expressions.
"""
 
Line 1,417 ⟶ 2,213:
# A negative step means we reverse the range.
start, stop = stop, start
 
step = abs(step)
if start < stop:
step = abs(step)
else:
start -= 1
stop -= 1
 
elif start > stop:
Line 1,463 ⟶ 2,264:
cases = [
r"simpleNumberRising{1..3}.txt",
r"steppedNumberRising{1..6..2}.txt",
r"steppedNumberDescending{20..9..2}.txt",
r"simpleAlphaDescending-{Z..X}.txt",
r"steppedDownAndPadded-{10..00..5}.txt",
r"minusSignFlipsSequence {030..20..-5}.txt",
r"reverseSteppedNumberRising{1..6..-2}.txt",
r"combined-{Q..P}{2..1}.txt",
r"emoji{🌵..🌶}{🌽..🌾}etc",
r"li{teral",
r"rangeless{random}string",
r"rangeless{}empty",
r"rangeless{random}string",
# Extra examples, not from the task description.
r"steppedNumberRising{1..6..2}.txt",
r"steppedNumberDescending{20..9..2}.txt",
r"steppedAlphaDescending-{Z..M..2}.txt",
r"reverseSteppedAlphaRising{A..F..-2}.txt",
r"reversedSteppedAlphaDescending-{Z..M..-2}.txt",
]
Line 1,489 ⟶ 2,293:
if __name__ == "__main__":
examples()
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,497 ⟶ 2,301:
simpleNumberRising2.txt
simpleNumberRising3.txt
 
steppedNumberRising{1..6..2}.txt ->
steppedNumberRising1.txt
steppedNumberRising3.txt
steppedNumberRising5.txt
 
steppedNumberDescending{20..9..2}.txt ->
steppedNumberDescending20.txt
steppedNumberDescending18.txt
steppedNumberDescending16.txt
steppedNumberDescending14.txt
steppedNumberDescending12.txt
steppedNumberDescending10.txt
 
simpleAlphaDescending-{Z..X}.txt ->
Line 1,525 ⟶ 2,316:
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
reverseSteppedNumberRising{1..6..-2}.txt ->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
 
combined-{Q..P}{2..1}.txt ->
Line 1,540 ⟶ 2,336:
li{teral ->
li{teral
 
rangeless{}empty ->
rangeless{}empty
 
rangeless{random}string ->
rangeless{random}string
 
steppedNumberRising{1..6..2}.txt ->
rangeless{}empty ->
steppedNumberRising1.txt
rangeless{}empty
steppedNumberRising3.txt
steppedNumberRising5.txt
 
steppedNumberDescending{20..9..2}.txt ->
steppedNumberDescending20.txt
steppedNumberDescending18.txt
steppedNumberDescending16.txt
steppedNumberDescending14.txt
steppedNumberDescending12.txt
steppedNumberDescending10.txt
 
steppedAlphaDescending-{Z..M..2}.txt ->
Line 1,555 ⟶ 2,364:
steppedAlphaDescending-P.txt
steppedAlphaDescending-N.txt
 
reverseSteppedAlphaRising{A..F..-2}.txt ->
reverseSteppedAlphaRisingE.txt
reverseSteppedAlphaRisingC.txt
reverseSteppedAlphaRisingA.txt
 
reversedSteppedAlphaDescending-{Z..M..-2}.txt ->
Line 1,565 ⟶ 2,379:
reversedSteppedAlphaDescending-Y.txt
</pre>
 
=={{header|Raku}}==
{{works with|Rakudo|2020.08.1}}
Also implements some of the string list functions described on the bash-hackers page.
 
<syntaxhighlight lang="raku" perl6line>my $range = rx/ '{' $<start> = <-[.]>+? '..' $<end> = <-[.]>+? ['..' $<incr> = ['-'?\d+] ]? '}' /;
my $list = rx/ ^ $<prefix> = .*? '{' (<-[,}]>+) +%% ',' '}' $<postfix> = .* $/;
 
Line 1,657 ⟶ 2,470:
say '';
}
</syntaxhighlight>
</lang>
{{out}}
<pre>simpleNumberRising{1..3}.txt ->
Line 1,748 ⟶ 2,561:
multi char emoji ranges fail {🌵🌵..🌵🌶}
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
Added threea furtherfew more examples to test:the minimum number needed for the task.
<syntaxhighlight lang="wren">import "./fmt" for Fmt
* Mixed number/alpha ranges which apparently are not expanded.
* Stepped alpha ranges which appear to be allowed.
* Stepped ranges which stop after the endpoint (Raku example).
<br>
<lang ecmascript>import "/fmt" for Fmt
 
var parseRange = Fn.new { |r|
Line 1,784 ⟶ 2,592:
asc = !asc
var t = n1
n1var d = (n1 - n2).abs % (-n3)
n1 = n2 - d * (n2 - n1).sign
n2 = t
n3 = -n3
Line 1,835 ⟶ 2,644:
"steppedDownAndPadded-{10..00..5}.txt",
"minusSignFlipsSequence {030..20..-5}.txt",
"reverseSteppedNumberRising{1..6..-2}.txt",
"combined-{Q..P}{2..1}.txt",
"emoji{🌵..🌶}{🌽..🌾}etc",
Line 1,842 ⟶ 2,652:
"mixedNumberAlpha{5..k}",
"steppedAlphaRising{P..Z..2}.txt",
"stops after endpoint-{02..10..3}.txt",
"steppedNumberRising{1..6..2}.txt",
"steppedNumberDescending{20..9..2}",
"steppedAlphaDescending-{Z..M..2}.txt",
"reversedSteppedAlphaDescending-{Z..M..-2}.txt"
]
 
Line 1,850 ⟶ 2,664:
System.print(res.join("\n "))
System.print()
}</langsyntaxhighlight>
 
{{out}}
Line 1,873 ⟶ 2,687:
minusSignFlipsSequence 025.txt
minusSignFlipsSequence 030.txt
 
reverseSteppedNumberRising{1..6..-2}.txt ->
reverseSteppedNumberRising5.txt
reverseSteppedNumberRising3.txt
reverseSteppedNumberRising1.txt
 
combined-{Q..P}{2..1}.txt ->
Line 1,910 ⟶ 2,729:
stops after endpoint-05.txt
stops after endpoint-08.txt
 
steppedNumberRising{1..6..2}.txt ->
steppedNumberRising1.txt
steppedNumberRising3.txt
steppedNumberRising5.txt
 
steppedNumberDescending{20..9..2} ->
steppedNumberDescending20
steppedNumberDescending18
steppedNumberDescending16
steppedNumberDescending14
steppedNumberDescending12
steppedNumberDescending10
 
steppedAlphaDescending-{Z..M..2}.txt ->
steppedAlphaDescending-Z.txt
steppedAlphaDescending-X.txt
steppedAlphaDescending-V.txt
steppedAlphaDescending-T.txt
steppedAlphaDescending-R.txt
steppedAlphaDescending-P.txt
steppedAlphaDescending-N.txt
 
reversedSteppedAlphaDescending-{Z..M..-2}.txt ->
reversedSteppedAlphaDescending-N.txt
reversedSteppedAlphaDescending-P.txt
reversedSteppedAlphaDescending-R.txt
reversedSteppedAlphaDescending-T.txt
reversedSteppedAlphaDescending-V.txt
reversedSteppedAlphaDescending-X.txt
reversedSteppedAlphaDescending-Z.txt
</pre>
2,442

edits