# Generate newspaper page number sets

A newspaper is made of several sheets; for the purposes of this question, each sheet of newsprint holds four pages of the final newspaper. Here is an example of three sheets of newsprint making up a newspaper with twelve pages:

 ___________
|2    |   11|
|  ___|_____|_
| |4    |    9|
|_|  ___|_____|_
| |6    |    7|
|_|     |     |
|     |     |
|_____|_____|


(Pages 1, 3, 5, 8, 10 and 12 are on the reverse of these sheets so you can't see them here.)

Your challenge, should you choose to accept it, is to output all the sets of pages that are on each sheet of a given newspaper.

You can take either the number of sheets (which is always a positive integer) or the number of pages (which is always a positive multiple of 4), but please indicate which.

You can output the sets of pages in any reasonable order, as long as it is clear which pages belong in which set.

For example, given an input of 3 sheets or 12 pages, you could output (1, 2, 11, 12), (3, 4, 9, 10) and (5, 6, 7, 8); or you could output (8, 5, 7, 6), (10, 3, 9, 4) and (12, 1, 11, 2); or any variant thereof, but you cannot of course output 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12.

This is code golf, so please make your program or function as short as possible. (I will even accept the shortest overall program as the answer on request of its author if doing so will earn me a Winter Bash hat.)

# convey, 34 bytes

}
/1:%""{
^1"v4!<
+"+v}+1
^<","-}


Try it online!

Pushes n and n+1 to the right per loop.

For each value outputs i and i-pages+1.

Whenever the left loop passes through the top part, output a newline /}. Allow n to pass the loop only pages % 4 times.

• what fresh hell is this programming language, even the site linked is basically ¯\_(ツ)_/¯ Dec 21 '20 at 6:51

# J, 18 bytes

Takes number of sheets as input

_4>:\2/:@(,|.)@#i.


Try it online!

_4>:\2/:@(,|.)@#i.
i.  0…n: 0 1 2
2         #    repeat each 2 times: 0 0 1 1 2 2
(,|.)@     append its rotated version: 0 0 1 1 2 2 2 2 1 1 0 0
/:@           get the indices to sort: 0 1 10 11 2 3 8 9 4 5 6 7
_4  \               group by 4: 0 1 10 11, 2 3 8 9, 4 5 6 7
>:                and increment: 1 2 11 12, 3 4 9 10, 5 6 7 8

• Could you explain the “indices to sort” further? Dec 20 '20 at 1:26
• @D.BenKnoble Sort using 0 0 1 1 2 2 2 2 1 1 0 0 as key. so first two and last two, then second two and second last two etc. Dec 20 '20 at 2:18

# Husk, 9 bytes

←½Sz+↔C2ḣ


Try it online!

Argument is the number of pages.

        ḣ   # list of all the page numbers 1..input
C2    # split into groups of two
S         # hook: S(fgx) means f(x,g(x))
z        # zip together
+       # by combining elements from both lists
# x = the list of groups of two)
↔      # and itself reversed
←½          # now take just the first half of this list
# of lists of 4-pages per sheet


# Perl 5-n, 38 bytes

$,=$";say$.++,$.++,$_--,$_--while$_>$.


Try it online!

Takes the number of pages as input

# APL (Dyalog Extended), 16 14 bytes

¯1 4⍴⍋2/,∘⌽⍨…⎕


A port of xash's solution.

a full program which returns a matrix.

-2 bytes from Bubbler.

# R, 48 bytes

function(N)split(rbind(x<-1:N,N:1)[x],(x-1)%/%4)


Try it online!

Takes input as the number of pages.

# R, 51 bytes

function(N)split(1:(4*N),c(x<-rep(1:N,e=2),rev(x)))


Try it online!

Takes input as number of sheets.

• The 48-byter is a lovely matrix-based solution! And even shorter by outputting as a matrix, too... Dec 19 '20 at 23:51

# Scala, 37 bytes

p=>1.to(p/2)zip p.to(p/2,-1)grouped 2


Try it online!

Returns an iterator of 2-element vectors, each containing a 2-tuple of page numbers opposite each other.

# Python 2, 46 bytes

def f(n,i=2):i>n>_;print~-i,i,n-1,n;f(n-2,i+2)


Try it online!

Takes the number of pages n as input.

A function that prints and terminates with error. If we avoid errors, many different ways to structure the code come out very close.

50 bytes: Try it online!

i=n=input()
while i*2>n:i-=2;print-~i,i+2,n+~i,n-i


50 bytes: Try it online!

n=input()
i=1
while i<n:print-~i,i,n-1,n;i+=2;n-=2


51 bytes: Try it online!

n=input()
i=1
while i*2<n:print-~i,i,n-i,n-i+1;i+=2


51 bytes: Try it online!

f=lambda n,i=1:n/i*[0]and[(i,i+1,n-1,n)]+f(n-2,i+2)


51 bytes: Try it online!

lambda n:[(i,i+1,n-i,n-i+1)for i in range(1,n/2,2)]


# K (oK), 21 19 bytes

-2 bytes thanks to coltim

 {1+0N 4#<x,|x:&x#2}


Try it online!

A port of xash's J solution - please upvote it too!

• It requires shuffling some things around, but a couple bytes can be saved by using & (where) on a list of integers, i.e. {1+0N 4#<x,|x:&x#2}. Dec 19 '20 at 15:42
• @coltim & is very useful here, thank you! Dec 19 '20 at 17:04

# Jelly, 7 bytes

ḶạÞH‘s4


A monadic Link accepting the number of pages (four times the number of sheets) which yields a list of lists of the page numbers belonging to each sheet.

Try it online!

### How?

ḶạÞH‘s4 - Link: integer, P   e.g.  12
Ḷ       - lowered range (P)        [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11]
H    - halve (P)                6
Þ     - sort by:
ạ      -   absolute difference  ( [ 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5] )
-                       -> [ 6, 5, 7, 4, 8, 3, 9, 2,10, 1,11, 0]
‘   - increment                [ 7, 6, 8, 5, 9, 4,10, 3,11, 2,12, 1]
4 - four                     4
s  - split into chunks        [[7,6,8,5],[9,4,10,3],[11,2,12,1]]


# AWK, 46 43 bytes

x=$1{for(;y<x;)$++v=++y","++y","x--","x--}1


Takes the number of pages.

x=$1{  Set x to the number of pages. That will always evaluate to true given the rules, so the block of code will always run.  for(;y<x;)  Loop until the forward page counter x is larger then the backwards page counter y. It's effectively looping once for every 4 pages, since x and y both change by 2 each time through the loop. $++v=++y","++y","x--","x--


Set positional argument v (incremented before it's used) to the next set of 4 pages, adjusting the forward and backwards counters as they are used.

                                         }


Ends the code block.

                                          1


An unconditionally true test with no defined code block causes the default action, which is to print all the positional arguments joined by the OFS variable. The default for that is a space.

Try it online!

• If it's your answer, and it's in the same language, and it's shorter, then you should totally put that as your scoring answer. (Whether you want to keep your previous solution in your answer or let people check your edit history is up to you.)
– Neil
Dec 19 '20 at 11:44

# JavaScript (ES6), 47 bytes

f=(n,N=1)=>N<n?[[N,N+1,n-1,n],...f(n-2,N+2)]:[]


Try it online!

# Ruby 2.7, 43 bytes

->n{((1..n/2)%2).map{|v|[v,v+1,n-v,n-v+1]}}


No TIO link, as TIO supports an older version of Ruby.

# Ruby, 45 bytes

f=->n,k=1{k<n ?[[k,k+1,n-1,n]]+f[n-2,k+2]:[]}


Try it online!

# C (gcc), 72 70 bytes

• -2 bytes thanks to ceilingcat

Takes the number of physical pages.

I compute the last page and then loop through each physical page, getting the distance from the bounds for each one starting from the last page (the middle page numbers).

f(n,i,j){for(i=n*4;n--;)printf("%d/%d/%d/%d ",j+1,i-j,++j,i-j,j=n*2);}


Try it online!

• 52 Dec 19 '20 at 10:50

# 05AB1E, 7 bytes

Input is the number of pages, output is in a different order, both the pages on each sheet and the sheets.

Lι€Âøιн


Try it online!

          # implicit input                          8
L         # push the range [1..input]               [1, 2, 3, 4, 5, 6, 7, 8]
ι        # uninterleave, push [a[0::2],a[1::2]]    [[1, 3, 5, 7], [2, 4, 6, 8]]
€Â      # duplicate and reverse each list         [[7, 5, 3, 1], [1, 3, 5, 7], [8, 6, 4, 2], [2, 4, 6, 8]]
ø     # transpose the list of lists             [[7, 1, 8, 2], [5, 3, 6, 4], [3, 5, 4, 6], [1, 7, 2, 8]]
ι    # uninterleave                            [[[7, 1, 8, 2], [3, 5, 4, 6]], [[5, 3, 6, 4], [1, 7, 2, 8]]]
н   # take the first element                  [[7, 1, 8, 2], [3, 5, 4, 6]]


# 05AB1E, 8 bytes

Takes the number of pages as an input. Output is in the natural order.

Lι€Âø€{Ù


Try it online!

          # implicit input                          8
L         # push the range [1..input]               [1, 2, 3, 4, 5, 6, 7, 8]
ι        # uninterleave, push [a[0::2],a[1::2]]    [[1, 3, 5, 7], [2, 4, 6, 8]]
€Â      # duplicate and reverse each list         [[7, 5, 3, 1], [1, 3, 5, 7], [8, 6, 4, 2], [2, 4, 6, 8]]
ø     # transpose the list of lists             [[7, 1, 8, 2], [5, 3, 6, 4], [3, 5, 4, 6], [1, 7, 2, 8]]
€{   # sort each list                          [[1, 2, 7, 8], [3, 4, 5, 6], [3, 4, 5, 6], [1, 2, 7, 8]]
Ù  # uniquify the list of lists              [[1, 2, 7, 8], [3, 4, 5, 6]]

• Sets don't have an order, so you don't have to worry about natural order, unless you're doing this for completeness.
– Neil
Dec 19 '20 at 23:32
• @Neil just kept the original input with "nice" output for completeness. I wouldn't use the other one as my answer if I thought it would be invalid ;)
– ovs
Dec 19 '20 at 23:37

# Charcoal, 17 14 bytes

Thanks to Neil for -3 bytes!

ＩＥ⪪…⁰⊘θ²⁺⊕ι⁻θι


Try it online! Link is to verbose version of code.

Input is (now) the number of pages.

### Explanation

Ｉ               Cast to string
Ｅ             Map (forEach)
⪪    ²       Split on 2 (split into slices of length 2)
…⁰          Range from 0...
⊘θ        ...to half of first input (θ)
⁺⊕ι    Add (concatenate) ι (current item, which is the slice), with every element incremented...
⁻θι ...to first input (θ) minus the slice (ι)

• -2 bytes by switching to input as pages instead of sheets.
– Neil
Dec 20 '20 at 9:56
• -1 more byte by rearranging the increments.
– Neil
Dec 20 '20 at 10:00
• (both changes also work with non-JSON input, which is nice)
– Neil
Dec 20 '20 at 10:01
• (you should mention that the input is [now] the number of pages)
– Neil
Dec 21 '20 at 15:19

# PowerShell, 5652 49 bytes

-4 bytes thanks to Neil!
-3 bytes thanks to mazzy!

Takes input as the number of pages:

param($x)for(;$x-$y){++$y,++$y,$x--,$x---join","}  Try it online! • Welcome to the site! Consider using Try it Online! to create a runnable demo of your code. You don't have to output the numbers in any particular order, only the grouping is important. This might allow you to reduce the size of your code slightly. Also, I suspect this answer takes input as the number of pages, could you include that information as part of your answer? Thanks! – Neil Dec 21 '20 at 15:19 • Thanks, @Neil! I updated the answer Dec 21 '20 at 15:32 • ---join actually works? Cool! (I was worried you'd have to move the $x--s to the start so you could write ,++$y-join.) – Neil Dec 21 '20 at 16:18 • Truth be told; I really thought I'd have to shuffle them around; came as a surprise to me as well! Dec 21 '20 at 16:22 • param($x) is sorter then $x=$args[0] Try it online! Dec 21 '20 at 20:48

# VyxalṀ, 14 13 bytes

ƛd›D⁰4*ε:›^›W


Try it Online!

# Bash, 42 bytes

-1 bytes from @pxeger

for((x=$1;x>y;)){ echo {,}$[++y]\ $[x--];}  I'm usually the Zsh guy, but here Bash wins by a few bytes because it evaluates brace expansion before parameter expansion: echo {,}{$[++y],$[x--]} echo$[++y] $[x--]$[++y] \$[x--]

• You don't need the {,} around the parameter expansion; you can actually just escape a space for -1 byte Try it online! May 25 '21 at 10:57

# Jelly, 8 bytes

Żx2m0Ụs4


Try it online!

Another port of xash’s answer, drop that an upvote as well

## How it works

Żx2m0Ụs4 - Main link. Takes n on the left
Ż        - [0,1,2,...,n]
x2      - [0, 0, 1, 1, 2, 2, ..., n, n]
m0    - Append its reverse
Ụ   - Grade up; sort the indices by values
s4 - Split into runs of 4


# 05AB1E,  10  9 bytes

-1 thanks to ovs!

LΣ<I;α}4ô


Try it online!

Port of my Jelly answer. Input is the number of pages (four times the number of sheets).

LΣ<I;α}4ô
L         - range
Σ   }    - sort by:
<       -   decrement
I      -   push input
;     -   halve
α    -   absolute difference
4  - push four
ô - split into chunks


# 05AB1E, 20 11 bytes

L2ô2äRδ«Å\


Try it online!

-9 thanks to @ovs

• 2ä is shorter for splitting a list in 2 equal sized parts.
– ovs
Dec 19 '20 at 16:50
• 15 bytes by doing 2ô before 2ä and ćrн -> `.
– ovs
Dec 19 '20 at 18:37
• – ovs
Dec 19 '20 at 19:04