20

課題は、シーケンス内の現在の位置に基づいて、シーケンス内の数値の具体的なサイズのサブセットを生成するアルゴリズムを作成することです。

Stack Overflow や Digg のような忙しいサイトでコンテンツの多くのページをナビゲートしているときに、最初のページ、最後のページ、または現在のページに近い特定のページにすばやくジャンプする方法をユーザーに提供することが望ましいことがよくあります。見る。

要件

  • 最初と最後のページ番号は常に表示されます
  • ページ番号のサブセットには、現在のページ番号とその前後のページ番号が含まれます (現在のページによって異なります)。
  • ページ番号のサブセットは常に固定ページ数であり、次の場合を除き、その固定数を超えたり下回ったりすることはありません。
    • totalPages < fixedWidth
  • サブセット内の現在のページ番号の位置は、次の場合を除いて固定されています。
    • 1 <= currentPage < (fixedWidth - defaultPostion) また
    • (totalPages - currentPage) < (fixedWidth - defaultPostion)
  • 出力は、データの最初のページとサブセットの最初のページの間、およびサブセットの最後のページとデータの最後のページの間に0 より大きい差があることを示す必要があります。このインジケータは、いずれかの位置に最大 1 回表示する必要があります。

これをまだ想像できない場合は、質問/回答の下にあるスタック オーバーフロー プロファイルを見てください。どちらかが 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 未満の場合、ギャップ インジケーターを含める必要はありません。 [1][2][3][x][5][6]...[15][1][2][3][x][5][6][7]

あらゆる言語でのソリューションを歓迎します。

幸運を!

4

14 に答える 14

7

パイソン - 156 182140文字

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現在のページ番号)を追加します。

于 2010-07-29T11:43:24.927 に答える
4

GolfScript - 89 80 78 文字

~:&;\: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]
于 2010-07-30T16:27:05.333 に答える
3

F# ! - 233 の有効文字。

すべてのオプションがサポートされ、仕様内です。

プログラム:

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]
于 2010-07-29T10:54:24.217 に答える
2

Common Lisp: 有効文字数 262 文字

(defun [(n)(フォーマット t"[~a]"n))(defun p(cm &key(s 5)(p 2))(let((l(max(min(- cp)(- ms - 1))1))(r(min(max(+ c(- p)s -1)s)m)))(when(> l 1)([ 1))(when(> l 2)(プリンク"..."))(l から r までの n のループ do([ (if(= nc)#\xn)))(when(< r(1- m))(princ"...")) (いつ(< 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)
于 2010-07-29T10:37:41.000 に答える
1

Perl、92文字

$_=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";
}
于 2010-08-24T04:19:42.670 に答える
1

PHP、234 文字

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]が、それを考慮すると、はるかにエレガントではなくなります。

于 2010-07-29T22:41:34.600 に答える
1

C#、240/ 195 184 文字

他の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;
    }
}
于 2010-07-30T02:16:08.010 に答える
0

Python-334文字-完全な機能

短い回答がすでに投稿されていることはわかっていますが、ページのサブセットで構成可能な幅と位置をサポートしていません。私のはそうです。

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

于 2010-07-31T12:58:09.413 に答える
0

ルビー 1.9.1 — 114

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
于 2010-08-23T05:59:55.907 に答える
0

Python - 321 文字

コマンドライン(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ページであると想定しています。肩をすくめる

于 2010-07-29T04:18:21.383 に答える
0

Javascript - 398 393 文字


働く機能

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>");
}
}
于 2010-08-01T17:48:00.777 に答える
0

C# 278 文字


プログラム

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]
于 2010-07-30T00:27:00.467 に答える
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]
于 2010-07-29T09:15:28.680 に答える
0

Ruby 1.9 - 197 文字

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]

于 2010-07-29T15:43:55.893 に答える