[Question]
  [
> 
> Given a string, you've to split it into groups of three characters (by padding `_` at the end).
> 
> 
> [Related](https://codegolf.stackexchange.com/questions/77310/split-string-into-n-pieces-or-pieces-of-length-n), 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](https://www.dropbox.com/s/aruy7r9on8z4xst/ThreeSpreeText.txt?raw=1)
This is a [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so fewest bytes will win!
**Edit:** Finally, output is *unrestricted*.
  
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~9~~ 8 bytes
```
…___«3ô¨
```
[Try it online!](https://tio.run/##yy9OTMpM/f//UcOy@Pj4Q6uND285tOL/f0MjYxMA "05AB1E – Try It Online")
or as a [Test Suite](https://tio.run/##yy9OTMpM/W/i9v9Rw7L4@PhDq40Pbzm04r/O/8Sk5JRULkMjYxMuJTDgCskoSk1VKC4AkooA)
**Explanation**
```
…___«      # append "___" to input
     3ô    # split into groups of 3
       ¨   # discard the last group
```
[Answer]
# 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](https://tio.run/##K6gsycjPM/7/v6AoM69EIy@/RAGIo2M1//8HAA)) on empty input
```
lambda x:[*zip(*[iter(x+"__")]*3)]
```
[TIO](https://tio.run/##K6gsycjPM/6fZhvzPycxNyklUaHCKlqrKrNAQys6syS1SKNCWyk@XkkzVstYM/Z/QVFmXolGmoaSoZGxiamSpuZ/AA)
[Answer]
# JavaScript, 25 bytes
```
s=>`${s}__`.match(/.../g)
```
[Try it](https://tio.run/##y0osSyxOLsosKNFNSkxKzdHNy09J/Z9m@7/Y1i5Bpbq4Nj4@QS83sSQ5Q0NfT09PP13zf3J@XnF@TqpeTn66RnSCoZGxSYJOQkIsUFWBRpqm5n8A)
[Answer]
# 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](https://tio.run/##SyzI0U2pTMzJT9dNzkksLs5M/v@ob6qvz6O2CcZcjzra0/5rPOrp0HjUNvFR75ZizcPbjTWNgSyNYqACoEJNHfX4ePX/QIX/07jUDY2MTdS5gIzEpOSUVDArJKMoNVWhuABIKqoDAA "APL (Dyalog Classic) – Try It Online")
[Answer]
# [Perl 5](https://www.perl.org/), ~~16~~ 15 bytes
```
"@_\__"=~/.../g
```
[Try it online!](https://tio.run/##RY7BjsIgEIbvPMVImgCRra7bvdjQ9AW8eVsNWXVc2dS2KTXGGPfV62CtywGY7/9moMam@OxOHmGJvp3PF1WD0NLVmyxJ2fECeaiMZADie7PdoYDnMhl8BSQ0iB1asdbBeZ99JC@ldwgFJ7GD858PTs@XhwYRfE37SPS9hEIv4XBQ1FcjsWYqZeeDK1A@fqiuNOF4kZHTUaWMrwu3xUeip3qWUui8hN/KlVKMhd6TqFR4NawXzqmXahX8unFlCzxyAG8ZAIf46cEYhgHE@KrkKbsxf9rA/trx3K6s5eZvEsfx5Ke7dXc "Perl 5 – Try It Online")
[Answer]
# JavaScript, ~~51 50 48 27~~ 25
```
b=>(b+"__").match(/.../g)
```
[Try it online!](https://tio.run/##bcnLDkAwEEDRva@gqzZixGPLT7BvZmq8Uioqfr@sxeYuzl3xRm/O5bgyQmKb7W7gMDaBmlZSKrQWCja8zCxzAMgnFYzbvbMM1k1ylALJDCyUij5elFX9wz/Uzydz3B1vk3eHBw "JavaScript (Babel Node) – Try It Online")
[Answer]
# [Perl 6](https://github.com/nxadm/rakudo-pkg), 19 bytes
```
{$_~"__"~~m:g/.../}
```
[Try it online!](https://tio.run/##K0gtyjH7n1upoJamYPu/WiW@Tik@XqmuLtcqXV9PT0@/9r81V1p@kYJGTmZearGmQjWXgkJxYqWCnloaV@3/xKTklFQuQyNjEy6ukIyi1FSF4gIgqQgA "Perl 6 – 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.
[Answer]
# [Japt](https://github.com/ETHproductions/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](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=qfIzIPonXzM&input=IjEyMzQi)
```
©ò3 ú'_3     :Implicit input of string
©            :Logical AND with
 ò3          :Split into chunks of 3
    ú'_3     :Right pad each with "_" to length 3
```
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 7 [bytes](https://github.com/tomtheisen/stax/blob/master/docs/packed.md#packed-stax)
```
é☻εgP▀╪
```
[Run and debug it](https://staxlang.xyz/#p=8202ee6750dfd8&i=%22abcde%22%0A%221234%22%0A%22%22%0A%22Three+spree%21%22&a=1&m=2)
For an empty string input, the result is an empty array, which is a falsey value in stax.
[Answer]
# [CJam](https://sourceforge.net/p/cjam), 11 bytes
```
q'_3*+3/);p
```
[Try it online!](https://tio.run/##S85KzP3/v1A93lhL21hf07rg///EpOSUVAA "CJam – 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
```
[Answer]
# [Retina 0.8.2](https://github.com/m-ender/retina/wiki/The-Language/a950ad7d925ec9316e3e2fb2cf5d49fd15d23e3d), 10 bytes
```
$
__
!`...
```
[Try it online!](https://tio.run/##K0otycxL/K@q4Z7wX4UrPp5LMUFPT@///8Sk5JRULkMjYxMurpCMotRUheICIKkIAA "Retina 0.8.2 – 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 `!`.)
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 67 bytes
```
i;f(char*_){for(;*_;puts(""))for(i=3;i--;)putchar(*_?*_++:95);_=0;}
```
[Try it online!](https://tio.run/##JY3NDoIwEITvPMXaxKTlJ1HBg67El/CmpMFShBKRlHIifXZs4TKZnZl8K5KPEMvSYk1FU@qQs7n@aYohx2EyIyWEMR@0eYptkiBzqR/SkN9DHkXXy5khzw9ol2/Z9pTNAawgI0czPovc3UDKt6gkib09ntJsc5s@Gi0ljIPTHQnAYgDrv96Aclh1y1BFkceCzzrIoaYbXBXMrWHQrqgpoVqaSfcM9tWrJ3HnSxvY5Q8 "C (gcc) – Try It Online")
Always returns a falsey value (0).
[Answer]
# **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]}
```
[Answer]
# [Wolfram Language (Mathematica)](https://www.wolfram.com/wolframscript/), ~~28~~ 21 bytes
-7: No longer requires falsy (`False`) value on empty input
```
Partition[#,3,1,1,_]&
```
[Try it online!](https://tio.run/##y00syUjNTSzJTE78n2b7PyCxqCSzJDM/L1pZx1jHEAjjY9X@BxRl5pVEK@vapTk4ZyQWJSaXpBYVOyjHquk7VHMpJSYlp6Qq6XApGRoZm4BoEA7JKEpNVSguAJKKSly1/wE "Wolfram Language (Mathematica) – Try It Online")
Takes a list of characters as input. Returns a list of 3-tuples of characters padded with `Blank`s (`_`).
---
### ~~34~~ 27 bytes
```
StringPartition[#<>"__",3]&
```
[Try it online!](https://tio.run/##y00syUjNTSzJTE78n2b7P7ikKDMvPSCxqCSzJDM/L1rZxk4pPl5JxzhW7X8AUKokWlnXLs1BOVZN36GaSykxKTklVUmHS8nQyNgERINwSEZRaqpCcQGQVFTiqv0PAA "Wolfram Language (Mathematica) – Try It Online")
String input, list of strings output
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 9 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
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!](https://tio.run/##AS0A0v9qZWxsef//czNv4oKs4oCcX19f4oCd/8OHxZLhuZj//2FiY2RlZmdoaWprbG0 "Jelly – 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](https://tio.run/##AS0A0v9qZWxsef//bzPDkMak4oCcX19f4oCd/8OHxZLhuZj//2FiY2RlZmdoaWprbG0 "Jelly – Try It Online")
---
[Answer]
# [J](http://jsoftware.com/), 16 bytes
```
[:}:_3]\'___',~]
```
[Try it online!](https://tio.run/##y/qfVmyrp2CgYKVg8D/aqtYq3jg2Rj0@Pl5dpy72vyaXkp6CepqtnrqCjkKtlUJaMRdXanJGvkKagnpiUnJKqjqca2hkbILghWQUpaYqFBcASUWEqPp/AA "J – Try It Online")
# [K (oK)](https://github.com/JohnEarnest/ok), ~~19~~ 17 bytes
-2 bytes thanks to ngn!
```
{-1_0N 3#x,"___"}
```
[Try it online!](https://tio.run/##y9bNz/7/P82qWtcw3sBPwVi5QkcpPj5eqfZ/mrqGUmJSckqqkrWSoZGxCZACopCMotRUheICIKmopPkfAA "K (oK) – Try It Online")
[Answer]
# 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.](https://tio.run/##rVDNUoMwEL7zFCunpJVYxJMRHB/Aeqg3humEkLbBNDBJwOl0eHZMoXr0oped2Z/vb2vWs6iuPkaumLXwyqQ@BwBSO2F2jAtYX1qAt7IW3AFHG2ek3oPF1M@HwBfrmJMc1qAhhdFG2dku03C7DalnAZVaooTeuwPCd8mtTBXtmQGTavEJM1muCrprDKIyirIVxSaXhUfZrrTTHsmFBy6SZYKpEa4zGtRT/LzK4kdDh5FeTLRdqbyJq5e@kRUcfZar3bwAhucgm5N14kiazpHWr5zSqPY/IJ2TirwYw06WuGaGoR841oSjkJW8EiHGU/a/UcX3ycOvTNNV@B9S7wcjBNjW15tvySEYxi8)
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.](https://tio.run/##pU9JbsMwDLz7FaxPUlOri3sTHKAPaC7trQgCWVYSuYpskJKLIPDbXWXrA5oDCZKDmeG0alBF23xP2ikieFfWHzIA64PBtdIGFscV4COg9ZuvJWh2HoG4TMiYpUZBBathAR4qmKiYH2hW5atVLpMOuIqEM34Ttow/lnJQCFh583PVdEu57pBJVxTzJ8kxHRKDYk0nnLn78iHVrOQSTYjoAeU4yaNxH2uXjC/@Q2cb2KUE7O9bxS/v7ymYnehiEH2CgvOsTclFDNaJN0S1JxG6M415oVmuat2YnPNTyv8IPL@Ur7fwb@F@btEYoD71u6vOmI3TLw)
**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
```
[Answer]
## [C# (Visual C# Interactive Compiler)](https://www.mono-project.com/docs/about-mono/releases/5.0.0/#csc), 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!](https://tio.run/##jcxBC4JAEAXgu79i29NsmpV2M/emEHgqoaPoNuqCbbG7gv/epARv4RwezHvwCbMTRo5pr8TZWC1V410S1T9Rl1WHc8U5qUk8mpgvk38tVYNw8MD4GarGtm7A9iHzb9ihsCBjDsalRUGnqq9@EMht6IWMjZFTAy0r8cBpzl@ZNBaYn750UooWBhJzctfSYiYVwsBY5Cwv3c1H2Zc5BuFppUL@MHmrEYl5T7lZyY0f)
[Answer]
# [Kotlin](https://kotlinlang.org), 34 bytes
```
{"${it}__".chunked(3).dropLast(1)}
```
[Try it online!](https://tio.run/##JcuxDsIgEIDhvU9xIQ53g02MW6P1Bdh8gIYU0EvxSih1ITw7NvHfvuFf1hxY2tcE8APgMyeWF8F5BM1bvv09wr0VdSqc6zSpfn7vsjiLV@ptWqM2W8YL1eZ3gY9hQYLSwVE85hwEPSZnrGZxSI9BKaKuQnOR5x8 "Kotlin – Try It Online")
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 55 bytes
```
i;f(char*s){for(;i%4|*s;)putchar(++i%4?*s?*s++:95:10);}
```
[Try it online!](https://tio.run/##JU3LDoIwELzzFWsTkpZiAooHqcSf8KYcsLTyiJW05YR8e20l2UxmZ3Zm@f7FuXM9k5h3jU4MWeRHY9bHxTcxjEyzDTqm1CvXxPihtDyfyjwjbHXvpleYLBH8w1YYa@515XdAzZO3AqWB5odjsbENb50WAszkcYciWFkE4WmvLAxVxoZLwQZKQy0EbYQKJN7Kh5r4a5i0NyRGWAs7a0Ugbh8KpWMw12h1Pw "C (gcc) – Try It Online")
[Answer]
# [Bash](https://www.gnu.org/software/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!](https://tio.run/##JcuxCoQwDADQXwmYod1EN0P9EkGSNFpFTrgbHKTf3lO6vyf8S6VooK9xBCYOeHOeZ7rSdhg4h840nYB3w9mPnfcUT5BXDe3QZ9KAOgFKnQ1KfsDHqC4thUWjLWva9j8 "Bash – Try It Online")
[Answer]
# [PowerShell](https://docs.microsoft.com/en-us/powershell/), ~~58~~ 35 bytes
```
$args-split'(...)'-ne''|% *ht 3 '_'
```
-23 bytes thanks to [mazzy](https://codegolf.stackexchange.com/users/80745/mazzy).
[Try it online!](https://tio.run/##NY7BDoIwDIbve4pKimVmkCicTHgL7wRkiskCc8NoAjw7FtAe1v7f1yy13Vs732hjZqwgh2HG0t197K159BQlSSIpbjXRGMKh6SEFKmiehMDu5nNSJCIqq2utScEyqFoXJBXT4ynNFshdZcUPMsD2Zcy2seq/ujROa/CW390iOCsGiolakIQRwkEAF1r@5sPXYrFlx/Oe70e75gAj1rF@spFnwMFNgZjmLw)
[Answer]
## [GNU sed](https://www.gnu.org/software/sed/), 27 bytes
```
s:$:__:
s:...:& :g
s: _*$::
```
[Try it online!](https://tio.run/##K05N0U3PK/3/v9hKxSo@3oqr2EpPT89KTcEqHchUiNdSsbL6/7@SKz@by9HJmcvQyNiEKzEpOSWVKySjKDVVobgASCoCAA)
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.
[Answer]
# 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
└∊──────────────────────────┘
```
[Answer]
# [C (clang)](http://clang.llvm.org/), 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!](https://tio.run/##S9ZNzknMS///P00jOSOxSCtbszotv0jDWivbOltbW7OgKDOvJE1DSTUZBGPylHS0snW0tLWz7a0sTeEMTeva/7mJmXkaiTplmmBjtMqsq7kUgACoNzEpOSVVSdNaQV9foSS1uEQhObE4lav2PwA "C (clang) – Try It Online")
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 6 bytes
```
s3Zz”_
```
[Try it online!](https://tio.run/##y0rNyan8/7/YOKrqUcPc@P@H27X1HzWtOTrp4c4ZmpH//yslJiWnpCrpKCgZGhmbgGgQDskoSk1VKC4AkopKAA "Jelly – 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
```
[Answer]
# [Factor](https://factorcode.org/) + `grouping.extras`, 27 bytes
```
[ 3 95 pad-groups 3 group ]
```
[![enter image description here](https://i.stack.imgur.com/ZVtEZ.gif)](https://i.stack.imgur.com/ZVtEZ.gif)
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 7 bytes
```
3ẇ∩\_ÞṪ
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCIz4bqH4oipXFxfw57huaoiLCIiLCJUaHJlZSBzcHJlZSEiXQ==)
## How?
```
3ẇ∩\_ÞṪ
3ẇ      # Split into chunks of three
  ∩     # Transpose
   \_ÞṪ # Transpose with "_" as filler
```
[Answer]
# [Thunno 2](https://github.com/Thunno/Thunno2), 5 [bytes](https://github.com/Thunno/Thunno2/blob/main/docs/codepage.md)
```
³'_3Ŀ
```
[Try it online!](https://Not-Thonnu.github.io/run#aGVhZGVyPSZjb2RlPSVDMiVCMydfMyVDNCVCRiZmb290ZXI9JmlucHV0PWFiY2RlJmZsYWdzPQ==)
```
³'_ƬṬ
```
[Try it online!](https://Not-Thonnu.github.io/run#aGVhZGVyPSZjb2RlPSVDMiVCMyUyMCdfJTIwdHJhbnNwb3NlX3dpdGhfZmlsbGVyJTIwdHJhbnNwb3NlJmZvb3Rlcj0maW5wdXQ9YWJjZGUmZmxhZ3M9dg==)
#### 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
```
[Answer]
# [Haskell](https://haskell.org/), 40 bytes
```
f(a:b:c:t)=[a,b,c]:f t
f _=[]
f.(++"__")
```
]