División de cadena en la primera aparición de cada carácter

45

Relacionado.

Dada una cadena ASCII imprimible, divídala en una lista de cadenas no vacías con una nueva subcadena que comienza cada vez que aparece un carácter, que no se ha visto previamente en el mismo caso.

Ejemplos

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

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

"AAA" → ["AAA"]

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

"" → []


Anécdota : El resultado tendrá entre 0 y 95 elementos. La subcadena 95a necesariamente continuará hasta el final porque en ese punto, todos los caracteres ASCII imprimibles han comenzado una subcadena, por lo que cada carácter adicional habrá ocurrido antes y, por lo tanto, no puede causar que comience una nueva subcadena.

Adán
fuente
1
Un ejemplo que contiene "y 'parece una buena idea.
Emigna
Sería ""[""]ser aceptable?
Arnauld
55
@Emigna Eso simplemente se mete con el formato de salida de ejemplo sin aportar más claridad.
Adám
1
Si sale como una cadena separada por una nueva línea, ¿puede haber una nueva línea inicial / final?
wastl
2
@wastl Uh, lo permitiré en este caso porque no puede indicar segmentos vacíos, aunque sí choca con mi decisión anterior de [""]no ser válido. Suspiro.
Adám

Respuestas:

22

Jalea , 4 bytes

QƤĠị

Pruébalo en línea!

Explicación

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 representación interna de las cadenas, que muestra el enlace TIO, es ligeramente diferente.

Zgarb
fuente
10

Retina , 9 bytes

q1,`.
¶$&

Pruébalo en línea!

Explicación

Haga coincidir cada carácter ( .), descarte las coincidencias repetidas ( q), descarte la primera coincidencia ( 1,) e inserte un salto de línea delante de cada coincidencia ¶$&.

Martin Ender
fuente
6

05AB1E , 11 bytes

ÙSk¥sg¸«£õK

Pruébalo en línea!

Explicación

Ù             # 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
fuente
1
Para cualquiera que encuentre esta respuesta, ¸«puede estar ªen la nueva versión de 05AB1E.
Kevin Cruijssen
6

C,  75   65  63 bytes

¡Gracias a @Digital Trauma por guardar 10 bytes y gracias a @gastropner y @ l4m2 por guardar un byte cada uno!

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

Imprime una nueva línea líder.

Pruébalo en línea!

Sin una nueva línea principal (71 bytes):

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

Pruébalo en línea!

Steadybox
fuente
1
64 bytes
gastropner
@gastropner Truco inteligente; ¡Gracias!
Steadybox
{0}=> {}?
l4m2
@ l4m2 Sí, gracias!
Steadybox
5

Perl 6 ,  58 52  40 bytes

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

Intentalo

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

Intentalo

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

Pruébelo
(la entrada es una lista de caracteres y la salida es una lista de listas de caracteres)

Expandido:

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

La salida de classifyes

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

Y .sortsolo lo convierte en:

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

».value quita las llaves

[
  ['m'],
  ['i'],
  ['s','s','i','s','s','i'],
  ['p','p','i'],
]
Brad Gilbert b2gills
fuente
¿Por qué las llaves alguna vez estarían fuera de servicio? ¿No se rastrea el orden de inserción como un HashMapvs. a LinkedHashMapen Java, donde el orden se basa en la memoria vs. el orden de inserción?
Urna mágica del pulpo
1
@MagicOctopusUrn Ninguna versión de Perl ha pedido Hashes. De hecho, la versión 18 de Perl 5 hizo que Hashes sea más aleatorio, lo que ayuda a que un cierto tipo de ataque de denegación de servicio sea menos posible, y también ha causado que el código de usuario defectuoso exponga su comportamiento defectuoso con más frecuencia. Ahora alguien podría (y probablemente lo ha hecho) implementar una clase que sí realiza un seguimiento, pero requeriría más de 5 caracteres para cargar y usar.
Brad Gilbert b2gills
5

J , 7 bytes

~:<;.1]

Pruébalo en línea!

Explicación

¡La oportunidad de Tam tam para brillar!

~: <;.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
col
fuente
2
Estaba a punto de publicar exactamente la misma respuesta (no sorprendentemente), es bueno que eche un vistazo a su presentación antes de eso :)
Galen Ivanov
2
@GalenIvanov I, y me imagino que la mayoría de los golfistas de J también, disfrutan de la posibilidad de usar nub tamve o auto clasificarse.
cole
5

APL (Dyalog Unicode) , SBCS de 8 bytes

(≢¨∪\)⊆⊢

Pruébalo en línea!

ngn
fuente
Pero, pero ... Oh, Dios mío.
Adám
Sospeché que podría haber publicado este desafío debido a la nueva primitiva (⊆). Evidentemente no :)
ngn
Parece un Kirby avergonzado sosteniendo un biberón.
Urna mágica del pulpo
para todos los que tiene que mirar hacia arriba "Kirby" como lo hice - es una bola rosa antropomórfica de un videojuego japonés
NGN
5

05AB1E , 8 bytes

Ùvyy¶ì.;

Pruébalo en línea!


Siempre generará 1 nueva línea anterior, que es constante y no indica una división, la alternativa de 10 bytes que no genera una nueva línea anterior es Ùvyy¶ì.;}¦, puede intentarlo aquí . Según Adam, una nueva línea anterior o posterior es aceptable.


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

Después de cada iteración obtenemos:

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

Cual es:

m
i
ssissi
ppi
Urna de pulpo mágico
fuente
¡Agradable!
Gáneme
@Emigna, esto estuvo sentado como un comentario en tu respuesta durante 2 días, luego lo publiqué b / c sin respuesta jaja: P.
Urna de pulpo mágico
Extraño, no he visto ninguna notificación al respecto. Sin embargo, es lo suficientemente diferente para su propia respuesta :)
Emigna
@Emigna bueno, quiero decir, lo borré jaja.
Urna de pulpo mágico
Saltarse el bucle guarda un byte ÙSD¶ì.;. No estoy seguro de por qué no pensamos en eso antes: P
Emigna
5

Haskell , 39 bytes

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

Pruébalo en línea!

Inserta un símbolo de nueva línea antes de cada carácter que aparece por primera vez, lo que resulta en una cadena separada por una nueva línea, con una nueva línea inicial. Anteponer lines.para producir una lista.


Haskell , 55 bytes

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

Pruébalo en línea!

Toma el prefijo repetidamente el primer carácter más los caracteres no únicos que lo siguen.

xnor
fuente
@WheatWizard Vaya, sí lines.
xnor
Es posible que desee hacer tail.linespara eliminar la cadena vacía adicional ahora que lo pienso.
Wheat Wizard
4

APL (Dyalog) , 9 bytes

¡Gracias, Erik the Outgolfer por guardar 1 byte!

⊢⊂⍨⍳∘≢∊⍳⍨

Pruébalo en línea!

Explicación:

⍳⍨: Para cada personaje, obtenga el índice de su primera aparición. p.ejmississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢: El rango de 1 a la longitud de la entrada.

: Afiliación. p.ej1 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

⊢⊂⍨: Particionar la cadena de entrada con nuevas particiones que comienzan en 1s en el vector de arriba

H.PWiz
fuente
9 bytes (monádico fgy monádico se f∘gcomportan igual)
Erik the Outgolfer
¿Por qué en lugar de =?
Adám
Al momento de escribir, no había considerado que los índices estarían en las posiciones correctas. Aunque está claro que lo son
H.PWiz
4

Japt , 11 bytes

‰ r@=iRUbY

¡Pruébelo en línea!

Explicación

Esto fue inspirado por la magia pulpo Urna 's solución 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.
ETHproducciones
fuente
1
Japt está teniendo una crisis de identidad aquí, se llama a sí misma Ruby por alguna razón. iRUbY!
Urna de pulpo mágico
3

JavaScript (ES6), 37 bytes

Se guardaron 7 bytes: se permitió explícitamente una nueva línea principal (¡Gracias @Shaggy!)

Toma la entrada como una matriz de caracteres. Emite una cadena separada por una nueva línea.

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

Casos de prueba

Arnauld
fuente
Se permiten nuevas líneas principales para que pueda reducir esto a 37 bytes
Shaggy
3

brainfuck, 66 bytes

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

Formateado:

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

Pruébalo en línea

La nueva línea inicial en la salida (que solo se imprime si la entrada no está vacía) se puede eliminar a un costo de 5 bytes reemplazando el cuerpo xdel bucle principal (más externo) con .>,[x].

Mitch Schwartz
fuente
2

K4 , 19 bytes

Solución:

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

Ejemplos:

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

Explicación:

8 bytes es solo para manejar ""...

$[#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, "" => [""]
callejero
fuente
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:])

Pruébalo en línea!

varilla
fuente
Guardar dos con la lista (set (map (s.find, s)))
Jonathan Allan
@JonathanAllan es un efecto secundario engañoso, setno mantengas el orden, a prueba de contrarrestar ->s='c'*6+'a'*100+'b'
Rod
Sé que no podemos confiar en él en futuras implementaciones, pero creo que dados los enteros ordenados mantenemos el orden en el conjunto debido a que el hash de un entero es el entero (como ha demostrado, lo mismo no es cierto para otros objetos, ¿puede encontrar ¿Una palabra que no funciona con mi alternativa?).
Jonathan Allan
@JonathanAllan tampoco es cierto
Rod
¡Ah, sí, mi creencia era falsa!
Jonathan Allan
2

Perl, 30 bytes

Incluye +1parap

Dar entrada sin seguir la nueva línea en STDIN. La salida también es sin línea nueva:

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

Si no se preocupan por las nuevas líneas iniciales y finales de este 25( +3por -pya que el código contiene ') también trabaja:

#!/usr/bin/perl -p
s%%$/x!$v{$'&~v0}++%eg
Ton Hospel
fuente
Gran solución como siempre! Según los casos de prueba proporcionados, no necesita nombrar su hash, puede hacerlo ${$&}++. No es tan robusto, pero ¿podría ser suficiente para este desafío? Además, ha habido un consenso sobre el meta que perl -pno necesita un byte adicional, solo necesita tener el encabezado, en Perl with `-p` lugar de solo Perl. Estoy tratando de recordar hacerlo yo mismo ...
Dom Hastings
@DomHastings La anécdota sobre un máximo de 95 cadenas posibles implica que 1es válida, en cuyo caso ves necesaria. Con respecto al conteo, principalmente sigo codegolf.meta.stackexchange.com/a/7539/51507, que para mí es la meta publicación más consistente sobre contar perl.
Ton Hospel
Siempre es bueno aprender del maestro. Específicamente, en este caso, &~v0para agarrar el primer personaje. Gracias por unirse a este sitio y compartir su larga experiencia.
msh210
Puede usar Strawberry Perl, que usa en "lugar de 'with -e, y luego puede contar -epcomo +1 en lugar de +3. (Probado)
msh210
2

JavaScript, 61 54 52 bytes

Toma la entrada como una matriz de caracteres.

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

Intentalo

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>

Lanudo
fuente
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))

Pruébalo en línea!

Devuelve una lista (posiblemente vacía) de subcadenas.

¡Gracias a Michael M por guardar 7 bytes!

Giuseppe
fuente
3
function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))sería más corto - y por supuesto un poco más feo ...
Michael M
¿Por qué en substringlugar de substr?
plannapus
@MichaelM ¡Muy bien! Todavía tengo que agregar if(n)allí porque substringarroja un error para la entrada de cadena vacía.
Giuseppe
1
@plannapus substrdevuelve un vector de longitud igual a su primera entrada, mientras que substringdevuelve uno de longitud igual a la mayor de sus entradas.
Giuseppe
@Giuseppe: soltar el "if (n)" en R 3.4.3 asigna la cadena de entrada vacía "" a la cadena de salida vacía "", lo que debería estar bien (?)
Michael M
2

Stax , 8 bytes

ç↓‼►▐NVh

Ejecutar y depurar en línea

La representación ascii del mismo programa es esta.

c{[Ii=}(m

Para cada carácter, se divide cuando el índice del carácter actual es la posición actual.

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
recursivo
fuente
2

> <> , 22 17 14 bytes

-1 byte gracias a Emigna

i:::a$1g?!o1po

Pruébalo en línea!

Imprime una nueva línea inicial y final.

Realiza un seguimiento de las letras que ya han aparecido pemitiendo una copia del carácter en ese punto correspondiente en la segunda fila e imprimiendo una nueva línea si el valor obtenido desde esa posición no era 1. Finaliza un error cuando intenta imprimir-1

Jo King
fuente
Gran uso de g/p! 16 bytes
Emigna
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]

Toma la entrada como una lista de caracteres.

Casos de prueba:

Rick Hitchcock
fuente
Tuve una solución similar y pregunté si [""]era aceptable para el último caso de prueba. Pero no lo es . :-(
Arnauld
Oh, bueno, tienes una solución mucho mejor de todos modos:)
Rick Hitchcock
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;
}

Pruébalo en línea!

Saurabh Chandra Patel
fuente
2
Hola y bienvenidos a PPCG! Edité su publicación en nuestro formato estándar y agregué un enlace a Probar en línea para que otras personas puedan probar su código. El objetivo de Code Golf es escribir el código más corto posible, y puedo ver un par de maneras de hacer esto más corto, como usar nombres de variables más cortos y omitir algunos espacios en blanco. Puede consultar los consejos generales y las páginas de consejos de PHP para obtener más ideas.
No es un árbol
1

Rojo , 79 bytes

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

Pruébalo en línea!

Sin golf:

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

Pruébalo en línea!

Imprime las subcadenas separadas por nuevas líneas.

Explicación:

line S(for SPLIT) en realidad no se divide, sino que extrae el primer carácter de Ny lo guarda ( .) en Y. En una Fenfermedad, salta a END. La coincidencia solo debe fallar cuando Nes la cadena vacía. Por lo tanto, cuando la entrada está vacía, salta directamente ENDy no genera nada.

S = S Yconcatena Yen S.

SPAN(S)codiciosamente hace coincidir una serie de caracteres Sy los envía ( .) a OUTPUT, estableciendo ( .) Na los REMcaracteres principales de N(si hay alguno). Luego vuelve a saltar S.

Giuseppe
fuente
1

PowerShell, 73 bytes

{$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"]
Don Cruickshank
fuente
puede guardar algunos bytes. ¡ Pruébelo en línea!
mazzy
1

Ruby , 65 62 58 bytes

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

Pruébalo en línea!

Una lambda que acepta una cadena y devuelve una serie de cadenas.

Enfoque: para cada índice, agregue el carácter en ese índice en sla matriz de resultados o en la última cadena de la matriz de resultados. String#indexdevuelve el índice de la primera instancia del argumento.

-2 bytes: Inicialice acomo un argumento splat en lugar de en su propia línea. ¡Gracias, Value Ink !

-1 bytes: Uso c=s[i]... cen lugar de s[i]... s[i]. ¡Gracias, Value Ink !

-4 bytes: usar en .timeslugar de.map

benj2240
fuente
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 gracias a @raznagul (por algo obvio que de alguna manera me extrañé ...)
-3 bytes gracias a @OOBalance (de nuevo por algo obvio que de alguna manera me extrañé ..: S)

Explicación:

Pruébalo en línea.

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
fuente
1
No creo que necesites el if(l<1). Si les así, 0el bucle no debería ejecutarse de todos modos como 0<0es false.
raznagul
@raznagul No estoy seguro de cómo me perdí eso, ¡pero estás completamente en lo cierto! ..>.>
Kevin Cruijssen
Estás configurando i=0dos veces. Puede guardar 3 bytes soltando el segundo:for(;i<l;i++)
OOBalance
@OOBalance No estoy seguro de cómo sucedió eso ... S: ¡Pero gracias por notarlo! :)
Kevin Cruijssen