# Goto the Nth Page

It is common to need to make a page selection interface. It typically looks like this:

prev 1 ... 3 4 [5] 6 7 ... 173 next

Which means there are totally 173 pages, and you are on the 5th page currently.

This challenge requires you take the total number of pages and the current page number as input, and output a string (or an array) to "display" the page selector.

## Input

2 positive integers

• current page number
• count of pages

It is guaranteed that 1 <= current <= total.

## Output

Output a string or an array which represent the ui for page selectors.

• If output as string, a single space (U+0020) should be used between each pages.
• If output as an array, the array should produce same result as the string after convert each item to string and join them with a single space.
• The three dots (...) is not optional for array output.

## Details

• If current == 1, no "prev" will be outputted, otherwise, "prev" comes first.
• If current == total, no "next" will be outputted, otherwise, "next" comes last.
• The first page (1) and the last page (total) should always be outputted.
• The current page, (current - 1) page, (current - 2) page, (current + 1) page, (current + 2) page should be outputted as long as the are in the range of [1..total].
• No other pages numbers should be outputted.
• Pages outputted should be sorted in ascending order.
• Output should not contain duplicate page numbers.
• Current page should be highlighted by wrap it in a pair of [].
• If there is a gap between any neighbors, three dots (...) should be inserted.

## Test Cases

Current Total    Output
1       1        [1]
1       2        [1] 2 next
1       10       [1] 2 3 ... 10 next
3       3        prev 1 2 [3]
3       6        prev 1 2 [3] 4 5 6 next
4       6        prev 1 2 3 [4] 5 6 next
4       7        prev 1 2 3 [4] 5 6 7 next
3       10       prev 1 2 [3] 4 5 ... 10 next
5       10       prev 1 ... 3 4 [5] 6 7 ... 10 next
10      10       prev 1 ... 8 9 [10]
52      173      prev 1 ... 50 51 [52] 53 54 ... 173 next

## Rules

• This is code-golf, the shortest code wins!
• Might be worth adding 4 , 6 as a test case. Similar to the 3, 6 case, but ensures dots are not added to the left side. – Tom Carpenter Nov 7 '17 at 11:53
• Just gonna YOINK some of these for a web project... – Stan Strum Nov 7 '17 at 17:50
• Building on @TomCarpenter 's comment a 4,7 test case would be greatly appreciated - would insure that both of the boundary cases that exclude ellipses may be concurrently met – Taylor Scott Nov 7 '17 at 21:10
• @TaylorScott Both added. – tsh Nov 8 '17 at 2:12
• @StanStrum The next challenge is to write an infinite scroller. – Carl Nov 8 '17 at 5:47

# Retina, 125113109 107 bytes

.+
$* r1\G 1$'
¶

O1+
\b(1+) \1\b

Try it online

• Nice use of  $  and$'! Had a little play with this, but wasn't able to get it down much, but by using <> instead of the regex and using -a to keep a reference to $_, I was able to drop to 111: Try it online! (-l added for readability) – Dom Hastings Nov 7 '17 at 16:39 • Fine, I didn't think to @F – Nahuel Fouilleul Nov 7 '17 at 16:51 • I've been enjoying the use of "@F" for singular inputs, it's a nice workaround! The -l isn't needed in byte count though, only for running all tests at once :). I didn't say, but your ellipsis validation is very nice! – Dom Hastings Nov 7 '17 at 16:55 • indeed i've just seen one of my first posts could be improved – Nahuel Fouilleul Nov 7 '17 at 17:10 # Ruby, 127 bytes I'm not particularly happy with this, especially the prev/next logic. ->c,t{"prev #{(1..t).chunk{|n|n<2||n==t||n>c-3&&n<c+3}.map{|t,a|t ?a:?.*3}*" "} next".sub(/(prev )?\b(#{c})\b( next)?/,'[\2]')} Try it online! ## Ungolfed ->c,t{ "prev #{ (1..t) .chunk {|n| n < 2 || n == t || n > c - 3 && n < c + 3 } .map {|t,a| t ? a : ?. * 3 } * " " } next" .sub(/(prev )?\b(#{ c })\b( next)?/, '[\2]') } # PHP (Browser), 267 Bytes <?php parse_str($_SERVER['QUERY_STRING']);$c=$a!=1?$a>3?$a>4?'prev 1 . . . ':'prev 1 ':'prev ':'[1] ';$d=$a<$b-2?$a+3:$b;for($i=$a<=2?$a==1?$i=2:$i=$a-1:$i=$a-2;$i<$d;$i++)$c.=$a==$i?"[$i] ":"$i ";if($a<$b-2)$c.=" . . . $b next";else$c.=$a==$b?"[$b]":"$b next";echo $c?> Try it online! Definitely not as small as it could have been, and as was demonstrated above, using PHP in command line can be much smaller. The input is through GET requests, a is the selected number, b is the limit. This looks like foo.bar.com/index.php?a=2&b=12 # Ungolfed <? parse_str($_SERVER['QUERY_STRING']);
$c=$a!=1?$a>3?$a>4?'prev 1 . . . ':'prev 1 ':'prev ':'[1] ';
$d=$a<$b-2?$a+3:$b; for($i=$a<=2?$a==1?$i=2:$i=$a-1:$i=$a-2;$i<$d;$i++)
$c.=$a==$i?"[$i] ":"$i "; if($a<$b-2)$c.=" . . . $b next";else$c.=$a==$b?"[$b]":"$b next";
echo $c ?> I am pretty sure my ternary operators can be improved, feel free to try. • Making my answer work in a browser would cost one or two bytes: [,$k,$n]=$argv; --> <?[$k,$n]=$_GET; if I insist on current page being the first argument and number of pages the second; <?extract($_GET); if I want to use named arguments. – Titus Nov 8 '17 at 11:33
• fails for a=b-3; replace $a<$b-2 with $a<$b-3 to fix. – Titus Nov 8 '17 at 13:45
• golfed: <?=($a=$_GET['a'])>1?'prev 1 ':'[1] ',$a>4?'... ':'';for($i=$a>4?$a-3:1;$i<$a+3&++$i<$b=$_GET['b'];)echo$a-$i?"$i ":"[$i] ";echo$a<$b-3?"... ":"",$a<$b?"$b next":"[$b]"; (169 bytes) – Titus Nov 8 '17 at 14:28 # IBM/Lotus Notes Formula, 217 211 Bytes -2 with thanks to @KevinCruijssen -4 by using variables for the @Text values o:=@If(a=1;"[1]";"Prev 1 ")+@If(a>4;"... ";"");@For(x:=2;x<b;x:=x+1;T:=@Text(x);o:=o+@If(x>a-3&x<a+3;@If(a=x;"["+T+"]";T)+" ";""));Z:=@Text(b);o:=o+@If(b>1;@If(b-a>3;"... ";"")+@If(a=b;"["+Z+"]";Z+" Next");"");o Basically a port of my Python 2 answer just for the fun of trying to remember how to use Formula. There's no TIO for Formula so here's a screenshot of some of the test cases: • Is there a reason why spaces are required at x>a-3 & x<a+3 in Lotus Notes Formula? Is &x reserved for something, or is there no reason in particular why the spaces on both sides are mandatory? I never programmed in this language btw, was just curious. :) – Kevin Cruijssen Nov 7 '17 at 16:23 • @KevinCruijssen - To be honest I don't know. Never thought of trying it without. Too used to writing readable code :-). I'll check tomorrow when I get to a machine with Notes installed and let you know. – ElPedro Nov 7 '17 at 18:11 • @KevinCruijssen - you were right! – ElPedro Nov 8 '17 at 8:51 • Hehe, glad I could help. :) +1 from me, and I see you've golfed some more by creating a variable for @Text. When I saw it was used two times two yesterday it crossed my mind that might be possible. – Kevin Cruijssen Nov 8 '17 at 9:03 # Excel VBA, 202 201 Bytes Anonymous VBE immediate window function that takes input from range A1:A2 and outputs to the VBE immediate window. For i=[Max(A1-2,1)]To[Min(A1+2,A2)]:s=s &IIf([A1]=i,"[" &i &"]",i)&" ":Next:?[If(A1=1,"","prev "&If(A1>3,1&If(A1>4," ... "," "),""))]s[If(A1<A2,If(A1-A2<-3,"... ","")&If(A1-A2<-2,A2&" ","")&"next","")] ### Subroutine Version Included for readablity Public Sub PageSelect(Optional ByVal Current As Long = -1, _ Optional ByVal Total As Long = -1) Call Sheet1.Activate Let [A1] = IIf(Current = -1, [A1], Current) Let [A2] = IIf(Total = -1, [A1], Total) Dim s As String Let s = "" For i = [Max(A1-2,1)] To [Min(A1+2,A2)] Step 1 Let s = s & IIf([A1] = i, "[" & i & "]", i) & " " Next Debug.Print [If(A1=1,"","prev "&If(A1>3,1&If(A1>4," ... "," "),""))]; _ s; _ [If(A1<A2,If(A1-A2<-3,"... ","")&If(A1-A2<-2,A2&" ","")&"next","")] End Sub # PowerShell, 237 bytes param($a,$n)('prev 1','[1]')[$n-lt2]+" ... $($n-2) $($n-1) [$n]"*($n-gt4)+" 2 3 [4]"*($n-eq4)+" 2 [3]"*($n-eq3)+" [2]"*($n-eq2)+"$($n+1)$($n+2) ..."*($n-lt$a-3)+"$($n+1)$($n+2)"*($n-eq$a-3)+"$($n+1)"*($n-eq$a-2)+"$a next"*($n-ne$a)

Try it online!

One gigantic string concatenation with way too many dollar signs. Working on golfing further. Nope, I think this is as short as this approach can go.

# Javascript (ES6), 265263258240239220194193182 178 bytes

-2 from removing a debug tool

-5 from realizing that I'm using ES6 and can do away with parenthesis sometimes

-18 from removing something from an earlier version that is now obsolete

-1 from doing some sneaky stuff

-19 from removing unnecessary variables

-26 bytes from removing the all too complicated remove falsey values. I'm new to ES6

-1 from using shorter comparisons

-11 from using a recursive function

*-4 from replacing ?...:0 with &&..., and ... ${t} with ...+t This took way too much of my life, and didn’t give enough upvotes. but I am so glad the final code is a power of 2 (2^8) I do know there is another JavaScript answer that is about 120 bytes. but I still love this code EDIT: i don't know what i was thinking. 265 is not 2^8... While making this, I managed to break the ungolfed version. God, do I hate ungolfing code. EDIT 2: now it's looking like the better 121 byte solution y=(e,i,t="")=>i++<e?y(e,i,t+i+' '):t.slice(0,-1);m=(t,p)=>[p-1&&"prev",p<5?y(p-1,0):"1 ... "+y(p-1,p-3),[${t}],t-p<4?y(t,p):y(p+2,p)+ ... +t,t-p&&"next"].filter(e=>e).join

Explanation:

to come but basically y is range(end, start) and it does some cool stuff like:

1. show prev if page is 1
2. show left dots if page > 4
3. show right dots if total - page < 4
4. show next if total - page == 0

and stuff like that and just joins it by ' '. I know you don't have to but I like the fact that is semi-conventional. I don't know. Enjoy.

Try it online!

Validate it online!

Here's a 186 185 174 170 byte solution that I don't like: Try it online!

# PowerShell, 141 bytes

param($c,$t)($('prev'*($c-ne1)
1
'...'*($c-gt4) ($c-2)..($c+2)-gt1-lt$t
'...'*($t-$c-gt4)
$t 'next'*($t-ne$c))|?{$_}|gu)-replace"^$c$","[$c]" Try it online! Less golfed: param($current,$total)$uiElements=$( 'prev'*($current-ne1)
1
'...'*($current-gt4) ($current-2)..($current+2)-gt1-lt$total
'...'*($total-$current-gt4)
$total 'next'*($total-ne$current) ) ($uiElements|where{$_}|Get-Unique)-replace"^$current$","[$current]"