Rebol3 Code Examplex
Range extraction
Compress a sorted list of integers into a compact string by replacing runs of at least three consecutive numbers with start-end notation.
Rebol [
title: "Rosetta code: Range extraction"
file: %Range_extraction.r3
url: https://rosettacode.org/wiki/Range_extraction
]
extract-range: function/with [
"Compress a sorted block of integers into a compact range string."
integers [block! string!] "Block of integers in increasing order, e.g. [1 2 3 5 7 8 9]"
][
if string? integers [
;; normalize comma-separated string input into a block of integers
integers: sort transcode replace/all copy integers #"," #" "
]
if empty? integers [return ""]
start: first integers ;; begin of current run
prev: start ;; last seen value
out: clear "" ;; reset shared output buffer
foreach n next integers [
either n = (prev + 1) [
prev: n ;; extend current run
][
;; gap found - emit completed run, start a new one
emit start prev
start: prev: n
]
]
emit start prev ;; emit final run
copy next out ;; return string, skipping the leading comma
][
out: "" ;; shared output buffer (reset each call via clear "")
emit: func [s e] [
;; spans of 1 or 2 integers are emitted as individual values, 3+ as s-e
repend out either e - s > 1 [
[#"," s #"-" e]
][
either/only s = e [#"," s] [#"," s #"," e]
]
]
]
probe compress-range {
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}
probe compress-range [1 2 3 5 7 8 9]Output:
** Script error: compress-range has no value
** Where: catch either try either -apply- do try unless foreach while with do either either if -apply-
** Near: catch/quit either mark [
[do/next body mark]
] [
bod...