September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
0-2,4,6-8,11,12,14-25,27-33,35-39
|
||||
51
Task/Range-extraction/Gambas/range-extraction.gambas
Normal file
51
Task/Range-extraction/Gambas/range-extraction.gambas
Normal 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
|
||||
55
Task/Range-extraction/Haskell/range-extraction-3.hs
Normal file
55
Task/Range-extraction/Haskell/range-extraction-3.hs
Normal 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]
|
||||
31
Task/Range-extraction/Haskell/range-extraction-4.hs
Normal file
31
Task/Range-extraction/Haskell/range-extraction-4.hs
Normal 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 ]
|
||||
|
|
@ -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
|
||||
]);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
]);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
grp : {(&~1=0,-':x)_ x}
|
||||
fmt : {:[1=#s:$x;s;(*s),:[3>#s;",";"-"],*|s]}
|
||||
erng: {{x,",",y}/,//'fmt'grp x}
|
||||
|
|
@ -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"
|
||||
37
Task/Range-extraction/Kotlin/range-extraction.kotlin
Normal file
37
Task/Range-extraction/Kotlin/range-extraction.kotlin
Normal 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))
|
||||
}
|
||||
|
|
@ -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)
|
||||
79
Task/Range-extraction/OoRexx/range-extraction.rexx
Normal file
79
Task/Range-extraction/OoRexx/range-extraction.rexx
Normal 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
|
||||
|
|
@ -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 ]}}
|
||||
|
|
@ -1 +0,0 @@
|
|||
0-2,4,6-8,11,12,14-25,27-33,35-39
|
||||
|
|
@ -1 +0,0 @@
|
|||
0-2,4,6-8,11,12,14-25,27-33,35-39
|
||||
|
|
@ -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))
|
||||
|
|
@ -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)
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
49
Task/Range-extraction/Swift/range-extraction.swift
Normal file
49
Task/Range-extraction/Swift/range-extraction.swift
Normal 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)))
|
||||
|
|
@ -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,":':,:")
|
||||
|
|
|
|||
10
Task/Range-extraction/Zkl/range-extraction-1.zkl
Normal file
10
Task/Range-extraction/Zkl/range-extraction-1.zkl
Normal 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(",");
|
||||
}
|
||||
11
Task/Range-extraction/Zkl/range-extraction-2.zkl
Normal file
11
Task/Range-extraction/Zkl/range-extraction-2.zkl
Normal 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();
|
||||
Loading…
Add table
Add a link
Reference in a new issue