Given an array of integers, what is the simplest way to iterate over it and figure out all the ranges it covers? for example, for an array such as:
$numbers = ar
If the array is sorted, as in your example, I would define buckets containing a min and a max.
Initialize: Create a bucket with a min and a max equal to the first value.
Loop: Compare each value with the max of the current bucket. If it is equal to or 1 more than the current max, update the max. If it is more than 1 greater than the max, save the bucket to a list of buckets and start a new bucket.
At the end you will have a set of buckets with a min and a max in each. If the min is the same as the max, print a single number (ie: in your example, the first bucket would have a min and a max of 1). If they are different, print as a range.
Example implementation in lisp:
CL-USER> (defun print-ranges (integer-list)
(let ((sorted-list (sort integer-list #'<)))
(loop with buckets = ()
with current-bucket
for int in sorted-list
initially (setf current-bucket (cons (first sorted-list) (first sorted-list)))
do (cond ((= int (cdr current-bucket))) ; do nothing, this number is already in range
((= (1- int) (cdr current-bucket)) ; number is 1 higher--update bucket's max
(setf (cdr current-bucket) int))
(t
(push current-bucket buckets)
(setf current-bucket (cons int int)))) ; set up a new bucket
finally (push current-bucket buckets)
(loop for firstp = t then nil
for bucket in (nreverse buckets) do
(cond ((= (car bucket) (cdr bucket))
(format t "~:[,~;~]~D" firstp (car bucket)))
(t
(format t "~:[,~;~]~D-~D" firstp (car bucket) (cdr bucket))))))))
PRINT-RANGES
CL-USER> (print-ranges (list 1 3 4 5 6 8 11 12 14 15 16))
1,3-6,8,11-12,14-16
NIL
CL-USER>
Basically you end up with a list of things, where each thing has (lowest-in-bucket, highest-in-bucket). Those are your ranges.
If the list is not already sorted, sort it first.