Split string into n pieces (or pieces of length n)

11

1

The Challenge

In this challenge you have to do two different (but related) tasks depending of the order of the input.
Your program will recieve a string s and an integer n as input and will

  • split s into pieces of length n if s comes first. The last element will be shorter if necessary.
  • split s into n pieces of equal length if n comes first. If len(s) is not a multiple of n the first len(s) mod n elements will be one longer.

You may only take those 2 inputs. s will never contain only digits.

Notes

  • You may use the reverse mapping. Note this in your answer if you do that.
  • s will only contain printable ASCII characters (no newlines).
  • You may not use any builtins that solve either those two tasks directly. All other builtins are allowed.
  • You have to take both arguments from the same source.
  • You may take the arguments in an ordered list or any other format which clearly indicates their order as long as it is unambiguous.
  • You may take the input as one string/ stream and use a character which is not a valid input (like a nullbyte) to separate them.
  • n will always be equal or less than the length of s and greater than zero.
  • You may output the resulting list in any resonable format as long as it clearly indicates the particular pieces and their order.

Example

Input: programming, 3
The last element contains only 2 characters, because 11 is not divisible by 3.
Output: ["pro", "gra", "mmi", "ng"]

Input: 3, programming
11 is not a multiple of 3, so the first 2 elements will be one longer:
Output: ["prog", "ramm", "ing"]

Rules

Test cases

The test cases got generated with this Pyth program (uses builtins, so no valid answer). Thanks to @FryAmTheEggman for providing the base version of that!

3, helloworld -> ['hell', 'owo', 'rld']
helloworld, 3 -> ['hel', 'low', 'orl', 'd']
1, programming -> ['programming']
programming, 1 -> ['p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g']
8, programming -> ['pr', 'og', 'ra', 'm', 'm', 'i', 'n', 'g']
programming, 8 -> ['programm', 'ing']
9, code golf -> ['c', 'o', 'd', 'e', ' ', 'g', 'o', 'l', 'f']
code golf, 9 -> ['code golf']
4, 133tspeak -> ['133', 'ts', 'pe', 'ak']
133tspeak, 4 -> ['133t', 'spea', 'k']

Happy Coding!

Denker

Posted 2016-04-07T15:51:57.763

Reputation: 6 639

You may not use any builtins that solve those two tasks. Does that include other built-ins, such get every n-th character from a string or split at occurrences? – Dennis – 2016-04-07T16:54:13.930

@Dennis This was just meant to rule out builtins that solve this directly. I clarified. – Denker – 2016-04-07T16:55:58.643

If our language does not support arrays, how should we output? Would a newline between each result of the string be acceptable? – Conor O'Brien – 2016-04-08T03:50:22.967

Also, for languages where the input is an array of ambiguous numbers, what should the procedure be? – Conor O'Brien – 2016-04-08T03:54:58.850

@CᴏɴᴏʀO'Bʀɪᴇɴ Can't happen. s will never contain only digits. Also You may output the resulting list in any resonable format as long as it clearly indicates the particular pieces and their order which includes multiline output of course. – Denker – 2016-04-08T04:39:52.293

@DenkerAffe Let me clarify. The input to the program 65, "Hello!" would be read by the program as 65,72,101,108,108,111,33, so it cannot disambiguate which is the string and which isn't. To compensate, could one take a number that represents the order of the arguments? So the input could be 1 <n> <s> or 0 <s> <n>. Secondly, you say the input can have printable ASCII characters, including newlines, which would make my output ambiguous as well. – Conor O'Brien – 2016-04-08T04:42:50.517

@CᴏɴᴏʀO'Bʀɪᴇɴ I don't count newlines as printable ASCII, so thats one problem solved. However, taking a number which indicates the input order would be a huge advantage, so I can't really allow that, sorry.

– Denker – 2016-04-08T04:55:13.747

Let us continue this discussion in chat.

– Conor O'Brien – 2016-04-08T04:55:30.883

I assume the answer is no, but can builtins that solve one task be used to solve the other? – Unrelated String – 2019-05-19T23:33:40.537

Answers

3

MATL, 46 26 21 27 29 42 bytes

jtU?jtbUe!tn2Gn>?0t(]tgbw(}ie]!2t$X{Oc''Zt

Try it Online! (Updated slightly to work with the latest version of the language)

Explanation

j           % Explicitly grab the first input as a string
t           % Duplicate
U           % Attempt to convert it to a number
?           % If the conversion to a number was successful
    j       % Explicitly grab the second input as a string
    t       % Duplicate the value
    b       % Bubble-up the first element in the stack
    U       % Convert to a number from a string
    e       % Reshape the string into a nGroup x nPerGroup matrix
    !       % Take the transpose
    t       % Duplicate the result
    n       % Number of characters in the repmat result
    2Gn     % Number of characters in the string
    >?      % If chars in repmat > chars in string
        O   % Zero
        t   % Duplicate 
        (   % Assign the last element to a null character (bug in MATL)
    ]       % End if statement
    t       % Duplicate this matrix
    g       % Convert to a logical matrix
    b       % Bubble-up the original string
    w       % Flip the top two elements
    (       % Assign the non-empty characters to the chars from the input string
}           % Else the string comes first
    i       % Explicitly grab the second input (the number)
    e       % Reshape the characters into an nPerGroup x nGroup 2D array
]           % End of if statement
!           % Take the transpose so it reads left-to-right
2           % Number literal
t           % Duplicate
$X{         % Call num2cell to convert to a cell array
Oc          % Null character
''          % Empty string
Zt          % Replace null chars with empty strings
            % Implicit display of stack contents

Suever

Posted 2016-04-07T15:51:57.763

Reputation: 10 257

What are those unprintables that appear at the end of some list elements? Those are not part of the input and should therefore not be part of the output either. – Denker – 2016-04-08T07:17:22.523

Isn't e a prohibited builtin ? – FliiFe – 2016-04-08T09:11:01.417

Maybe replace XUZN?... by U?... and swap the two if branches. Also, you don't need the 3$ – Luis Mendo – 2016-04-08T09:22:07.230

@DenkerAffe Sorry about that. Should be fixed now. – Suever – 2016-04-08T12:30:42.930

@FliiFe Based on the comments on the initial post, e doesn't directly solve the problem, so I don't consider it to be prohibited, no. – Suever – 2016-04-08T12:31:22.087

@LuisMendo Thanks! I had that at one iteration or another but it must have gotten lost. – Suever – 2016-04-08T12:31:54.480

@Suever Are you sure? I still see them in the online interpreter. – Denker – 2016-04-08T12:48:49.163

@DenkerAffe Thanks to you we found a bug in MATL! Also, apparently null characters are displayed differently across browsers. It is now fixed! – Suever – 2016-04-10T17:32:03.300

4

JavaScript (ES6), 132 bytes

(s,t)=>+t?[...Array(-~(~-s.length/+t))].map((_,i)=>s.substr(i*t,t)):[...Array(s=+s)].map(_=>t.slice(p,p-=~((t.length-p-1)/s--)),p=0)

This is probably hopelessly over-engineered.

Neil

Posted 2016-04-07T15:51:57.763

Reputation: 95 035

Well, my (now deceased) solution was grossly under-engineered. +1 for you – edc65 – 2016-04-08T22:40:03.153

4

JavaScript (Firefox), 88 87 bytes

a=>b=>(s=+b?a:b,i=x=0,l=s.length,[for(c of s)if(r=s.slice(x,x+=+b||l/a+(i++<l%a)|0))r])

Call it like (...)("programming")(3) using Firefox 30+.

user81655

Posted 2016-04-07T15:51:57.763

Reputation: 10 181

2

AWK, 121 130 128 122 Bytes

$1~/^[0-9]+$/{s=1}{a=$(s+1)
b=s?$1:$2
$0=""
for(j=-b;j<=c=length(a);)$0=$0 substr(a,j+=b+s,b+(s=s&&j<c%b*(b+1)?1:0))" "}1

The only issue is if the first entry is a string that starts with a numeric value. This would cause AWK to see the string as that number and the second entry as the string.

OK... fixed the numeric issue, but it added 9 bytes :(.

Reworked a bit to save a couple bytes.

Almost back to the original length. :)

Robert Benson

Posted 2016-04-07T15:51:57.763

Reputation: 1 339

OK, @DenkerAffe , fixed it to work in general and only (eventually) added 1 byte. – Robert Benson – 2016-04-08T13:53:58.743

2

Ruby, 119 bytes

->x,y{r=[t=0];x.to_s==x ?(r.push x[t...t+=y]while x[t]):x.times{r.push y[t...t+=y.size/x+(r[y.size%x]? 0:1)]};r[1..-1]}

And I take first place by 2 bytes...

MegaTom

Posted 2016-04-07T15:51:57.763

Reputation: 3 787

Regex objects in Ruby can have values injected into them the same way strings can, so x.scan(/.{,#{y}}) works just as well for splitting the strings in the first case. Or does that count as a builtin? – Value Ink – 2016-04-08T06:11:02.493

1

Haskell, 131 bytes

import Data.Lists
q(d,m)=splitPlaces$(d+1<$[1..m])++[d,d..]
a#b|all(`elem`['0'..'9'])a=q(divMod(length b)$read a)b|1<2=q(read b,0)a

Usage example:

*Main> "8" # "programming"
["pr","og","ra","m","m","i","n","g"]
*Main> "programming" # "8"
["programm","ing"]

How it works: the main work is done by the helper function q which takes a pair of numbers (d,m) and a string s. It first builds a list of m times d+1 followed by infinite many d (e.g (1,3) -> [2,2,2,1,1,1,1,1,...]). It then uses splitPlaces to split s into chunks of lengths given by the list. splitPlaces stops if s runs out of elements, so an infinite list is fine.

The main function # checks which parameter is the number n / string str and calls q with either (div (length str) n, mod (length str) n) or (n, 0) plus str.

nimi

Posted 2016-04-07T15:51:57.763

Reputation: 34 639

0

PHP, 114 bytes

[$t,$n,$p]=$argv;for(@+$p?$s=$n:$f=$n*($p=strlen($s=$p)/$n)%$n;$t;)echo$t=substr($s,$a+=$e,$e=$p+($i++<$f)|0),"
";
  • String should not start with digits.
    (Replace +@$p with is_numeric($p) to fix.)
  • Output should not contain a chunk "0".
    (Insert ~ for printable ASCII, a& for any ASCII before $t; to fix.)
  • Run with -nr or try it online.

Titus

Posted 2016-04-07T15:51:57.763

Reputation: 13 814

0

PowerShell, 122 118 bytes

param($a,$b)if($a-is[int]){$a,$b=$b,((($l=$b|% Le*)-($c=$l%$a))/$a)}$a-split("(..{$b})"*$c+"(.{0,$b})"*$a.Length)-ne''

Try it online!

Less golfed:

param($a,$b)
if($a-is[int]){
    $length=$b|% Length
    $c=$length%$a
    $a,$b=$b,(($length-$c)/$a)  # recalc length and swap
}
$pattern="(..{$b})"*$c+"(.{0,$b})"*$a.Length
$parts=$a -split $pattern       # pattern like '(..{3})(..{3})(.{0,3})(.{0,3})(.{0,3})'
$parts -ne ''                   # output not empty parts

mazzy

Posted 2016-04-07T15:51:57.763

Reputation: 4 832

0

Pyth, 181 bytes

Let's pretend the longest code in bytes wins \o/

DyGK@G0J:@G1"."1=YJV%lJKW<l@YN.EclJK=YXYN+@YN@YhN=Y.DYhN)FNr%lJK/-lJ%lJK/-lJ%lJKKW<l@YNsclJK=YXYN+@YN@YhN=Y.DYhN))RY)DPG=K@G1=J:@G0"."1=YJV/lJKW<l@YNK=YXYN+@YN@YhN=Y.DYhN))RY).xyQPQ

Try it here ! (The online interpreter seem to have a bug, it displays the input while it should not)

Here's the output from the terminal:

» pyth split.pyth <<<'["helloworld", 3]' 
['hel', 'low', 'orl', 'd']
» pyth split.pyth <<<'[3, "Helloworld"]'
['Hell', 'owo', 'rld']

Seriously, I am open to new approach. I'm new to python, so I probably missed a few shorthands.

I mean, I think my answer is deseperate from the point it is longer than the javascript answer...

FliiFe

Posted 2016-04-07T15:51:57.763

Reputation: 543

Can you provide a sample input and output? – Leaky Nun – 2016-04-08T01:22:01.317

Note the official solution under the header testcases. The testcases are generated by Pyth. The solution is .xcsJKcJsK, where J and K are the two arguments. – Leaky Nun – 2016-04-08T01:24:11.913

@KennyLau I added a link to the online pyth interpreter. Strangely, it outputs the input too while I'm sure it did not yesterday... Will try to fix that. – FliiFe – 2016-04-08T08:53:36.687

use spaces to suppress printing – Leaky Nun – 2016-04-08T09:41:14.777

@KennyLau spaces where ? – FliiFe – 2016-04-08T09:44:12.803

"J" would print while " J" would not. Spaces before the expression. – Leaky Nun – 2016-04-08T09:49:21.087

@KennyLau The problem is to figure out the expression that prints. It works on my computer without additional printing – FliiFe – 2016-04-08T09:51:49.450

Do you have debug mode? You can see which expression prints in debug mode. – Leaky Nun – 2016-04-08T23:01:45.243

@KennyLau Now it works (without modification). I really think it was a bug with the online interpreter. – FliiFe – 2016-04-09T12:59:47.477

0

C# (LINQPAD) - 335 bytes

var y=Util.ReadLine().Split(',');int x,j=0;var t=int.TryParse(y[0].Trim(),out x);x=x==0?int.Parse(y[1].Trim()):x;var i=t?y[1].Trim():y[0];var z="";if(!t){while(i.Substring(j).Length>x){z+=i.Substring(j).Length>x?i.Substring(j,x)+", ":"";j+=x;}z+=i.Substring(j);}else z=string.Join(", ",i.Split(x).Select(s=>string.Concat(s)));z.Dump();

The input reading part took up a bit of space. Winner of longest answer.

Usage #1:

$ 3, helloworld

>> hell, owo, rld

Usage #2:

$ helloworld, 3

>>hel, low, orl, d

jzm

Posted 2016-04-07T15:51:57.763

Reputation: 369

owo what's this? – Benjamin Urquhart – 2019-05-19T12:41:11.607