挑战在于创建一种算法,用于根据序列中的当前位置生成序列中特定大小的数字子集。
在Stack Overflow或Digg等繁忙网站上浏览多页内容时,通常需要让用户快速跳转到第一页,最后一页或特定页面在他们正在查看的当前页面附近。
totalPages
< fixedWidth
1 <= currentPage <
(fixedWidth - defaultPostion)
或(totalPages -
currentPage) < (fixedWidth - defaultPostion)
如果您还无法想象,请查看问题/答案下的Stack Overflow配置文件。如果你有一个超过10个,你应该在底部看到以这种方式生成的分页链接。那,或者滚动到http://digg.com的底部并观察它们的分页控制。
所有示例都假定子集大小为5,当前页面位于第3位,但这些都是
应该可以在您的解决方案中配置。 ...
表示页码之间的差距,[x]
表示当前页面。
当前页:1/30
输出:[x][2][3][4][5]...[30]
当前页:2/30
输出:[1][x][3][4][5]...[30]
当前页:13/30
输出:[1]...[11][12][x][14][15]...[30]
当前页:27/30
输出:[1]...[25][26][x][28][29][30]
当前页:30/30
输出:[1]...[26][27][28][29][x]
当前页:3/6
输出:[1][2][x][4][5][6]
当前页:4/7
输出:[1][2][3][x][5][6][7]
numberOfPages
除非它们是顺序的
numberOfPages
的一部分,如
[1][x][3][4][5]...[30]
或
[1]...[26][27][28][x][30]
,但不是
[1]...[8][9][x][11][12]...[30]
fixedWidth + 2
中的[1][2][3][x][5][6]...[15]
或[1][2][3][x][5][6][7]
{{1}} 欢迎任何和所有语言的解决方案。
祝你好运!
答案 0 :(得分:7)
f=lambda c,m,n:'...'.join(''.join((' ','[%s]'%(p,'x')[p==c])[min(m-n,c-1-n/2)<p<max(n+1,c+1+n/2)or p in(1,m)]for p in range(1,m+1)).split())
对OP中的示例进行测试:
for c, m, expect in (
(1, 30, "[x][2][3][4][5]...[30]"),
(2, 30, "[1][x][3][4][5]...[30]"),
(13, 30, "[1]...[11][12][x][14][15]...[30]"),
(27, 30, "[1]...[25][26][x][28][29][30]"),
(30, 30, "[1]...[26][27][28][29][x]"),
(3, 6, "[1][2][x][4][5][6]"),
(4, 7, "[1][2][3][x][5][6][7]"),
):
output = f(c, m, 5)
print "%3d %3d %-40s : %s" % (c, m, output, output == expect)
感谢您的评论。 :)
PS。大量编辑以减少字数并添加n
=当前页面周围的页数(m
是最大页数,c
是当前页面否)
答案 1 :(得分:4)
~:&;\:C;:T,{-1%[T&-T)C-:C&2/-(]$0=:|1>{.1<\|>}*}2*]${{)]`[C]`/'[x]'*}%}%'...'*
样本I / O:
$ echo "27 30 5"|golfscript page_numbers.gs
[1]...[25][26][x][28][29][30]
所有页码的输出需要83个字符(对主体进行微小修改)。
~:&;:T,{:C;T,{-1%[T&-T(C-:C&2/-]$0=:|1>{.1<\|>}*}2*]${{)]`[C)]`/'[x]'*}%}%'...'*n}
样本I / O:
$ echo "7 5"|golfscript page_numbers.gs
[x][2][3][4][5]...[7]
[1][x][3][4][5]...[7]
[1][2][x][4][5]...[7]
[1][2][3][x][5][6][7]
[1]...[3][4][x][6][7]
[1]...[3][4][5][x][7]
[1]...[3][4][5][6][x]
$ echo "7 3"|golfscript page_numbers.gs
[x][2][3]...[7]
[1][x][3]...[7]
[1][2][x][4]...[7]
[1]...[3][x][5]...[7]
[1]...[4][x][6][7]
[1]...[5][x][7]
[1]...[5][6][x]
答案 2 :(得分:3)
支持所有选项并在规格范围内。
程序:
let P c b n f m s =
let p = b/2
let u = max 1 (if n-b <= c-p then n-b+1 else max 1 (c-p))
let v = min n (if b >= c+p-1 then b else min n (c+p))
let P = printf
let C c a n = if c then P a n
C (u > 1) f 1
C (u = 3) f 2
C (u > 3) "%s" s
let I = Seq.iter (P f)
I {u .. c-1}
P "%s" m
I {c+1 .. v}
C (n - 2 > v) "%s" s
C (v = n - 2) f (n-1)
C (n > v) f n
测试:
for p in 1..6 do
P p 5 30 "[%d]" "[x]" "..."
printfn ""
for p in 25..30 do
P p 5 30 "[%d]" "[x]" "..."
printfn ""
输出:
[x][2][3][4][5]...[30]
[1][x][3][4][5]...[30]
[1][2][x][4][5]...[30]
[1][2][3][x][5]...[30]
[1][2][3][4][x][6][7]...[30]
[1]...[4][5][x][7][8]...[30]
[1]...[23][24][x][26][27]...[30]
[1]...[24][25][x][27][28][29][30]
[1]...[26][x][28][29][30]
[1]...[26][27][x][29][30]
[1]...[26][27][28][x][30]
[1]...[26][27][28][29][x]
答案 3 :(得分:2)
(defun [(n)(格式t“[〜a]”n))(defun p(cm&amp; key(s 5)(p 2))(let((l(max(min( - cp) )( - ms -1))1))(r(min(max(+ c( - p)s -1)s)m)))(当(> l 1)([1))(当( &gt; l 2)(princ“...”))(n从l到r的循环do([(if(= nc)#\ xn)))(当(&lt; r(1-m))( princ“...”))(当(&lt; rm)([m))))
未压缩:
(defun print[] (n)
(format t "[~a]" n))
(defun page-bar (current max &key (subset-size 5) (current-position 2))
(let ((left (max (min (- current current-position)
(- max subset-size -1))
1))
(right (min (max (+ current (- current-position) subset-size -1)
subset-size)
max)))
(when (> left 1) (print[] 1))
(when (> left 2) (princ "..."))
(loop for p from left upto right
do (print[] (if (= p current) #\x p)))
(when (< right (1- max)) (princ "..."))
(when (< right max) (print[] max))))
测试:
CL-USER> (mapc (lambda (n) (p n 7) (format t "~%")) '(1 2 3 4 5 6 7))
[x][2][3][4][5]...[7]
[1][x][3][4][5]...[7]
[1][2][x][4][5]...[7]
[1][2][3][x][5][6][7]
[1]...[3][4][x][6][7]
[1]...[3][4][5][x][7]
[1]...[3][4][5][6][x]
(1 2 3 4 5 6 7)
CL-USER> (p 1 1)
[x]
NIL
CL-USER> (p 1 2)
[x][2]
NIL
CL-USER> (p 0 0)
NIL
CL-USER> (p 0 1)
[1]
NIL
CL-USER> (p 0 30)
[1][2][3][4][5]...[30]
NIL
CL-USER> (p 31 30)
[1]...[26][27][28][29][30]
NIL
子集大小和该子集中当前页面的位置可以在可选参数中给出(:current-position
在子集中从零开始,自然而然):
CL-USER> (page-bar 8 15 :subset-size 6 :current-position 5)
[1]...[3][4][5][6][7][x]...[15]
NIL
编辑:压缩版本中的调用将是:
CL-USER> (p 8 15 :s 6 :p 5)
答案 4 :(得分:1)
function pages($t,$c,$s=5){$m=ceil($s/2);$p=range(1,$t);$p[$c-1]='x';$a=array();return preg_replace('~(\[('.implode('|',array_merge($c-$m<2?$a:range(2,$c-$m),$t-1<$c+$m?$a:range($c+$m,$t-1))).')\])+~','...','['.implode('][',$p).']');}
(排序)未经宣传:
function pages($max, $current, $subset=5) {
$m = ceil($subset / 2); // amount to go in each direction
$arr = range(1, $max); // array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
$arr[$current-1] = 'x'; // array(1, 2, 3, 4, x, 6, 7, 8, 9, 10)
// replace ~(\[(2|8|9)\])+~ with ...
$pattern = '~(\[(' . implode('|', array_merge($current-$m >= 2 ? range(2, $current-$m) : array(), $max-1 >= $current+$m ? range($current+$m, $max-1): array())) . ')\])+~';
return preg_replace($pattern, '...', '['.implode('][',$arr).']');
}
这并不完全符合规范([1][x][3][4]...[30]
而不是[1][x][3][4][5]...[30]
),但会因此而变得不那么优雅。
答案 5 :(得分:1)
与其他C#答案类似,但有一些令人讨厌的副作用填充LINQ。我想这会有点短暂。
void Pages(int p,int t,int s) {
int h=s/2,l=0;
foreach(var c in Enumerable.Range(1,t).Where(x=>x==1||x==t||(p+h<s&&x<=s)||(p-h>t-s&&x>t-s)||(x>=p-h&&x<=p+h)).Select(x=>{Console.Write((x-l>1?"...":"")+(x==p?"[X]":"["+x+"]"));l=x;return x;}));
}
编辑:
结果显示命令式版本的边距较短( 195 184个字符):
void Pages(int p,int t,int s){
int h=s/2,l=0,i=1;
for(;i<=t;i++)
if(i==1||i==t||p+h<s&&i<=s||p-h>t-s&&i>t-s||i>=p-h&&i<=p+h){
Console.Write((i-l>1?"...":"")+(i==p?"[X]":"["+i+"]"));
l=i;
}
}
答案 6 :(得分:1)
$_=join'',map{$_==1||$_==$n||abs($_-$x)<=$a?$_==$x?'[x]':"[$_]":'_'}(1..$n);s/_+/.../g;print
完整测试:
@i=(
[1,30,2],
[2,30,2],
[13,30,2],
[27,30,2],
[30,30,2],
[3,6,2],
[4,7,2]
);
for$r(@i)
{
($x,$n,$a)=@$r;
$_=join'',map{$_==1||$_==$n||abs($_-$x)<=$a?$_==$x?'[x]':"[$_]":'_'}(1..$n);s/_+/.../g;print
;print"\n";
}
答案 7 :(得分:0)
我假设您在命令行(stdin)上输入当前页面和总页数:
import sys
p=sys.stdout.write
c,t=raw_input().split()
c,t=int(c),int(t)
r=range(1,t+1)
l=len(r)
p("[1]")
if c>7:
p("...")
for n in r[c-3:c+2]:
if n==1:continue
if n-t==-5 and l>7:continue
if c==n:n="X"
p("[%s]"%n)
if l<7:
for n in range(2,6):
if c==n:n="X"
p("[%s]"%n)
if r[c+2]<t and l>6:
p("...")
p("[%d]"%t)
没有真正打高尔夫球(只是简短的名字)所以我希望最好的解决方案至少是这个长度的一半。
python pag.py
3 30
[1][2][X][4][5]...[30]
编辑:我意识到这对于“2 4”或“2 2”这样的事情是失败的 - 它假定至少有6页。 耸肩
答案 8 :(得分:0)
Groovy: 242 232个字符,支持可配置的组长度
调用语法:Paging(currentOffset, totalWidth, groupSize)
def(c,t,g)=args.collect{it.toInteger()};def p,s=Math.max(c-(g/2).toInteger(),1);p='['+((c==1?'x':1)+(s>2?']...':']'));(s..Math.min(s+g-1,t)).each{if(it>1&&it<t)p+='['+(c==it?'x':it)+']'};print p+(t>s+g?'...[':'[')+(t==c?'x':t)+']';
可读版本:
def (c,t,g) = args.collect{it.toInteger()};
def p,s = Math.max(c - (g/2).toInteger(), 1);
p = '['+((c==1?'x':1)+(s>2?']...':']'));
(s .. Math.min(s+g-1,t)).each{
if(it > 1 && it < t)
p += '[' + (c == it ? 'x' : it) + ']'
};
print p + (t > s + g ? '...[' : '[') + (t==c ? 'x' : t) + ']';
这样称呼:
Paging ([1, 20, 5])
println '';
Paging ([10, 20, 5])
println '';
Paging ([20, 20, 5])
println '';
Paging ([7, 17, 3])
println '';
Paging ([2, 228, 3])
println '';
Paging ([2, 5, 3])
println '';
Paging ([1, 5, 5])
产生这些结果:
[x][2][3][4][5]...[20]
[1]...[8][9][x][11][12]...[20]
[1]...[18][19][x]
[1]...[6][x][8]...[17]
[1][x][3]...[228]
[1][x][3]...[5]
[x][2][3][4][5]
答案 9 :(得分:0)
p,s,t=$*.map &:to_i
a=p-s/2
e=a+s-1
a<1&&(e+=1-a;a=1)
e>t&&(a-=e-t;e=t)
s>=t&&(a=1;e=t)
m=(a..e).map{|n|"[#{n==p ??x:n}]"}.join
a>2&&m='...'+m
a>1&&m='[1]'+m
e<t-1&&m<<'...'
e<t&&m<<"[#{t}]"
puts m
用法:ruby pager.rb [position] [sampleSize] [totalWidth]
答案 10 :(得分:0)
void Pages(int c,int t,int w){
int p=(w/2)+1;
int b=c-p;
int f=c+(w-p);
if(b<0){
f+=b*-1;
}else if(f>t){
b-=f-t;
f=t;
}
for(int i=1;i<=t;i++){
if(t<=w||(i==1||i==t)||(i>b&&i<=f))
Console.Write(i==c?"[X]":"[{0}]",i);
else if(t>w&&(i==b||i==f+1))
Console.Write("...");
}
}
for(int i=1;i<=5;i++) {
Pages(i,5,5);
Console.WriteLine();
}
for(int i=1;i<=15;i++) {
Pages(i,15,5);
Console.WriteLine();
}
[X][2][3][4][5]
[1][X][3][4][5]
[1][2][X][4][5]
[1][2][3][X][5]
[1][2][3][4][X]
[X][2][3][4][5]...[15]
[1][X][3][4][5]...[15]
[1][2][X][4][5]...[15]
[1][2][3][X][5][6]...[15]
[1]...[3][4][X][6][7]...[15]
[1]...[4][5][X][7][8]...[15]
[1]...[5][6][X][8][9]...[15]
[1]...[6][7][X][9][10]...[15]
[1]...[7][8][X][10][11]...[15]
[1]...[8][9][X][11][12]...[15]
[1]...[9][10][X][12][13]...[15]
[1]...[10][11][X][13][14][15]
[1]...[11][12][X][14][15]
[1]...[11][12][13][X][15]
[1]...[11][12][13][14][X]
答案 11 :(得分:0)
我意识到已经发布了一个较短的答案,但该答案不支持页面子集中的可配置宽度和位置。我的确如此。
def paginator(c, n, w, o):
b = range(c-w/2+o,c+w/2+1+o)
b = [e+abs(b[0])+1 for e in b]if b[0]<=0 else[e-abs(n-b[w-1])for e in b]if b[w-1]>n else b
p = ([]if 1 in b else[1])+b+([]if n in b else[n])
return ''.join(('...'if p[i]-p[i-1]!=1 and i>0 and i<len(p)else'')+'[%d]'%p[i]if p[i]!=c else'[x]'for i in range(len(p)))
以下是所有通过的测试
if __name__ == '__main__':
for current, n, width, offset, expect in (
(1, 30, 5, 0, "[x][2][3][4][5]...[30]"),
(2, 30, 5, 0, "[1][x][3][4][5]...[30]"),
(13, 30, 5, 0, "[1]...[11][12][x][14][15]...[30]"),
(13, 30, 5, 1, "[1]...[12][x][14][15][16]...[30]"),
(13, 30, 5, -1, "[1]...[10][11][12][x][14]...[30]"),
(27, 30, 5, 0, "[1]...[25][26][x][28][29][30]"),
(30, 30, 5, 0, "[1]...[26][27][28][29][x]"),
(30, 30, 5, 1, "[1]...[26][27][28][29][x]"),
(3, 6, 5, 0, "[1][2][x][4][5][6]"),
(3, 6, 5, -1, "[1][2][x][4][5][6]"),
(3, 6, 5, 1, "[1][2][x][4][5][6]"),
(4, 7, 5, 0, "[1][2][3][x][5][6][7]"),
):
output = paginator(current, n, width, offset)
print "%3d %3d %3d %3d %-40s : %s" % (current, n, width, offset, output, output == expect)
print ''
这是我的第一个代码 - 高尔夫,很棒的东西,从现在开始会做更多的事情:P
答案 12 :(得分:0)
v(j, o, l)
,其中:
j
是页码o
是总页数l
是要显示的页数(子集大小) v(10, 30, 5)
返回:[1]...[8][9][x][11][12]…[30]
function v(j,o,l){function k(q){return q.length}function y(n,m){t=[];while(n<=m){t.push(n);n++}return t}r=y(1,j-1);g=y(j+1,o);b=k(r);a=k(g);c=l/2;(b>l/2&&a>=c)?r=r.splice(-l/2):((a<=c)?r=r.splice(-l+a+1):0);b=k(r);g=g.slice(0,l-1-b);a=k(g);r.push("x");g[a-1]==o-1?g.push(o):0;r[0]==2?r.unshift(1):0;r=r.concat(g);return(r[0]>2?"[1]...":"")+"["+r.join("][")+"]"+(g[k(g)-1]<o-1?"...["+o+"]":"")}
function run(cp, tp, l) {
function y(n,m){t=[];while(n<=m){t.push(n);n++}return t};
var before=y(1, cp-1);
var after=y(cp+1, tp);
var b=before.length;
var a=after.length;
var c=Math.floor(l/2);
if (b>l/2 && a>=c) {
before=before.splice(-l/2);
} else if (a<=c) {
before=before.splice(-(l-a)+1);
}
b=before.length;
after=after.slice(0, l-1-b);
a=after.length
before.push("x");
if (after[a-1]==tp-1)
after.push(tp);
if (before[0]==2)
before.unshift(1);
before=before.concat(after);
// Add bounds to either side
var pre=["",""];
if (before[0]>2) pre[0]="[1]...";
if (after[after.length-1]<tp-1) pre[1]="...["+tp+"]";
return pre[0]+"["+before.join("][")+"]"+pre[1];
}
function testValues() {
var ts=[1, 30, "[x][2][3][4][5]...[30]",
2, 30, "[1][x][3][4][5]...[30]",
13, 30, "[1]...[11][12][x][14][15]...[30]",
27, 30, "[1]...[25][26][x][28][29][30]",
30, 30, "[1]...[26][27][28][29][x]",
3, 6, "[1][2][x][4][5][6]",
4, 7, "[1][2][3][x][5][6][7]"];
for (var i=0; i<ts.length; i+=3) {
var rr=v(ts[i], ts[i+1], 5);
document.write(ts[i]+" of "+ts[i+1]+": "+rr+" |Correct-> "+ts[i+2]+"<br>");
ts[i+2]==rr ? document.write("<span style='color:green'>Check!</span>") : document.write("<span style='color:red'>Fail</span>");
document.write("<br><br>");
}
}
答案 13 :(得分:0)
for x,n,w in [[1,30,5],[2,30,5],[13,30,5],[27,30,5],[30,30,5],[3,6,5],[4,7,5]]
puts (1..n).map{|i|i>[-w/2+x,n-w].min&&i<=[x+w/2,w].max||i==1||i==n ?"[#{i==x ?'x':i}]":'-'}.join.gsub(/-+/,'...')
end