Dividi la stringa alla prima occorrenza di ciascun carattere


45

Relazionato.

Data una stringa ASCII stampabile, dividerla in un elenco di stringhe non vuote con una nuova sottostringa che inizia ogni volta che si verifica un carattere, che non è mai stato visto nello stesso caso.

Esempi

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

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

"AAA" → ["AAA"]

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

"" → []


Aneddoto : il risultato avrà tra 0 e 95 elementi. La 95a sottostringa continuerà necessariamente fino alla fine perché a quel punto tutti i caratteri ASCII stampabili hanno iniziato una sottostringa, quindi ogni carattere aggiuntivo si è verificato prima e quindi non può causare l'inizio di una nuova sottostringa.


1
Un esempio che contiene "e 'sembra una buona idea.
Emigna,

Sarebbe ""[""]essere accettabile?
Arnauld,

5
@Emigna Che fa solo confusione con il formato di output di esempio senza portare ulteriore chiarezza.
Adám,

1
Se l'output è una stringa separata da una nuova riga, può esserci una nuova riga iniziale / finale?
wastl,

2
@wastl Uh, lo permetterò in questo caso perché non può indicare segmenti vuoti, anche se si scontra con la mia precedente sentenza di [""]non essere valida. Sospiro.
Adám,

Risposte:


22

Gelatina , 4 byte

QƤĠị

Provalo online!

Spiegazione

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

La rappresentazione interna delle stringhe, visualizzata dal collegamento TIO, è leggermente diversa.


10

Retina , 9 byte

q1,`.
¶$&

Provalo online!

Spiegazione

Abbina ogni carattere ( .), scarta le partite ripetute ( q), scarta la prima partita ( 1,) e inserisci un avanzamento di riga davanti a ogni partita ¶$&.


6

05AB1E , 11 byte

ÙSk¥sg¸«£õK

Provalo online!

Spiegazione

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

1
Per chiunque trovi questa risposta, ¸«può essere ªnella nuova versione di 05AB1E.
Kevin Cruijssen l'

6

C,  75   65  63 byte

Grazie a @Digital Trauma per aver salvato 10 byte e sia a @gastropner che a @ l4m2 per salvare un byte ciascuno!

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

Stampa una nuova riga principale.

Provalo online!

Senza una nuova riga iniziale (71 byte):

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

Provalo online!



@gastropner trucco intelligente; Grazie!
Steadybox,

{0}=> {}?
l4m2

@ l4m2 Sì, grazie!
Steadybox

5

Perl 6 ,  58 52  40 byte

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

Provalo

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

Provalo

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

Provalo
(l'input è un elenco di caratteri e l'output è un elenco di elenchi di caratteri)

Allargato:

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

L'output di classifyè

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

E .sortlo trasforma in:

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

».value rimuove le chiavi

[
  ['m'],
  ['i'],
  ['s','s','i','s','s','i'],
  ['p','p','i'],
]

Perché le chiavi non sarebbero mai fuori servizio? L'ordine di inserimento non viene tracciato come un HashMapvs. a LinkedHashMapin Java dove l'ordine si basa sulla memoria rispetto all'ordine di inserimento?
Magic Octopus Urn,

1
@MagicOctopusUrn Nessuna versione di Perl ha ordinato hash. In effetti, Perl 5 versione 18 ha reso gli Hash più randomizzati, il che aiuta a rendere meno sicuro un certo tipo di attacco denial of service e ha anche causato il codice utente con buggy per esporre il suo comportamento con buggy più spesso. Ora qualcuno potrebbe (e probabilmente ha) implementare una classe che tiene traccia, ma che richiederebbe più di 5 caratteri per caricare e usare.
Brad Gilbert b2gills

5

J , 7 byte

~:<;.1]

Provalo online!

Spiegazione

La possibilità di Nub Sieve di brillare!

~: <;.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

2
Stavo per pubblicare esattamente la stessa (non a sorpresa) risposta, è bene che ho dato un'occhiata alla tua presentazione prima di questo :)
Galen Ivanov,

2
@GalenIvanov I - e immagino anche la maggior parte degli altri golfisti di J - apprezzo la possibilità di usare il setaccio nub o l'autoclassificazione.
Cole

5

APL (Dyalog Unicode) , 8 byte SBCS

(≢¨∪\)⊆⊢

Provalo online!


Ma, ma ... Oh mio Dio.
Adám,

Sospettavo che potresti aver pubblicato questa sfida a causa della nuova primitiva (⊆). Evidentemente no :)
ngn

Sembra un Kirby imbarazzato con in mano un biberon.
Magic Octopus Urn,

per tutti quelli che hanno bisogno di cercare "Kirby" come ho fatto io - è una palla rosa antropomorfa di un videogioco giapponese
ngn

5

05AB1E , 8 byte

Ùvyy¶ì.;

Provalo online!


Emetterà sempre 1 newline precedente, che è costante e non indicativo di una divisione, l'alternativa a 10 byte che non genera una newline precedente è Ùvyy¶ì.;}¦, puoi provare qui . Secondo Adam è accettabile una nuova riga precedente o finale.


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

Dopo ogni iterazione otteniamo:

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

Che è:

m
i
ssissi
ppi

Bello!
Battimi

@Emigna questo è stato seduto come commento sulla tua risposta per 2 giorni, quindi l'ho appena pubblicato b / c nessuna risposta ahah: P.
Magic Octopus Urn,

Strano, non ho visto alcuna notifica al riguardo. Abbastanza diverso per la sua risposta però :)
Emigna,

@Emigna bene, voglio dire, l'ho cancellato ahah.
Magic Octopus Urn,

Saltare il loop salva un byte ÙSD¶ì.;. Non so perché non ci abbiamo pensato prima: P
Emigna l'

5

Haskell , 39 byte

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

Provalo online!

Inserisce un simbolo di nuova riga prima di ogni carattere che appare per la prima volta, risultando in una stringa separata da nuova riga, con una nuova riga iniziale. Preparati lines.a produrre un elenco.


Haskell , 55 byte

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

Provalo online!

Prende ripetutamente il prefisso dal primo carattere più i caratteri non univoci che lo seguono.


@WheatWizard Ops, sì, lines.
xnor

Potrebbe voler fare tail.linesper rimuovere la stringa extra vuota ora che ci penso.
Wheat Wizard

4

APL (Dyalog) , 9 byte

Grazie, Erik the Outgolfer per aver salvato 1 byte!

⊢⊂⍨⍳∘≢∊⍳⍨

Provalo online!

Spiegazione:

⍳⍨: Per ogni personaggio, ottieni l'indice della sua prima occorrenza. per esempiomississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢: L'intervallo da 1 alla lunghezza dell'input.

: Iscrizione. per esempio1 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

⊢⊂⍨: Partiziona la stringa di input con nuove partizioni che iniziano con 1s nel vettore sopra


9 byte (monadic fge monadic si f∘gcomportano allo stesso modo)
Erik the Outgolfer,

Perché invece di =?
Adám,

Al momento in cui scrivevo, non avevo considerato che gli indici sarebbero stati nelle posizioni corrette. Anche se è chiaro che lo sono
H.Piz,

4

Japt , 11 byte

‰ r@=iRUbY

Provalo online!

Spiegazione

Questo è stato ispirato da Magia Octopus Urna 's soluzione 05AB1E .

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

1
Japt sta avendo una crisi di identità qui, si sta chiamando Ruby per qualche motivo. iRUbY!
Magic Octopus Urn,

3

JavaScript (ES6), 37 byte

Salvataggio di 7 byte: una nuova riga principale è stata esplicitamente consentita (Grazie @Shaggy!)

Accetta input come una matrice di caratteri. Emette una stringa separata da nuova riga.

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

Casi test



3

Brainfuck, 66 byte

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

formattato:

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

Provalo online

La nuova riga iniziale nell'output (che viene stampata solo se l'input non è vuoto) può essere rimossa al costo di 5 byte sostituendo il corpo xdel loop principale (più esterno) con .>,[x].



2

K4 , 19 byte

Soluzione:

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

Esempi:

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

Spiegazione:

8 byte è solo per gestire ""...

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

2

Python 2 , 81 74 byte

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

Provalo online!



@JonathanAllan è un effetto collaterale fuorviante, setnon mantenere l'ordine, contro-prova ->s='c'*6+'a'*100+'b'
Rod

So che non possiamo fare affidamento su di esso nelle future implementazioni, ma credo che, dato i numeri interi ordinati, manteniamo l'ordine nel set perché l'hash di un numero intero è il numero intero (come hai mostrato lo stesso non è vero per altri oggetti - puoi trovare una parola che non funziona con la mia alternativa?).
Jonathan Allan,

@JonathanAllan non è vero né
Rod

Ah, abbastanza giusto, la mia convinzione era falsa!
Jonathan Allan,


2

Perl, 30 byte

Include +1perp

Fornisci input senza trascinare newline su STDIN. L'output è anche senza trascinamento newline:

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

Se non si cura di leader e ritorni a capo questa finale 25( +3per -pquanto il codice contiene ') funziona anche:

#!/usr/bin/perl -p
s%%$/x!$v{$'&~v0}++%eg

Ottima soluzione come sempre! Sulla base dei casi di test forniti, non è necessario nominare l'hash, è possibile farlo ${$&}++. Non è così robusto, ma potrebbe essere sufficiente per questa sfida? Inoltre, c'è stato un consenso su meta che perl -pnon ha bisogno di un byte aggiuntivo, devi solo avere l'intestazione come Perl with `-p` invece di solo Perl. Sto cercando di ricordare di farlo da solo ...
Dom Hastings,

@DomHastings L'annecdote su al massimo 95 possibili stringhe implica fortemente che ciò 1sia valido, nel qual caso vè necessario. Per quanto riguarda il conteggio, seguo principalmente codegolf.meta.stackexchange.com/a/7539/51507 che per me è il meta post più coerente sul conteggio perl.
Ton Hospel,

Sempre bello imparare dal maestro. In particolare, in questo caso, &~v0per afferrare il primo personaggio. Grazie per esserti iscritto a questo sito e aver condiviso la tua lunga esperienza.
msh210

Puoi usare Strawberry Perl, che usa "invece di 'con -e, e quindi puoi contare -epcome +1 anziché +3. (Testato.)
msh210,

2

JavaScript, 61 54 52 byte

Accetta input come una matrice di caratteri.

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

Provalo

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>


2

R , 94 87 byte

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

Provalo online!

Restituisce un elenco (possibilmente vuoto) di sottostringhe.

Grazie a Michael M per aver salvato 7 byte!


3
function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))sarebbe più breve - e ovviamente un po 'più brutto ...
Michael M,

Perché substringinvece di substr?
plannapus,

@MichaelM Molto bello! Devo ancora aggiungere l'interno if(n)perché substringgenera un errore per l'input di stringa vuota.
Giuseppe,

1
@plannapus substrrestituisce un vettore di lunghezza uguale al suo primo input mentre substringrestituisce uno di lunghezza uguale al più lungo dei suoi input.
Giuseppe,

@Giuseppe: Rilasciare "if (n)" in R 3.4.3 associa la stringa di input vuota "" alla stringa di output vuota "", che dovrebbe andare bene (?)
Michael M,

2

Stax , 8 byte

ç↓‼►▐NVh

Esegui ed esegui il debug online

La rappresentazione ASCII dello stesso programma è questa.

c{[Ii=}(m

Per ogni personaggio, si divide quando l'indice del personaggio corrente è la posizione corrente.

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

2

> <> , 22 17 14 byte

-1 byte grazie a Emigna

i:::a$1g?!o1po

Provalo online!

Stampa una nuova riga iniziale e finale.

Tiene traccia di quali lettere sono già comparse pemettendo una copia del personaggio nel punto corrispondente sulla seconda riga e stampando una nuova riga se il valore recuperato da quella posizione non era 1. Termina in un errore quando tenta di stampare-1


Ottimo uso di g/p! 16 byte
Emigna


1

JavaScript (ES6), 68 byte

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

Accetta input come un elenco di caratteri.

Casi test:


Avevo una soluzione simile e ho chiesto se [""]era accettabile per l'ultimo caso di test. Ma non lo è . :-(
Arnauld,

Oh, beh, hai comunque una soluzione molto migliore:)
Rick Hitchcock,

1

PHP, 317 byte

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

Provalo online!


2
Ciao e benvenuto in PPCG! Ho modificato il tuo post nel nostro formato standard e ho aggiunto un link a Provalo online in modo che altre persone possano testare il tuo codice. Lo scopo di Code Golf è quello di scrivere il codice più breve possibile, e posso vedere un paio di modi per renderlo più breve, come usare nomi di variabili più brevi e tralasciare alcuni spazi bianchi. Puoi dare un'occhiata ai suggerimenti generali e alle pagine dei suggerimenti PHP per qualche altra idea.
Non un albero il

1

Rosso , 79 byte

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

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

1

SNOBOL4 (CSNOBOL4) , 115 91 77 byte

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

Provalo online!

Stampa le sottostringhe separate da newline.

Spiegazione:

line S(for SPLIT) in realtà non si divide, ma estrae invece il primo carattere di Ne lo salva ( .) in Y. In caso di Fdisturbi, salta a END. La corrispondenza dovrebbe fallire solo quando Nè la stringa vuota. Pertanto, quando l'ingresso è vuoto, passa direttamente a ENDe non genera nulla.

S = S Ysi concatena Ysu S.

SPAN(S)abbina avidamente una serie di caratteri in S, e lo invia ( .) a OUTPUT, impostando ( .) Nai REMcaratteri finali di N(se ce ne sono). Quindi torna a S.


1

PowerShell, 73 byte

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

uso

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

puoi salvare alcuni byte - Provalo online!
mazzy

1

Rubino , 65 62 58 byte

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

Provalo online!

Un lambda che accetta una stringa e restituisce una matrice di stringhe.

Approccio: per ciascun indice, aggiungere il carattere di tale indice salla matrice dei risultati o all'ultima stringa nella matrice dei risultati. String#indexrestituisce l'indice della prima istanza dell'argomento.

-2 byte: inizializza acome argomento splat anziché sulla propria riga. Grazie, Value Ink !

-1 byte: Uso c=s[i]... cal posto di s[i]... s[i]. Grazie, Value Ink !

-4 byte: utilizzare .timesinvece di.map



1

Java 8, 193 169 155 151 byte

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 byte grazie a @raznagul (per qualcosa di ovvio in qualche modo mi sono perso ..)
-3 byte grazie a @OOBalance (di nuovo per qualcosa di ovvio in qualche modo mi sono perso ..: S)

Spiegazione:

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

1
Non penso che tu abbia bisogno di if(l<1). If lis 0the loop non dovrebbe essere eseguito comunque come 0<0è false.
raznagul,

@raznagul Non sono sicuro di come mi sia perso, ma sei completamente giusto! ..>.>
Kevin Cruijssen

Stai impostando i=0due volte. Puoi salvare 3 byte rilasciando il secondo:for(;i<l;i++)
OOBalance il

@OOBalance Non sono sicuro di come sia successo ..: S Ma grazie per averlo notato! :)
Kevin Cruijssen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.