Shorter than a Split Second!

16

5

Challenge

You task for this question is to split an input array of integers on the second occurrence of every integer in that array.

Not clear enough ? Here is an example to help

Input array:

[2 1 1 2 3 2 2 4 5 6 7 3 7 0 5]

Output:

[[2 1] [] [3 2 2 4 5 6 7] [] [0] []]

Explanation:

Here is the array with just the second element highlighted in bold:

[2 1 1 2 3 2 2 4 5 6 7 3 7 0 5]

Now we put the splitting array blocks around these bold second occurrences:

[2 1] 1 [] 2 [3 2 2 4 5 6 7] 3 [] 7 [0] 5 []

and wrap these splitted arrays in an array to get the final

[[2 1] [] [3 2 2 4 5 6 7] [] [0] []]

Note that when adjacent second occurrences occur, there will be empty arrays.

Rules

As usual, you have to write a full program or a function taking the input array via STDIN, ARGV or function argument.

Input

The input consists on any convenient array (or array-like) format of integers.

For instance, any of the following would be acceptable:

2 1 1 1 4 5 6
[2 1 1 1 4 5 6]
[2, 1, 1, 1, 4, 5, 6]

Output

When outputting to STDOUT, your array can also be printed in any convenient (nested) array format, e.g. one of

[[2 1] [1 4 5 6]]
[[2, 1], [1, 4, 5, 6]]
{{2, 1}, {1, 4, 5, 6}}

(This will usually be the native string representation of arrays in your language.)

Also note that trailing empty arrays should be printed as the part of the array.

Scoring

This is so shortest code in bytes win!

Optimizer

Posted 2014-12-20T12:27:38.443

Reputation: 25 836

@PeterTaylor many questions allow for different formats of arrays in both output and inputl. – Optimizer – 2014-12-20T12:30:30.993

5What's the point of allowing "" as the empty array? This smells of favourism towards a specific golfing language. – John Dvorak – 2014-12-20T12:46:43.343

@JanDvorak After discussion in chat, the intention was actually to be more inclusive and generally allow languages to use their native representation. I've edited the wording now to make that clearer. – Martin Ender – 2014-12-20T12:56:52.673

1Can I just output 2 1, 1 4 5 6? – jimmy23013 – 2014-12-20T14:41:19.063

@user23013 depends on the language you have chosen. – Optimizer – 2014-12-20T14:43:58.723

Answers

6

APL 25

1↓¨(1,∨⌿<\2=+\∘.=⍨a)⊂1,a←

Example:

]display 1↓¨(1,∨⌿<\2=+\∘.=⍨a)⊂1,a←2 1 1 2 3 2 2 4 5 6 7 3 7 0 5
┌→──────────────────────────────────────┐
│ ┌→──┐ ┌⊖┐ ┌→────────────┐ ┌⊖┐ ┌→┐ ┌⊖┐ │
│ │2 1│ │0│ │3 2 2 4 5 6 7│ │0│ │0│ │0│ │
│ └~──┘ └~┘ └~────────────┘ └~┘ └~┘ └~┘ │
└∊──────────────────────────────────────┘

Old One:

{1↓¨(1,(⍳⍴⍵)∊,{1↑1↓⍵}⌸⍵)⊂1,⍵}

This is a nice question for the key operator (⌸) which was introduced with Dyalog APL v14. It takes the left argument function ({1↑1↓⍵}) and gives it for each unique argument, the indices in the vector for that argument. Here I'm taking the second index, then i check which of the indices is present in this list ((⍳⍴⍵)∊) and use the resulting boolean for splitting the original vector.

Can be tried online here:

http://tryapl.org

Moris Zucca

Posted 2014-12-20T12:27:38.443

Reputation: 1 519

Damn. Still not less than 24 ? – Optimizer – 2014-12-23T11:47:24.317

@Optimizer: 25... I'm trying ;-) – Moris Zucca – 2014-12-23T14:01:37.517

Accepting this instead of my own solution :) – Optimizer – 2015-01-06T17:01:31.267

Only 24, and a proper function: 1↓¨{1,∨⌿<\2=+\∘.=⍨⍵}⊂1∘, – Adám – 2016-12-20T16:21:06.313

does not work unfortunately... the omega in the dfn is not the same as "a" – Moris Zucca – 2016-12-21T08:10:31.723

9

APL (Dyalog 14) (31)

{1↓¨(1,(⍳⍴⍵)∊2⍳⍨¨↓+\∘.=⍨⍵)⊂0,⍵}

This is a function that takes an array and returns a nested array.

Test:

      +V← {1↓¨(1,(⍳⍴⍵)∊2⍳⍨¨↓+\∘.=⍨⍵)⊂0,⍵} 2 1 1 2 3 2 2 4 5 6 7 3 7 0 5
┌───┬┬─────────────┬┬─┬┐
│2 1││3 2 2 4 5 6 7││0││
└───┴┴─────────────┴┴─┴┘
      ⍝ this return value is a real nested array:
      ⎕←'Length: ',⍴V ⋄ (⍳⍴V){⎕←'Array #',⍺,': (', ⍵, ')'}¨V 
Length:  6
Array # 1 : ( 2 1 )
Array # 2 : ()
Array # 3 : ( 3 2 2 4 5 6 7 )
Array # 4 : ()
Array # 5 : ( 0 )
Array # 6 : ()

Explanation:

  • 0,⍵: Add a 0 to the front of , for easier processing. (It does not count as an occurrence.)
  • (...)⊂: Split the array according to the given bitmask. A new group starts at each 1 in the bitmask.
    • +\∘.=⍨⍵: for each value in (the original) , find all occurrences in . Then make a running sum for each value, giving a square matrix showing for each position in how many of each value have already occurred.
    • : Split the matrix by its rows, giving for each value an array showing the amount of times it has occurred by each position.
    • 2⍳⍨¨: In each of these arrays, find the index of the first 2.
    • (⍳⍴⍵)∊: For each possible index into , see if it is contained in the list of indices of second occurrences. (These start each group, except the first one.)
    • 1,: Add an 1 to the front, marking the start of the first group.
  • 1↓¨: Remove the first element from each group. (These are the added 0, and the second occurrence of each value.)

marinus

Posted 2014-12-20T12:27:38.443

Reputation: 30 224

8

J, 28 24 char

Special thanks to randomra.

(1&,<;._1~1,2=+/@(={:)\)

It works like this. Over all prefixes (\) of the input array, we look at how many (+/@) elements of the prefix are equal to the last element (={:) of that prefix. When this number is 2, we know this is the second occurrence of that item in the array, so we split the array there using <;._1.

   a=.2 1 1 2 3 2 2 4 5 6 7 3 7 0 5
   (={:)\ a
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
1 0 0 1 0 1 0 0 0 0 0 0 0 0 0
1 0 0 1 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 1
   +/@(={:)\ a
1 1 2 2 1 3 4 1 1 1 1 2 2 1 2

Old thing using sort tricks: (1&,<;._1~1,1=i.~(]-{)/:@/:).

algorithmshark

Posted 2014-12-20T12:27:38.443

Reputation: 8 144

(1&,<;._1~1,2=+/@(={:)\) is 4 bytes shorter and a lot simpler. (/:@/: is a nice trick though.) – randomra – 2015-03-27T12:33:35.493

7

Mathematica, 58 51 49 bytes

Rest/@SplitBy[(f@#=0;#)&/@{a}~Join~#,++f[#]==3&]&

This is an unnamed function which takes a list like

Rest/@SplitBy[(f@#=0;#)&/@{a}~Join~#,++f[#]==3&]&[{2,1,1,2,3,2,2,4,5,6,7,3,7,0,5}]

and returns a nested list like

{{2, 1}, {}, {3, 2, 2, 4, 5, 6, 7}, {}, {0}, {}}

How it works

This uses some pretty obscure magic with SplitBy.

I'm keeping track of the occurrences of each number in a function f. In Mathematica, you can define the value of a function for each input separately, and you don't need to specify the value for all possible inputs (it's more like a hash table on steroids).

So I start out by initialising f to 0 for values that are present in the input with (f@#=0;#)&/@.

Now SplitBy takes a list and a function and "splits list into sublists consisting of runs of successive elements that give the same value when f is applied" (note that SplitBy does not remove any elements). But the (undocumented) catch is, that f is called twice on each element - when comparing it to its predecessor and its successor. So if we do

 SplitBy[{1,2,3,4},Print]

we don't just get each number once, but instead this prints

 1
 2
 2
 3
 3
 4

which is 6 calls for 3 comparisons.

We can split the list before each second occurrence, if we write a function which always returns False but returns True when a second occurrence is compared to the element before it. That is the third check on that element (two checks on the first occurrence, plus the first check on the second occurrence). Hence, we use ++f[#]==3&. The nice thing is that this already returns False again on the second check of the second occurrence, such that I can return True for consecutive second occurrences, but still split between them. Likewise, this won't split after second occurrences, because the function already returns False again on the second check.

Now, the question wants us to also remove those second occurrences, so we drop the first element from each list, with Rest/@. But of course, we don't want to remove the very first element in the input, so we actually start off, by adding an element a to the beginning of the list with {a}~Join~#. a is an undefined variable, which Mathematica just treats as an unknown, so it won't affect any other values of f. This also ensures that the first actual element in the input gets its two checks like every other element.

Martin Ender

Posted 2014-12-20T12:27:38.443

Reputation: 184 808

That's pretty clever. You also actually don't need Boole in there. – swish – 2014-12-23T15:30:19.183

@swish Ah, thanks for reminding me... I noticed that while on mobile, but wanted to test it before changing it. – Martin Ender – 2014-12-23T15:31:29.903

5

Python, 148 bytes

def s(a):z=len(a);x=[-1]+sorted({[i for i in range(z)if a[i]==n][1]for n in a if a.count(n)>1})+[z];return[a[x[i]+1:x[i+1]]for i in range(len(x)-1)]

Pretty horrendous solution. There's got to be a better way...

Call with s([2, 1, 1, 1, 4, 5, 6]).

Ungolfed version

def split(array):
  indices = [-1]
  second_occurrences = set()

  for n in array:
      if array.count(n) > 1:
          occurrences = [i for i in range(len(array)) if array[i] == n]
          second_occurrences.add(occurrences[1])

  indices += sorted(second_occurrences)
  indices += [len(array)]

  return [array[indices[i]+1:indices[i+1]] for i in range(len(indices)-1)]

Sp3000

Posted 2014-12-20T12:27:38.443

Reputation: 58 729

1What the what… Could you edit in an un-golfed version? XD 148 characters is a very long line ;) – Sean Allred – 2014-12-20T23:05:33.360

1@SeanAllred I didn't want to post an explanation since I was sure I could do better, but since I'm having trouble I've posted the ungolfed version :P – Sp3000 – 2014-12-21T06:21:39.107

5

Haskell, 115 113 106 88

f?(x:s)|1<-f x=[]:x%f?s|a:b<-x%f?s=(x:a):b
f?x=[x]
(x%f)h=sum$f h:[1|x==h]
r s=(\_->0)?s

this stores the amount every element appeared so far as a function from elements to their respective amount, which is an interesting trick.

this works using %, a function that given a function f and an argument x returns a new function that returns f applied to it's argument if it is different than x, and 1 + f x otherwise.

for example, 3 % const 0 is a function which returns 0 for every argument except 3, for which it returns 1. update: fused the foldl to get a much smaller program.

proud haskeller

Posted 2014-12-20T12:27:38.443

Reputation: 5 866

This looks interesting. Could you provide an ungolfed version? – radomaj – 2015-01-16T23:41:38.627

4

Ruby 66 demo

f=->a{c=Hash.new 0
r=[[]]
a.map{|e|2==(c[e]+=1)?r<<[]:r[-1]<<e}
r}

Ruby stabby lambda that takes an array as a parameter and returns an array of arrays.

Cristian Lupascu

Posted 2014-12-20T12:27:38.443

Reputation: 8 369

4

Python: 100 byte

def g(l):
 i=j=0;o=[]
 for e in l:
  if l[:i].count(e)==1:o+=[l[j:i]];j=i+1
  i+=1
 return o+[l[j:]]

Straightforward solution. I iterate over the list, count how many times a character appeared before, and append the part since the last check to the output list.

Jakube

Posted 2014-12-20T12:27:38.443

Reputation: 21 462

3

Ruby, 64 bytes

s=->a{x=[];b=[[]];a.map{|e|x<<e;x.count(e)==2?b<<[]:b[-1]<<e};b}

AlexRath

Posted 2014-12-20T12:27:38.443

Reputation: 139

3

CJam, 25 24 bytes

q~{_L+:L1$a/,3=S@?}%Sa/p

Takes input from STDIN like

[ 2 1 2 1 0 2 2 1 1 3 4 3]

and outputs like

[[2 1] "" [0 2 2 1 1 3 4] ""]

I am basically iterating over all elements of the array, one by one putting them into another array. Then I get the count of the current element in the other array. If its 2, I start another array from that location. This kind of random array starting can only be achieved in a stack based language.

Code expansion:

q~{_L+:L1$a/,3=S@?}%Sa/p
q~{               }%             "Evaluate the input array and map it on this block";
   _                             "Copy the current element in iteration";
    L+:L                         "Add the copy to an initially blank array L and update L";
        1$a/                     "Make another copy of the element and split L on it";
            ,3=                  "This checks if the splitted array is of length 3";
                                 "which indirectly means that L contains the element twice";
               S@?               "If the above is true, replace the element by space";
                    Sa/          "Split the final array on space. This final array contains";
                                 "second occurrence of every integer replaced by a space";
                       p         "Print the stringified version of the final nested array";

Try it online here

1 byte saved from Martin's tip on chat

Optimizer

Posted 2014-12-20T12:27:38.443

Reputation: 25 836

3

Ruby, 66

f=->a{s=Hash.new 0
r=[[]]
a.map{|e|(s[e]+=1)==2?r<<[]:r[-1]<<e}
r}

Explanation

  • e is a Hash of occurrence counts for each element, r is an Array in which the result is stored.
  • Loop trough the input, increment the occurrence count for each element by 1.
    • If the occurrence count is 2, we need to split. Add an empty Array to the result.
    • Otherwise just add the element to the last Array in result.

britishtea

Posted 2014-12-20T12:27:38.443

Reputation: 1 189

2Nice hat!! Oh wait. – Optimizer – 2014-12-20T16:48:45.537

4

What an incredible coincidence! The answer I posted seconds before yours is almost identical. :)

– Cristian Lupascu – 2014-12-20T16:49:54.843

Oh my, it's even 1 character shorter! – britishtea – 2014-12-20T16:51:23.750

It's a saving you can easily apply to yours. I think it's awesome that we had the same idea at the same time. :D – Cristian Lupascu – 2014-12-20T16:51:50.690

3

Perl 5: 36

Not sure if this is acceptable as no actual splitting happens here.

#!perl -pa
$x{$_}++-1or$_=']['for@F;$_="[[@F]]"

Example:

$ perl spl.pl <<<"2 1 1 2 3 2 2 4 5 6 7 3 7 0 5"
[[2 1 ][ ][ 3 2 2 4 5 6 7 ][ ][ 0 ][]]

nutki

Posted 2014-12-20T12:27:38.443

Reputation: 3 634

Totally acceptable. – Optimizer – 2014-12-23T15:06:08.587

Nice answer. But standard practice, I think, is to count -pa as two extra bytes (because it "costs" only two bytes, since you can write it as -pae instead of -e). So that'd be 38, not 36. – msh210 – 2016-06-21T14:45:41.690

2

CJam, 28 bytes

Lq~{1$1$a/,3=S2$?@++}/-2%S/`

Takes input on STDIN like

[2 1 1 2 3 2 2 4 5 6 7 3 7 0 5]

and prints the output to STDOUT like

[[2 1] "" [3 2 2 4 5 6 7] "" [0] ""]

Note that empty strings and empty arrays are the same thing in CJam, and are displayed as "" by default (this is the native representation of empty arrays).

(I started working on this a bit before the challenge was posted, because we were discussing how difficult the challenge would be.)

Explanation

Basically, I'm duplicating each element in the array, unless it's the second occurrence, in which case I replace the first copy with a space. For golfing reasons, this modified array is constructed in reverse. So [2 1 1 2 3 2 3] becomes

[3 S 2 2 3 3 2 S 1 S 1 1 2 2]

Then I pick out every second element from the end, which is the original array, but with second occurrences replaced by spaces, i.e.

[2 1 S S 3 2 S]

Finally, I simply split the array on spaces. Here is a breakdown of the code:

L                            "Push empty array.";
 q~                          "Read STDIN an evaluate.";
   {                }/       "For each element of the input.";
    1$1$                     "Copy the array and the element.";
        a/                   "Split the array by that element.";
          ,3=                "Check that it's split into 3 parts.";
             S2$?            "If so, push a space, else, copy the current number.";
                 @++         "Pull up the array from the bottom and add both to the beginning.";
                      -2%    "Pick every second element from the end.";
                         S/  "Split on spaces.";
                           ` "Get the string representation.";

Martin Ender

Posted 2014-12-20T12:27:38.443

Reputation: 184 808

Since this is my own challenge, I am giving a chance first :P. I have a 25 byte Cjam solution with me. – Optimizer – 2014-12-20T13:21:56.933

Doesn't display empty arrays correctly--obviously invalid! – feersum – 2014-12-20T13:31:21.880

1@feersum displaying empty arrays as "" is explicitly allowed in the first revision of the question. The current revision states "any convenient format ... usually native string represtation of arrays". – John Dvorak – 2014-12-20T13:58:58.473

2

Unix tools, 100 bytes

grep -o '[-0-9]*'|awk '{print(++A[$0]-2)?$0:"] ["}'|paste -sd' '|sed -e '/]/s/.*/[\0]/' -e's//[\0]/'

Excepts the input via stdin. It basically just replaces every second occurrence with "] [". Does not work with empty strings, [] will give an empty string, which I think is a convenient representation of an empty array :)

pgy

Posted 2014-12-20T12:27:38.443

Reputation: 830

Well, then the answer is not meeting the spec, right ? (about negative integers). Also, what about 11 ? will it get converted to 1][ ? – Optimizer – 2014-12-20T14:27:17.077

It works well for 11, but you are right about negative numbers, fixed that, and it now also accepts singleton arrays. – pgy – 2014-12-20T14:38:03.467

2

APL, 42 characters

{'(',')',⍨⍵[(2=+/¨(↑=↓)¨⌽¨,\⍵)/⍳⍴⍵]←⊂')('}

Example:

{'(',')',⍨⍵[(2=+/¨(↑=↓)¨⌽¨,\⍵)/⍳⍴⍵]←⊂')('}2 1 1 2 3 2 2 4 5 6 7 3 7 0 5

Output:

( 2 1  )(   )(  3 2 2 4 5 6 7  )(   )(  0  )(  )

Tested here.

If I must output a string that is interpreted exactly as the right structure in APL... 49 characters

{'1↓1(',',⍬)',⍨⍵[(2=+/¨(↑=↓)¨⌽¨,\⍵)/⍳⍴⍵]←⊂',⍬)('}

jimmy23013

Posted 2014-12-20T12:27:38.443

Reputation: 34 042

How is a nested list actually represented in APL ? Maybe you might not need to do string manipulation – Optimizer – 2014-12-20T14:56:32.413

@Optimizer The outputed string is a valid list in an APL program. However it wouldn't be nested if there is only one list in it. Prepending a 1↓1 seemed to fix the problem, but that looks too weird. – jimmy23013 – 2014-12-20T15:15:38.347

2

Java, 223

This only works on Oracle or OpenJDK JRE, since I make use of this quirk in their implementation of quantifier and length check in look-behind to implement variable-length look-behind.

class W{public static void main(String a[]){System.out.print("["+new java.util.Scanner(System.in).nextLine().replaceAll(" *\\b(\\d+)\\b(?=(.*))(?<=^(?=(.*\\b\\1\\b){2}\\2).*)(?<!^(?=(.*\\b\\1\\b){3}\\2).*) *","] [")+"]");}}

Most of the work is done in the regex, which is shown below in raw form:

 *\b(\d+)\b(?=(.*))(?<=^(?=(.*\b\1\b){2}\2).*)(?<!^(?=(.*\b\1\b){3}\2).*) *

Before we look at the regex above, let us look at equivalent .NET regex, which is simpler, since it directly supports variable-length look-behind (.NET look-behind is most likely done by right-to-left matching mode):

 *\b(\d+)\b(?<=(.*\b\1\b){2})(?<!(.*\b\1\b){3}) *
  •  *\b(\d+)\b and  * at the end matches a number and the surrounding spaces (if any). The bound checks are to prevent partial number from being matched, since spaces on both sides are optional. It also captures the number to check whether it is the 2nd appearance in the array.

  • (?<=(.*\b\1\b){2}) checks that 2 instances of the number captured above can be found. (?<!(.*\b\1\b){3}) checks that no 3 instances of the number captured can be found. Both conditions combined asserts that there are only 2 instances of the number so far. The bound checks are there to make sure the whole number is tested.

Back to the Java version. To implement variable-length look behind, we transform

(?<=var-length-pattern)

to

(?<=^(?=.*var-length-pattern).*)

I am a bit hand-waving regarding the fact that . excludes line separators, but it can be fixed easily and I don't want to further complicate the syntax.

The look-ahead is always 0 in length, and the length check passes due to the implementation of * quantifier.

The ^ is not necessary to make it work, but it is there to make the failing case fails faster. Look-behind in Oracle/OpenJDK implementation is done by stepping back the minimum length of the pattern, then match, then rinse and repeat by incrementing the length until a match is found, or in the worst case, to the maximum length of the pattern. With ^, I make sure the prefix string is only matched once.

However, the look-ahead inside the look-behind is not limited by look-behind's right-boundary, so it can match all the way to the end of the string. In order to assert the boundary, I capture the rest of the string into another capturing group inside a look ahead, and use it to limit the reign of the variable length pattern.

(?=(.*))(?<=^(?=.*var-length-pattern\m).*)
   ^--^                              ^
   mth capturing group               m is the number of the capturing group marked

Since my pattern already starts with .*, I don't need to add another .* in front.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Posted 2014-12-20T12:27:38.443

Reputation: 5 683

1

Pure bash 111 94

81 for only splitting:

for i;do [ "${b[i]}" == 7 ]&&c+=("${d# }") d=||d+=\ $i;b[i]+=7;done;c+=("${d# }")
declare -p c

The second line declare -p c just dumping the variable

Sample:

splitIntFunc() {
    local b c d i
    for i;do
        [ "${b[i]}" == 7 ]&&c+=("${d# }") d=||d+=\ $i
        b[i]+=7
      done
    c+=("${d# }")
    declare -p c
}

Nota: the line local b c d i is only required for running the function several times.

splitIntFunc 2 1 1 2 3 2 2 4 5 6 7 3 7 0 5
declare -a c='([0]="2 1" [1]="" [2]="3 2 2 4 5 6 7" [3]="" [4]="0" [5]="")'

splitIntFunc 2 1 1 1 4 5 6
declare -a c='([0]="2 1" [1]="1 4 5 6")'

splitIntFunc $(sed 's/./& /g;w/dev/stderr' <<<${RANDOM}${RANDOM}${RANDOM})
1 6 5 3 2 2 4 3 9 4 2 9 7 7 4 
declare -a c='([0]="1 6 5 3 2" [1]="4" [2]="9" [3]="2" [4]="7" [5]="4")'

splitIntFunc $(sed 's/./& /g;w/dev/stderr' <<<${RANDOM}${RANDOM}${RANDOM})
2 4 5 2 9 1 1 4 8 7 8 1 0 3 
declare -a c='([0]="2 4 5" [1]="9 1" [2]="" [3]="8 7" [4]="1 0 3")'

For sexiest presentation (+26)

splitIntFunc() {
    local b c d i
    for i;do
        [ "${b[i]}" == 7 ]&&c+=("${d# }") d=||d+=\ $i
        b[i]+=7
      done
    c+=("${d# }")
    printf -v l "(%s) " "${c[@]}"
    echo "<$l>"

Will render something like:

splitIntFunc 2 1 1 2 3 2 2 4 5 6 7 3 7 0 5
<(2 1) () (3 2 2 4 5 6 7) () (0) () >

splitIntFunc $(sed 's/./& /g;w/dev/stderr' <<<${RANDOM}${RANDOM}${RANDOM})
4 3 8 1 4 5 7 9 2 7 8 4 0 
<(4 3 8 1) (5 7 9 2) () (4 0) >

splitIntFunc $(sed 's/./& /g;w/dev/stderr' <<<${RANDOM}${RANDOM}${RANDOM})
3 1 3 0 2 5 3 6 6 9 2 5 5 
<(3 1) (0 2 5 3 6) (9) () (5) >

splitIntFunc $(sed 's/./& /g;w/dev/stderr' <<<${RANDOM}${RANDOM}${RANDOM})
2 2 2 9 1 9 5 0 2 2 7 6 5 4 
<(2) (2 9 1) (5 0 2 2 7 6) (4) >


}

F. Hauri

Posted 2014-12-20T12:27:38.443

Reputation: 2 654

1

Perl 108

map{$e[$_]==1?do{push@a,[@b];@b=();}:push@b,$_;$e[$_]++}split" ";push@a,[@b];s/.*/Data::Dumper->Dump(\@a)/e;

In action:

perl -MData::Dumper -pe '
    $Data::Dumper::Terse = 1;
    $Data::Dumper::Indent = 0;
    @a=@b=@e=();
    map{$e[$_]==1?do{push@a,[@b];@b=();}:push@b,$_;$e[$_]++}split" ";
    push@a,[@b];
    s/.*/Data::Dumper->Dump(\@a)/e;
' <<<$'2 1 1 2 3 2 2 4 5 6 7 3 7 0 5\n2 1 1 1 4 5 6\n'"$(
    sed 's/./& /g;w/dev/stderr' <<< ${RANDOM}${RANDOM}${RANDOM}$'\n'${RANDOM}${RANDOM})"
2 4 4 7 7 2 9 8 8 4 6 0 1 8 
1 0 3 9 3 7 9 
[2,1][][3,2,2,4,5,6,7][][0][]
[2,1][1,4,5,6]
[2,4][7][][9,8][4,6,0,1,8]
[1,0,3,9][7][]

Nota: The two first lines $Data::... are there only for nicer presentation and third line @a=@b=@e=(); is there for making the tool working on multiple lines.

F. Hauri

Posted 2014-12-20T12:27:38.443

Reputation: 2 654

1

R, 76

y=scan();r=split(y,cumsum(ave(y,y,FUN=seq)==2));c(r[1],lapply(r[-1],"[",-1))

Output for the example: A list of five elements, including three empty vectors. (numeric(0)).

$`0`
[1] 2 1

$`1`
numeric(0)

$`2`
[1] 3 2 2 4 5 6 7

$`3`
numeric(0)

$`4`
[1] 0

$`5`
numeric(0)

By the way: The code generates a warning message that can be ignored.

Sven Hohenstein

Posted 2014-12-20T12:27:38.443

Reputation: 2 464

1

awk 29

a[$1]++==1{print"-";next}1

This takes a bit of liberty with the input and output formats. Input "array" is vertical, one number per line. Output is also vertical, one number per line, with dashes separating arrays.

Input:

2
1
1
2
3
2
2
4
5
6
7
3
7
0
5

Output:

2
1
–
–
3
2
2
4
5
6
7
–
–
0
–

Kevin

Posted 2014-12-20T12:27:38.443

Reputation: 501

1

Pyth 30 32

This is my first time experimenting with Pyth. It's the same solution as in my Python solution.

VQIq/<QN@QN1~Y]:QZN=ZhN;+Y]>QZ

You can try it online: Pyth Compiler/Executor

E.g. The input

[2,1,1,2,3,2,2,4,5,6,7,3,7,0,5]

will print

[[2, 1], [], [3, 2, 2, 4, 5, 6, 7], [], [0], []]

Explanation:

                                 # Q = input(), Y = [], Z = 0
VQ                               # for loop: N iterates over the indices of Q
  I                              # if 
   q\<QN@QN1                     #    Q[N] appears exactly once in Q[:N]
            ~Y]:QZN              #         append the list [Q[Z:N]] to Y
                   =ZhN          #         and assign Z = N + 1
                       ;         # end if and for loop
                        +Y]>QZ   # print Y + [Q[Z:]]

Jakube

Posted 2014-12-20T12:27:38.443

Reputation: 21 462

Is there a better alternative for =Y+Y...? – Jakube – 2014-12-22T19:59:16.873

this is - ~Y... – Optimizer – 2014-12-22T20:17:55.547

1

Python 2, 84

l=[[]];p=[]
for x in input():p+=[x];b=p.count(x)==2;l+=[[]]*b;l[-1]+=[x][b:]
print l

The list l is the output so far. We iterate over the elements. If the current one is the second appearance, we start a new empty sublist; otherwise, we add it to the latest sublist. The list of elements seen so far is stored in p. Strangely, reconstructing the list seems shorter than slicing the input.

xnor

Posted 2014-12-20T12:27:38.443

Reputation: 115 687

0

Scala, 122111

Take character collection, print in form of [21][][3224567][][0][], 122111:

def s(a:Any*)=print((("[","")/:a){case((b,c),d)=>if(b.indexOf(d)==c.indexOf(d))(b+d,c)else(b+"][",c+d)}._1+"]")

...or take a character collection and return nested lists, 135129:

def s(a:Char*)=(("",List(List[Any]()))/:a){case((b,c),d)=>b+d->(if(b.count(d==)==1)List()::c else(c.head:+d)::c.tail)}._2.reverse

I'm sure there are some savings I could get, I have not looked too hard.

Chad Retz

Posted 2014-12-20T12:27:38.443

Reputation: 131

0

Python 220 bytes

The below is 220 bytes which isn't great compared to a lot of the others but runs fast enough with larger integers!

xlist = list(input()); result = []; x = 0
for i in range(len(xlist)):
    if xlist[0:i+1].count(xlist[i]) == 2: result.append(xlist[x:i]);x = i+1
    elif i == len(xlist)-1: result.append(xlist[x:])
print(result)

S rick

Posted 2014-12-20T12:27:38.443

Reputation: 1

Hi, and welcome to PPCG! However, your code isn't really short enough. I see some places where you can definitely shorten it. Please continue golfing. – Rɪᴋᴇʀ – 2016-06-21T14:43:10.807

Hello! If you need help golfing, you can remove the spaces around =, change xlist and result to shorter names, and remove spaces around ==, ;, and :. If you need more help, just type @NoOneIsHere (or any username) and I/the user will try to help. – NoOneIsHere – 2016-06-21T15:27:09.583

-1

Java: 563 bytes

note this uses Java 8, pre-JDK8 would be a few bytes longer due to the foreach.

import java.util.*;public class a{static String c(String[]b){List<String>d=new ArrayList<>(Arrays.asList(b));Set<String>e=new HashSet<>();Set<String>f=new HashSet<>();for(int i=0;i<Integer.MAX_VALUE;i++){String g;try{g=d.get(i);}catch(IndexOutOfBoundsException ex){break;}
if(e.contains(g)&&!f.contains(g)){d.remove(i);d.add(i,"]");d.add(i+1,"[");f.add(g);i++;}else{e.add(g);}}
d.add(0,"[[");d.add(d.size(),"]]");StringBuilder sb=new StringBuilder();d.forEach(sb::append);return sb.toString();}
public static void main(String[]args){System.out.println(c(args));}}

PoweredByRice

Posted 2014-12-20T12:27:38.443

Reputation: 171

where else can I use lambda?

looping till array's length is not correct because the list keeps expanding as you add more "]" and "[". – PoweredByRice – 2014-12-23T17:22:55.237

incrementing the length each time is just as lengthy as catching the exception, also I don't think it's possible in Java to change CEILING in (for i = 0; i < CEILING; i++). – PoweredByRice – 2014-12-23T17:28:12.103

Really ? – Optimizer – 2014-12-23T17:35:07.203

hmm didn't know that, thanks for pointing out. – PoweredByRice – 2014-12-23T17:44:58.427

What about converting Integer.MAX_VALUE to 2147483647 ? It's the same value with less bytes. Also, IndexOutOfBoundsException can be shortened to Exception – Charlie – 2014-12-26T09:07:10.933