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

Why should you golf in Haskell? Find out here. In that answer, Zgarb defines a task:

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 :) – caird coinheringaahing Jun 3 at 21:04
• I don't know what a 'Bronie' is, but it doesn't sound good. – A username Jun 4 at 10:28
• @AidenChow You can output a single string with a clear separator between the parts (see Neil's Retina answer), does that work? – caird coinheringaahing Jun 4 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 :( – caird coinheringaahing Jun 4 at 20:48
• @cairdcoinheringaahing Yes that can work! Thanks for being flexible with your specifications regarding I/O. – Aiden Chow Jun 5 at 4:30

# Haskell, 26 bytes

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! – cnamejj Jun 4 at 1:03
• Neat approach! Using FS and RS uses 3 less bytes: sub(FS$1,RS$1) Try it online! – Pedro Maimere Jun 4 at 3:34
• 3 fewer……..….:) – Anush Jun 4 at 5:57

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

# Vyxal, 18 7 bytes

Ṙṫ:‟€vp


Try it Online!

# Vim, 3 bytes/keystrokes

*O<esc>


Jump to next occurrence of word and make a new line.

# 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 – D. Ben Knoble Jun 5 at 0:03 • Is * command helpful? – tsh Jun 5 at 1:43 • @tsh doh! I was trying to be too general! – D. Ben Knoble Jun 5 at 2:47 • since the question requires the element to be inside the split, I think *i<cr> should be correct. – Razetime Jun 5 at 5:04 • @Razetime thanks ; somehow I missed that. – D. Ben Knoble Jun 5 at 11:12 # 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. – FryAmTheEggman Jun 4 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 – Jakque Jun 4 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 at 8:56
• @Jakque It was a legacy of my original approach, but obviously it's entirely unnecessary now, thanks! – Neil Jun 4 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? – Razetime Jun 4 at 9:15 • @Razetime it works. – tsh Jun 4 at 9:37 # 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). – Nick Kennedy Jun 3 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. – hyper-neutrino Jun 4 at 0:58 # Python 3.8, 41 bytes lambda l:[l[:(i:=l.index(l[0],1))],l[i:]]  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 # 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  # 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) – cubic lettuce Jun 5 at 16:16 # 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! • – pajonk Jun 4 at 18:34 • @pajonk - Yes! Thanks! How did I miss that? – Dominic van Essen Jun 4 at 18:40 • And it doesn't output in reverse order anymore after the edit. – pajonk Jun 5 at 19:34 • -1 with by() – digEmAll Jun 7 at 15:42 • @digEmAll - Well, thanks very much, then! Updated. – Dominic van Essen Jun 7 at 18:15 # 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 at 2:02 # Haskell, 56 bytes 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) :) – flawr Jun 3 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 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 – flawr Jun 3 at 21:30
• @flawr Feels a bit like cheating to me...let's do it! – user Jun 3 at 21:31

# 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│
└───────┴───────┘


# PowerShell Core, 60 57 bytes

$a,$b=$args$r=(,$a),$y
$b|%{$r[$r[1]-or$_-eq$a]+=,$_}
• @mazzy Yes this is on purpose, I needed something null, shorter than $null or @() – Julian Jun 5 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 at 3:18 • or 26 with a more generous I/O interpretation – att Jun 4 at 3:20 # 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

# 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]]) – caird coinheringaahing Jun 3 at 21:17
• @cairdcoinheringaahing Ah, didn't notice that. That actually saves two bytes! – Redwolf Programs Jun 3 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! – flawr Jun 3 at 22:50
• @flawr sadly, this doesn't work in MATLAB. – elementiro Jun 3 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

# ><>, 21 bytes

<0o{oa.0*3+)3l=}:{::i


Try it online!

Takes input as a list of characters (though you are free to put whatever you want in-between digits). Managed to reuse my check that we're not splitting on the first input with the jump quite nicely.

### Explanation

<                      Go left from the start
::i   Get the input and duplicate it twice
=}:{      Compare it with the first character of the input
)3l          Check if this is not the first char
*3+             Add these checks together and multiply by 3
This will be 3 if the digit is not the same, or if it is the first digit, otherwise 6
.0                Jump to that point on the first line
{oa                  If it is the split point, print a newline and clear the first digit
o                     Print the current digit
0                      Push a zero to increase the stack height for the first digit check


# APL (Dyalog Unicode), 13 bytes (SBCS)

Anonymous tacit prefix function

⊢⊂⍨1,⊃<\⍤=1↓⊢


Try it online!

⊢ the argument

1↓ drop first element

⊃…  apply the following tacit infix function to that, with the first element of the argument as left argument:

⍤= Boolean mask indicating where they are equal

<\ cumulative right-associative less-than scan (effectively zeroes any one after the first one)

1, prepend a one

⊢⊂⍨ use that to partition the argument, starting a new segment on every 1

# Python 3.8, 40 chars

If outputting a list of two strings is allowed...

lambda s:[s[:(i:=s.find(s[0],1))],s[i:]]
`