# 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 ¯\_(ツ)_/¯ Commented Dec 21, 2020 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? Commented Dec 20, 2020 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. Commented Dec 20, 2020 at 2:18
• 17 bytes - 2(</.#\)@#i.,i.@- Commented Sep 9, 2022 at 13:31

# 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.

• Quick -2 bytes Commented Dec 19, 2020 at 7:59

# 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... Commented Dec 19, 2020 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}. Commented Dec 19, 2020 at 15:42
• @coltim & is very useful here, thank you! Commented Dec 19, 2020 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
Commented Dec 19, 2020 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 Commented Dec 19, 2020 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
Commented Dec 19, 2020 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
Commented Dec 19, 2020 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
Commented Dec 20, 2020 at 9:56
• -1 more byte by rearranging the increments.
– Neil
Commented Dec 20, 2020 at 10:00
• (both changes also work with non-JSON input, which is nice)
– Neil
Commented Dec 20, 2020 at 10:01
• (you should mention that the input is [now] the number of pages)
– Neil
Commented Dec 21, 2020 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 Commented Dec 21, 2020 at 15:19 • Thanks, @Neil! I updated the answer Commented Dec 21, 2020 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 Commented Dec 21, 2020 at 16:18 • Truth be told; I really thought I'd have to shuffle them around; came as a surprise to me as well! Commented Dec 21, 2020 at 16:22 • param($x) is sorter then $x=$args[0] Try it online! Commented Dec 21, 2020 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! Commented May 25, 2021 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
Commented Dec 19, 2020 at 16:50
• 15 bytes by doing 2ô before 2ä and ćrн -> `.
– ovs
Commented Dec 19, 2020 at 18:37
• – ovs
Commented Dec 19, 2020 at 19:04