Code Golf: Numeric Ranges
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
Output
1 - 4, 7, 8, 10, 12 - 15
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?'-':',';}
精彩评论