# Print a booklet

Reading a book is easy, but printing a book can be a bit tricky. When printing a booklet, the printer needs to have the pages arranged in a certain manner in order to be read from left to right. The way this is done is using a pattern like below

n, 1, 2, n-1, n-2, 3, 4, n-3, n-4, 5, 6, n-5, n-6, 7, 8, n-7, n-8, 9, 10, n-9, n-10, 11, 12, n-11…


## Test Cases

4 page booklet: 4, 1, 2, 3

8 page booklet: 8,1,2,7,6,3,4,5

12 page booklet: 12,1,2,11,10,3,4,9,8,5,6,7

16 page booklet: 16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9

20 page booklet: 20,1,2,19,18,3,4,17,16,5,6,15,14,7,8,13,12,9,10,11

Your task is to, given an integer n that is a multiple of 4, display an array of numbers that could be used to print a book of n pages.

Note: As long as the output generates the correct numbers, whether delimited by spaces, commas, hyphens, or parenthesis, any method to getting to a solution can be used

This is a question so answers will be scored in bytes, with the fewest bytes winning.

• Are we guaranteed that input will always be divisible by 4 or even an even number? Either way, could you add a few more test cases, please? And welcome to PPCG :) – Shaggy Aug 6 '17 at 23:51
• Welcome to PPCG and nice first challenge! Note that we recommend proposing new challenges in the sandbox before posting them. – Oliver Ni Aug 6 '17 at 23:57
• Your input needs to be a multiple of 4 – tisaconundrum Aug 6 '17 at 23:57
• Would be nice (but maybe trivial) to support any value, filling with blank pages if needed (another challenge, maybe?) – Barranka Aug 7 '17 at 14:56
• Can we delimit the array with a space, hyphen, or other delimiter instead of a comma? – TehPers Aug 7 '17 at 20:01

# 05AB1E, 98 7 bytes

L[Žˆrˆ


Try it online!

Explanation

L           # push range [1 ... input]
# split as separate to stack
[Ž        # loop until stack is empty
ˆ       # add top of stack to global list
r      # reverse stack
ˆ     # add top of stack to global list
# implicitly display global list


## JavaScript (ES6), 49 45 bytes

Saved 4 bytes with help from @RickHitchcock

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


### Demo

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

console.log(JSON.stringify(f(4)))
console.log(JSON.stringify(f(8)))
console.log(JSON.stringify(f(12)))
console.log(JSON.stringify(f(16)))
console.log(JSON.stringify(f(20)))

## Non-recursive, 51 bytes

n=>[...Array(n)].map((_,i)=>[2*n-i,,++i][i&2]+1>>1)


### Demo

let f =

n=>[...Array(n)].map((_,i)=>[2*n-i,,++i][i&2]+1>>1)

console.log(JSON.stringify(f(4)))
console.log(JSON.stringify(f(8)))
console.log(JSON.stringify(f(12)))
console.log(JSON.stringify(f(16)))
console.log(JSON.stringify(f(20)))

• 47 bytes: f=(n,a=1)=>n<a+3?[]:[n,a,a+1,n-1,...f(n-2,a+2)] – Rick Hitchcock Aug 7 '17 at 13:32
• @RickHitchcock n<a is actually enough, so that's 4 bytes saved. Thanks! – Arnauld Aug 7 '17 at 13:51

# Python 2, 9993885856 55 bytes

f=input()
for i in range(1,f/2,2):print-~f-i,i,i+1,f-i,


Try it online!

-6 bytes by removing unneeded indentation, thanks Oliver Ni

-5 bytes by changing the conditional, thanks Luis Mendo

-30 bytes by optimizing the print statements, thanks Arnold Palmer

-2 bytes by putting the loop on one line, thanks nedla2004

-1 byte by doing some wizardry, thanks Mr. Xcoder

• Save bytes by using 1 space instead of 4. – Oliver Ni Aug 7 '17 at 0:20
• Oh yeah, I always forget about that. Thanks. – LyricLy Aug 7 '17 at 0:21
• -29 bytes using a lambda (although this might be different enough to warrant a separate answer). – notjagan Aug 7 '17 at 0:37
• @notjagan Go ahead and post that yourself if you want. – LyricLy Aug 7 '17 at 0:45
• 58 bytes by changing your print up just a bit. It now prints f-i+1,i,i+1,f-i in each loop instead of conditionally printing the last value. This also allowed removing the initial print f,. – Arnold Palmer Aug 7 '17 at 2:09

# Python 2, 46 bytes

lambda n:map(range(1,n+1).pop,n/4*[-1,0,0,-1])


Try it online!

Generates the range [1..n] and pops from the front and back in the repeating pattern back, front, front, back, ...

Python 2, 49 bytes

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


Try it online!

Generates the first 4 elements, then recursively continues with the upper value n decreased by 2 and the lower value k increased by 2.

Python 2, 49 bytes

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


Try it online!

Directly generates the i'th value of the list, using -i%4/2 as a Boolean for whether to take the lower or higher value.

# Python 3, 6863 62 bytes

−5 bytes thanks to @notjagan (removing spaces and using [*...] instead of list()).

−1 byte thanks to @ovs (*1 instead of [:]).

def f(n):r=[*range(1,n+1)];return[r.pop(k%4//2-1)for k in r*1]


Try it online!

• -5 bytes. – notjagan Aug 7 '17 at 1:26
• You can use r*1 instead of r[:] for -1 byte – ovs Aug 7 '17 at 5:42

# MATL, 1917 10 bytes

:t"0&)@o?P


Try it online!

### Explanation

:          % Implicitly input n. Push range [1 2 ... n]
t          % Duplicate
"          % For each (that is, do n times)
0&)      %   Push last element, and then subarray with remaining elements
@        %   Push 1-based iteration index
o?       %   Is it odd? If so
P      %     Reverse subarray of remaining elements
%   Implicit end
% Implicit end
% Implicitly display stack


# Jelly,  12  11 bytes

Improved to 11 bytes, "Combinatorial Methods":

9Bṁ×ḶṚÆ¡‘Œ?


Try it online!

### How?

This uses permutation calculations and the factorial number system:

9Bṁ×ḶṚÆ¡‘Œ? - Link n                        e.g. 16
9B          - nine in binary                     [1,0,0,1]
ṁ         - mould like n                       [1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1]
Ḷ       - lowered range(n)                   [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
×        - multiply                           [0,0,0,3,4,0,0,7,8,0,0,11,12,0,0,15]
Ṛ      - reverse                            [15,0,0,12,11,0,0,8,7,0,0,4,3,0,0,0]
Æ¡    - convert from factorial base        19621302981954 (=15*15!+12*12!+...+3*3!)
‘   - increment                          19621302981955 (we actually wanted 1*0! too)
Œ? - shortest permutation of natural numbers [1,2,...] that would reside at that
-   index in a sorted list of all permutations of those same numbers
-                                    [16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9]


Unimproved 12 byter, "Knitting Patterns":

RṚ‘żRs2Z€FḊṁ


Try it online!

### How?

This is the simple approach, it creates two strands, interleaves them and then trims the loose ends:

RṚ‘żRs2Z€FḊṁ - Link: n                      e.g. 8
R            - range(n)                          [1,2,3,4,5,6,7,8]
Ṛ           - reverse                           [8,7,6,5,4,3,2,1]
‘          - increment                         [9,8,7,6,5,4,3,2]
R        - range(n)                          [1,2,3,4,5,6,7,8]
ż         - zip (interleave)                  [[9,1],[8,2],[7,3],[6,4],[5,5],[4,6],[3,7],[2,8]]
s2      - split into chunks of length 2     [[[9,1],[8,2]],[[7,3],[6,4]],[[5,5],[4,6]],[[3,7],[2,8]]]
Z€    - transpose €ach (cross-stitch?!)   [[[9,8],[1,2]],[[7,6],[3,4]],[[5,4],[5,6]],[[3,2],[7,8]]]
F   - flatten                           [9,8,1,2,7,6,3,4,5,4,5,6,3,2,7,8]
Ḋ  - dequeue (removes excess start)    [8,1,2,7,6,3,4,5,4,5,6,3,2,7,8]
ṁ - mould like n (removes excess end) [8,1,2,7,6,3,4,5]

• This is clever. +1 – Erik the Outgolfer Aug 7 '17 at 10:14

# Octave, 43 36 bytes

A port of this answer in C (gcc) can be found here.

@(n)[n-(k=1:2:n/2)+1;k;k+1;n-k](:)';


# Explanation

1. k=1:2:n/2: Generates a linear sequence from 1 to n/2 in steps of 2. Note that this is immediately used in the next step.
2. [n-k+1;k;k+1;n-k]: Creates a 4 row matrix such that the first row creates the sequence n, n-2, n-4... down to n-(n/2)+2, the second row is 1, 3, 5... up to n/2 - 1, the third row is the second row added by 1 and the fourth row is the first row added by 1.
3. [n-k+1;k;k+1;n-k](:)': This stacks all of the columns of this matrix together from left to right to make a single column vector, and we transpose it to a row vector for easy display. Stacking the columns together this way precisely creates the sequence desired.

Note that this is an anonymous function, so you can assign it to a variable prior to using it, or you can use the built-in ans variable that gets created after creating the function.

Try it online!

• Hi, I think you can even shorten it by making it a anonymous function, so you don't have to call input. See this link: gnu.org/software/octave/doc/v4.0.3/… – Michthan Aug 7 '17 at 13:10
• @Michthan True. I originally did it that way because the code was more than one statement. I took another crack at it so remove the call to input and I abused the syntax a bit more by storing the base incremental vector as I was creating the first row and taking the input n from the actual anonymous function input itself so I can now fit it into one statement. Thanks! – rayryeng Aug 7 '17 at 14:50

# R, 48 bytes (improved)

Thanks to @Giuseppe for -7 bytes!

n=scan();(x=order(1:n%%2))[order(-(n/2+.5-x)^2)]


The trick is that x=1:n;x[order(x%%2)] is equivalent to order(1:n%%2).

Try it online!

# R, 55 bytes (original)

## Golfed

n=scan();x=1:n;x=x[order(x%%2)];x[order(-(n/2+.5-x)^2)]


## Ungolfed with comments

Read n from stdin.

n=scan()


Define x as sequence of pages from 1 to n.

x=1:n


Order pages so even pages are before uneven pages.

x=x[order(x%%2)]


Order pages in descending order with respect to the centre of the book computed by n/2+.5.

x[order(-(n/2+.5-x)^2)]


Example with 8 pages:

• centre is 4.5;
• pages 1 and 8 are the most distant from the centre, but 8 comes first because 8 is even;
• pages 2 and 7 are the next most distant from the centre, but 2 comes first as 2 is even;
• and so on.

Try it online!

• nice, way better than my (stolen) solution – Giuseppe Aug 7 '17 at 21:34
• 48 bytes! – Giuseppe Aug 7 '17 at 21:44
• The trick was noticing that (1:n)[order(1:n%%2)] is the same as order(1:n%%2) – Giuseppe Aug 7 '17 at 21:45

# Mathematica, 5453 45 bytes

Join@@Range[#][[(-1)^k{k,-k}]]~Table~{k,#/2}&


## Explanation

Join@@Range[#][[(-1)^k{k,-k}]]~Table~{k,#/2}&  (* Input: # *)
~Table~{k,#/2}   (* Iterate from k=1 to #/2 *)
Range[#][[            ]]                 (* From {1..#}, take... *)
{k,-k}                   (* k-th and negative k-th element *)
(* negative k-th = k-th from the end *)
(-1)^k                         (* Reversed for odd k *)
Join@@                                         (* Join the result *)


# Python 2, 64 63 bytes

-1 byte thanks to ovs!

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


Try it online!

• n-i-1 can be n+~i – ovs Aug 7 '17 at 5:40

## Haskell, 42 bytes

n#a|n<a=[]|x<-n-2=n:a:a+1:n-1:x#(a+2)
(#1)


Try it online!

One byte longer:

### Haskell, 43 bytes

f n=[1,3..div n 2]>>= \x->[n-x+1,x,x+1,n-x]


# Java 8, 84 72 bytes

n->{for(int j=0;++j<n;System.out.printf("%d,%d,%d,%d,",n--,j++,j,n--));}


or

n->{for(int j=0;++j<n;System.out.print(n--+","+j+++","+j+","+n--+","));}


-12 bytes thanks to @TheLethalCoder's comment on the C# answer.

Old answer (84 bytes):

n->{int r[]=new int[n],i=1,N=n,J=1;for(r[0]=n;i<n;r[i]=-~i++%4<2?J++:--N);return r;}


Explanation:

Try it here.

n->{                  // Method with integer parameter and no return-type
for(int j=0;++j<n;  //  Loop from 1 to n (exclusive)
System.out.printf("%d,%d,%d,%d,",n--,j++,j,n--)
//   Print four numbers simultaneously
);                  //  End of loop
}                     // End of method


# Perl 5, 47 + 1 (-n) = 48 bytes

$,=$";print$_--,$i+++1,$i+++1,$_--,''while$_>$i


Try it online!

• Managed to find a slightly different approach, but ended up with the exact same byte count! Try it online! – Dom Hastings Aug 7 '17 at 12:04

# Swift 3, 74 bytes

func g(f:Int){for i in stride(from:1,to:f/2,by:2){print(f-i+1,i,i+1,f-i)}}


Try it online!

# Swift 3, 60 bytes

{f in stride(from:1,to:f/2,by:2).map{(f-$0+1,$0,$0+1,f-$0)}}


For some reason, this does not work in any online environment I have tried so far. If you want to test it, put var g= in front of it, and call it with print(g(12)) in Xcode (Playgrounds).

Here is a picture after I've ran it in an Xcode playground, version 8.3.1 (Running Swift 3.1):

# QBIC, 25 bytes

[1,:/2,2|?b-a+1,a,1+a,b-a


Although the input is %4, the actual rhythm is 2-based.

## Explanation

[1,:/2,2|   FOR ( b=1; b <= <input>/2; b=b+2)
?           PRINT
b-a+1,     n
a,         1
1+a,       2
b-a        n-1


# C (gcc), 66 bytes

A port of my Octave answer to C (gcc):

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


Try it online!

# cQuents, 21 bytes

=n::n-z+1,z+1,x-1,z-1


Try it online!

## Explanation

                            Implicit input n
=n                          First item in the sequence is n
::                        Mode :: (Sequence 2): print sequence from 1 to n
Comma delimited items are rotated through
n-z+1,                    n - previous + 1
z+1,                previous + 1
x-1,            third-previous - 1
z-1         previous - 1


# R, 64 60 bytes

Devastatingly outgolfed by djhurio! His answer is quite elegant, go upvote it.

n=scan();matrix(c(n-(k=seq(1,n/2,2))+1,k,k+1,n-k),4,,T)[1:n]


A port of rayryeng's Octave answer.

Try it online!

### original solution (64 bytes):

f=function(n,l=1:n)if(n,c(l[i<-c(n,1,2,n-1)],f(n-4,l[-i])),{})


Recursive function.

Try it online!

• First time someone's ever used an answer of mine as inspiration. Thanks :) – rayryeng Aug 7 '17 at 16:12
• It was hard to beat you, but I managed this with 55 byte answer (codegolf.stackexchange.com/a/138045/13849). – djhurio Aug 7 '17 at 21:35

# Bash + Perl + Groff + Psutils, 48 bytes

perl -nE'say".bp
"x--$_'|groff|psbook>/dev/null  Shows output on stderr. Output contains some trailing garbage. Example of use: $ echo 20 | perl -nE'say".bp

# Haskell, 58 bytes

(x:y:r)#(a:b:s)=x:y:a:b:r#s
f n=take n$n:[1..]#[n-1,n-2..]  Try it online! # Pyth, 2724 23 bytes -3 bytes by printing throughout instead of at the end. -1 Thanks to Mr. Xcoder V:1/Q2 2pjd[-QtNNhN-QNk  Try it online! Or on the online Compiler/Executor This is my first real program in Pyth, so there's probably better methods that I don't know about. # Explanation V:1/Q2 2pjd[-QtNNhN-QNk V:1/Q2 2 # For N in range(1, Q/2, 2): pjd # print " ".join(...), [-QtNNhN-QNk # The list [n - (N-1), N, N + 1, n - N, ""] (n is input)  • I found some improvements, and decided they deserved their own answer. – Mr. Xcoder Aug 7 '17 at 5:58 • By the way, replace FN with V for -1 byte – Mr. Xcoder Aug 7 '17 at 5:59 # C++ (gcc), 8984 68 bytes As unnamed generic lambda. n is #pages (%4==0) and C is a reference parameter for the result, an empty container like vector<int> (only push_back is needed). [](int n,auto&C){for(int i=0,j=0;i<n;C.push_back(++j%4<2?n--:++i));}  previous solution: #define P C.push_back( [](int n,auto&C){for(int i=0;i<n;P n--),P++i),P++i),P n--));}  Try it online! Slightly ungolfed: auto f= [](int n,auto&C){ for(int i=0,j=0; i<n; C.push_back(++j%4<2 ? n-- : ++i)); }  previous solution slightly ungolfed: auto f= [](int n, auto&C){ for( int i=0; i<n; P n--), P++i), P++i), P n--) ); } ;  It was quite straightforward developed and there are sure some minor optimizations in the arithmetics. • Edit1: unification of the arithmetics saved 5 byte • Edit2: after the unification the 4 steps were combined Usage: std::vector<int> result; f(n, result);  ### Print-Variant, 77 bytes out-dated If you insist on printing the values, there is this solution: [](int n,auto&o){for(int i=0;i<n;o<<n--<<' '<<++i<<' '<<++i<<' '<<n--<<' ');}  Where o is your desired std::ostream, like std::cout Usage (if 2nd lambda was assigned to g): g(n, std::cout);  # Common Lisp, 79 bytes (defun f(n &optional(k 1))(and(> n k)(,n,k,(1+ k),(1- n),@(f(- n 2)(+ k 2)))))  Try it online! ## Lua, 94 bytes For this challenge I actually came up with 2 different methods that are both 94 bytes. Method 1: function f(n,i)i=i or 1 return n>i and('%s,%s,%s,%s,%s'):format(n,i,i+1,n-1,f(n-2,i+2))or''end  Commented Code: function f(n,i) i=i or 1 -- On the first iteration i will be nil so I'm setting it's value to 1 if it is. return n>i and ('%s,%s,%s,%s,%s'):format(n,i,i+1,n-1,f(n-2,i+2)) or '' -- Here i return a ternary statement -- If n>i is true, it will return a string using string.format() and part of this is recursion -- If it's false, it will just return an empty string end  Method 2: function f(n,i)i=i or 1 return n>i and n..','..i..','..i+1 ..','..n-1 ..','..f(n-2,i+2)or''end  This method is similar to the first method however I'm instead returning a concatenated string instead of string.format() In both methods I have used the concept of n and i getting closer together # PHP, 51+1 bytes while($i<$k=&$argn)echo$k--,_,++$i,_,++$i,_,$k--,_;


prints page numbers separated by underscore with a trailing delimiter.
Run as pipe with -nR or try it online.

# J, 22 bytes

($,)_2|.]\1+],@,.&i.-  Try it online! ## Explanation ($,)_2|.]\1+],@,.&i.-  Input: integer n
]          Identity
-  Negate
&i.   Form the ranges [0, 1, ..., n-1] and [n-1, ..., 1, 0]
,.      Interleave
,@        Flatten
                 Cycle between these two operations
`