开发者

Code Golf: Numeric Ranges

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.

Challenge

Compactify a long list of numbers by replacing consecutive runs with ranges.

Example

Input

1, 2, 3, 4, 7, 8, 10, 12, 13, 14, 15

The input is guaranteed to be in ascending order and will not contain duplicates.

Output

1 - 4, 7, 8, 10, 12 - 15

Note that ranges of two numbers should be left as is. (7, 8; not 7 - 8)

Rules

You can accept a sorted list of integers (or equivalent datatype) as a method parameter, from the commandline, or from standard in. (pick whichever opti开发者_如何学Con results in shorter code)

You can output a list of strings by printing them, or by returning either a single string or set of strings.

Reference Implementation

(C#)

IEnumerable<string> Sample(IList<int> input) {
    for (int i = 0; i < input.Count; ) {
        var start = input[i];
        int size = 1;
        while (++i < input.Count && input[i] == start + size)
            size++;

        if (size == 1)
            yield return start.ToString();
        else if (size == 2) {
            yield return start.ToString();
            yield return (start + 1).ToString();
        } else if (size > 2)
            yield return start + " - " + (start + size - 1);
    }
}


Python, 98 characters

def f(a):
 for x in a:
  if x-1not in a or x+1not in a:print x,"-"if x+1in a and x+2in a else",",

Python - 86 characters

This one doesn't include an extra ',' at the end

f=lambda a:''.join(`x`+",-"[(x+1in a)&x+2in a]for x in a if(x-1in a)&(x+1in a)^1)[:-1]


Python, 83 characters

def f(l,a=2):
 for x in l:
  b,a=a,(x+1in l)*(x-1in l)
  if a<1:print',- '[b],`x`,

Demo:

>>> l=[1, 2, 3, 4, 7, 8, 10, 12, 13, 14, 15]
>>> f(l)
  1 - 4 , 7 , 8 , 10 , 12 - 15


Ruby, 165 characters

a=[]
def o(a)print "#{@s}#{a[0]}#{"#{a.size<3?',':' -'} #{a[-1]}"if a.size>1}";@s=', 'end
ARGV[0].split(', ').each{|n|if a[0]&&a[-1].succ!=n;o(a);a=[]end;a<<n;};o(a)


C++, 166 characters

#define o std::cout
void f(std::vector<int> v){for(int i=0,b=0,z=v.size();i<z;)i==z-1||v[i+1]>v[i]+1?b?o<<", ":o,(i-b?o<<v[b]<<(i-b>1?" - ":", "):o)<<v[i],b=++i:++i;}

Don't you all just love abusing the ?: operator? ;)

More readable version:

#define o std::cout
void f(std::vector<int> v){
    for(int i=0,b=0,z=v.size();i<z;)
        i==z-1||v[i+1]>v[i]+1 ?
            b?o<<", ":o,
            (i-b?o<<v[b]<<(i-b>1?" - ":", "):o)<<v[i],
            b=++i
        :++i;
}


Common Lisp, 442/206 chars

(defun d (l)
  (if l
      (let ((f (car l))
        (r (d (cdr l))))
      (if r
          (if (= (+ f 1) (caar r))
          (push `(,f ,(cadar r)) (cdr r))
          (push `(,f ,f) r))
          `((,f ,f))
          ))
      nil))

(defun p (l)
  (mapc #'(lambda (x)
          (if (= (car x) (cadr x))
          (format t "~a " (car x))
          (if (= (+ 1 (car x)) (cadr x))
              (format t "~a ~a " (car x) (cadr x))
              (format t "~a-~a " (car x) (cadr x)))))
      (d l)))

The "d" function rewrites the input list into a canonical form. For fun I did this entirely recursively. The "p" function formats the output to the equivalent of the reference implementation.


F#, 188 chars

let r(x::s)=
 let f=printf
 let p x=function|1->f"%A "x|2->f"%A %A "x (x+1)|n->f"%A-%A "x (x+n-1)
 let rec l x n=function|y::s when y=x+n->l x (n+1)s|y::s->p x n;l y 1 s|[]->p x n
 l x 1 s

More readable:

let range (x::xs) =
  let f = printf
  let print x = function
    | 1 -> f "%A " x
    | 2 -> f "%A %A " x (x+1)
    | n -> f "%A-%A " x (x+n-1)
  let rec loop x n = function
    | y::ys when y=x+n ->
        loop x (n+1) ys
    | y::ys ->
        print x n
        loop y 1 ys
    | [] ->
        print x n
  loop x 1 xs


Ruby : 123 characters

def y(n) t=[];r=[];n.each_with_index do |x,i| t<<x;if(x.succ!=n[i+1]);r=((t.size>2)?r<<t[0]<<-t[-1]:r+t);t=[];end;end;r;end

More Readable

def y(n) 
t=[];r=[];
n.each_with_index do |x,i|
 t << x
 if (x.succ != n[i+1])
    r = ((t.size > 2) ? r << t[0] << -t[-1] : r+t)  
    t=[]
 end
 end
 r
end

And execute like

 > n=[1, 2, 3, 4, 7, 8, 10, 12, 13, 14, 15]
 > y n
 => [1, -4, 7, 8, 10, 12, -15]


PHP 95 chars

(actually it's the second language after python)

Given $a=array(numbers);

Algos:

for($i=0;$i<count($a);$i++){$c=$i;while($a[$i+2]==$a[$i]+2)$i++;echo $a[$c],$i-$c>1?'-':',';}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜