Reverse a string by chunks

Your task is to write a program which, given a number and a string, splits the string into chunks of that size and reverses them.

Rules

Your program will receive a positive integer n, as well as a string s with length at least one consisting of only printable ASCII (not including whitespace). The string should then be split into chunks of length n, if the length of the string isn't divisible by n any leftover at the end should be considered its own chunk. Then, reverse the order of the chunks and put them together again.

Test Cases

n   s           Output

2   abcdefgh    ghefcdab
3   foobarbaz   bazbarfoo
3   abcdefgh    ghdefabc
2   a           a
1   abcdefgh    hgfedcba
2   aaaaaa      aaaaaa
2   baaaab      abaaba
50  abcdefgh    abcdefgh
6   abcdefghi   ghiabcdef


This is , so you should aim for as few bytes as possible.

• Apr 14, 2017 at 20:51

Jelly, 2 bytes

sṚ


A full program that prints the result.

Try it online!

How?

sṚ - Main link: string, number                                   e.g. 'abcdefg', 3
s  - split string into chunks of length number (keeping any overflow) ["abc","def","g"]
Ṛ - reverse the resulting list                                       ["g","def","abc"]
- implicit print                                                   gdefabc

• I like how two bytes generated 4 lines of explanation. Apr 14, 2017 at 21:17

Python 3, 35 bytes

f=lambda s,n:s and f(s[n:],n)+s[:n]


Try it online!

• How does the and keyword work here ? @Dennis Apr 15, 2017 at 9:06
• @ShinMigami13 empty string is not truthy so this ends the recursion Apr 15, 2017 at 14:31

05AB1E, 5 4 3 bytes

-1 thanks to Dennis
-1 thanks to carusocomputing

ôRJ


Try it online!

     # Implicit: push input
ô   # Split in pieces of length b
RJ # Reverse and join

• ¹ isn't needed. Jun 5, 2017 at 16:11

JavaScript (ES6), 37 bytes

n=>F=s=>s&&F(s.slice(n))+s.slice(0,n)


Takes input by currying: number first, then string, like f(2)("abcdefgh").

let f =
n=>F=s=>s&&F(s.slice(n))+s.slice(0,n)

let g = (n, s) => console.log(f(${n})("${s}"): ${f(n)(s)}) g(2, "abcdefgh") g(3, "foobarbaz") g(3, "abcdefgh") g(2, "a") g(1, "abcdefgh") g(2, "aaaaaa") g(2, "baaaab") g(50, "abcdefgh") Perl 6, 28 20 bytes {$^b.comb($^a).reverse.join}  Try it {[R~]$^b.comb($^a)}  Try it Expanded: { # bare block lambda with placeholder parameters ｢$a｣ and ｢$b｣ [R[~]] # reduce the following using the reverse meta operator R # combined with the string concatenation operator # comb with a number splits the invocant into chunks of that size$^b.comb($^a) }  Bash + coreutils, 22 fold -$1|tac|tr -d \\n

• I've learned 4 new linux commands this week on PPCG fold is one of them, thanks! Jun 5, 2017 at 16:18

n#""=""
n#s=n#drop n s++take n s


Try it online!

• Pretty. It's nice when precedence works in golf Apr 15, 2017 at 14:33

PHP, 53 Bytes

<?=join(array_reverse(str_split($argv[2],$argv[1])));


Röda, 36 bytes

f n{[[_]..[try head n-1]]|reverse|_}


Try it online!

It's a function that takes one argument. The characters of the string must be in the stream.

try is used to discard errors in case that the head function can't read n-1 values.

Explanation:

f n{[[_]..[try head n-1]]|reverse|_}
f n{                               } /* Function declaration */
/* In a loop: */
_                              /*   Pull one value */
try head n-1              /*   Pull n-1 values (or less) */
[ ]..[            ]             /*   Make an array */
[                   ]            /*   Push it to the stream */
|reverse    /* Reverse all values in the stream */
|_  /* Flat all arrays in the stream */
/* Characters in the stream are printed */


Not as obfuscated as usually. I think it's quite beautiful. :)

• You managed to make a program less readable than the jelly solution. Apr 14, 2017 at 21:57
• Why doesn't [[try head n]] work instead of [[_]..[try head n-1]]? Jun 5, 2017 at 16:26
• @KritixiLithos Because _ loops the expression. [[try head n]] would take n values once, but [[_]..[try head n-1]] takes n values as long as there are values left. Jun 5, 2017 at 17:31

CJam, 5 bytes

q~/W%


Input is a number and a string enclosed in double quotes, separated by whitespace.

Explanation

q~   e# Read all input and evaluate: pushes a number and a string
/    e# Split string into chunks of that size. Last chunk may be
e# smaller. Gives an array of strings
W%   e# Reverse the array. Implicitly display


Batch, 74 bytes

@if %2=="" (echo %~3)else set s=%~2&call %0 %1 "%%s:~%1%%" "%%s:~,%1%%%~3"


Rather annoyingly this ends up being recursive rather than tail recursive.

V, 13 10 bytes

òÀ|lDÏpòÍî


Try it online!

ò      ò    ' Recursively
À|         ' Go to the "nth" column
l        ' Move one character right (breaks loop when no more chunks)
D       ' Delete from here to the end of the line
Ï      ' Add a line above the current line (now contains one chunk)
p     ' Paste the remainder of the line that was deleted
Íî  ' Remove all newlines


In Action:

abcdefghijkl


turns into

efghijkl
abcd


which becomes

ijkl
efgh
abcd


before all newlines are removed

brainfuck, 78 bytes

,<<<+[[>]>+>[[>],<[<]>+>-]<-[->>[>]>>+<<<[<]<]>>]<<<<[[<]>[-[+.[-]]+>]<[<]<<<]


The first byte of the input is the chunk size, given by byte value. The rest of the bytes are considered to be the string.

Try it online!

Expanded and commented

Read the chunk size byte
This cell will become a counter cell
,

Move left a few cells an increment;
this is to make the starting position
line up with the relative positioning
needed to fit in with the loop
<<<+

While the current cell is nonzero:
[

Move right to the first zero cell
[>]

Move right once and increment and then move right to the counter cell
The increment is required because of "move to zero cell" loops
>+>

This loop will store one chunk of the input in consecutive memory cells
[
[>]   Move right until a zero cell is hit
,     Store 1 byte of input there
<[<]  Move back left until a zero cell (other than the current one) is hit
>+>-  Increment the temporary cell by 1 and decrement the counter
] (end loop once the counter hits zero)

Decrement the temp cell (because we needed to have 1 there initially to make the cell location work)
<-

Move the temp cell to three cells after the end of the chunk
This is the new counter cell for the next chunk
[->>[>]>>+<<<[<]<]

Move two cells right from where the temp cell was
This is the first cell of the chunk; if it's 0
then the input is finished and the loop should end
>>
]

Due to the way the counter is kept track of the tape head
will always be four cells to the right of the last input cell
when the loops breaks
<<<<

Now the chunks are printed one by one
At the start of an iteration the tape head is at the end of a chunk
[
Locate the start of the last chunk
[<]>

Print the chunk:
[
Print the byte held in the current cell if it isn't 1
This is necessary because we left a stray 1 in a cell at
the start which shouldn't be printed
-[+.[-]]+

Move to the next cell
>
]

Move to just left of the chunk
<[<]

Move three cells over to the end of the next chunk
<<<
]


PowerShell, 56 49 bytes

-7 bytes thanks to mazzy

param($n,$s)$s-split"(.{$n})"-ne''|%{$r=$_+$r};$r


Try it online!

• 1) 49 bytes 2) Please, post a full program, not a codesnippet. How to check? Extract your code in a separate file with the extension .ps1 and try calling this script instead of your code. If it works, then the test was successful. Mar 20, 2019 at 14:49

Mathematica, 46 bytes

""<>Reverse@Partition[Characters@#2,#,#,1,{}]&


Anonymous function. Takes a number and a string as input and returns a string as output. Not much to see here.

Javascript - 54 47 46 bytes

(s,n)=>s.match(eval(/.{1,${n}}/g)).reverse()  Used as f=(s,n)=>s.match(eval(/.{1,${n}}/g)).reverse()


Thank you to @ETHproductions for some RegEx quickenning Thank you to @Shaggy for an extra byte in the eval!

Original:

(s,n)=>s.match(new RegExp('.{1,'+n+'}','g')).reverse()

• Nice answer! I believe you can save a couple bytes by creating the regex with eval('/.{1,'+n+'}/g') Apr 15, 2017 at 17:24
• @ETHproductions Ah yes. That's what I've been attempting to do. I wasn't familiar enough with regex to do it though! Apr 15, 2017 at 17:50
• I think you can save a byte with currying, s=>n=> ...  Apr 15, 2017 at 20:50
• Save a byte with eval("/.{1,${n}}/g"), using backticks instead of quotation marks. Apr 16, 2017 at 20:12 Pyth, 5 bytes s_c.*  Explanation  .* splat implicit input c split into chunks length n _ reverse s join  Retina, 38 bytes 1 byte saved thanks to @LeakyNun ^ +(.* (1)+¶)((?<-2>.)+)$3$1 1+¶  (Note the space on the second line, and the trailing space) This program takes input as unary on the first line, and the string on the second. Try it online! Test Suite! (slightly modified) Explanation The first step is to prepend a space (will become important later on). ^  Now we reverse. This uses .NET's balancing groups. It is important to note that groups here act as stacks, so every match is essentially pushed onto the stack. Here we capture every digit in the unary number into group 2. Now each time a character in the string is found, a match is popped from group 2. This ensures the the number of characters does not exceed that of the unary number. +(.* (1)+¶) Capture the unary number in group 2 ((?<-2>.)+) Balancing group for substrings$3$1 Reverse  And finally remove the unary number and the newline.  1+¶  • I think it is acceptable to take the number in unary. Apr 24, 2017 at 17:31 • Anyhow, you can replace \d by . to save a byte. Apr 24, 2017 at 17:39 • The second ^ is also redundant. Apr 24, 2017 at 17:42 • @LeakyNun The program now takes input in unary, so I have no need for the \d anymore. And thanks for golfing away the caret :) Apr 24, 2017 at 17:48 • 33 bytes by using lazy (non-greedy) match. Apr 24, 2017 at 17:50 Java, 147 138 Bytes String r(String s,int n){String r="";int l=s.length();for(int i=l/n*n;i>=0;i-=n)if(!(i>=l))r+=(i+n)>=l?s.substring(i):s.substring(i,i+n);return r;} Saved 9 Bytes thanks to Kevin Cruijssen! String r(String s,int n){String r="";int l=s.length(),i=l/n*n;for(;i>=0;i-=n)if(i<l)r+=i+n>=l?s.substring(i):s.substring(i,i+n);return r;}  In expanded form: String r(String s,int n){ String r=""; int l=s.length(),i=l/n*n; for(;i>=0;i-=n) if(i<l) r+=i+n>=l?s.substring(i):s.substring(i,i+n); return r; }  This is actually my first try to codegolf ever, so any feedback is welcome! • Welcome to PPCG! Apr 23, 2017 at 20:23 • Hi, welcome to PPCG! This is already pretty good, but there are still a few things to golf some more: int l=s.length();for(int i=l/n*n; can be int l=s.length(),i=l/n*n;for(; so you only have int  once. And if(!(i>=l)) can be if(l<i). And r+=(i+n)>=l? can be without the parenthesis: r+=i+n>=l?. Also, if you haven't seen it yet, I can recommend looking through Tips for Golfing in Java for some pretty cool golfing tips to use. :) Once again, welcome. Apr 24, 2017 at 12:46 Perl 5, 25 bytes Uses the -lnM5.010 flags. say reverse<>=~/.{1,$_}/g


Try it online!

Shoutout to Grinnz for telling me about =~ m/.{1,$n}/g -M5.010 enables the use of the say function, which for our purposes is print with a shorter name. -n puts the first line of input into $_, and -l chomps off the trailing newline.

We then get the second line of input using <>, and apply it to the regex .{1,$_}: any character, between 1 and$_ (the first input) times. Since this is greedy by default, it tries to always match $_ characters. The 1, is needed for the possible leftover chunk at the end. The /g modifier gives us every match of that regex in the input string as a list, which is then reversed and printed. In Perl, passing a list to say joins it without any delimiter by default. Dyalog APL Extended, 16 15 bytes {∊⌽⍵⊂⍨(≢⍵)⍴=⍳⍺}  Try it online! • You don't need the f← Mar 20, 2019 at 15:02 • Why, ,/∊ – Adám Mar 20, 2019 at 15:04 • @Adám Oh hey that applies to my answer too, thanks Mar 20, 2019 at 15:04 • Pavel: yep, obviously.. @Adám thanks! Mar 20, 2019 at 15:06 • 14: ∊∘⌽⊢⊂⍨≢⍤⊢⍴1↑⍨⊣ – Ven Mar 20, 2019 at 15:53 Python, 62 bytes lambda n,s:''.join([s[i:i+n]for i in range(0,len(s),n)][::-1])  Try it online! • Python3 answer is shorter & also works for python 2.7: f=lambda n,s:s and f(n,s[n:])+s[:n] Mar 20, 2019 at 19:51 Stacked, 9 bytes #<rev''#  Try it online! #< chunks, rev reverses, and ''# joins by empty string. Quite simple. QBIC, 24 bytes :;[1,_lA|,a|Z=_sA,b,a|+Z  This makes excellent use of the new substring-function I recently added to QBIC: :; Read in the cmd line params a (number) and A$ (text)
[1,_lA|,a|  Set up a FOR loop: FOR b = 1; b <= A$.length; b += a Z= Modify Z$; Z$is autoprinted at the end of QBIC code _sA,b,a| SUBSTRING: _s is the function followed by the string to take from, the starting pos and the # of chars +Z Take chunks from further into A$, put them before Z\$


Pyth, 4 bytes

s_cF


Takes input as "s",n: Try it for yourself!

Convex, 2 bytes

/¥


Try it online!

C, 69 bytes

i;f(s,n)char*s;{i=strlen(s);for(i-=i%n;printf("%.*s",n,s+i),i;i-=n);}


Result is printed out to the standard output.

Scala, 57 55 bytes

(n:Int,s:String)=>(""/:s.grouped(n).toSeq.reverse)(_+_)


Thanks Jacob! Try it here.

Note: By using the symbol form of foldLeft ("/:"), I was able to take off a couple more bytes.

• make it anonymous function, and use mkString instead of reduceLeft, and shave off 7 bytes: (n:Int,s:String)=>s.grouped(n).toSeq.reverse.mkString("") Apr 23, 2017 at 13:43

Ohm, 5 bytes

σ]QWJ


Try it online!

Explanation

σ]QWJ
σ         # Split input1 into input2 pieces
]        # Flatten array
Q       # Reverses stack
W      # Wraps stack to array
J     # Joins stack
# Implicit print


R, 69 60 bytes

function(s,n)cat(substring(s,(x=nchar(s):0*n)+1,x+n),sep="")


Try it online!

Thanks to Kirill L. for the suggestion to remove seq.

• Looks like this works too for 66. Mar 20, 2019 at 19:43
• @KirillL. we can go to 60 bytes if we reverse the order of arguments to : and some manipulation lets us get rid of the trailing -1. Mar 20, 2019 at 19:48
• Smart, very nice! Mar 20, 2019 at 19:49