51
\$\begingroup\$

Related.

Given a printable ASCII string, split it into a list of non-empty strings with a new sub-string beginning every time a character, which has not previously been seen in the same case, occurs.

Examples

"mississippi" → ["m","i","ssissi","ppi"]

"P P & C G" → ["P"," P ","& ","C ","G"]

"AAA" → ["AAA"]

"Adam" → ["A","d","a","m"]

"" → []


Anecdote: The result will have between 0 and 95 elements. The 95th sub-string will necessarily continue until the end because at that point, all printable ASCII characters have begun a sub-string, so every additional character will have occurred before and thus cannot cause a new sub-string to begin.

\$\endgroup\$
19
  • 1
    \$\begingroup\$ An example containing " and ' seems like a good idea. \$\endgroup\$
    – Emigna
    Commented Feb 19, 2018 at 18:15
  • \$\begingroup\$ Would ""[""] be acceptable? \$\endgroup\$
    – Arnauld
    Commented Feb 19, 2018 at 18:18
  • 5
    \$\begingroup\$ @Emigna That just messes with the example output format without bringing any further clarity. \$\endgroup\$
    – Adám
    Commented Feb 19, 2018 at 18:22
  • 1
    \$\begingroup\$ If outputting as a newline-separated string, can there be a leading/trailing newline? \$\endgroup\$
    – wastl
    Commented Feb 19, 2018 at 21:32
  • 2
    \$\begingroup\$ @wastl Uh, I'll permit it in this case because it cannot indicate empty segments, although it does clash with my earlier ruling of [""] to be invalid. Sigh. \$\endgroup\$
    – Adám
    Commented Feb 19, 2018 at 21:56

55 Answers 55

25
\$\begingroup\$

Jelly, 4 bytes

QƤĠị

Try it online!

Explanation

QƤĠị  Input is a string, say s = "adam"
 Ƥ    For each prefix of s: ["a","ad","ada","adam"]
Q     remove duplicates: ["a","ad","ad","adm"]
  Ġ   Group indices by equal values: [[1],[2,3],[4]]
   ị  Index into s: ["a","da","m"]

The internal representation of the strings, which the TIO link displays, is slightly different.

\$\endgroup\$
4
  • \$\begingroup\$ Can someone explain the logic of this solution? I can see that it does work, but I can't get my head around why it works; like, I wouldn't have thought that indexing back into the original string where the deduped prefixes match would yield the answer. \$\endgroup\$
    – Aaron
    Commented Feb 27 at 5:55
  • \$\begingroup\$ The list p of nonempty prefixes of s has the same length as s. For each index i, the string p[i] is the prefix of s up to and including s[i]. Two adjacent chars s[i] and s[i+1] should be in the same chunk in the output if s[i+1] already occurred before index i, or in other words, in the prefix p[i]. This is equivalent to p[i] and p[i+1] having the same set of unique characters. I compute with the unique characters of each prefix p[i]. \$\endgroup\$
    – Zgarb
    Commented Feb 29 at 11:17
  • \$\begingroup\$ @Aaron Then with Ġ I group the indices i of this list of strings: indices i and i+1 go in the same chunk if p[i] and p[i+1] have the same unique characters. Finally, with I index back to the original string s, essentially grouping it into chunks in the same way as the indices i. \$\endgroup\$
    – Zgarb
    Commented Feb 29 at 11:18
  • \$\begingroup\$ Thank you, that's starting to make a bit more sense for me. Impressive answer! \$\endgroup\$
    – Aaron
    Commented Feb 29 at 19:51
10
\$\begingroup\$

Retina, 9 bytes

q1,`.
¶$&

Try it online!

Explanation

Match each character (.), discard repeated matches (q), discard the first match (1,), and insert a linefeed in front of each match ¶$&.

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

05AB1E, 11 bytes

ÙSk¥sg¸«£õK

Try it online!

Explanation

Ù             # remove duplicates in input
 S            # split to a list of characters
  k           # get the (first) index of each character in the input
   ¥          # calculate delta's
    sg¸«      # append the length of the input
        £     # split the list into pieces of these sizes
         õK   # remove empty string (for the special case "" -> [])
\$\endgroup\$
1
  • 1
    \$\begingroup\$ For anyone coming across this answer, ¸« can be ª in the new version of 05AB1E. \$\endgroup\$ Commented Mar 8, 2019 at 12:43
6
\$\begingroup\$

J, 7 bytes

~:<;.1]

Try it online!

Explanation

Nub sieve's chance to shine!

~: <;.1 ]
        ]  Input
~:         Nub sieve (1 if the character is the first instance in string)
    ;.1    Split input on 1s in nub sieve
   <       And box each
\$\endgroup\$
2
  • 2
    \$\begingroup\$ I was about to post exactly the same (not surprisingly) answer, it's good that I glanced your submission before that :) \$\endgroup\$ Commented Feb 19, 2018 at 19:48
  • 2
    \$\begingroup\$ @GalenIvanov I -- and I imagine most other J golfers, too -- relish the chance to use nub sieve or self-classify. \$\endgroup\$
    – cole
    Commented Feb 19, 2018 at 20:18
6
\$\begingroup\$

APL (Dyalog Unicode), 8 bytesSBCS

(≢¨∪\)⊆⊢

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ But, but… Oh my. \$\endgroup\$
    – Adám
    Commented Feb 20, 2018 at 18:06
  • \$\begingroup\$ I suspected you might have posted this challenge because of the new primitive (⊆). Evidently not :) \$\endgroup\$
    – ngn
    Commented Feb 20, 2018 at 20:15
  • \$\begingroup\$ It looks like an embarrassed Kirby holding a baby bottle. \$\endgroup\$ Commented Feb 20, 2018 at 20:24
  • \$\begingroup\$ Can be just three characters now ≠⊂⊢ \$\endgroup\$
    – Tbw
    Commented Feb 21 at 17:51
6
\$\begingroup\$

05AB1E, 8 bytes

Ùvyy¶ì.;

Try it online!


Always will output 1 preceding newline, which is constant and not indicative of a split, the 10-byte alternative that does not output a preceding newline is Ùvyy¶ì.;}¦, you can try that here. According to Adam a preceding or trailing newline is acceptable.


Input      = mississippi                               | Stack
-----------#-------------------------------------------+----------------------------------
Ù          # Push unique letters of first input.       | ['misp']
 v         # Iterate through each unique letter.       | []
  yy       # Push 2 copies of the letter (or yD)       | ['m','m']
    ¶      # Push a newline char.                      | ['m','m','\n']
     ì     # Prepended to the letter.                  | ['m','\nm']
      .;   # Replace first instance with '\n + letter' | ['\nmississippi']

After each iteration we get:

['\nmississippi'] > ['\nm\nississippi'] > ['\nm\ni\nssissippi'] > ['\nm\ni\nssissi\nppi']

Which is:

m
i
ssissi
ppi
\$\endgroup\$
5
  • \$\begingroup\$ Nice! Beat me by a fair margin ;) \$\endgroup\$
    – Emigna
    Commented Feb 28, 2018 at 13:57
  • \$\begingroup\$ @Emigna this was sitting as a comment on your answer for 2 days then I just posted it b/c no response haha :P. \$\endgroup\$ Commented Feb 28, 2018 at 14:06
  • \$\begingroup\$ Weird, haven't seen any notification on that. Different enough for its own answer though :) \$\endgroup\$
    – Emigna
    Commented Feb 28, 2018 at 14:14
  • \$\begingroup\$ @Emigna well, I mean, I deleted it haha. \$\endgroup\$ Commented Feb 28, 2018 at 15:56
  • 1
    \$\begingroup\$ Skipping the loop saves a byte ÙSD¶ì.;. Not sure why we didn't think of that before :P \$\endgroup\$
    – Emigna
    Commented Mar 8, 2019 at 12:10
6
\$\begingroup\$

C,  75   65  63 bytes

Thanks to @Digital Trauma for saving 10 bytes and thanks to both @gastropner and @l4m2 for saving a byte each!

f(char*s){for(int l[128]={};*s;putchar(*s++))l[*s]++||puts(l);}

Prints a leading newline.

Try it online!

Without a leading newline (71 bytes):

f(char*s){int l[128]={};for(l[*s]=1;*s;putchar(*s++))l[*s]++||puts(l);}

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 64 bytes \$\endgroup\$
    – gastropner
    Commented Feb 21, 2018 at 15:30
  • \$\begingroup\$ {0} => {} ? \$\endgroup\$
    – l4m2
    Commented Mar 9, 2018 at 23:02
5
\$\begingroup\$

Perl 6,  58 52  40 bytes

{$/={};.comb.classify({$+=!$/{$_}++}).sort».value».join}

Try it

*.comb.classify({$+=!(%){$_}++}).sort».value».join

Try it

*.classify({$+=!(%){$_}++}).sort».value

Try it
(input is a list of characters, and output is a list of lists of characters)

Expanded:

*                   # parameter for WhateverCode lambda

  .classify(        # classify that list
    {
        $           # anonymous scalar state variable (accumulator)

      +=            # increment it if:

        !           # Bool invert the following
          (
            %       # anonymous hash state variable
          ){ $_ }++ # look to see if the character was seen already
    }
  ).sort\           # sort the Pairs by key (makes the order correct)
  ».value           # get the value from each Pair

The output from classify is

{ # Hash
  1 => ['m'],
  2 => ['i'],
  3 => ['s','s','i','s','s','i'],
  4 => ['p','p','i'],
}

And .sort just turns it into:

[
  1 => ['m'],
  2 => ['i'],
  3 => ['s','s','i','s','s','i'],
  4 => ['p','p','i'],
]

».value removes the keys

[
  ['m'],
  ['i'],
  ['s','s','i','s','s','i'],
  ['p','p','i'],
]
\$\endgroup\$
2
  • \$\begingroup\$ Why would the keys ever be out of order? Is insertion order not tracked like a HashMap vs. a LinkedHashMap in Java where the order is based on memory vs. insert order? \$\endgroup\$ Commented Feb 20, 2018 at 17:18
  • 1
    \$\begingroup\$ @MagicOctopusUrn No version of Perl has had ordered Hashes. In fact Perl 5 version 18 made Hashes more randomized which helps make a certain type of denial of service attack less possible, and has also caused buggy user code to expose it's buggy behaviour more often. Now someone could (and likely has) implement a class which does keep track, but that would take more than 5 characters to load and use. \$\endgroup\$ Commented Feb 20, 2018 at 20:12
5
\$\begingroup\$

Haskell, 39 bytes

foldl(\s c->s++['\n'|all(/=c)s]++[c])""

Try it online!

Inserts a newline symbol before every character that appears for the first time, resulting in a newline-separated string, with a leading newline. Prepend lines. to produce a list.


Haskell, 55 bytes

(""%)
_%[]=[]
p%s|(a,b)<-span(`elem`s!!0:p)s=a:(a++p)%b

Try it online!

Repeatedly takes the prefix the first character plus the non-unique characters that follow it.

\$\endgroup\$
2
  • \$\begingroup\$ @WheatWizard Oops, yes, lines. \$\endgroup\$
    – xnor
    Commented Feb 21, 2018 at 4:42
  • \$\begingroup\$ Might want to do tail.lines to remove the extra empty string now that I think about it. \$\endgroup\$
    – Wheat Wizard
    Commented Feb 21, 2018 at 6:06
4
\$\begingroup\$

APL (Dyalog), 9 bytes

Thanks, Erik the Outgolfer for saving 1 byte!

⊢⊂⍨⍳∘≢∊⍳⍨

Try it online!

Explanation:

⍳⍨: For each character, get the index of its first occurrence. e.g mississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢: The range from 1 to the length of the input.

: Membership. e.g 1 2 3 4 5 6 7 8 9 10 11∊1 2 3 3 2 3 3 2 9 9 2 -> 1 1 1 0 0 0 0 0 1 0 0

⊢⊂⍨: Partition the input string with new partitions starting at 1s in the vector above

\$\endgroup\$
3
  • \$\begingroup\$ 9 bytes (monadic fg and monadic f∘g behave the same) \$\endgroup\$ Commented Feb 19, 2018 at 18:37
  • \$\begingroup\$ Why instead of =? \$\endgroup\$
    – Adám
    Commented Feb 20, 2018 at 9:32
  • \$\begingroup\$ At the time of writing, I hadn't considered that the indices would be in the correct positions. Although it is clear that they are \$\endgroup\$
    – H.PWiz
    Commented Feb 20, 2018 at 17:01
4
\$\begingroup\$

JavaScript (ES6), 37 bytes

Saved 7 bytes: a leading newline was explicitly allowed (Thanks @Shaggy!)

Takes input as an array of characters. Outputs a newline-separated string.

s=>s.map(c=>s[c]=s[c]?c:`
`+c).join``

Test cases

let f =

s=>s.map(c=>s[c]=s[c]?c:`
`+c).join``

;[
  [..."mississippi"],
  [..."P P & C G"],
  [..."AAA"],
  [..."Adam"],
  [...""]    
]
.forEach(s => console.log('{' + f(s) + '}\n'))

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

Japt, 11 bytes

‰ r@=iRUbY

Test it online!

Explanation

This was inspired by Magic Octopus Urn's 05AB1E solution.

‰ r@=iRUbY    Implicit: U = input string
‰             Split U into chars, and keep only the first occurrence of each.
   r@          Reduce; for each char Y in this string...
        UbY      Find the first index of Y in U.
      iR         Insert a newline at this index in U.
     =           Set U to the result.
               As reduce returns the result of the last function call, this gives the
               value of U after the final replacement, which is implicitly printed.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Japt is having an identity crisis here, it's calling itself Ruby for some reason. iRUbY! \$\endgroup\$ Commented Feb 21, 2018 at 15:37
3
\$\begingroup\$

Python 2, 81 74 bytes

def f(s):d=sorted(map(s.find,set(s)));print map(lambda a,b:s[a:b],d,d[1:])

Try it online!

\$\endgroup\$
5
  • \$\begingroup\$ Save two with list(set(map(s.find,s))) \$\endgroup\$ Commented Feb 19, 2018 at 19:41
  • \$\begingroup\$ @JonathanAllan it's a misleading side-effect, set do not keep order, counter-proof -> s='c'*6+'a'*100+'b' \$\endgroup\$
    – Rod
    Commented Feb 19, 2018 at 19:59
  • \$\begingroup\$ I know we cannot rely on it in future implementations but I believe given ordered integers we maintain order in the set due to the hash of an integer being the integer (as you have shown the same is not true for other objects -- can you find a word that does not work with my alternative?). \$\endgroup\$ Commented Feb 19, 2018 at 22:07
  • \$\begingroup\$ @JonathanAllan not true either \$\endgroup\$
    – Rod
    Commented Feb 20, 2018 at 0:14
  • \$\begingroup\$ Ah, fair enough, my belief was false! \$\endgroup\$ Commented Feb 20, 2018 at 0:22
3
\$\begingroup\$

Python 2, 47 bytes

lambda s:reduce(lambda r,c:r+'\n'[c in r:]+c,s)

Try it online!

Outputs a newline-separated string. Barely beats the program version:

Python 2, 48 bytes

r=''
for c in input():r+='\n'[c in r:]+c
print r

Try it online!

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

R, 94 87 bytes

function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))

Try it online!

Returns a (possibly empty) list of substrings.

Thanks to Michael M for saving 7 bytes!

\$\endgroup\$
7
  • 3
    \$\begingroup\$ function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n)) would be shorter - and of course a bit uglier... \$\endgroup\$
    – Michael M
    Commented Feb 19, 2018 at 20:25
  • \$\begingroup\$ Why substring instead of substr? \$\endgroup\$
    – plannapus
    Commented Feb 20, 2018 at 9:48
  • \$\begingroup\$ @MichaelM Very nice! I still have to add the if(n) in there because substring throws an error for empty string input. \$\endgroup\$
    – Giuseppe
    Commented Feb 20, 2018 at 12:20
  • 1
    \$\begingroup\$ @plannapus substr returns a vector of length equal to its first input while substring returns one of length equal to the longest of its inputs. \$\endgroup\$
    – Giuseppe
    Commented Feb 20, 2018 at 12:22
  • \$\begingroup\$ @Giuseppe: Dropping the "if(n)" in R 3.4.3 maps the empty input string "" to the empty output string "", which should be fine(?) \$\endgroup\$
    – Michael M
    Commented Feb 20, 2018 at 14:51
3
\$\begingroup\$

brainfuck, 66 bytes

,[>+[<[>+<<-<+>>-]>[>]<<[[+]++++++++++.>>>]<]<[>+<-]>>>[>>]<<-.>,]

Formatted:

,
[
  >+
  [
    <[>+< <-<+>>-]
    >[>]
    <<[[+]++++++++++.>>>]
    <
  ]
  <[>+<-]
  >>>[>>]
  <<-.>,
]

Try it online

The leading newline in the output (which is only printed if the input is non-empty) can be removed at the cost of 5 bytes by replacing the body x of the main (outermost) loop with .>,[x].

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

BQN, 11 6 bytes

⌈`∘⊐⊸⊔

Try it at BQN online!

Explanation

⌈`∘⊐⊸⊔
   ⊐    Classify: replace each letter with a number based on the order of
        their first occurrences
⌈`∘     Scan with maximum: replace each number with the largest number so far
    ⊸⊔  Group the original string into those buckets

A couple of worked examples:

"dodos"            "Mississippi"
⟨ 0 1 0 1 2 ⟩       ⟨ 0 1 2 2 1 2 2 1 3 3 1 ⟩
⟨ 0 1 1 1 2 ⟩       ⟨ 0 1 2 2 2 2 2 2 3 3 3 ⟩
⟨ "d" "odo" "s" ⟩   ⟨ "M" "i" "ssissi" "ppi" ⟩
\$\endgroup\$
3
\$\begingroup\$

R, 86 bytes

function(s)strsplit(intToUtf8(Reduce(function(a,b)c(a,9*!b%in%a,b),utf8ToInt(s))),"	")

Try it online!

Based on the great +1 xnor's answer with some R-specific features.

Takes a string as an input and outputs a vector of strings.

EDIT: added strsplit(...) to output as a vector.

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

Jelly, 6 bytes

ŒQœṗ⁸Ḋ

Try it online!

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

K4, 19 bytes

Solution:

$[#x;(*:'.=x)_;,]x:

Examples:

q)k)$[#x;(*:'.=x)_;,]x:"mississippi"
,"m"
,"i"
"ssissi"
"ppi"
q)k)$[#x;(*:'.=x)_;,]x:"P P & C G"
,"P"
" P "
"& "
"C "
,"G"
q)k)$[#x;(*:'.=x)_;,]x:"AAA"
"AAA"
q)k)$[#x;(*:'.=x)_;,]x:"Adam"
,"A"
,"d"
,"a"
,"m"
q)k)$[#x;(*:'.=x)_;,]x:""
,[""]

Explanation:

8 bytes is just to handle ""...

$[#x;(*:'.=x)_;,]x: / the solution
                 x: / save input as variable x
$[  ;         ; ]   / $[condition;true;false]
  #x                / length of x ("" has length 0, i.e. false)
             _      / cut right at left indices
     (      )       / do together
          =x        / group x into key/value (char!indices)
         .          / return value (get indices)
      *:'           / first (*:) each
               ,    / enlist, "" => [""]
\$\endgroup\$
2
\$\begingroup\$

Perl, 30 bytes

Includes +1 for p

Give input without trailing newline on STDIN. Output is also without trailing newline:

echo -n adam | perl -pE 's%.%$v{$&}+++!pos?$&:$/.$&%eg'; echo

If you don't care about leading and trailing newlines this 25 (+3 for -p because the code contains ') also works:

#!/usr/bin/perl -p
s%%$/x!$v{$'&~v0}++%eg
\$\endgroup\$
5
  • \$\begingroup\$ Great solution as always! Based on the test cases provided, you don't need to name your hash, you can do ${$&}++. It's not as robust, but might suffice for this challenge? Also, there's been a consensus on meta that perl -p doesn't need an additional byte, you just need to have the header as Perl with `-p` instead of just Perl. I'm trying to remember to do that myself... \$\endgroup\$ Commented Feb 20, 2018 at 10:08
  • \$\begingroup\$ @DomHastings The annecdote about at most 95 possible strings quite strongly implies that 1 is valid, in which case the v is needed. Regarding the counting, I mostly follow codegolf.meta.stackexchange.com/a/7539/51507 which to me is the most consistent meta post about counting perl. \$\endgroup\$
    – Ton Hospel
    Commented Feb 20, 2018 at 13:04
  • \$\begingroup\$ Always nice to learn from the master. Specifically, in this case, &~v0 for grabbing the first character. Thank you for joining this site and sharing your long expertise. \$\endgroup\$
    – msh210
    Commented Mar 6, 2018 at 21:54
  • \$\begingroup\$ You can use Strawberry Perl, which uses " instead of ' with -e, and then you can count the -ep as +1 rather than +3. (Tested.) \$\endgroup\$
    – msh210
    Commented Mar 6, 2018 at 22:06
  • \$\begingroup\$ Redoing your 30 byte solution which does not put in a leading newline, I think you can save by using a negative lookbehind to skip the first newline. That way, the use of pos can be eliminated, also removing the need for the conditional operator. Try it online! \$\endgroup\$
    – Xcali
    Commented Feb 21 at 17:48
2
\$\begingroup\$

JavaScript, 61 54 52 bytes

Takes input as an array of characters.

s=>s.map(x=>a[x]?a[y]+=x:a[x]=a[++y]=x,a=[],y=-1)&&a

Try it

o.innerText=JSON.stringify((f=
s=>s.map(x=>a[x]?a[y]+=x:a[x]=a[++y]=x,a=[],y=-1)&&a
)([...i.value=""]));oninput=_=>o.innerText=JSON.stringify(f([...i.value]))
<input id=i><pre id=o></pre>

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

Stax, 8 bytes

ç↓‼►▐NVh

Run and debug online

The ascii representation of the same program is this.

c{[Ii=}(m

For each character, it splits when the index of the current character is the current position.

c            copy the input
 {    }(     split the string when the result of the enclosed block is truthy
  [          duplicate the input string under the top of the stack
   I         get the character index of the current character
    i=       is it equal to the iteration index?
        m    print each substring
\$\endgroup\$
2
\$\begingroup\$

Java 8, 193 169 155 151 bytes

s->{for(int l=s.length(),i=0,j;i<l;i++)if(s.indexOf(s.charAt(i))==i){for(j=i;++j<l&&s.indexOf(s.charAt(j))!=j;);System.out.println(s.substring(i,j));}}

-14 bytes thanks to @raznagul (for something obvious I somehow missed myself..)
-3 bytes thanks to @O.O.Balance (again for something obvious I somehow missed myself.. :S)

Explanation:

Try it online.

s->{                    // Method with String parameter and no return-type
  for(int l=s.length(), //  The length of the input-String
          i=0,j;        //  Index integers
      i<l;i++)          //  Loop `i` from 0 to `l` (exclusive)
    if(s.indexOf(s.charAt(i))==i){
                        //   If the character at index `i` hasn't occurred yet:
      for(j=i;++j<l     //    Inner loop `j` from `i` to `l` (exclusive),
          &&s.indexOf(s.charAt(j))!=j;);
                        //     as long as the character at index `j` has already occurred
      System.out.println(//    Print:
        s.substring(i,j));}}
                        //     The substring of the input from index `i` to `j` (exclusive)
\$\endgroup\$
4
  • 1
    \$\begingroup\$ I don't think you need the if(l<1). If l is 0 the loop shouldn't be executed anyway as 0<0 is false. \$\endgroup\$
    – raznagul
    Commented Feb 20, 2018 at 14:46
  • \$\begingroup\$ @raznagul Not sure how I missed that, but you're complete right!.. >.> \$\endgroup\$ Commented Feb 20, 2018 at 14:56
  • \$\begingroup\$ You're setting i=0 twice. You can save 3 bytes by dropping the second one: for(;i<l;i++) \$\endgroup\$ Commented Jul 18, 2018 at 19:27
  • \$\begingroup\$ @O.O.Balance Not sure how that happened.. :S But thanks for noticing! :) \$\endgroup\$ Commented Jul 19, 2018 at 8:23
2
\$\begingroup\$

><>, 22 17 14 bytes

-1 byte thanks to Emigna

i:::a$1g?!o1po

Try it online!

Prints a leading and trailing newline.

It keeps track of which letters have already appeared by putting a copy of the character at that corresponding spot on the second row, and printing a newline if the value fetched from that position was not 1. Ends in an error when it tries to print -1

\$\endgroup\$
1
  • \$\begingroup\$ Great use of g/p! 16 bytes \$\endgroup\$
    – Emigna
    Commented Mar 8, 2019 at 12:22
2
\$\begingroup\$

Perl 5 + -pl, 22 bytes

s@.@$/x!$h{$&}++.$&@ge

Try it online!

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

R, 83 82 bytes

function(s)if(s>"")substring(s,i<-which(!duplicated(utf8ToInt(s))),c(i[-1],1e6)-1)

Try it online!

Different approach to int 21h Glory to Ukraine's answer.

Note, though, that int 21h Glory to Ukraine could still beat this by reverting to the (allowed) output format of a single newline-separated string.

(Edit: after scrolling down after posting, I noticed that this approach is similar an earlier answer by Giuseppe, but saves some bytes by using utf8ToInt instead of substring to split-up the input vector).

\$\endgroup\$
1
  • 1
    \$\begingroup\$ That's another victory of utf8ToInt! :-) \$\endgroup\$ Commented Jul 6 at 11:27
1
\$\begingroup\$

Haskell, 62 bytes

r#c|any(elem c)r=init r++[last r++[c]]|1<2=r++[[c]]
foldl(#)[]

Try it online!

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

JavaScript (ES6), 68 bytes

s=>s.map(c=>o[c]?t+=c:(t&&m.push(t),t=o[c]=c),t='',o=m=[])&&[...m,t]

Takes input as a list of characters.

Test cases:

let f=
s=>s.map(c=>o[c]?t+=c:(t&&m.push(t),t=o[c]=c),t='',o=m=[])&&[...m,t]

console.log(f([...'mississippi']));
console.log(f([...'P P & C G']));
console.log(f([...'AAA']));
console.log(f([...'Adam']));
console.log(f([...'']));

\$\endgroup\$
2
  • \$\begingroup\$ I had a similar solution and asked if [""] was acceptable for the last test case. But it's not. :-( \$\endgroup\$
    – Arnauld
    Commented Feb 19, 2018 at 23:27
  • \$\begingroup\$ Oh, well, you got a much better solution anyway : ) \$\endgroup\$ Commented Feb 20, 2018 at 0:36
1
\$\begingroup\$

PHP, 317 bytes

function SplitOnFirstUnique($s){
    $len = strlen($s); 
    $output = [];
    $newstring = '';
    for ($i=0; $i < $len ; $i++) { 
        $newstring = $newstring.$s[$i];
        if(!in_array($s[$i] , $output  )){
            $output[] = $newstring;
            $newstring = '';
        }
    }
    return $output;
}

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Hello, and welcome to PPCG! I've edited your post to our standard format, and added a link to Try It Online so other people can test your code. The aim of Code Golf is to write the shortest code possible, and I can see a couple of ways to make this shorter, like using shorter variable names and leaving out some of the whitespace. You can check out the general tips and PHP tips pages for some more ideas. \$\endgroup\$
    – Not a tree
    Commented Feb 20, 2018 at 6:34

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.