Подтвердить что ты не робот

Code Golf - создавать близлежащие номера страниц на основе текущей страницы

Задача состоит в том, чтобы создать алгоритм для генерации подмножества чисел определенного размера в последовательности, основанной на текущей позиции в этой последовательности.

Во время навигации по многим страницам контента на занятом сайте, таком как Qaru или Digg, часто желательно дать пользователю возможность быстро перейти на первую страницу, последнюю страницу или конкретную страницу, которая находится рядом с текущей страницы, которую они просматривают.

Требования

  • Всегда отображаются номера последних и последних страниц.
  • Подмножество номеров страниц будет содержать текущий номер страницы а также номера страниц до и/или после него (в зависимости от текущей страницы)
  • Подмножество номеров страниц будет всегда должно быть фиксированное количество страниц и никогда не может превышать это фиксированное число, если:
    • totalPages < fixedWidth
  • Позиция текущей страницы число в подмножестве фиксировано если:
    • 1 <= currentPage < (fixedWidth - defaultPostion) или
    • (totalPages - currentPage) < (fixedWidth - defaultPostion)
  • Выход должен указывать, когда есть разница больше 0 между первым страницы данных и первой страницы подмножество, а также между последняя страница подмножества и последняя страница данных. Этот индикатор должен появиться не более одного раза в любом положении.

Если вы еще не можете это сделать, взгляните на свой профиль в разделе вопросов/ответов. Если у вас более 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]
  • Не следует включать индикатор пробелов, если расстояние между концом подмножества и первым или последняя страница меньше 1. Таким образом, возможно иметь неразрывную последовательность страниц до fixedWidth + 2, как в [1][2][3][x][5][6]...[15] или [1][2][3][x][5][6][7]

Решения на всех языках приветствуются.

Удачи!

4b9b3361

Ответ 1

Python - 156 182 140 символов

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. сильно отредактированный, чтобы уменьшить счетчик char и добавить n= количество страниц вокруг текущего (m - максимальное количество страниц, а c - текущая страница нет)

Ответ 2

GolfScript - 89 80 78 символов

~:&;\:C;:T,{-1%[T&-T)C-:C&2/-(]$0=:|1>{.1<\|>}*}2*]${{)]`[C]`/'[x]'*}%}%'...'*

Пример ввода-вывода:

$ 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}

Пример ввода-вывода:

$ 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]

Ответ 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]

Ответ 4

Общие Lisp: 262 значащих символа

(defun [(n) (формат t "[~ a]" n)) (defun p (cm & key (s 5) (p 2)) (пусть ((l (max (min (- cp )()() (1) (1)) (когда ( > (1) l()()()()()()()()()(), (если (< r (1- m)) (принц "..." )) (когда (< 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

EDIT: вызов в сжатой версии:

CL-USER> (p 8 15 :s 6 :p 5)

Ответ 5

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).']');}

(Сортировка) unminified:

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]), но это станет намного менее элегантным, учитывая это.

Ответ 6

С#, 240/ 195 184 символа

Как и в случае с другим ответом С#, но с некоторым неприятным побочным эффектом, заполненным 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;}));
}

Edit:

Оказывается, императивная версия короче с хорошим запасом ( 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;
    }
}

Ответ 7

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)[email protected]$r;

$_=join'',map{$_==1||$_==$n||abs($_-$x)<=$a?$_==$x?'[x]':"[$_]":'_'}(1..$n);s/_+/.../g;print
;print"\n";
}

Ответ 8

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 страниц. развести руками

Ответ 9

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]

Ответ 10

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]

Ответ 11

Символы С# 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("...");
    }
}

Test

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]

Ответ 12

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

Ответ 13

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>");
}
}

Ответ 14

Ruby 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