Dividir string na primeira ocorrência de cada caractere


45

Relacionado.

Dada uma sequência ASCII imprimível, divida-a em uma lista de seqüências não vazias com uma nova sub-sequência iniciando sempre que um caractere, que não foi visto anteriormente no mesmo caso, ocorre.

Exemplos

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

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

"AAA" → ["AAA"]

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

"" → []


Anedota : O resultado terá entre 0 e 95 elementos. A 95 ª sub-corda vai necessariamente continuar até o fim, porque nesse ponto, todos os caracteres ASCII imprimíveis começaram uma sub-string, então cada personagem adicional terá ocorrido antes e, portanto, não pode causar uma nova sub-string para começar.


1
Um exemplo que contém "e 'parece ser uma boa ideia.
Emigna

Seria ""[""]ser aceitável?
Arnauld

5
@ Emigna Isso apenas mexe com o exemplo de formato de saída sem trazer mais clareza.
Adám 19/02/19

1
Se estiver imprimindo como uma sequência separada por nova linha, pode haver uma nova linha inicial / final?
Wastl

2
@wastl Uh, vou permitir neste caso, porque não pode indicar segmentos vazios, embora colidir com a minha decisão anterior de [""]ser inválida. Suspiro.
Adám

Respostas:


22

Gelatina , 4 bytes

QƤĠị

Experimente online!

Explicação

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

A representação interna das seqüências de caracteres, que o link TIO exibe, é um pouco diferente.


10

Retina , 9 bytes

q1,`.
¶$&

Experimente online!

Explicação

Combine cada caractere ( .), descarte as correspondências repetidas ( q), descarte a primeira correspondência ( 1,) e insira um avanço de linha na frente de cada correspondência ¶$&.


6

05AB1E , 11 bytes

ÙSk¥sg¸«£õK

Experimente online!

Explicação

Ù             # 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
Para quem se deparar com esta resposta, ¸«pode estar ªna nova versão do 05AB1E.
Kevin Cruijssen 8/03

6

C,  75   65  63 bytes

Agradecemos ao @Digital Trauma por salvar 10 bytes e obrigado a @gastropner e @ l4m2 por salvar um byte cada!

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

Imprime uma nova linha principal.

Experimente online!

Sem uma nova linha principal (71 bytes):

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

Experimente online!



@gastropner Truque inteligente; obrigado!
Steadybox

{0}=> {}?
L4m2

@ l4m2 Sim, obrigado!
Steadybox

5

Perl 6 ,  58 52  40 bytes

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

Tente

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

Tente

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

Experimente
(entrada é uma lista de caracteres e saída é uma 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

A saída de classifyé

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

E .sortapenas transforma em:

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

».value remove as chaves

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

Por que as chaves estavam fora de ordem? O pedido de inserção não é rastreado como um HashMapvs. a LinkedHashMapem Java, onde o pedido é baseado na memória versus no pedido de inserção?
Urna de polvo mágico

1
@MagicOctopusUrn Nenhuma versão do Perl encomendou Hashes. De fato, a versão 18 do Perl 5 tornou o Hashes mais randomizado, o que ajuda a tornar um certo tipo de ataque de negação de serviço menos possível e também fez com que o código do usuário com erros expusesse seu comportamento com erros com mais frequência. Agora, alguém poderia (e provavelmente tem) implementar uma classe que mantém controle, mas isso levaria mais de 5 caracteres para carregar e usar.
Brad Gilbert b2gills

5

J , 7 bytes

~:<;.1]

Experimente online!

Explicação

A chance da peneira de Nub brilhar!

~: <;.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
Eu estava prestes a postar exatamente a mesma resposta (não surpreendentemente), bom é que eu olhei a sua apresentação antes que :)
Galen Ivanov

2
@ GalenIvanov I - e também imagino a maioria dos outros jogadores de golfe J - aproveita a chance de usar peneira nub ou se classificar automaticamente.
19418 cole


5

05AB1E , 8 bytes

Ùvyy¶ì.;

Experimente online!


Sempre produzirá 1 nova linha anterior, que é constante e não indica uma divisão, a alternativa de 10 bytes que não gera uma nova linha anterior é Ùvyy¶ì.;}¦, você pode tentar isso aqui . Segundo Adam, uma nova linha anterior ou posterior é aceitável.


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

Após cada iteração, obtemos:

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

Qual é:

m
i
ssissi
ppi

Agradável! Bata-me por uma margem justa;)
Emigna

@ Emigna isso estava sentado como um comentário em sua resposta por 2 dias, então eu acabei de postar b / c sem resposta haha: P.
Magic Octopus Urn

Estranho, não vi nenhuma notificação sobre isso. Bastante diferente para a sua própria resposta embora :)
Emigna

@ Emigna bem, quero dizer, eu apaguei haha.
Urna de polvo mágico

Ignorar o loop salva um byte ÙSD¶ì.;. Não sei por que não pensamos nisso antes: P
Emigna

5

Haskell , 39 bytes

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

Experimente online!

Insere um símbolo de nova linha antes de cada caractere que aparece pela primeira vez, resultando em uma sequência separada por nova linha, com uma nova linha inicial. Anexar lines.para produzir uma lista.


Haskell , 55 bytes

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

Experimente online!

Pega o prefixo repetidamente no primeiro caractere mais os caracteres não exclusivos que o seguem.


@WheatWizard Opa, sim lines,.
Xnor

Talvez queira fazer tail.linespara remover a string extra vazia agora que penso nisso.
Assistente de trigo

4

APL (Dyalog) , 9 bytes

Obrigado, Erik, o Outgolfer, por economizar 1 byte!

⊢⊂⍨⍳∘≢∊⍳⍨

Experimente online!

Explicação:

⍳⍨: Para cada caractere, obtenha o índice de sua primeira ocorrência. por exemplomississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢: O intervalo de 1 ao comprimento da entrada.

: Assinatura. por exemplo1 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

⊢⊂⍨: Particione a sequência de entrada com novas partições começando em 1s no vetor acima


9 bytes (monadic fge monadic f∘gse comportam da mesma)
Erik a Outgolfer

Por que ao invés de =?
Adám

No momento em que escrevi, não havia considerado que os índices estivessem nas posições corretas. Embora seja claro que eles são
H.PWiz

4

Japonês , 11 bytes

‰ r@=iRUbY

Teste online!

Explicação

Isto foi inspirado por Magia Octopus Urna 's solução 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 está tendo uma crise de identidade aqui, está se chamando Ruby por algum motivo. iRUbY!
Magic Octopus Urn

3

JavaScript (ES6), 37 bytes

Economizou 7 bytes: uma nova linha principal foi explicitamente permitida (Obrigado @Shaggy!)

Recebe a entrada como uma matriz de caracteres. Gera uma sequência separada por nova linha.

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

Casos de teste


Novas linhas principais são permitidos para que possa obter esse baixo para 37 bytes
Shaggy

3

brainfuck, 66 bytes

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

Formatado:

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

Experimente online

A nova linha principal na saída (que é impressa apenas se a entrada não estiver vazia) pode ser removida ao custo de 5 bytes, substituindo o corpo xdo loop principal (mais externo) por .>,[x].



2

K4 , 19 bytes

Solução:

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

Exemplos:

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

Explicação:

8 bytes é apenas para lidar com ""...

$[#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 bytes

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

Experimente online!



@JonathanAllan é um efeito colateral enganoso, setnão mantenha ordem, contra-prova ->s='c'*6+'a'*100+'b'
Rod

Eu sei que não podemos confiar nele em implementações futuras, mas acredito que, dados inteiros ordenados, mantemos a ordem no conjunto devido ao hash de um número inteiro ser o número inteiro (como você mostrou o mesmo não é verdadeiro para outros objetos - você pode encontrar uma palavra que não funciona com a minha alternativa?).
Jonathan Allan

@JonathanAllan também não é verdade
Rod

Ah, justo, minha crença era falsa!
Jonathan Allan


2

Perl, 30 bytes

Inclui +1parap

Dê entrada sem rastrear nova linha no STDIN. A saída também é sem nova linha à direita:

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

Se você não se preocupam esquerda e à direita newlines este 25( +3para -pporque o código contém ') também funciona:

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

Ótima solução como sempre! Com base nos casos de teste fornecidos, você não precisa nomear seu hash, é possível ${$&}++. Não é tão robusto, mas pode ser suficiente para este desafio? Além disso, houve um consenso sobre a meta que perl -pnão precisa de um byte adicional, você só precisa ter o cabeçalho, e Perl with `-p` não apenas o Perl. Estou tentando lembrar-se de fazer isso sozinha ...
Dom Hastings

@DomHastings O relato de no máximo 95 possíveis seqüências implica fortemente que 1é válido; nesse caso, vé necessário. Em relação à contagem, sigo principalmente codegolf.meta.stackexchange.com/a/7539/51507, que para mim é o meta post mais consistente sobre a contagem de perl.
Ton Hospel

Sempre bom aprender com o mestre. Especificamente, neste caso, &~v0para pegar o primeiro caractere. Obrigado por ingressar neste site e compartilhar sua longa experiência.
Msh210

Você pode usar o Strawberry Perl, que usa em "vez de 'com -e, e pode contar -epcomo +1 em vez de +3. (Testado.)
msh210

2

JavaScript, 61 54 52 bytes

Recebe a entrada como uma matriz de caracteres.

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

Tente

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 bytes

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

Experimente online!

Retorna uma lista (possivelmente vazia) de substrings.

Agradecimentos a Michael M por economizar 7 bytes!


3
function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))seria mais curto - e, claro, um pouco mais feio ...
Michael M

Por que ao substringinvés de substr?
plannapus

@MichaelM Very nice! Eu ainda tenho que adicionar o if(n)lá porque substringgera um erro para a entrada de seqüência de caracteres vazia.
Giuseppe

1
@plannapus substrretorna um vetor de comprimento igual à sua primeira entrada, enquanto substringretorna um de comprimento igual à maior de suas entradas.
Giuseppe

@Giuseppe: Deixar cair o "se (n)" em R 3.4.3 mapeia a cadeia vazia de entrada "" para a cadeia de saída vazia "", que deve ser fino (?)
Michael M

2

Stax , 8 bytes

ç↓‼►▐NVh

Executar e depurar online

A representação ascii do mesmo programa é essa.

c{[Ii=}(m

Para cada caractere, ele é dividido quando o índice do caractere atual é a posição atual.

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 bytes

-1 byte graças a Emigna

i:::a$1g?!o1po

Experimente online!

Imprime uma nova linha inicial e final.

Ele rastreia quais letras já apareceram, pcitando uma cópia do caractere no local correspondente na segunda linha e imprimindo uma nova linha se o valor buscado nessa posição não for 1. Termina com um erro ao tentar imprimir-1


Ótimo uso de g/p! 16 bytes
Emigna 8/03


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]

Recebe a entrada como uma lista de caracteres.

Casos de teste:


Eu tive uma solução semelhante e perguntei se [""]era aceitável para o último caso de teste. Mas não é . :-(
Arnauld

Oh, bem, você tem uma solução muito melhor de qualquer maneira:)
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;
}

Experimente online!


2
Olá, e bem-vindo ao PPCG! Editei sua postagem no nosso formato padrão e adicionei um link para o Try It Online para que outras pessoas possam testar seu código. O objetivo do Code Golf é escrever o código mais curto possível, e posso ver algumas maneiras de torná-lo mais curto, como usar nomes de variáveis ​​mais curtos e deixar de fora parte do espaço em branco. Você pode conferir as dicas gerais e as páginas de dicas sobre PHP para mais algumas idéias.
Não é uma árvore

1

Vermelho , 79 bytes

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

Experimente 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 bytes

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

Experimente online!

Imprime as substrings separadas por novas linhas.

Explicação:

A linha S(for SPLIT) não é dividida, mas extrai o primeiro caractere de Ne salva ( .) em Y. Na Fdoença, ele pula para END. A correspondência só deve falhar quando Né a string vazia. Assim, quando a entrada está vazia, ela salta diretamente para ENDe não produz nada.

S = S Yconcatena Yem S.

SPAN(S)corresponde avidamente a uma série de caracteres Se a envia ( .) para OUTPUT, definindo ( .) Npara os REMcaracteres finais de N(se houver algum). Então ele volta para S.


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

você pode salvar alguns bytes - Experimente online!
mazzy 8/03

1

Ruby , 65 62 58 bytes

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

Experimente online!

Um lambda aceitando uma string e retornando uma matriz de strings.

Abordagem: para cada índice, acrescente o caractere nesse índice sà matriz de resultados ou à última sequência da matriz de resultados. String#indexretorna o índice da primeira instância do argumento.

-2 bytes: inicialize acomo um argumento de splat em vez de em sua própria linha. Obrigado, Value Ink !

-1 byte: Use c=s[i]... cem vez de s[i]... s[i]. Obrigado, Value Ink !

-4 bytes: use em .timesvez de.map



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 graças a @raznagul (por algo óbvio, de alguma forma, senti falta de mim ..)
-3 bytes graças a @OOBalance (novamente por algo óbvio, de alguma forma, senti falta de mim mesmo ..: S)

Explicação:

Experimente 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
Eu não acho que você precise do if(l<1). If lis, 0o loop não deve ser executado como 0<0está false.
raznagul

@raznagul Não sei como eu perdi isso, mas você está completa certo ..>>!.
Kevin Cruijssen

Você está configurando i=0duas vezes. Você pode salvar 3 bytes largando o segundo:for(;i<l;i++)
OOBalance

@OOBalance Não sei como isso aconteceu ..: S Mas obrigado por perceber! :)
Kevin Cruijssen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.