Split into three!

16

3

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.

Rahul Verma

Posted 2019-05-19T12:09:09.797

Reputation: 621

10Why special case the empty string? May we choose which character to use for the padding? – Shaggy – 2019-05-19T14:49:57.557

Is null considered a falsey value? – Luis felipe De jesus Munoz – 2019-05-19T14:58:58.147

2@LuisfelipeDejesusMunoz, falsey values are defined by the language, not the challenge author. – Shaggy – 2019-05-19T15:00:38.160

12So the task is actually: Given a string, return a falsey value if it is empty, otherwise split it into groups of three, padding with underscores if necessary? Seems like an odd pair-up of two unrelated tasks (checking string length and splitting). – Adám – 2019-05-19T15:27:44.410

15Things to avoid: Exceptional edge cases. In this case, an empty string should returnan empty array or equivalent, not a falsey value – Jo King – 2019-05-19T22:05:25.930

6Lots of statically-typed languages cannot return more than one type from a function – Embodiment of Ignorance – 2019-05-19T23:30:03.253

@JoKing But in Python (and likely many other languages), an empty array is Falsey, so this is not necessarily a complication at all. – manassehkatz-Moving 2 Codidact – 2019-05-20T16:33:07.160

4@manassehkatz Yes, but only in those languages. In some languages it makes solutions far more complicated, or even impossible (e.g statically typed languages). – Jo King – 2019-05-20T22:01:57.927

@JoKing In Java a return type of Object works, in C void * (or another pointer type), etc. – Jakob – 2019-05-25T04:14:49.620

1@JoKing, as I understand I have to return either empty array or falsy value, so there is no special edge case. – Qwertiy – 2019-05-25T21:53:46.690

@Qwertiy That has since been edited in – Jo King – 2019-05-26T04:12:04.627

Answers

9

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

Emigna

Posted 2019-05-19T12:09:09.797

Reputation: 50 798

8

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

Benjamin Urquhart

Posted 2019-05-19T12:09:09.797

Reputation: 1 262

6

JavaScript, 25 bytes

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

Try it

Shaggy

Posted 2019-05-19T12:09:09.797

Reputation: 24 623

5

Perl 5, 16 15 bytes

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

Try it online!

Kjetil S.

Posted 2019-05-19T12:09:09.797

Reputation: 1 049

115 with "@_\__"=~/.../g. There were other 16s: (pop.__)=~/.../g or map/.../g,pop.__. – Grimmy – 2019-05-20T11:50:27.020

1Thx to @Grimy for the tip on . It shaved off 1 byte and I learned something new. – Kjetil S. – 2019-05-20T13:30:35.240

4

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

Graham

Posted 2019-05-19T12:09:09.797

Reputation: 3 184

@Adám. Throws a domain error in APL+WIN at the right most ⍴ – Graham – 2019-05-19T13:45:38.847

Fails on '', no? I think OP (for some strange reason) requires the result to be 0 (with any rank). – Adám – 2019-05-19T15:47:32.453

1@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. – Graham – 2019-05-19T16:12:51.693

4

JavaScript, 51 50 48 27 25

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

Try it online!

VFDan

Posted 2019-05-19T12:09:09.797

Reputation: 173

Welcome to PPCG! :) But ... https://codegolf.stackexchange.com/a/185808/58974

– Shaggy – 2019-05-24T16:51:27.537

@Shaggy I didn't even see that ¯\(ツ) – VFDan – 2019-05-24T17:21:29.053

No worries, it happens. – Shaggy – 2019-05-24T17:24:51.913

3

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.

Jo King

Posted 2019-05-19T12:09:09.797

Reputation: 38 234

3

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

Shaggy

Posted 2019-05-19T12:09:09.797

Reputation: 24 623

2

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.

recursive

Posted 2019-05-19T12:09:09.797

Reputation: 8 616

2

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

Luis Mendo

Posted 2019-05-19T12:09:09.797

Reputation: 87 464

2

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 !.)

Neil

Posted 2019-05-19T12:09:09.797

Reputation: 95 035

2

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

attinat

Posted 2019-05-19T12:09:09.797

Reputation: 3 495

2

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

attinat

Posted 2019-05-19T12:09:09.797

Reputation: 3 495

1Do you even need to return anything? – ceilingcat – 2019-05-20T14:11:10.663

63 bytes – Johan du Toit – 2019-05-21T10:28:22.463

1

C (clang), 128 126 94 67 bytes

67 bytes thanks to @ceilingcat

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

Try it online!

a stone arachnid

Posted 2019-05-19T12:09:09.797

Reputation: 1 053

1

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

Jonathan Allan

Posted 2019-05-19T12:09:09.797

Reputation: 67 804

1

J, 16 bytes

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

Try it online!

K (oK), 19 17 bytes

-2 bytes thanks to ngn!

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

Try it online!

Galen Ivanov

Posted 2019-05-19T12:09:09.797

Reputation: 13 815

1k: (0N;3) -> 0N 3 – ngn – 2019-05-20T07:21:04.970

@ngn Thank you! – Galen Ivanov – 2019-05-20T07:28:22.243

1

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

Kevin Cruijssen

Posted 2019-05-19T12:09:09.797

Reputation: 67 575

An empty array is now allowed – Benjamin Urquhart – 2019-05-26T03:57:40.513

1

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]}

Max Langerak

Posted 2019-05-19T12:09:09.797

Reputation: 111

1The 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.) – manatwork – 2019-05-20T15:06:03.067

1

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!

Innat3

Posted 2019-05-19T12:09:09.797

Reputation: 791

67 – dana – 2019-05-22T05:20:20.840

57 – my pronoun is monicareinstate – 2019-05-25T01:22:13.330

1

Kotlin, 34 bytes

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

Try it online!

snail_

Posted 2019-05-19T12:09:09.797

Reputation: 1 982

this does not work, try {"${it}___".chunked(3).dropLast(1)} – pme – 2019-05-21T06:45:32.040

1

C (gcc), 55 bytes

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

Try it online!

l4m2

Posted 2019-05-19T12:09:09.797

Reputation: 5 985

Using 9(\t) instead of 10(\n) should be fine, but that's not main point – l4m2 – 2019-05-20T15:23:55.367

1

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!

PJF

Posted 2019-05-19T12:09:09.797

Reputation: 71

1

PowerShell, 58 35 bytes

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

-23 bytes thanks to mazzy.

Try it online!

Andrei Odegov

Posted 2019-05-19T12:09:09.797

Reputation: 939

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

– mazzy – 2019-05-25T05:18:42.220

1

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.

seshoumara

Posted 2019-05-19T12:09:09.797

Reputation: 2 878

0

JavaScript (Babel Node), 45 bytes

_=>_.match(/.{1,3}/g).map(a=>a.padEnd(3,`_`))

Try it online!

Luis felipe De jesus Munoz

Posted 2019-05-19T12:09:09.797

Reputation: 9 639

44 – Shaggy – 2019-05-19T15:13:37.863

Doesn't work for me – VFDan – 2019-05-22T21:55:38.327

0

Jelly, 10 bytes

s3;€⁾__ḣ€3

Try it online!

It feels like an 8 or 9 should be possible, but haven’t found one yet.

Nick Kennedy

Posted 2019-05-19T12:09:09.797

Reputation: 11 829

0

Pyth, 10 9 bytes

Pc+z*3\_3

Try it online!

-1 from u_ndefined.

Is it ok if it throws an error on empty input? (does that count as falsey)

uanirudhx

Posted 2019-05-19T12:09:09.797

Reputation: 11

It works on TIO, but not on Pyth compiler/executor. Is there a reason? (i.e. Pyth compiler/executor is outdated?) – uanirudhx – 2019-05-19T19:45:13.347

-1 byte – u_ndefined – 2019-05-21T13:27:48.300

0

Attache, 34 23 bytes

PadRight&"_"&3=>@Chop&3

Try it online!

Explanation (outdated)

{On[#_-1,PadRight&"_"&3,_]}@Chop&3
                           @Chop&3    chop the input string into groups of 3s
{On[#_-1               ,_]}           on the last group
        ,PadRight                         pad it
                     &3                   to length three
                 &"_"                     with underscores

Conor O'Brien

Posted 2019-05-19T12:09:09.797

Reputation: 36 228

Would you save anything by padding all the elements instead of just the last one? – Shaggy – 2019-05-19T20:18:44.527

@Shaggy Good point! I’ll look into it – Conor O'Brien – 2019-05-19T20:19:20.507

0

Charcoal, 10 bytes

E⪪S³…⁺ι__³

Try it online! Link is to verbose version of code. Explanation:

  S         Input string
 ⪪ ³        Split into groups of up to 3 characters
E           Map over each group
      ι     Current group
     ⁺      Concatenated with
       __   Literal `__`
    …    ³  Moulded to length 3
            Each group implicitly printed on its own line

Neil

Posted 2019-05-19T12:09:09.797

Reputation: 95 035

0

Scala, 31 bytes

(s+"___").grouped(3).toSeq.init

Try it online!

Explanation

(s+"___")       // add "___"
  .grouped(3)   // make groups of 3
  .toSeq        // change to Seq
  .init         // take all but last

pme

Posted 2019-05-19T12:09:09.797

Reputation: 111

0

Befunge-93, 30 29 bytes

~:1+%,~:1+!"`"*+,~:1+!"`"*+,,

Try it online!

Outputs nothing for an empty input, otherwise outputs strings of length 3 separated by NUL characters.

Explanation:

~                               Push character of input to stack
 :1+                            Duplicate input and add 1
    %                           Modulo top 2 values of stack and push result
                                If input was -1 (end of stream), calculate -1%0 -> halt
                                Otherwise calculate input%(input+1) -> input
     ,                          Pop and output character
      ~                         Push character of input to stack
       :1+!                     Duplicate input, add 1 and perform logical NOT
           "`"*                 Multiply by 96 (ASCII code for '`')
                                This returns 96 or 0 depending on the result of the NOT
               +                Add the top 2 values from the stack and push the result
                                If the input was -1 (end of stream), pushes -1+96=95, or the ASCII code for '_'
                                Otherwise pushes input+0
                ,               Pop and output character
                 ~:1+!"`"*+,    Same block again to handle the third character
                            ,   Output a NUL character (stack is empty, so popping from stack just returns 0)

The instruction pointer wraps around at the end, looping the entire line.

negative seven

Posted 2019-05-19T12:09:09.797

Reputation: 1 931

0

Haskell, 62 61 59 bytes

z(a:b:c:d)=[a,b,c]:z d
f s=takeWhile(/="___")$z$s++cycle"_"

Infinite lists and strings!

Try it online!

Leo Tenenbaum

Posted 2019-05-19T12:09:09.797

Reputation: 2 655

0

Rust, 93 bytes

Works for ASCII input strings. Empties the input string and returns a Vec<String>.

|mut s:String|{s+="__";let mut v=vec![];while s.len()>2{let t=s.split_off(3);v.push(s);s=t}v}

Try It Online

Jakob

Posted 2019-05-19T12:09:09.797

Reputation: 2 428

0

GoLang, 84 bytes

func(x string)[]string{return regexp.MustCompile("...").FindAllString(x+"__",-1)}(s)

Try it !

salixor

Posted 2019-05-19T12:09:09.797

Reputation: 1

0

SNOBOL4 (CSNOBOL4), 93 bytes

	S =INPUT
	S =S DUPL('_',REMDR(3 - REMDR(SIZE(S),3),3))
R	S LEN(3) . OUTPUT REM . S	:S(R)
END

Try it online!

SNOBOL has a size limit on the length of its input (1023 bytes).

Giuseppe

Posted 2019-05-19T12:09:09.797

Reputation: 21 077

0

Julia 1.0, 40 bytes

s->[(s*"__")[i:i+3] for i=1:3:length(s)]

Try it online!

gggg

Posted 2019-05-19T12:09:09.797

Reputation: 1 715

137 bytes – H.PWiz – 2019-06-03T19:53:18.600

0

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
└∊──────────────────────────┘

RosLuP

Posted 2019-05-19T12:09:09.797

Reputation: 3 036