September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,111 +1,94 @@
on run
rangeString([0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, ¬
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, ¬
28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39])
end run
-- rangeString :: [Int] -> String
on rangeString(xs)
script addNumberOrRange
property iLast : length of xs
-- [[Int]] -> Int -> Int -> [Int] -> [[Int]]
on lambda(lstAccumulator, x, iPosn, xs)
if iPosn < iLast then
if ((item (iPosn + 1) of xs) - x) > 1 then -- rightward gap > 1
[[x]] & lstAccumulator --> start of new series
else
-- Prepended to current series
-- (if a series-breaker, or start list, is at left)
if ((iPosn = 1) or (x - (item (iPosn - 1) of xs)) > 1) then
[[x] & (item 1 of lstAccumulator)] & tail(lstAccumulator)
else
lstAccumulator -- Stet - series continues
end if
end if
-- rangeFormat :: [Int] -> String
on rangeFormat(xs)
script rangeString
on |λ|(xs)
if length of xs > 2 then
(item 1 of xs as string) & "-" & (item -1 of xs as string)
else
[[x]]
intercalate(",", xs)
end if
end lambda
end |λ|
end script
interCalate(",", ¬
map(my delimitedString, ¬
foldr(addNumberOrRange, [], xs)))
end rangeString
script nonConsec
on |λ|(a, b)
b - a > 1
end |λ|
end script
intercalate(",", map(rangeString, splitBy(nonConsec, xs)))
end rangeFormat
-- delimitedString :: [Int] -> String
on delimitedString(lstInt)
set intFirst to item 1 of lstInt
--TEST ------------------------------------------------------------------------
on run
set xs to {0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, ¬
17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, ¬
33, 35, 36, 37, 38, 39}
if length of lstInt > 1 then
set intSecond to item 2 of lstInt
set delta to intSecond - intFirst
rangeFormat(xs)
--> "0-2,4,6-8,11,12,14-25,27-33,35-39"
end run
-- GENERIC FUNCTIONS ----------------------------------------------------------
-- splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
on splitBy(f, xs)
set mf to mReturn(f)
if length of xs < 2 then
{xs}
else
set delta to 0
script p
on |λ|(a, x)
set {acc, active, prev} to a
if mf's |λ|(prev, x) then
{acc & {active}, {x}, x}
else
{acc, active & x, x}
end if
end |λ|
end script
set h to item 1 of xs
set lstParts to foldl(p, {{}, {h}, h}, items 2 thru -1 of xs)
item 1 of lstParts & {item 2 of lstParts}
end if
end splitBy
if delta > 0 then
(intFirst as string) & cond(delta > 1, "-", ",") & intSecond as string
else
intFirst as string
end if
end delimitedString
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- GENERIC LIBRARY FUNCTIONS
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- intercalate :: Text -> [Text] -> Text
on interCalate(strText, lstText)
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end interCalate
-- foldr :: (a -> b -> a) -> a -> [b] -> a
on foldr(f, startValue, xs)
set mf to mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from lng to 1 by -1
set v to mf's lambda(v, item i of xs, i, xs)
end repeat
return v
end foldr
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
set mf to mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to mf's lambda(item i of xs, i, xs)
end repeat
return lst
end map
-- cond :: Bool -> (a -> b) -> (a -> b) -> (a -> b)
on cond(bool, f, g)
if bool then
f
else
g
end if
end cond
-- tail :: [a] -> [a]
on tail(xs)
if class of xs is list and length of xs > 1 then
items 2 thru -1 of xs
else
{}
end if
end tail
end intercalate
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
@ -114,7 +97,7 @@ on mReturn(f)
f
else
script
property lambda : f
property |λ| : f
end script
end if
end mReturn

View file

@ -1,36 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
size_t rprint(char *s, int *x, int len)
{
#define sep (a > s ? "," : "") /* use comma except before first output */
#define ol (s ? 100 : 0) /* print only if not testing for length */
int i, j;
char *a = s;
for (i = j = 0; i < len; i = ++j) {
for (; j < len - 1 && x[j + 1] == x[j] + 1; j++);
if (i + 1 < j)
a += snprintf(s?a:s, ol, "%s%d-%d", sep, x[i], x[j]);
else
while (i <= j)
a += snprintf(s?a:s, ol, "%s%d", sep, x[i++]);
}
return a - s;
#undef sep
#undef ol
}
int main()
{
int x[] = { 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39 };
char *s = malloc(rprint(0, x, sizeof(x) / sizeof(int)) + 1);
rprint(s, x, sizeof(x) / sizeof(int));
printf("%s\n", s);
return 0;
}

View file

@ -1 +0,0 @@
0-2,4,6-8,11,12,14-25,27-33,35-39

View file

@ -0,0 +1,51 @@
siInput As New Short[]
siInput1 As Short[] = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39]
siInput2 As Short[] = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
sOutput As New String[]
siCount As Short
siNum As Short
'__________________
Public Sub Main()
Dim siLoop As Short
For siLoop = 0 To 1
If siLoop = 0 Then siInput = siInput1.Copy() Else siInput = siInput2.Copy()
siCount = 0
siNum = 0
Repeat
If siInput[siCount + 1] = siInput[siCount] + 1 Then
Inc siCount
Else
GetOutput
Endif
Until siCount = siInput.Max
GetOutput
Print sOutput.join(", ")
sOutput.clear
Next
End
'__________________
Public Sub GetOutput()
If siNum = siCount Then
sOutput.add(siInput[siNum])
Inc siCount
siNum = siCount
End If
If siNum <> siCount Then
If siNum = siCount - 1 Then
sOutput.add(siInput[siNum])
sOutput.add(siInput[siNum + 1])
siCount += 2
siNum += 2
Return
End If
sOutput.Add(siInput[siNum] & "-" & siInput[siCount])
Inc siCount
siNum = siCount
End If
End

View file

@ -0,0 +1,55 @@
import Data.List (intercalate)
import Data.Function (on)
-- RANGE FORMAT --------------------------------------------------------------
rangeFormat :: [Int] -> String
rangeFormat = intercalate "," . (rangeString <$>) . splitBy ((/=) . succ)
where
rangeString xs
| length xs > 2 = x ++ '-' : last t
| otherwise = intercalate "," ps
where
ps@(x:t) = show <$> xs
-- GENERIC FUNCTION ----------------------------------------------------------
-- Split wherever a supplied predicate matches the relationship
-- between two consecutive items.
-- E.G. at boundaries between vowels and consonants:
-- splitBy (on (/=) (flip elem "aeiouAEIOU")) "Constantinople"
-- -> ["C","o","nst","a","nt","i","n","o","pl","e"]
-- At boundaries between non-successive integers:
-- splitBy ((/=) . succ) [0, 1, 2, 4, 6, 7, 8, 11, 12, 14]
-- -> [[0,1,2],[4],[6,7,8],[11,12],[14]]
splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
splitBy _ [] = []
splitBy _ [x] = [[x]]
splitBy f xs@(_:t) = active : acc
where
(active, acc) =
foldr
(\(x, prev) (active, acc) ->
let current =
if null active
then [prev]
else active
in if f x prev
then ([x], current : acc)
else (x : current, acc))
([], [])
(zip xs t)
-- TEST ----------------------------------------------------------------------
main :: IO ()
main =
print $
rangeFormat
[ 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]

View file

@ -0,0 +1,31 @@
import Data.List (intercalate, groupBy, isPrefixOf)
import Data.List.Split (chop)
rangeFormat :: [Int] -> String
rangeFormat xs =
intercalate "," $
(\x -> head (if_ (length x > 1) (tail x) x)) <$>
groupBy isPrefixOf (rangeString <$> chop succSpan (zip xs (tail xs)))
where
rangeString [] = ""
rangeString xxs@(x:xs)
| null xs = show (snd x)
| otherwise = intercalate "-" (show <$> [fst x, snd (last xs)])
succSpan [] = ([], [])
succSpan (xxs@(x:xs))
| null ys = ([x], xs)
| otherwise = (ys, zs)
where
(ys, zs) = span (uncurry ((==) . succ)) xxs
if_ :: Bool -> a -> a -> a
if_ True x _ = x
if_ False _ y = y
main :: IO ()
main =
putStrLn $
rangeFormat [ 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39 ]

View file

@ -1,45 +1,64 @@
(function (lstTest) {
(function () {
'use strict';
function rangeString(xs) {
var iRightmost = xs.length - 1,
// rangeFormat :: [Int] -> String
var rangeFormat = function (xs) {
return splitBy(function (a, b) {
return b - a > 1;
}, xs)
.map(rangeString)
.join(',');
};
// Using foldr/reduceRight proves simpler here than foldl/reduce
// (the left end of the list is easier to reach than the tip of the tail)
lstSeries = xs.reduceRight(function (a, x, i, l) {
// rangeString :: [Int] -> String
var rangeString = function (xs) {
return xs.length > 2 ? [head(xs), last(xs)].map(show)
.join('-') : xs.join(',');
};
return i < iRightmost ? (
// GENERIC FUNCTIONS
// new series if rightward gap > 1
l[i + 1] - x > 1 ? (
[[x]].concat(a)
) : (
// Splitting not on a delimiter, but whenever the relationship between
// two consecutive items matches a supplied predicate function
// This value prepended to current series (if a
// series-breaker, or the start of the list, is at left)
(i === 0 || (x - l[i - 1]) > 1) ? (
[[x].concat(a[0])].concat(a.slice(1))
// splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
var splitBy = function (f, xs) {
if (xs.length < 2) return [xs];
var h = head(xs),
lstParts = xs.slice(1)
.reduce(function (a, x) {
var acc = a[0],
active = a[1],
prev = a[2];
// or, if the series continues to the left,
// just an unmodified copy of the accumulator
) : a
)
) : [[x]];
return f(prev, x) ? (
[acc.concat([active]), [x], x]
) : [acc, active.concat(x), x];
}, [
[],
[h], h
]);
return lstParts[0].concat([lstParts[1]]);
};
}, []);
// head :: [a] -> a
var head = function (xs) {
return xs.length ? xs[0] : undefined;
};
return lstSeries.map(function (r) {
var lng = r.length,
d = lng > 1 ? r[1] - r[0] : 0;
// last :: [a] -> a
var last = function (xs) {
return xs.length ? xs.slice(-1)[0] : undefined;
};
return d ? r[0] + (d > 1 ? '-' : ',') + r[1] : r[0];
// show :: a -> String
var show = function (x) {
return JSON.stringify(x);
};
}).join(',');
}
return rangeString(lstTest);
})([0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]);
// TEST
return rangeFormat([0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32,
33, 35, 36, 37, 38, 39
]);
})();

View file

@ -1 +1,55 @@
"0-2,4,6-8,11,12,14-25,27-33,35-39"
(() => {
'use strict';
// rangeFormat :: [Int] -> String
const rangeFormat = xs =>
splitBy((a, b) => b - a > 1, xs)
.map(rangeString)
.join(',');
// rangeString :: [Int] -> String
const rangeString = xs =>
xs.length > 2 ? (
[head(xs), last(xs)].map(show)
.join('-')
) : xs.join(',')
// GENERIC FUNCTIONS
// Splitting not on a delimiter, but whenever the relationship between
// two consecutive items matches a supplied predicate function
// splitBy :: (a -> a -> Bool) -> [a] -> [[a]]
const splitBy = (f, xs) => {
if (xs.length < 2) return [xs];
const
h = head(xs),
lstParts = xs.slice(1)
.reduce(([acc, active, prev], x) =>
f(prev, x) ? (
[acc.concat([active]), [x], x]
) : [acc, active.concat(x), x], [
[],
[h],
h
]);
return lstParts[0].concat([lstParts[1]]);
};
// head :: [a] -> a
const head = xs => xs.length ? xs[0] : undefined;
// last :: [a] -> a
const last = xs => xs.length ? xs.slice(-1)[0] : undefined;
// show :: a -> String
const show = x => JSON.stringify(x);
// TEST
return rangeFormat([0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
]);
})();

View file

@ -1,3 +0,0 @@
grp : {(&~1=0,-':x)_ x}
fmt : {:[1=#s:$x;s;(*s),:[3>#s;",";"-"],*|s]}
erng: {{x,",",y}/,//'fmt'grp x}

View file

@ -1,2 +0,0 @@
erng 0 1 2 4 6 7 8 11 12 14 15 16 17 18 19 20 21 22 23 24 25 27 28 29 30 31 32 33 35 36 37 38 39
"0-2,4,6-8,11,12,14-25,27-33,35-39"

View file

@ -0,0 +1,37 @@
// version 1.0.6
fun extractRange(list: List<Int>): String {
if (list.isEmpty()) return ""
val sb = StringBuilder()
var first = list[0]
var prev = first
fun append(index: Int) {
if (first == prev) sb.append(prev)
else if (first == prev - 1) sb.append(first, ",", prev)
else sb.append(first, "-", prev)
if (index < list.size - 1) sb.append(",")
}
for (i in 1 until list.size) {
if (list[i] == prev + 1) prev++
else {
append(i)
first = list[i]
prev = first
}
}
append(list.size - 1)
return sb.toString()
}
fun main(args: Array<String>) {
val list1 = listOf(-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20)
println(extractRange(list1))
println()
val list2 = listOf(0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39)
println(extractRange(list2))
}

View file

@ -1,30 +0,0 @@
import parseutils, re, strutils
proc extractRange(input: string): string =
var list = input.replace(re"\s+").split(',').map(parseInt)
var ranges: seq[string] = @[]
var i = 0
while i < list.len:
var first = list[i] # first element in the current range
var offset = i
while True: # skip ahead to the end of the current range
if i + 1 >= list.len:
# reached end of the list
break
if list[i + 1] - (i + 1) != first - offset:
# next element isn't in the current range
break
i.inc
var last = list[i] # last element in the current range
case last - first
of 0: ranges.add($first)
of 1: ranges.add("$1,$2".format([$first, $last]))
else: ranges.add("$1-$2".format([$first, $last]))
i.inc
return ranges.join(",")
echo("""
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39""".extractRange)

View file

@ -0,0 +1,79 @@
/* Rexx */
parse arg userInput
call runSample userInput
return
exit
-- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-- Compact a list of numbers by reducing ranges
compact:
procedure
--trace ?r;nop
parse arg expanded
nums = expanded~changestr(',', ' ')~space -- remove possible commas & clean up the string
rezult = ''
RANGE = 0
FIRST = nums~word(1) -- set starting value
loop i_ = 2 to nums~words -- each word in the string is a number to examine
LOCAL = nums~word(i_)
if LOCAL - FIRST - RANGE == 1 then do
-- inside a range
RANGE += 1
end
else do
-- not inside a range
if RANGE \= 0 then do
-- we have a range of numbers so collect this and reset
rezult = rezult || FIRST || delim(RANGE) || FIRST + RANGE || ','
RANGE = 0
end
else do
-- just collect this number
rezult = rezult || FIRST || ','
end
FIRST = LOCAL -- bump new starting value
end
end i_
if RANGE \= 0 then do
-- collect terminating value (a range)
rezult = rezult || FIRST || delim(RANGE) || FIRST + RANGE
end
else do
-- collect terminating value (a single number)
rezult = rezult || FIRST
end
return rezult~space(1, ',') -- format and return result string
-- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-- determine if the range delimiter should be a comma or dash
delim:
procedure
parse arg range .
if range == 1 then dlm = ','
else dlm = '-'
return dlm
-- ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-- sample driver
runSample:
procedure
parse arg userInput
td. = 0
if userInput~words > 0 then do
td.0 += 1; r_ = td.0; td.r_ = userInput
end
else do
td.0 += 1; r_ = td.0; td.r_ = '-6 -3 -2 -1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20'
td.0 += 1; r_ = td.0; td.r_ = '0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39'
td.0 += 1; r_ = td.0; td.r_ = '-4, -3, -2, 0, 1, 2, 4, 6, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39'
end
loop r_ = 1 to td.0
say 'Original: ' td.r_~changestr(',', ' ')~space(1, ',')
say 'Compacted:' compact(td.r_)
say
end r_
return

View file

@ -1,47 +0,0 @@
declare
fun {Extract Xs}
{CommaSeparated
{Map {ExtractRanges Xs} RangeToString}}
end
fun {ExtractRanges Xs}
fun {Loop Ys Start End}
case Ys
of Y|Yr andthen Y == End+1 then {Loop Yr Start Y}
[] Y|Yr then Start#End|{Loop Yr Y Y}
[] nil then [Start#End]
end
end
in
case Xs
of X|Xr then {Loop Xr X X}
[] nil then nil
end
end
fun {RangeToString S#E}
if E-S >= 2 then
{VirtualString.toString S#"-"#E}
else
{CommaSeparated
{Map {List.number S E 1} Int.toString}}
end
end
fun {CommaSeparated Xs}
{Flatten {Intersperse "," Xs}}
end
fun {Intersperse Sep Xs}
case Xs of X|Y|Xr then
X|Sep|{Intersperse Sep Y|Xr}
else
Xs
end
end
in
{System.showInfo
{Extract [ 0 1 2 4 6 7 8 11 12 14
15 16 17 18 19 20 21 22 23 24
25 27 28 29 30 31 32 33 35 36
37 38 39 ]}}

View file

@ -1 +0,0 @@
0-2,4,6-8,11,12,14-25,27-33,35-39

View file

@ -1 +0,0 @@
0-2,4,6-8,11,12,14-25,27-33,35-39

View file

@ -1,19 +0,0 @@
def rangeextract(lst):
lenlst = len(lst)
i, ranges = 0, []
while i< lenlst:
low = lst[i]
while i <lenlst-1 and lst[i]+1 == lst[i+1]: i +=1
hi = lst[i]
ranges.append(
'%i-%i' % (low, hi) if hi - low >= 2 else
('%i,%i' % (low, hi) if hi - low == 1 else
'%i' % low) )
i += 1
return ','.join(ranges)
lst = [ 0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]
print(rangeextract(lst))

View file

@ -1,26 +0,0 @@
def grouper(lst):
src = iter(lst)
acc = [ next(src) ]
for i in src:
if i == acc[-1] + 1: acc.append(i)
else:
yield acc
acc = [i]
yield acc
raise StopIteration()
def rangegrouper(lst):
for g in grouper(lst):
if len(g) == 2:
# satisfy rule that only runs longer than 2 are grouped
a,b = g
yield [a]
yield [b]
else: yield g
raise StopIteration()
input= [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 35, 36,37, 38, 39]
print list(rangegrouper(input)) # print groups
as_strings= ['%s%s%s' % ((g[0],'-',g[-1]) if len(g) > 1 else (g[0],'','')) for g in rangegrouper(input)]
print as_strings
print ', '.join(as_strings)

View file

@ -1,47 +0,0 @@
func rangesFromInts(ints:[Int]) -> [(Int, Int)] {
var range : (Int, Int)?
var ranges = [(Int, Int)]()
for this in ints {
if let (start, end) = range {
if this == end + 1 {
range = (start, this)
}
else {
ranges.append(range!)
range = (this, this)
}
}
else { range = (this, this) }
}
ranges.append(range!)
return ranges
}
func descriptionFromRanges(ranges:[(Int, Int)]) -> String {
var desc = ""
for (start, end) in ranges {
desc += desc.isEmpty ? "" : ","
if start == end {
desc += "\(start)"
}
else if end == start + 1 {
desc += "\(start),\(end)"
}
else {
desc += "\(start)-\(end)"
}
}
return desc
}
let ex = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
let longer = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]
descriptionFromRanges(rangesFromInts(ex))
descriptionFromRanges(rangesFromInts(longer))

View file

@ -1,35 +0,0 @@
extension NSIndexSet {
var rangesDescription : String {
var out = ""
indexSet.enumerateRangesUsingBlock { range, _ in
let start = range.location
let end = range.location+range.length-1
out += out.isEmpty ? "" : ","
if start == end {
out += "\(start)"
}
else if end == start + 1 {
out += "\(start),\(end)"
}
else {
out += "\(start)-\(end)"
}
}
return out
}
}
let ex = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
let longer = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]
var indexSet = NSMutableIndexSet()
ex.map { indexSet.addIndex($0) }
indexSet.rangesDescription
var indexSet2 = NSMutableIndexSet()
longer.map { indexSet2.addIndex($0) }
indexSet2.rangesDescription

View file

@ -0,0 +1,49 @@
import Darwin
func ranges(from ints:[Int]) -> [(Int, Int)] {
var range : (Int, Int)?
var ranges = [(Int, Int)]()
for this in ints {
if let (start, end) = range {
if this == end + 1 {
range = (start, this)
}
else {
ranges.append(range!)
range = (this, this)
}
}
else { range = (this, this) }
}
ranges.append(range!)
return ranges
}
func description(from ranges:[(Int, Int)]) -> String {
var desc = ""
for (start, end) in ranges {
desc += desc.isEmpty ? "" : ","
if start == end {
desc += "\(start)"
}
else if end == start + 1 {
desc += "\(start),\(end)"
}
else {
desc += "\(start)-\(end)"
}
}
return desc
}
let ex = [-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20]
let longer = [0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39]
print(description(from: ranges(from: ex)))
print(description(from: ranges(from: longer)))

View file

@ -1,4 +1,4 @@
$$ MODE TUSCRIPT
$$ MODE TUSCRIPT,{}
MODE DATA
$$ numbers=*
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
@ -6,7 +6,7 @@ $$ numbers=*
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39
$$ MODE TUSCRIPT
numbers=EXCHANGE (numbers,":,><<> :':")
numbers=EXCHANGE (numbers,":,{0-00} :':")
unrangednrs=JOIN (numbers,"")
rangednrs=COMBINE (unrangednrs,"")
rangednrs=EXCHANGE (rangednrs,":':,:")

View file

@ -0,0 +1,10 @@
fcn range(ns){
fcn(w){
if (w.atEnd) return(Void.Stop);
a:=b:=w.next(); n:=0;
while(b+1 == (c:=w.peekN(n))){ n+=1; b=c }
if(n>1){do(n){w.next()}; return("%d-%d".fmt(a,b)); }
a
} :
(0).pump(*,List,_.fp(ns.walker().tweak(Void,Void))).concat(",");
}

View file

@ -0,0 +1,11 @@
var ns=T(-6,-3,-2,-1,0,1,3,4,5,7,8,9,10,11,14,15,17,18,19,20);
range(ns).println();
ns=T(
0, 1, 2, 4, 6, 7, 8, 11, 12, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 27, 28, 29, 30, 31, 32, 33, 35, 36,
37, 38, 39);
range(ns).println();
range([1..100]).println();