Split string on first occurrence of each character

45

4

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.

Adám

Posted 2018-02-19T17:59:49.553

Reputation: 37 779

1An example containing " and ' seems like a good idea. – Emigna – 2018-02-19T18:15:59.913

Would ""[""] be acceptable? – Arnauld – 2018-02-19T18:18:51.940

Can I return a newline-separated string? Since the input contains only printable ASCII, that would be unambiguous. – Dennis – 2018-02-19T18:19:34.700

Yes, I thought that was a default output format for lists of strings. – Adám – 2018-02-19T18:21:29.550

5@Emigna That just messes with the example output format without bringing any further clarity. – Adám – 2018-02-19T18:22:19.480

@Arnauld I don't think so

– Mr. Xcoder – 2018-02-19T18:22:48.750

@Arnauld No, [""] isn't a list of non-empty substrings. – Adám – 2018-02-19T18:22:59.857

Can the input be a list of characters, and the output be a list of lists of characters? ("A","d","d","a","m","s") => (("A"),("d","d"),("a"),("m"),("s")) – Brad Gilbert b2gills – 2018-02-19T18:51:46.493

@BradGilbertb2gills Yes, that's covered by default I/Os. – Adám – 2018-02-19T18:53:02.120

Not sure if intentional but your 'P P & C G' → ["P"," P ","& ","C ","G"] example uses single quotes on the left and double quotes on the right. – cole – 2018-02-19T19:24:16.490

@cole Neither is part of the string or the output array, so I doubt it matters. They're just delimiters to show the start and end of the input, not part of it, and likewise for the elements of the output. – Fund Monica's Lawsuit – 2018-02-19T20:24:18.477

1If outputting as a newline-separated string, can there be a leading/trailing newline? – wastl – 2018-02-19T21:32:08.740

2@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. – Adám – 2018-02-19T21:56:26.997

Can there be both leading and trailing newlines? – Jo King – 2018-07-19T12:54:30.220

@JoKing Sure, why not? – Adám – 2018-07-19T14:49:40.783

Not specified...the first string of input Mississippi would be M i s SI ppi – RosLuP – 2019-03-08T08:46:25.143

@RosLuP It is actually indirectly specified in the anecdote. Since there may be up to 95 substrings, and there are only 95 printable ASCII characters, this challenge must be case sensitive. I'll add a clarification anyway. – Adám – 2019-03-08T09:56:31.620

Shouldn't "Adam" be ["A","da","m"]? I'm not sure why its being split on the second a. (Compare to "Mississippi": there is no break began the first and second s) – Draco18s no longer trusts SE – 2019-03-08T14:57:07.813

@Draco18s which has not previously been seen in the same case – Adám – 2019-03-08T14:58:58.637

Answers

22

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.

Zgarb

Posted 2018-02-19T17:59:49.553

Reputation: 39 083

10

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 ¶$&.

Martin Ender

Posted 2018-02-19T17:59:49.553

Reputation: 184 808

6

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 "" -> [])

Emigna

Posted 2018-02-19T17:59:49.553

Reputation: 50 798

1For anyone coming across this answer, ¸« can be ª in the new version of 05AB1E. – Kevin Cruijssen – 2019-03-08T12:43:04.683

6

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!

Steadybox

Posted 2018-02-19T17:59:49.553

Reputation: 15 798

164 bytes – gastropner – 2018-02-21T15:30:54.203

@gastropner Clever trick; thanks! – Steadybox – 2018-02-21T15:34:57.110

{0} => {} ? – l4m2 – 2018-03-09T23:02:05.293

@l4m2 Yep, thanks! – Steadybox – 2018-03-10T00:16:48.323

5

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'],
]

Brad Gilbert b2gills

Posted 2018-02-19T17:59:49.553

Reputation: 12 713

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? – Magic Octopus Urn – 2018-02-20T17:18:28.977

1@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. – Brad Gilbert b2gills – 2018-02-20T20:12:01.780

5

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

cole

Posted 2018-02-19T17:59:49.553

Reputation: 3 526

2I was about to post exactly the same (not surprisingly) answer, it's good that I glanced your submission before that :) – Galen Ivanov – 2018-02-19T19:48:54.603

2@GalenIvanov I -- and I imagine most other J golfers, too -- relish the chance to use nub sieve or self-classify. – cole – 2018-02-19T20:18:31.703

5

APL (Dyalog Unicode), 8 bytesSBCS

(≢¨∪\)⊆⊢

Try it online!

ngn

Posted 2018-02-19T17:59:49.553

Reputation: 11 449

But, but… Oh my. – Adám – 2018-02-20T18:06:53.713

I suspected you might have posted this challenge because of the new primitive (⊆). Evidently not :) – ngn – 2018-02-20T20:15:33.380

It looks like an embarrassed Kirby holding a baby bottle. – Magic Octopus Urn – 2018-02-20T20:24:55.553

for everyone who needs to look up "Kirby" like I did - it's an anthropomorphic pink ball from a Japanese video game – ngn – 2018-02-20T20:41:02.490

5

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.

xnor

Posted 2018-02-19T17:59:49.553

Reputation: 115 687

@WheatWizard Oops, yes, lines. – xnor – 2018-02-21T04:42:59.490

Might want to do tail.lines to remove the extra empty string now that I think about it. – Post Rock Garf Hunter – 2018-02-21T06:06:28.823

5

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

Magic Octopus Urn

Posted 2018-02-19T17:59:49.553

Reputation: 19 422

Nice! Beat me by a fair margin ;) – Emigna – 2018-02-28T13:57:47.323

@Emigna this was sitting as a comment on your answer for 2 days then I just posted it b/c no response haha :P. – Magic Octopus Urn – 2018-02-28T14:06:33.457

Weird, haven't seen any notification on that. Different enough for its own answer though :) – Emigna – 2018-02-28T14:14:37.177

@Emigna well, I mean, I deleted it haha. – Magic Octopus Urn – 2018-02-28T15:56:44.460

Skipping the loop saves a byte ÙSD¶ì.;. Not sure why we didn't think of that before :P – Emigna – 2019-03-08T12:10:48.310

4

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

H.PWiz

Posted 2018-02-19T17:59:49.553

Reputation: 10 962

9 bytes (monadic fg and monadic f∘g behave the same) – Erik the Outgolfer – 2018-02-19T18:37:59.973

Why instead of =? – Adám – 2018-02-20T09:32:52.563

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 – H.PWiz – 2018-02-20T17:01:10.483

4

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.

ETHproductions

Posted 2018-02-19T17:59:49.553

Reputation: 47 880

1Japt is having an identity crisis here, it's calling itself Ruby for some reason. iRUbY! – Magic Octopus Urn – 2018-02-21T15:37:58.507

3

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'))

Arnauld

Posted 2018-02-19T17:59:49.553

Reputation: 111 334

Leading newlines are allowed so you can get this down to 37 bytes – Shaggy – 2018-02-20T09:39:58.953

3

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].

Mitch Schwartz

Posted 2018-02-19T17:59:49.553

Reputation: 4 899

2

Jelly, 6 bytes

ŒQœṗ⁸Ḋ

Try it online!

Erik the Outgolfer

Posted 2018-02-19T17:59:49.553

Reputation: 38 134

2

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!

Rod

Posted 2018-02-19T17:59:49.553

Reputation: 17 588

Save two with list(set(map(s.find,s)))

– Jonathan Allan – 2018-02-19T19:41:42.337

@JonathanAllan it's a misleading side-effect, set do not keep order, counter-proof -> s='c'*6+'a'*100+'b' – Rod – 2018-02-19T19:59:51.853

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?). – Jonathan Allan – 2018-02-19T22:07:05.003

@JonathanAllan not true either

– Rod – 2018-02-20T00:14:05.120

Ah, fair enough, my belief was false! – Jonathan Allan – 2018-02-20T00:22:38.717

2

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!

Giuseppe

Posted 2018-02-19T17:59:49.553

Reputation: 21 077

3function(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... – Michael M – 2018-02-19T20:25:56.063

Why substring instead of substr? – plannapus – 2018-02-20T09:48:54.380

@MichaelM Very nice! I still have to add the if(n) in there because substring throws an error for empty string input. – Giuseppe – 2018-02-20T12:20:53.703

1@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. – Giuseppe – 2018-02-20T12:22:03.967

@Giuseppe: Dropping the "if(n)" in R 3.4.3 maps the empty input string "" to the empty output string "", which should be fine(?) – Michael M – 2018-02-20T14:51:33.063

@MichaelM oh I see. The strsplit approach needed it and I must have tested a version of that instead of yours. My bad. – Giuseppe – 2018-02-20T14:58:21.990

It is pure luck that substring("", 1:0, 1:0) does not complaint :) – Michael M – 2018-02-20T15:38:24.123

2

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, "" => [""]

streetster

Posted 2018-02-19T17:59:49.553

Reputation: 3 635

2

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>

Shaggy

Posted 2018-02-19T17:59:49.553

Reputation: 24 623

2

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!

xnor

Posted 2018-02-19T17:59:49.553

Reputation: 115 687

2

><>, 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

Jo King

Posted 2018-02-19T17:59:49.553

Reputation: 38 234

Great use of g/p! 16 bytes

– Emigna – 2019-03-08T12:22:18.650

2

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

Ton Hospel

Posted 2018-02-19T17:59:49.553

Reputation: 14 114

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... – Dom Hastings – 2018-02-20T10:08:08.447

@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 https://codegolf.meta.stackexchange.com/a/7539/51507 which to me is the most consistent meta post about counting perl.

– Ton Hospel – 2018-02-20T13:04:22.240

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. – msh210 – 2018-03-06T21:54:02.527

You can use Strawberry Perl, which uses " instead of ' with -e, and then you can count the -ep as +1 rather than +3. (Tested.) – msh210 – 2018-03-06T22:06:38.153

2

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

recursive

Posted 2018-02-19T17:59:49.553

Reputation: 8 616

1

SNOBOL4 (CSNOBOL4), 115 91 77 bytes

	N =INPUT
S	N LEN(1) . Y	:F(END)
	S =S Y
	N SPAN(S) . OUTPUT REM . N	:(S)
END

Try it online!

Prints the substrings separated by newlines.

Explanation:

line S (for SPLIT) doesn't actually split, but instead extracts the first character of N and saves it (.) to Y. On Failure, it jumps to END. The match should only fail when N is the empty string. Thus, when the input is empty, it jumps directly to END and outputs nothing.

S = S Y concatenates Y onto S.

SPAN(S) greedily matches a run of characters in S, and sends it (.) to OUTPUT, setting (.) N to the REMaining characters of N (if there are any). Then it jumps back to S.

Giuseppe

Posted 2018-02-19T17:59:49.553

Reputation: 21 077

1

Haskell, 62 bytes

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

Try it online!

nimi

Posted 2018-02-19T17:59:49.553

Reputation: 34 639

1

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([...'']));

Rick Hitchcock

Posted 2018-02-19T17:59:49.553

Reputation: 2 461

I had a similar solution and asked if [""] was acceptable for the last test case. But it's not. :-(

– Arnauld – 2018-02-19T23:27:38.993

Oh, well, you got a much better solution anyway : ) – Rick Hitchcock – 2018-02-20T00:36:42.000

1

Ruby, 65 62 58 bytes

->s,*a{s.size.times{|i|(i==s.index(c=s[i])?a:a[-1])<<c}
a}

Try it online!

A lambda accepting a string and returning an array of strings.

Approach: For each index, either append the character at that index in s to the result array, or to the last string in the result array. String#index returns the index of the first instance of the argument.

-2 bytes: Initialize a as a splat argument instead of on its own line. Thanks, Value Ink!

-1 byte: Use c=s[i]...c instead of s[i]...s[i]. Thanks, Value Ink!

-4 bytes: Use .times instead of .map

benj2240

Posted 2018-02-19T17:59:49.553

Reputation: 801

-3 bytes by using some assignment tricks. – Value Ink – 2018-02-20T06:42:09.190

1

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!

Saurabh Chandra Patel

Posted 2018-02-19T17:59:49.553

Reputation: 111

2

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.

– Not a tree – 2018-02-20T06:34:07.263

1

Red, 79 bytes

func[s][foreach c next unique/case append s"^@"[print copy/part s s: find s c]]

Try it online!

Ungolfed:

f: func [s] [
    b: next unique/case append s "^@"  ; append `null` to the end of the string, than
                                       ; find the unique characters and 
                                       ; store all except the first to b  
    foreach c b [                      ; for each character in b
        print copy/part s s: find s c  ; print the part of the string to
                                       ; where the character is found and
                                       ; set the beginning of the string to that position
    ]
] 

Galen Ivanov

Posted 2018-02-19T17:59:49.553

Reputation: 13 815

1

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)

Kevin Cruijssen

Posted 2018-02-19T17:59:49.553

Reputation: 67 575

1I 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. – raznagul – 2018-02-20T14:46:40.563

@raznagul Not sure how I missed that, but you're complete right!.. >.> – Kevin Cruijssen – 2018-02-20T14:56:28.337

You're setting i=0 twice. You can save 3 bytes by dropping the second one: for(;i<l;i++) – O.O.Balance – 2018-07-18T19:27:18.090

@O.O.Balance Not sure how that happened.. :S But thanks for noticing! :) – Kevin Cruijssen – 2018-07-19T08:23:37.103

1

PowerShell, 73 bytes

{$r=@();$h=@{};[char[]]$ARGS[0]|%{if(!($h[$_]++)){$r+=""};$r[-1]+=$_};$r}

Usage

PS> & {$r=@();$h=@{};[char[]]$ARGS[0]|%{if(!($h[$_]++)){$r+=""};$r[-1]+=$_};$r} "mississipi" | ConvertTo-Json -Compress
["m","i","ssissi","pi"]

Don Cruickshank

Posted 2018-02-19T17:59:49.553

Reputation: 131

you can save some bytes - Try it online!

– mazzy – 2019-03-08T04:51:15.683

0

Retina 0.8.2, 22 20 19 bytes

1>`(.)(?<!\1.+)
¶$&

Try it online! Edit: Saved 2 3 bytes thanks to @MartinEnder.

Neil

Posted 2018-02-19T17:59:49.553

Reputation: 95 035

@MartinEnder Ah yes, the lookahead was an artefact from a previous iteration that had to deal with overlapping matches, but I don't think I can use the non-word boundary because I need to be able to support all printable ASCII characters. – Neil – 2018-02-20T09:02:07.510

Oh, right, you can still use a limit though: https://tio.run/##K0otycxL/P/f0C5BQ09Tw95GMcZQT1uT69A2FbX//3Mzi4tBqKAgEwA

– Martin Ender – 2018-02-20T09:06:37.083

0

Javascript, 200 bytes

My first (I think?) attempt at code golf:

function split(s) {let x=[];let y=[];let z="";let w=1;for(l of s.split('')){if (x.includes(l)){z+=l;}else{w=!w;if (w) {y.push(z);z='';w=0;}z+=l;x.push(l);}}y.push(z);if (y.join('')==0) y=[];return y;}

aimorris

Posted 2018-02-19T17:59:49.553

Reputation: 1 217

3You can remove almost all the spaces, no? – Adám – 2018-02-19T20:27:15.880

@Adám Ah, yes. Thanks for that tip. It's now 200 bytes. – aimorris – 2018-02-19T21:04:41.217

Ideas: one-letter function name, remove most remaining spaces, remove trailing semicolons: Try it online!

– Adám – 2018-02-19T21:08:45.843

In general, this may help you.

– Adám – 2018-02-19T21:14:26.100

I would remove the lets and replace function split(s) with s=>. Note: you don't need to name the function unless it's recursive. – Oliver – 2018-02-19T21:16:10.637

You can replace s.split('') with [...s], but I would map through the array instead of looping through it. for(l of [...s]) -> [...s].map(l=>` – Oliver – 2018-02-19T21:17:35.953

1

I would also replace the if-else with a ternary operator. I know this is your first golfing attempt. I would recommend visiting Tips for golfing in JavaScript :)

– Oliver – 2018-02-19T21:21:20.250

0

Mathematica, 84 bytes

a@{}={};a@b_:=a@b[[;;(c@b=Position[b,Tally[b][[-1,1]]][[1,1]])-1]]~Append~b[[c@b;;]]

Defines a function a. Takes a list of characters as input and returns a list of lists of characters as output. Uses a basic recursive structure.

LegionMammal978

Posted 2018-02-19T17:59:49.553

Reputation: 15 731

0

Perl 5 + -p, 37 bytes

for$a(32..126){$a=chr$a;s/\Q$a/\n$a/}

Run through printable ASCII and insert a newline before the first appearance

Try it online!

wastl

Posted 2018-02-19T17:59:49.553

Reputation: 3 089

For 30 (use a literal newline): eval";y/ -~/~ -}/;s/a/\na/"x95 – Ton Hospel – 2018-02-20T07:09:28.513

0

Lua, 74 bytes

t={}print(((...):gsub(".",load"c=...a=(t[c]or'\\n')..c t[c]=''return a")))

Try it online!

Prints one additional leading newline.

Jonathan S.

Posted 2018-02-19T17:59:49.553

Reputation: 423

0

GNU sed, 37 bytes

(includes +1 for -r option)

s/./\n&/g
:a
s/((.).*)\n\2/\1\2/
ta

We start by prepending a newline to every character in the string; then in the loop, we remove those that precede a second or subsequent occurrence.

Note that newline can't occur in the input, as that's the separator between strings. And it's not classified as a printable character.

Toby Speight

Posted 2018-02-19T17:59:49.553

Reputation: 5 058

0

C++, 176 bytes

#include<string>
#include<set>
std::string*s(std::string e){auto*r=new std::string[96];std::set<int>u;for(char p:e){if(u.find(p)==u.end())u.insert(p);r[u.size()]+=p;}return r;}

Returns an array of strings, valid strings member of the answer array are not of size 0.
Each call of the function allocate sizeof(std::string)*96, with the pointer returned, and must be delete[]d after usage. Code to test :

auto tests = {
    "mississippi","P P & C G", "AAA", "Adam",""
};

for (const auto& a : tests) {

    std::string* res = s(a);

    for (int i = 0; i < 96; ++i) {
        if (res[i].size() > 0)
            std::cout << '\"' << res[i] << "\", ";
    }

    delete[] res;
    std::cout << '\n';
}

HatsuPointerKun

Posted 2018-02-19T17:59:49.553

Reputation: 1 891

Would it save bytes to use #define or using for std::string? – Zacharý – 2018-07-18T21:01:03.877

using S=std::string should save ~10 bytes. – Zacharý – 2018-11-14T13:24:04.423

Oh, in addition, auto can be changed to S as well. – Zacharý – 2018-11-14T14:16:03.890

0

AWK, 63 bytes

func u(v){for(;j++<split(v,A,"");)S[s]=S[s+=m[A[j]]++?0:1]A[j]}

Try it online!

Calling function u() assigns strings to string array S[] which is of size s

TIO link has some functionality in the footer to clear assigned variables.

Might be able to save a byte or two by using FS="", but this is a more general solution.

Robert Benson

Posted 2018-02-19T17:59:49.553

Reputation: 1 339

0

JavaScript, 105 87 bytes

Changes: replaced poop emojis for tabs (Thanks @Adám !), replaced parenthesis and aposthrophes for template literals

a=[];f=s=>s.split``.map(x=>!a.includes(x)&&a.push(x)?'  '+x:x).join``.split`    `.slice(1);

Takes a string, returns an array of strings. A big chunk is converting from String->[char]->String->[string]. whitout conversions, this becomes:

a=[];f=s=>s.map(x=>!a.includes(x)&&a.push(x)?'\n'+x:x).join``.slice(1);

takes char array, returns newline separated string (71 bytes).

Also, this is my first post on this stack exchange!

Sebastián Mestre

Posted 2018-02-19T17:59:49.553

Reputation: 101

Welcome to the site and nice first post! This is actually 105 bytes in UTF-8, due to the emojis and we hope you'll continue to golf here! – caird coinheringaahing – 2018-03-05T21:55:03.013

Can't you use a literal tab instead of to save the extra bytes? – Adám – 2018-03-05T22:23:54.023

Ohh i thought poop emojis were 2 bytes long... Fixed – Sebastián Mestre – 2018-03-05T22:31:02.360

0

PowerShell, 61 bytes

$args|% t*y|%{if(!($r-cmatch"^[$_]")){$r+=,''};$r[-1]+=$_}
$r

Try it online!

mazzy

Posted 2018-02-19T17:59:49.553

Reputation: 4 832

0

Clojure, 111 96 bytes

#(reverse(reduce(fn[[f & r :as R]i](if((set(apply str R))i)(cons(str f i)r)(cons(str i)R)))[]%))

As Jim Carrey would say: Beautiful! :D

NikoNyrh

Posted 2018-02-19T17:59:49.553

Reputation: 2 361

0

Gema, 20 characters

?=${$1;\n}@set{$1;}?

Sample run:

bash-4.4$ gema '?=${$1;\n}@set{$1;}?' <<< 'mississippi'

m
i
ssissi
ppi

Try it online!

manatwork

Posted 2018-02-19T17:59:49.553

Reputation: 17 865

0

Java 8, 159 bytes


134 bytes of lambda + 25 bytes for HashSet import. Rip all linters and IDEs.

import java.util.HashSet;
...
s->{HashSet h=new HashSet();return s.chars().mapToObj(c->(char)c+"").reduce("",(x,y)->x+(!h.isEmpty()&h.add(y)?","+y:y)).split(",");};

Try it online!

Benjamin Urquhart

Posted 2018-02-19T17:59:49.553

Reputation: 1 262