22
\$\begingroup\$

Given a string, you've to split it into groups of three characters (by padding _ at the end).

Related, but still it's different.


Sample I/O:

  • 'abcde' -> 'abc', 'de_'

  • '1234' -> '123', '4__'

  • '' -> [] or falsey value

  • 'Three spree!' -> 'Thr', 'ee ', 'spr', 'ee!'

  • 6 MB string

This is a , so fewest bytes will win!

Edit: Finally, output is unrestricted.

\$\endgroup\$
3
  • 11
    \$\begingroup\$ Why special case the empty string? May we choose which character to use for the padding? \$\endgroup\$
    – Shaggy
    May 19, 2019 at 14:49
  • \$\begingroup\$ Is null considered a falsey value? \$\endgroup\$ May 19, 2019 at 14:58
  • 2
    \$\begingroup\$ @LuisfelipeDejesusMunoz, falsey values are defined by the language, not the challenge author. \$\endgroup\$
    – Shaggy
    May 19, 2019 at 15:00

48 Answers 48

10
\$\begingroup\$

05AB1E, 9 8 bytes

…___«3ô¨

Try it online! or as a Test Suite

Explanation

…___«      # append "___" to input
     3ô    # split into groups of 3
       ¨   # discard the last group
\$\endgroup\$
8
\$\begingroup\$

Python 3, 58 47 34 bytes

I'm sure someone else can do better Someone else did better. Thanks Jo King for -11 -24 bytes!

Output is unrestricted, welcome to tuple hell. Returns empty list (falsy) on empty input

lambda x:[*zip(*[iter(x+"__")]*3)]

TIO

\$\endgroup\$
0
6
\$\begingroup\$

JavaScript, 25 bytes

s=>`${s}__`.match(/.../g)

Try it

\$\endgroup\$
5
\$\begingroup\$

APL+WIN 36 24 22 bytes

12 bytes saved as a result of output now being de-restricted and using the code in @Adám's first comment modified to work in APL+WIN and a further 2 with his second comment. Thanks.

(⌈(↑⍴s)÷3)3⍴(s←⎕),'__'

Prompts for input of the string and outputs the result as a nx3 array

Try it online! Courtesy of Dyalog Classic

\$\endgroup\$
3
  • \$\begingroup\$ @Adám. Throws a domain error in APL+WIN at the right most ⍴ \$\endgroup\$
    – Graham
    May 19, 2019 at 13:45
  • \$\begingroup\$ Fails on '', no? I think OP (for some strange reason) requires the result to be 0 (with any rank). \$\endgroup\$
    – Adám
    May 19, 2019 at 15:47
  • 1
    \$\begingroup\$ @Adám It produces a 0 x 3 array. The OP now appears to want "falsey" for a null input. With the spec keeping on changing I am going to bow out at this point and leave my answer as its stands! Thanks for your improvements. \$\endgroup\$
    – Graham
    May 19, 2019 at 16:12
5
\$\begingroup\$

Perl 5, 16 15 bytes

"@_\__"=~/.../g

Try it online!

\$\endgroup\$
2
  • 2
    \$\begingroup\$ 15 with "@_\__"=~/.../g. There were other 16s: (pop.__)=~/.../g or map/.../g,pop.__. \$\endgroup\$
    – Grimmy
    May 20, 2019 at 11:50
  • 1
    \$\begingroup\$ Thx to @Grimy for the tip on \. It shaved off 1 byte and I learned something new. \$\endgroup\$
    – Kjetil S
    May 20, 2019 at 13:30
4
\$\begingroup\$

JavaScript, 51 50 48 27 25

b=>(b+"__").match(/.../g)

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to PPCG! :) But ... codegolf.stackexchange.com/a/185808/58974 \$\endgroup\$
    – Shaggy
    May 24, 2019 at 16:51
  • \$\begingroup\$ @Shaggy I didn't even see that ¯\_(ツ)_/¯ \$\endgroup\$
    – VFDan
    May 24, 2019 at 17:21
  • \$\begingroup\$ No worries, it happens. \$\endgroup\$
    – Shaggy
    May 24, 2019 at 17:24
3
\$\begingroup\$

Perl 6, 19 bytes

{$_~"__"~~m:g/.../}

Try it online!

Pads the string by two underscores then splits the string into chunks of three characters. Returns as an array of Match objects.

\$\endgroup\$
3
\$\begingroup\$

Japt, 8 bytes

+1 byte to special case the empty string. Can save 2 if we can choose our padding character.

©ò3 ú'_3

Try it

©ò3 ú'_3     :Implicit input of string
©            :Logical AND with
 ò3          :Split into chunks of 3
    ú'_3     :Right pad each with "_" to length 3
\$\endgroup\$
2
\$\begingroup\$

Stax, 7 bytes

é☻εgP▀╪

Run and debug it

For an empty string input, the result is an empty array, which is a falsey value in stax.

\$\endgroup\$
2
\$\begingroup\$

CJam, 11 bytes

q'_3*+3/);p

Try it online!

For empty input this gives an empty string, which is falsy.

How it works

q     e# Read input as a string
'_    e# Push char '_'
3*    e# String formed by that char repeated 3 times
+     e# Concatenate to input string
3/    e# Split in groups of 3, the last of which may be shorter. Gives array of strings
);    e# Detach last string from the array and delete it
p     e# Print string representation of the array
\$\endgroup\$
0
2
\$\begingroup\$

Retina 0.8.2, 10 bytes

$
__
!`...

Try it online! Link includes test cases. Explanation:

$
__

Append two _s, in case the last group needs to be padded.

!`...

Match as many groups of three as possible, outputting the matches themselves rather than the count. (In Retina 1 this would be L instead of !.)

\$\endgroup\$
2
\$\begingroup\$

C (gcc), 67 bytes

i;f(char*_){for(;*_;puts(""))for(i=3;i--;)putchar(*_?*_++:95);_=0;}

Try it online!

Always returns a falsey value (0).

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Do you even need to return anything? \$\endgroup\$
    – ceilingcat
    May 20, 2019 at 14:11
  • \$\begingroup\$ 63 bytes \$\endgroup\$
    – jdt
    May 21, 2019 at 10:28
2
\$\begingroup\$

Ruby, 73 42 bytes

a=gets
a.length!=0?a.scan(/.{1,3}/).map{|s|(s+'_'*3)[0,3]}:'falsey value'

Edit: As falsey value looks like it's not required:

gets.scan(/.{1,3}/).map{|s|(s+'_'*3)[0,3]}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ The maximum padding is of 2 characters, so '_'*2 would be enough, for which a literal '__' is shorter. But if you add the padding in advance then simply not match the pieces shorter than 3 characters, is shorter: puts"#{gets}__".scan /.../. (Note that without the explicit printing that is considered irb not ruby.) \$\endgroup\$
    – manatwork
    May 20, 2019 at 15:06
  • 1
    \$\begingroup\$ 29 bytes (note: -2 bytes with _1 syntax and -2 if a different padding character is allowed) \$\endgroup\$ Jun 2, 2020 at 20:51
  • \$\begingroup\$ @AsoneTuhid - That's different enough to be posted as a separate answer! ;-) \$\endgroup\$
    – vrintle
    Dec 5, 2020 at 16:34
2
\$\begingroup\$

Wolfram Language (Mathematica), 28 21 bytes

-7: No longer requires falsy (False) value on empty input

Partition[#,3,1,1,_]&

Try it online!

Takes a list of characters as input. Returns a list of 3-tuples of characters padded with Blanks (_).


34 27 bytes

StringPartition[#<>"__",3]&

Try it online!

String input, list of strings output

\$\endgroup\$
1
\$\begingroup\$

Jelly, 9 bytes

s3o€“___”

A monadic Link accepting a list of characters which yields a list of lists of characters (an empty input yields empty output).

Try it online!

How?

s3o€“___” - Link: list of characters
s3        - split into chunks of three
   €      - for each chunk:
  o       -   OR (vectorises):
    “___” -     list of characters = ['_', '_', '_']

Notes:
The is only necessary to handle the edge case of an empty input.
A full program can drop a trailing , but here we can't do that as the printing behaviour of a full program smashes everything together.


Equivalent 9:

o3ÐƤ“___”

Try it


Alternative 9:

;“___”s3Ṗ

Try it

\$\endgroup\$
1
\$\begingroup\$

J, 16 bytes

[:}:_3]\'___',~]

Try it online!

K (oK), 19 17 bytes

-2 bytes thanks to ngn!

{-1_0N 3#x,"___"}

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ k: (0N;3) -> 0N 3 \$\endgroup\$
    – ngn
    May 20, 2019 at 7:21
1
\$\begingroup\$

Java 10, 116 113 bytes

s->{s+="__";int l=s.length()/3,i=l;var r=new String[l];for(;i-->0;)r[i]=s.substring(i*3,i*3+3);return l<1?0>1:r;}

Try it online.

Or 104 101 bytes if an empty array instead of false is allowed as output..

s->{s+="__";int l=s.length()/3;var r=new String[l];for(;l-->0;)r[l]=s.substring(l*3,l*3+3);return r;}

Try it online.

Explanation:

s->{                             // Method with String as both parameter and return-type
  s+="__";                       //  Append two "_" to the input-String
  int l=s.length()/3;            //  Get the length, integer-divided by 3
  var r=new String[l];           //  Create a string-array with that many parts
  for(;l-->0;)                   //  Loop `l` in the range (l, 0]:
    r[l]=                        //   Set the `l`'th value of the array to:
         s.substring(l*3,l*3+3); //   Get the substring of size 3 from index `l*3` from `s`
  return r;}                     //  Return the array
\$\endgroup\$
1
  • \$\begingroup\$ An empty array is now allowed \$\endgroup\$ May 26, 2019 at 3:57
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 74 bytes

Just append two underscores '_' at the end of the input to make sure they get printed if the length of the input isn't a factor of 3.

s=>Enumerable.Range(0,(s.Length+2)/3).Select(i=>(s+"__").Substring(i*3,3))

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ 67 \$\endgroup\$
    – dana
    May 22, 2019 at 5:20
  • \$\begingroup\$ 57 \$\endgroup\$ May 25, 2019 at 1:22
1
\$\begingroup\$

Kotlin, 34 bytes

{"${it}__".chunked(3).dropLast(1)}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ this does not work, try {"${it}___".chunked(3).dropLast(1)} \$\endgroup\$
    – pme
    May 21, 2019 at 6:45
1
\$\begingroup\$

C (gcc), 55 bytes

i;f(char*s){for(;i%4|*s;)putchar(++i%4?*s?*s++:95:10);}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Using 9(\t) instead of 10(\n) should be fine, but that's not main point \$\endgroup\$
    – l4m2
    May 20, 2019 at 15:23
1
\$\begingroup\$

Bash, 90 bytes

This uses Bash features rather than a combination of more traditional Bourne shell plus *nix commands (which one version I created ended up at 205 bytes). I cheated by using the dodge of adding two _ characters to the string.

c=;read a;a=${a}__;while (($(echo ${#a})>2));do b=${a:0:3};c=$c\ $b;a=${a#$b};done;echo $c

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 58 35 bytes

$args-split'(...)'-ne''|% *ht 3 '_'

-23 bytes thanks to mazzy.

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Nice. 1) You can count a code that can be extracted into a ps1-file and executed. 2) See shortcuts. 3) Try to golf more \$\endgroup\$
    – mazzy
    May 25, 2019 at 5:18
1
\$\begingroup\$

GNU sed, 27 bytes

s:$:__:
s:...:& :g
s: _*$::

Try it online!

It gets a bit tricky regarding the empty string input, since sed has no meaning of a falsy value. So to deal with this, I provide you with two possible interpretations of the rules to validate my submission:


A. You essentially provide nothing as input, not even a trailing newline (as it is the case with all the examples, including that 6 Mb file).

Usage:

echo -n ""|sed -f script

Output: nothing is printed, because sed doesn't even run the script without input.


B. One could consider as falsy value for sed to be an unique string, i.e., returned only when the input is an empty string.

Usage:

echo ""|sed -f script

Output:

__

I prefer the first interpretation so much more, as I believe it to be the closest to the intended rule, but the last one helps if you run the script using that TIO link.

\$\endgroup\$
1
\$\begingroup\$

APL(NARS), 30 chars, 60 bytes

{(3/⍳3÷⍨≢v)⊂v←⍵,'_'⍴⍨3∣3-3∣≢⍵}

test:

  f←{(3/⍳3÷⍨≢v)⊂v←⍵,'_'⍴⍨3∣3-3∣≢⍵}
  ⎕fmt f 'abcde'
┌2────────────┐
│┌3───┐ ┌3───┐│
││ abc│ │ de_││
│└────┘ └────┘2
└∊────────────┘
  ⎕fmt f '1234'
┌2────────────┐
│┌3───┐ ┌3───┐│
││ 123│ │ 4__││
│└────┘ └────┘2
└∊────────────┘
  ⎕fmt f ''
┌0──┐
│┌0┐│
││ ││
│└¯┘2
└∊──┘
  ⎕fmt f 'Three spree!'
┌4──────────────────────────┐
│┌3───┐ ┌3───┐ ┌3───┐ ┌3───┐│
││ Thr│ │ ee │ │ spr│ │ ee!││
│└────┘ └────┘ └────┘ └────┘2
└∊──────────────────────────┘
\$\endgroup\$
1
\$\begingroup\$

C (clang), 128 126 94 67 63 bytes

63 bytes thanks to @ceilingcat.

f(char*k){for(;*k;k++)printf("%c%c%c\n",*k,*++k?:95,*++k?:95);}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Jelly, 6 bytes

s3Zz”_

Try it online!

How it works

s3Zz”_ - Main link. Takes a string S on the left
s3     - Split into chunks of 3
  Z    - Transpose
   z”_ - Transpose, using "_" as a filler
\$\endgroup\$
1
\$\begingroup\$

Factor + grouping.extras, 27 bytes

[ 3 95 pad-groups 3 group ]

enter image description here

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 7 bytes

3ẇ∩\_ÞṪ

Try it Online!

How?

3ẇ∩\_ÞṪ
3ẇ      # Split into chunks of three
  ∩     # Transpose
   \_ÞṪ # Transpose with "_" as filler
\$\endgroup\$
1
\$\begingroup\$

Thunno 2, 5 bytes

³'_3Ŀ

Try it online!

³'_ƬṬ

Try it online!

Explanation

³'_3Ŀ  '# Implicit input
³       # Split into threes
    Ŀ   # Left-justify each,
 '_    '# padding with "_"s
   3    # to length 3
        # Implicit output
³'_ƬṬ  '# Implicit input
³       # Split into threes
   Ƭ    # Transpose with
 '_    '# filler "_"
    Ṭ   # Tranpose again
        # Implicit output
\$\endgroup\$
1
\$\begingroup\$

Haskell, 40 bytes

f(a:b:c:t)=[a,b,c]:f t
f _=[]
f.(++"__")
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.