13
\$\begingroup\$

Let's say I have a non-empty list (array):

l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

I want to incrementally slice the list into incremented amount of elements per chunk.

For this array, my desired output is:

[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]

What would be the best way to slice the array in multiple chunks.

This is , so shortest code in bytes wins!

Note: For the final chunk, if the number of elements left in r is less than what the incremented output requires, the last chunk should just be all that remains in the list.

Test cases:

l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
-> [[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]

l = [10, 20, 30, 40]
-> [[10], [20, 30], [40]]

l = [100, 200, 300, 400, 500]
-> [[100], [200, 300], [400, 500]]
\$\endgroup\$
1
  • 7
    \$\begingroup\$ I suggest adding a test case with repeated elements (or specifying that cannot happen in the input) \$\endgroup\$
    – Luis Mendo
    Dec 27, 2021 at 15:49

24 Answers 24

8
\$\begingroup\$

Python, 40 bytes

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

Attempt This Online!

\$\endgroup\$
0
7
\$\begingroup\$

Husk, 3 2 bytes

Edit: -1 byte thanks to Razetime

CN

Try it online!

C       # Cut off substrings of the following lengths:
 N      # natural numbers
\$\endgroup\$
6
  • 1
    \$\begingroup\$ CN should work \$\endgroup\$
    – Razetime
    Dec 27, 2021 at 14:07
  • \$\begingroup\$ @Razetime - Oh, yeah, of course. Doh. Will you post that, then? \$\endgroup\$ Dec 27, 2021 at 15:00
  • 1
    \$\begingroup\$ nah, it's not worth an extra answer. Add it in if you want to. \$\endgroup\$
    – Razetime
    Dec 27, 2021 at 15:22
  • 1
    \$\begingroup\$ Wow 2 bytes... Is this language just made for this challenge? \$\endgroup\$ Dec 28, 2021 at 2:42
  • \$\begingroup\$ @U12-Forward Husk is (also) a golfing language (see its wiki). \$\endgroup\$ Dec 28, 2021 at 2:51
7
\$\begingroup\$

Vyxal, 2 bytes

żẇ

Try it Online!

Upgrading got me like

Explained

żẇ­⁡​‎‎⁡⁠⁡‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢‏‏​⁡⁠⁡‌­
ż   # ‎⁡The range [1, len(input)]
 ẇ  # ‎⁢Wrap the input list into chunks of each number. Stops grouping when there's no more items
💎

Created with the help of Luminespire.

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

Factor + grouping.extras math.unicode, 58 57 bytes

[ dup '[ _ index 1 + 2 * √ .5 + ⌊ ] group-by values ]

Try it online!

Group elements by the integer inverse triangular function of their indices. In other words, given a zero-based index \$i\$, its element belongs to group

$$\left\lfloor\sqrt{2(i + 1)} + \frac{1}{2}\right\rfloor$$

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

Jelly, 5 bytes

JÄ‘œṖ

Try it online!

How?

JÄ‘œṖ - Link: list, L                  e.g. [5,4,3,2,1,0,1,2]
J     - range of length of L                [1,2,3,4,5,6,7,8]
 Ä    - cumulative sums                     [1,3,6,10,15,21,28,36]
  ‘   - increment                           [2,4,7,11,16,22,29,37]
   œṖ - partition L before those indices    [[5],[4,3],[2,1,0],[1,2]]

Also 5 bytes TIO:

Jx`¹ƙ

...(J) range of length, (`) use right as both arguments with (x) repeat elements then (ƙ) apply to groups of identical values (¹) a no-op function.
i.e. build a list like [1,2,2,3,3,3,4,4,4,4,...] and group the original values like its equal values, [[1],[2,2],[3,3,3],[4,4,4,4],...].

or, equivalently (just reapplying J rather than using the quick `):

JxJ¹ƙ
\$\endgroup\$
16
  • \$\begingroup\$ Wow!! 5 bytes, but just curious, there is ÇŒṘ in the footer, what does that do? \$\endgroup\$ Dec 28, 2021 at 2:18
  • 2
    \$\begingroup\$ @U12-Forward The entry is a monadic function (AKA Link), but I want to avoid Jelly's full-program output formatting. Ç calls the Link above and ŒṘ formats the list in a Python style (Jelly's full-program output formatting shows singleton lists as the element they contain, so the example I give would look like [5,[4,3],[2,1,0],[1,2]] instead. (Jelly's list representation also smashes characters or mixed type lists, so [5,6,'a'] would be output as 56a which doesn't matter here, but both can be useful since we usually have the option of writing a function or full program.) \$\endgroup\$ Dec 28, 2021 at 2:35
  • 1
    \$\begingroup\$ Wow! Nice answer, 5 bytes... How? \$\endgroup\$
    – user110034
    Dec 28, 2021 at 2:41
  • 1
    \$\begingroup\$ @richardec Jelly is a language for golfing. See "How?" and if interested see the wiki. \$\endgroup\$ Dec 28, 2021 at 2:43
  • 1
    \$\begingroup\$ @JonathanAllan Thanks for the explanation. Interested in Jelly, for golfing. Might want to learn some of it. \$\endgroup\$ Dec 28, 2021 at 2:48
5
\$\begingroup\$

Ruby, 38 bytes

->l{(1..l.size).map{l.shift(_1)}-[[]]}
\$\endgroup\$
2
  • 3
    \$\begingroup\$ Welcome to Code Golf, and nice answer! \$\endgroup\$ Dec 27, 2021 at 20:20
  • 1
    \$\begingroup\$ Thanks @RedwolfPrograms \$\endgroup\$
    – Dorian
    Dec 28, 2021 at 7:26
4
\$\begingroup\$

Charcoal, 21 bytes

≔⮌AθWθ⊞υE⌊⟦Lθ⊕Lυ⟧⊟θIυ

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

≔⮌Aθ

Reverse the input list.

Wθ

Repeat until it is empty...

⊞υE⌊⟦Lθ⊕Lυ⟧⊟θ

... pop up to the next number of items from the input list into a new group.

Iυ

Output the grouped list.

\$\endgroup\$
4
\$\begingroup\$

R, 40 bytes

function(x)split(x,rep(s<-seq(!x),s)[s])

Try it online!

Inspired by Giuseppe's answer to "Chunk sort a sequence".

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I thought this challenge felt familiar! Nicely done. \$\endgroup\$
    – Giuseppe
    Dec 27, 2021 at 16:48
4
\$\begingroup\$

J, 12 bytes

</.~#{.#\##\

Try it online!

Consider 10 20 30 40 50 60:

  • #\ Gives 1 2 3 4 5 6 (ie, 1...n).

  • #\##\ Uses that list to "copy" itself:

    1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 6 6 6 6 6 6
    
  • #{. Take only the first n elements of that:

    1 2 2 3 3 3
    
  • </.~ Group the original input using that mask:

    ┌──┬─────┬────────┐
    │10│20 30│40 50 60│
    └──┴─────┴────────┘
    
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice approach! A Jelly port ties the existing 5-byte answer: JxJ¹ƙ. \$\endgroup\$
    – lynn
    Dec 27, 2021 at 20:20
4
\$\begingroup\$

Haskell, 40 bytes

n![]=[]
n!x=take n x:(n+1)!drop n x
(1!)

Try it online!

There seems like there should be a shorter way to do this maybe with scans or folds, but I can't figure it out.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think this needs a newline and (1!) included in the byte count. \$\endgroup\$
    – lynn
    Dec 27, 2021 at 20:16
3
\$\begingroup\$

APL+WIN, 18 bytes

Prompts for a vector of numbers or a string of characters. Outputs a nested vector.

(m↑(⍳m)/⍳m←⍴n)⊂n←⎕

Try it online! Thanks to Dyalog Classic

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

Perl 5, 45 bytes

sub{my@r;push@r,[splice@_,0,1+@r]while@_;\@r}

Try it online!

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

Scala, 92 bytes

a=>if(a.last.size>a.size)f(a.init++Seq(a.last.take(a.size))++Seq(a.last.drop(a.size)))else a

Try it online!

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

C (gcc), 86 \$\cdots\$ 77 76 bytes

r;i;f(a,n)int*a;{for(i=r=1;n--;r+=r*~r/2+i++?0:puts(""))printf("%d ",*a++);}

Try it online!

Saved a byte thanks to ceilingcat!!!

Inputs a pointer to an array of integers and its length (because pointers in C carry no length info).
Outputs to stdout each array slice with the array elements separated by spaces and the slices separated by newlines.

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

BQN, 24 22 15 14 12 bytes

Edit: -2 bytes thanks to Razetime, and -2 more bytes (and a BQN lesson) thanks to ovs

 1↓⊢⊔˜≠⥊·/˜⊒˜

Try it at BQN online REPL

\$\endgroup\$
9
  • 1
    \$\begingroup\$ ∾⥊¨˜ becomes \$\endgroup\$
    – Razetime
    Dec 27, 2021 at 17:19
  • 1
    \$\begingroup\$ @Razetime - (1) Thanks for spotting; (2) Drat! I'm sure I had it working in the REPL, but now I've lost how I did it (if at all...). Replaced with a longer working version for now, while I try to fix the shorter one... (3) And thanks v much for offer to help: I'll struggle a bit, and maybe ping you if I can't manage... \$\endgroup\$ Dec 27, 2021 at 17:20
  • \$\begingroup\$ @Razetime - Fixed. I'd somehow lost a ˜... \$\endgroup\$ Dec 27, 2021 at 18:51
  • 1
    \$\begingroup\$ 1↓⊢⊔˜≠⥊·/˜⊒˜ saves 2 bytes; The link includes a few steps, but it is a combinations of this tip and using Nothing to call a function monadically in a train. \$\endgroup\$
    – ovs
    Dec 27, 2021 at 22:19
  • 1
    \$\begingroup\$ The functions you put in parens are all applied to the argument(s) of the entire train. is not really the right argument of the train but rather a function that returns its right argument. (≠⊢) is a 2-train which calls on the result of (Equivalent to ≠∘⊢ - length atop right). Because the entire train is only applied to an argument on the right, this has the same effect as a bare (If the train would be called with a left argument, (≠⊢) and (≠) wouldn't be equivalent). \$\endgroup\$
    – ovs
    Dec 28, 2021 at 22:44
3
\$\begingroup\$

Wolfram Language (Mathematica), 33 bytes

GatherBy[#,i=1;Round@√(2i++)&]&

Try it online!

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

Uiua, 11 bytes

⊜□⬚2↙⧻,⊚⇡⧻.

Try it!

⊜□⬚2↙⧻,⊚⇡⧻.
          .  # duplicate
         ⧻   # length
        ⇡    # range
       ⊚     # where
      ,      # over
     ⧻       # length
  ⬚2↙        # take with fill element of 2
⊜□           # partition with boxing
\$\endgroup\$
2
  • \$\begingroup\$ If you want to handle arrays with repeated elements, I think you'll need to swap 'classify' for 'range-length', or something like that... \$\endgroup\$ Oct 16, 2023 at 7:40
  • \$\begingroup\$ @DominicvanEssen Thanks. Fixed for +1. \$\endgroup\$
    – chunes
    Oct 16, 2023 at 17:29
2
\$\begingroup\$

Python 2, 47 bytes:

def f(l,c=1):
 while l:yield l[:c];l=l[c:];c+=1

Try it Online!

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

JavaScript (ES6), 42 bytes

-2 thanks to @emanresuA because I'm a potato

x=>(f=n=>x+x&&[x.splice(0,++n),...f(n)])``
\$\endgroup\$
0
2
\$\begingroup\$

Python 3, 71 bytes

g=lambda x,s=1:[[c for c,_ in zip(x,range(s))]]+g(x[s:],s+1)if x else[]

Try it online!

-3 Thanks to @U12-Forward

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

Pip -xp, 12 bytes

a^@$+*\,\,#a

Attempt This Online!

Explanation

a^@$+*\,\,#a
          #a  Length(argument)
        \,    Inclusive range from 1 to ^
      \,      Inclusive range from 1 to each number in ^
   $+*        Sum each
a^@           Split argument at those indices
\$\endgroup\$
2
\$\begingroup\$

Scala, 74 bytes

a=>(0 to a.size).map(i=>a.slice(i*(i+1)/2,(i+1)*(i+2)/2)).filter(_.size>0)

Try it online!

The obvious way to avoid the filter at the end is to make the range from 0 to the biggest triangle number whose value is less than a.size, but the shortest way I could find to express that in Scala 2.13 was longer than the thing it was supposed to replace:

BigDecimal(0).until(pow(2*a.size+.25,.5)-.5,1)
\$\endgroup\$
1
\$\begingroup\$

Raku, 22 bytes

*.rotor(1..*,:partial)

Try it online!

The rotor method splits an array into chunks of a given size or sizes, eg:

  • rotor(5) splits an array into 5-element chunks.
  • rotor(2, 3) splits an array into chunks of alternating sizes 2 and 3.

Here, I pass the infinite range 1 .. * as the argument, so rotor will emit chunks of sizes 1, 2, 3, .... The :partial keyword argument causes all remaining elements to be grouped into the final chunk, even if there aren't enough of them.

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

APL (Dyalog Unicode), 17 bytes

This is a dfn that takes a vector as a right argument. It groups segments per specification into a nested array of vectors.


{⍵⊆⍨1+q⍸⍨+\q←⍳⍴⍵}

The index origin is set to 0 (⎕IO←0).

Try it on TryAPL.org!

This was an interesting challenge and demonstrates that there are many ways to get to a solution in the APL language. None I found had a lesser byte count, but the approaches may be of interest:

by recursion: {⍺←1 ⋄ ⍺≥⍴⍵:⊂⍵ ⋄ (⊂⍺↑⍵),(⍺+1)∇ ⍺↓⍵}

by formula: {⍵⊆⍨⌊0.5+0.5*⍨2×⍳⍴⍵}

by iteration: {p⊆⍨q↑∊{⍵⍴⍵}¨⍳q←⍴⍵}

\$\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.