# Split a list at the second occurrence of the first element

Let's define a function f that splits a list at the second occurrence of the first element, e.g. [0,2,2,3,0,1,0,1] -> ([0,2,2,3],[0,1,0,1]):

Alright then, lets!

You are to take a non-empty list consisting of digits, and output a pair of lists, clearly distinguished, such that the output is the input split before the second occurrence of the first element.

For example, you may output two strings of digits with a non-digit separator. The separator you choose between the elements of each pair and the pairs themselves must be distinct (e.g. space and newline), consistent and not contain digits.

The output must only contain 2 elements however. You may not output empty lists in the output. If you choose to use newlines as a separator between pairs, you may not have a leading newline. You may have trailing newlines no matter what, and you may have trailing whitespace, so long as its sensible.

You may assume:

• The input will be provided in any convenient method, and you may output in any convenient method
• The input will either be a list of digits, or a string
• The input will only contain the integers 0 though to 9
• The first element of the input will always occur at least twice
• The input will always have 3 or more elements in it

Additionally, this is , so the shortest code in bytes wins

## Test cases

[1, 1, 9] -> [[1], [1, 9]]
[4, 9, 4] -> [[4, 9], [4]]
[5, 7, 5, 5] -> [[5, 7], [5, 5]]
[8, 8, 0, 7] -> [[8], [8, 0, 7]]
[7, 1, 5, 7, 4, 2] -> [[7, 1, 5], [7, 4, 2]]
[0, 6, 9, 1, 1, 0, 2] -> [[0, 6, 9, 1, 1], [0, 2]]
[2, 9, 3, 2, 4, 2, 5, 9] -> [[2, 9, 3], [2, 4, 2, 5, 9]]
[0, 2, 2, 3, 0, 1, 0, 1] -> [[0, 2, 2, 3], [0, 1, 0, 1]]
[2, 7, 4, 6, 2, 6, 6, 4, 8, 2] -> [[2, 7, 4, 6], [2, 6, 6, 4, 8, 2]]
[8, 2, 2, 7, 5, 4, 7, 0, 8, 0, 7] -> [[8, 2, 2, 7, 5, 4, 7, 0], [8, 0, 7]]
[8, 7, 8, 9, 4, 2, 9, 4, 5, 7, 5, 1, 9] -> [[8, 7], [8, 9, 4, 2, 9, 4, 5, 7, 5, 1, 9]]
[3, 8, 1, 1, 7, 3, 6, 9, 7, 1, 4, 3, 4] -> [[3, 8, 1, 1, 7], [3, 6, 9, 7, 1, 4, 3, 4]]
[4, 7, 0, 5, 6, 5, 0, 1, 7, 8, 7, 8, 4, 1] -> [[4, 7, 0, 5, 6, 5, 0, 1, 7, 8, 7, 8], [4, 1]]
[2, 1, 8, 0, 3, 2, 2, 5, 7, 9, 4, 3, 5, 1, 9, 6, 9] -> [[2, 1, 8, 0, 3], [2, 2, 5, 7, 9, 4, 3, 5, 1, 9, 6, 9]]
[1, 1, 4, 1, 2, 5, 5, 3, 3, 4, 3, 2, 0, 8, 6, 0, 3] -> [[1], [1, 4, 1, 2, 5, 5, 3, 3, 4, 3, 2, 0, 8, 6, 0, 3]]
[4, 3, 5, 2, 2, 0, 6, 4, 8, 6, 6, 6, 7, 3, 4, 8, 7, 6] -> [[4, 3, 5, 2, 2, 0, 6], [4, 8, 6, 6, 6, 7, 3, 4, 8, 7, 6]]

• Brownie points for beating my quickly hacked together 8 byte Jelly answer :) Jun 3, 2021 at 21:04
• If I'm outputting each value as a single digit on its own line, can I use a separator that contains digits but is clearly distinct from the other values. Like this? Jun 4, 2021 at 8:29
• @AidenChow You can output a single string with a clear separator between the parts (see Neil's Retina answer), does that work? Jun 4, 2021 at 20:33
• @AidenChow If your language supports lists of integers, I believe that allowing people to output a flat list with -1 as a "separator" shouldn't break the challenge (e.g. [0,2,2,3,0,1,0,1] -> [0,2,2,3,-1,0,1,0,1]), so you're welcome to use that format. Otherwise, I don't see how you could use that language here :( Jun 4, 2021 at 20:48
• @cairdcoinheringaahing Yes that can work! Thanks for being flexible with your specifications regarding I/O. Jun 5, 2021 at 4:30

f(x:y)=([x],0)*>span(/=x)y


Try it online!

Shortens Zgarb's OG solution

f(x:y)|(a,b)<-span(/=x)y=(x:a,b)


by prepending x to the first element of (a,b) in a pointfree way, that is without explicitly binding (a,b).

It would be nice it we could do (x:)<$>(a,b), but that gives (a,x:b) -- the Functor instance of tuples lets us act on the second element but not the first. However, Applicative lets us combine tuples as: (p, f) <*> (a, b) = (p++a, f b) ([x], id) <*> (a, b) = (x:a, b)  It suffices to use *> which ignores f and leaves b unchanged. ((x:), 0) *> (a, b) = (x:a, b)  The 0 could be anything -- it doesn't matter. It would also work to use >> in place of *>. 26 bytes f(x:y)=([x],y)>>=span(/=x)  Try it online! A alternative, this time using the Monad instance and (>>=) :: Monoid a => (a, a0) -> (a0 -> (a, b)) -> (a, b) 27 bytes f(x:y)=([x],[])<>span(/=x)y  Try it online! Using <> to do concatenate elementwise (a, b) <> (c, d) = (a++c, b++d). This is available in Prelude without an import starting in version 8.4.1. # AWK, 17 14 bytes sub(FS$1,RS$1)  Try it online! Thanks to Pedro Maimere for the hint to lop off 3 bytes The interactions of the rules in the contest allow for pretty trivial AWK solution... Assuming the input can be a blank delimited string of numbers, this will work. If it has to include the brackets and commas (which I wasn't sure about from the linked article about convenient input), then it would be this instead. sub(", "(a=substr($1,2)),"]\n["a)


And here's one in ><> which might be shrinkable still... It's the first time I've managed to get something to work in that language, so I wouldn't be surprised to learn there some trick I don't know yet.

# ><>, 41 bytes

i:o&0v
?(0:i<o$v?<=1:+{=&:&:; 0+1o+19< ^  Try it online! I can add a more detail description if anyone is interested, but here's an overview of how it works. The input it expects is a string of digits. Since the challenge specified that the list was made up of single digit numbers, I chose not to include a delimiter. If that's a requirement, some additional stuff would have to be added... The first line reads in the first number, uses it to set the register (for comparison as the rest of the list is read in), then pushes a counter that tracks the number of times the first number has been seen. Then it passed control down to the next line. i:o&0v  That line reads one digit at a time, starting with the second digit, and prints it. There's a conditional code to add a \n when the counter hits 1 (meaning it found the second occurrence of the first digit). The code is interpreted right to left to save characters. ?(0:i<o$v?<=1:+{=&:&:;


The last line is effectively like a "function" call to print a linefeed and tweak the counter so that it will never be called again.

0+1o+19< ^

• FYI, the "doublepost" before happened when the StackExchange site was error'ing with a "We're doing maintenance" page for a few mins.... Sorry about that! Jun 4, 2021 at 1:03
• Neat approach! Using FS and RS uses 3 less bytes: sub(FS$1,RS$1) Try it online! Jun 4, 2021 at 3:34
• 3 fewer……..….:)
– user7467
Jun 4, 2021 at 5:57

# Vim, 3 bytes/keystrokes

*O<esc>


# V (vim), 2 bytes

*O


Try it online!

Since V has implicit escape after O (?), we can use just 2 bytes.

Old (general) 8-byter:

Y/<C-r>"<BS><CR>O<esc>


Input is each list item on a single line. Output is two lists separated by a blank line.

Uses vim notation for the keystrokes (<C-r> is Ctrl-R, etc.; see :help key-notation).

Explanation:

• Y yank the first line
• /<C-r>"<BS><CR> search for the next occurrence by inserting the yanked text into a search /. Yanking into the search register with "/Y doesn't work (:help quote/). The backspace deletes the line-ending, which is yanked. (Alternately, use y$/<C-r>"<CR>.) • O<esc> new blank line above. This generalizes to any type of list as long as each element is a single line. I don't think we can use POSIX vi for this, since I don't think it has <C-r> to insert registers. It doesn't have the search register "/, but that doesn't end up mattering. • Don't golf often, so not sure how to link/format the header in this case Jun 5, 2021 at 0:03 • Is * command helpful? – tsh Jun 5, 2021 at 1:43 • @tsh doh! I was trying to be too general! Jun 5, 2021 at 2:47 • since the question requires the element to be inside the split, I think *i<cr> should be correct. Jun 5, 2021 at 5:04 • @Razetime thanks ; somehow I missed that. Jun 5, 2021 at 11:12 # Vyxal, 18 7 bytes Ṙṫ:‟€vp  Try it Online! # K (ngn/k), 11 bytes {(2#*=x)_x}  Try it online! • (...)_x cut the input (x) at... • 2#*=x the indices of the first two occurrences of the first value in the input # Factor, 37 35 bytes [ dup first 1 pick index-from cut ]  Try it online! ## Explanation: • dup Duplicate the input. Stack: (e.g.) { 0 2 2 3 0 1 0 1 } { 0 2 2 3 0 1 0 1 } • first Get first element. Stack: { 0 2 2 3 0 1 0 1 } 0 • 1 Push 1. Stack: { 0 2 2 3 0 1 0 1 } 0 1 • pick Put a copy of the object third from the top on top of the stack. Stack: { 0 2 2 3 0 1 0 1 } 0 1 { 0 2 2 3 0 1 0 1 } • index-from Find the index of 0 starting from index 1 in the sequence on top of the stack. Stack: { 0 2 2 3 0 1 0 1 } 4 • cut Split a sequence in two at an index. Stack: { 0 2 2 3 } { 0 1 0 1 } # Jelly, 7 bytes œṡḢ©®;Ɱ  Try it online! œṡḢ©®;Ɱ Main Link œṡ Split at the first occurence of Ḣ The first element (pops the element) © (also copies that element to the register) Ɱ For each block ®; Prepend the register  As pointed out by Nick Kennedy in the comments (full credit to them), Ḣ;Ɱœṡ@¥ also works and is slightly more functionally pure (though Ḣ still modifies the list itself, so it's not entirely pure): Ḣ;Ɱœṡ@¥ Main Link Ḣ Cut off and return the first element ¥ Last two as a dyad (for chaining; this makes the right argument the modified list for both inner dyads rather than applying consecutively) ;Ɱ Prepend the first element to each of œṡ@ The modified list, split at the first occurrence of the first element  • Nice. Ḣ;Ɱœṡ@¥ is another 7 that doesn’t use the register (the functional programmer in me likes links that leave the environment unmodified, though of course Ḣ does actually modify the argument to the link). Jun 3, 2021 at 22:24 • @NickKennedy Ooh, nice. I was trying to figure out how to get that working but the register trick was easier for me to find and I forgot to keep trying to find the right chaining pattern, lol. Jun 4, 2021 at 0:58 # Python 3.8, 41 bytes lambda l:[l[:(i:=l.index(l[0],1))],l[i:]]  Try it online! # Retina 0.8.2, 18 17 bytes ^((.).*?)\2$1¶$2  Try it online! Link is to test suite that double-spaces the output for convenience. Takes input as a string of digits. Explanation: Simply finds the earliest next match of the first character and inserts a newline before it. Edit: Saved 1 byte thanks to @Jakque. • Found an odd same score solution which uses that the first match found ltr using a lookbehind is the one we want. Couldn't get it shorter, but figured it may provide some inspiration. Jun 4, 2021 at 3:10 • Can't you use ^ instead of 1 at the start of your regex to ensure it will be only one replacement? I could save 1 byte Jun 4, 2021 at 8:46 • @FryAmTheEggman's I actually started with that approach, and had juggled things around (e.g. 1(?<=(.).*)\1 -> ¶$1) before ending up with what I have now.
– Neil
Jun 4, 2021 at 8:56
• @Jakque It was a legacy of my original approach, but obviously it's entirely unnecessary now, thanks!
– Neil
Jun 4, 2021 at 8:57

# JavaScript (ES6), 31 bytes

Thanks Razetime for -1 byte.

a=>a.match(/^(.).*?(?=\1)|.+/g)


Try it online!

• since .+ will greedily match anything, is the $ needed? Jun 4, 2021 at 9:15 • @Razetime it works. – tsh Jun 4, 2021 at 9:37 # BQN, 12 11 bytesSBCS ⊢⊔˜·∨·»⊑=«  Try it here. Explanation: ⊢⊔˜·∨·»⊑=« # tacit function which can take input as either a list or a string « # the input list shifted left = # equality comparison with ⊑ # the first element of the input ·» # shift the result right ·∨ # 'or' scan ⊢⊔˜ # group the input according to those values  # R, 3837 36 bytes Edit: -1 byte thanks to pajonk, as well as outputting the right-way-around now, and then -1 byte thanks to digEmAll function(l)by(l,cumsum(l==l[1])>1,c)  Try it online! • Jun 4, 2021 at 18:34 • @pajonk - Yes! Thanks! How did I miss that? Jun 4, 2021 at 18:40 • And it doesn't output in reverse order anymore after the edit. Jun 5, 2021 at 19:34 • -1 with by() Jun 7, 2021 at 15:42 • @digEmAll - Well, thanks very much, then! Updated. Jun 7, 2021 at 18:15 # J, 17 16 bytes (]{.,<@;@}.)<;.1  Try it online! In a sentence: Cut on first element and then meld together the tail elements. Consider f 0 2 2 3 0 1 0 1 • <;.1 Cut using the first element as the fret: ┌───────┬───┬───┐ │0 2 2 3│0 1│0 1│ └───────┴───┴───┘  • {.,<@;@}. First element of that result {. catted with tail of that result }., razed ; and then reboxed <@. ┌───────┬───────┐ │0 2 2 3│0 1 0 1│ └───────┴───────┘  # Zsh, 35 bytes shift>$1
ls
for x
(rm $x&&od;<<<$x)


Try it online!

Explanation:

• >$1: create a file named the first input item • shift: shift the input array, removing the first item • ls: list the directory. Since we created $1, this prints the first item
• for x: for each item $x in the input array: ( • rm$x: try to remove the item. If the item $x is the same as the first input, and the item has not already been removed, this will succeed • &&: if that succeeds: • od: print 0000000 as a separator • <<<$x: print the item

With some loose interpretation of what is allowed as a separator, we could have:

## Zsh, 33 bytes

shift>$1 ls for x rm -v$x||<<<$x  Try it online! • rm -v is verbose; if the removal is successful, a message removing 'x' is printed which is arguably a separator, as well as printing the item • ||: if that fails: • <<<$x: print the item. We only need to do this if removal fails, because rm -v prints the item already

# Red, 49 46 bytes

func[x][reduce[take/part x find next x x/1 x]]


Try it online!

# Scala, 35 30 bytes

Saved 5 bytes thanks to @cubic lettuce!

x=>x splitAt x.indexOf(x(0),1)


Try it in Scastie!

Hopefully, I'm not FGITW'ing this.

• You can save 5 bytes via x=>x splitAt x.indexOf(x(0),1) Jun 5, 2021 at 16:16

# JavaScript (ES6), 34 bytes

a=>[a,a.splice(a.indexOf(a[0],1))]


Try it online!

• I am not quite sure... Is "return first part from modify parameter in-place, return second part from return value" allowed by this question? a=>a.splice(a.indexOf(a[0],1))
– tsh
Jun 4, 2021 at 2:02

f(h:t)=(h#t)[h]
(h#(x:y))a|x==h=(a,x:y)|0<1=(h#y)$a++[x]  Try it online! Because why not? ## flawr's suggestion, 33 bytes f(x:y)|(a,b)<-break(==x)y=(x:a,b)  Try it online! This is based on Zgarb's solution (f(x:y)|(a,b)<-span(/=x)y=(x:a,b)). • fyi @zgarb's original version was f(x:y)|(a,b)<-span(/=x)y=(x:a,b) :) Jun 3, 2021 at 21:25 • @flawr I know, hence the "Because why not?" :P This is the shortest I could get without stealing Zgarb's solution :/ – user Jun 3, 2021 at 21:27 • ah sorry:) then I misunderstood. I mean you could still use f(x:y)|(a,b)<-break(==x)y=(x:a,b) :P Jun 3, 2021 at 21:30 • @flawr Feels a bit like cheating to me...let's do it! – user Jun 3, 2021 at 21:31 # PowerShell Core, 60 57 bytes $a,$b=$args
$r=(,$a),$y$b|%{$r[$r[1]-or$_-eq$a]+=,$_}$r


Try it online!

It takes the input as an array of ints, returns two arrays

### Another approach for 59 bytes

param($a)$a[0..(($i=$a|% i*f $a[0] 1)-1)],$a[$i..$a.Length]


Try it online!

Takes the input as a string, returns two arrays

• The $y is always empty in the 2nd line Jun 4, 2021 at 6:37 • @mazzy Yes this is on purpose, I needed something null, shorter than $null or @() Jun 5, 2021 at 1:29

# Red, 67 bytes

func[b][collect[keep/only take/part b find next b b/1 keep/only b]]


Try it online!

# Python 2, 45 bytes

i=input()
a=i.index(i[0],1)
print i[:a],i[a:]


Try it online!

# Wolfram Language (Mathematica), 26 bytes

g[b_,a___,b_,c___]=b.a|b.c


Try it online!

-10 bytes thanks to @att

• 33 bytes
– att
Jun 4, 2021 at 3:18
• or 26 with a more generous I/O interpretation
– att
Jun 4, 2021 at 3:20

# 05AB1E, 8 7 bytes

ćk>Ig‚£


7 bytes alternative provided by @ovs:

ćk>°RÅ¡


Explanation:

ć       # Extract head of the (implicit) input-list; pop and push remainder-list and
# first item separated to the stack
k      # Get the first 0-based index of this item in the remainder-list
>     # Increase it by 1 to make it a 1-based index
Ig   # Get the length of the input-list
‚  # Pair them together
£ # And split the (implicit) input-list into parts of that size
# (after which the result is output implicitly as result)

ćk>     # Same as above
°    # Pop and push 10 to the power this 1-based index
R   # Reverse it, so we have a 1 with some leading 0s
Å¡ # Split the (implicit) input-list at the truthy indices (or singular index in
# this case: the 1)
# (after which the result is output implicitly as result)

• ćk>°RÅ¡ is another 7 byter.
– ovs
Jul 28, 2021 at 13:27
• @ovs Ah nice! My original 8-byter was using Å¡ as well, but I had something along the lines of āsćkÌQÅ¡ instead. I'll add yours as an alternative to the answer. Jul 28, 2021 at 15:44

# Vyxalṡ, 5 bytes

hẆḢḣf


Try it Online!

Explanation:

h      # Get the first element of the list
Ẇ     # Split list on head, without removing it from the list
Ḣḣ   # Get the first element from the resulting list
f  # Flatten the rest of the resulting list
# 'ṡ' flag - print both lists, separated by a space


# Japt, 8 bytes

Feels like there should be a shorter way for this, but can't seem to find it right now.

Selecting the right-hand element ensures we don't select the first letter itself, the check on the incremented variable ensures we only split once.

óÏ¦UÎªT°
ó        // Split the input string between char pairs where it's not true that
Ï       // the right-hand element
¦      // is different than
UÎ    // the first char of the input
ª   // or
T° // T, initially equals zero, plus plus.


Try it here.

• I can't seem to do better than 8, either. Jul 29, 2021 at 9:43

# JavaScript (V8), 54 bytes

x=>[x[s="slice"](0,i=x[s](1).indexOf(x[0])+1),x[s](i)]


Try it online!

• Note that you should split before not at the element, so the output should contain the same digits at the input, but as two lists ([0,1,0] -> [[0,1],[0]]) Jun 3, 2021 at 21:17
• @cairdcoinheringaahing Ah, didn't notice that. That actually saves two bytes! Jun 3, 2021 at 21:17

# MATLAB/Octave, 63 bytes

function y=f(x)
l=find(x==x(1));y={x(1:l(2)-1),x(l(2):end)};end


Try it online!
Outputs cell aray with 2 cells, which hold appropriate vectors. I've chosen such output because rules say 2 lists must be distinguished, not necessarily be separate variables. And outputting 2 variables turned out to give a little longer code.

Ungolfed/explained:

function y = f(x)
l = find( x==x(1) );   % indices of elements equal to first element
l2 = l(2);             % index of second occurence
y = { x(1:(l2-1)),...  % vector containing elements before 2nd occurence
x(l2:end) };     % vector containing elements from 2nd occurence
end


Interestingly, it's also possible to create anonymous function that does the same, but it's 2 bytes longer:

@(x){x(1:find(x(2:end)==x(1),1)),x(find(x(2:end)==x(1),1)+1:end)}


Try it online!
It is possible to shorten it more as flawr noticed, resulting in 42 bytes but it's an Octave-only solution, not working for MATLAB:

@(x){x(1:(l=find(x==x(1))(2))-1),x(l:end)}


Try it online!

• Actually you can shorten the anonymous function to f=@(x){x(1:(l=find(x==x(1))(2))-1),x(l:end)} - in Octave assignments are expressions too! Jun 3, 2021 at 22:50
• @flawr sadly, this doesn't work in MATLAB. Jun 3, 2021 at 23:24

# Husk, 12 bytes

Fȯ:;:←¹↕≠←¹t


Try it online!

no split at index builtin, but ↕ (span) helps a bit.

it's similar to xnor(and Zgarb)'s answer, but argument destructuring and functors don't exits, so it just uses a fold.

# Vyxal, 8 bytes

ḣ$£¥€ƛ¥p  Try it Online! This is possible in 8 bytes Imao # Stax, 10 bytes τÄ∩T╕(û▒(Ç  Run and debug it annoyingly long, but i guess it works. ### Stax, 12 bytes(regex) êt┴≈∟·M╤\+6)  Run and debug it ### Stax, 22 bytes(tsh's regex) "^(.).*?(?=\1)|.+$"|Fm
`

Run and debug it