Fractionner la chaîne à la première occurrence de chaque caractère

45

En relation.

Avec une chaîne ASCII imprimable, divisez-la en une liste de chaînes non vides avec une nouvelle sous-chaîne commençant chaque fois qu'un caractère qui n'a pas été vu auparavant dans la même casse apparaît.

Exemples

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

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

"AAA" → ["AAA"]

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

"" → []


Anecdote : Le résultat aura entre 0 et 95 éléments. La 95 e sous-chaîne se poursuivra nécessairement jusqu'à la fin car, à ce stade, tous les caractères imprimables ASCII ont commencé une sous-chaîne, de sorte que chaque caractère supplémentaire est déjà passé et ne peut donc pas entraîner le début d'une nouvelle sous-chaîne.

Adam
la source
1
Un exemple contenant "et 'semble être une bonne idée.
Emigna
Serait ""[""]acceptable?
Arnauld
5
@ Emigna Cela dérange juste avec l'exemple de format de sortie sans apporter plus de clarté.
Adám
1
Si la sortie est une chaîne séparée par une nouvelle ligne, peut-il y avoir une nouvelle ligne au début / à la fin?
wastl
2
@ Wastl Euh, je vais le permettre dans ce cas car il ne peut pas indiquer de segments vides, bien que cela soit en contradiction avec ma décision antérieure d' [""]invalidité. Soupir.
Adám

Réponses:

22

Gelée , 4 octets

QƤĠị

Essayez-le en ligne!

Explication

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 représentation interne des chaînes, que le lien TIO affiche, est légèrement différente.

Zgarb
la source
10

Retina , 9 octets

q1,`.
¶$&

Essayez-le en ligne!

Explication

Faites correspondre chaque caractère ( .), supprimez les correspondances répétées ( q), supprimez la première correspondance ( 1,) et insérez un saut de ligne devant chaque correspondance ¶$&.

Martin Ender
la source
6

05AB1E , 11 octets

ÙSk¥sg¸«£õK

Essayez-le en ligne!

Explication

Ù             # 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
la source
1
Pour toute personne rencontrant cette réponse, ¸«peut être ªdans la nouvelle version de 05AB1E.
Kevin Cruijssen Le
6

C,  75   65  63 octets

Merci à @ Digital Trauma pour avoir économisé 10 octets et merci à @gastropner et @ l4m2 pour avoir économisé un octet chacun!

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

Imprime une nouvelle ligne.

Essayez-le en ligne!

Sans nouvelle ligne principale (71 octets):

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

Essayez-le en ligne!

Steadybox
la source
1
64 octets
gastropner le
@gastropner astuce astucieuse; Merci!
Steadybox
{0}=> {}?
l4m2
@ l4m2 Oui, merci!
Steadybox
5

Perl 6 ,  58 52  40 octets

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

L'essayer

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

L'essayer

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

Essayez-le
(l'entrée est une liste de caractères et la sortie est une liste de listes de caractères)

Étendu:

*                   # 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 sortie de classifyest

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

Et le .sorttransforme simplement en:

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

».value enlève les clés

[
  ['m'],
  ['i'],
  ['s','s','i','s','s','i'],
  ['p','p','i'],
]
Brad Gilbert b2gills
la source
Pourquoi les clés seraient-elles jamais en panne? Est-ce que l'ordre d'insertion n'est pas suivi comme un HashMapvs contre LinkedHashMapen Java où l'ordre est basé sur l'ordre de la mémoire contre l'ordre d'insertion?
Urne magique Octopus
1
@MagicOctopusUrn Aucune version de Perl n'a commandé de hachage. En fait, Perl 5 version 18 a rendu les hachages plus aléatoires, ce qui contribue à rendre moins possible un certain type d'attaque par déni de service et a également amené le code utilisateur buggy à exposer plus souvent son comportement buggy. Maintenant, quelqu'un pourrait (et a probablement déjà) implémenté une classe qui garde une trace, mais cela prendrait plus de 5 caractères à charger et à utiliser.
Brad Gilbert b2gills
5

J , 7 octets

~:<;.1]

Essayez-le en ligne!

Explication

Nub sieve a la chance de briller!

~: <;.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
la source
2
J'étais sur le point de poster exactement la même réponse (sans surprise), c'est bien que j'ai jeté un coup d'œil sur votre soumission plus tôt :)
Galen Ivanov
2
@GalenIvanov I - et j'imagine la plupart des autres golfeurs J - apprécie également la possibilité d'utiliser un tamis à mailles ou de se classer lui-même.
Cole
5

APL (Dyalog Unicode) , SBCS sur 8 octets

(≢¨∪\)⊆⊢

Essayez-le en ligne!

ngn
la source
Mais, mais… Oh mon Dieu.
Adám
Je pensais que vous auriez pu poster ce défi à cause de la nouvelle primitive (). Evidemment pas :)
ngn
Cela ressemble à un Kirby embarrassé tenant un biberon.
Urne magique Octopus
pour tous ceux qui ont besoin de regarder "Kirby" comme moi - c'est une boule rose anthropomorphique issue d'un jeu vidéo japonais
ngn
5

05AB1E , 8 octets

Ùvyy¶ì.;

Essayez-le en ligne!


Toujours affichera 1 nouvelle ligne précédente, ce qui est constant et non indicatif d'un fractionnement. L'alternative à 10 octets ne produisant pas de nouvelle ligne précédente est Ùvyy¶ì.;}¦, vous pouvez l'essayer ici . Selon Adam, une nouvelle ligne précédente ou suivante est 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']

Après chaque itération on obtient:

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

Lequel est:

m
i
ssissi
ppi
Urne Magique De Pieuvre
la source
Agréable! Battez-moi de
justesse
@ Emigna c'était assis comme un commentaire sur votre réponse pendant 2 jours alors je viens de le poster b / c pas de réponse haha: P.
Urne Magic Octopus
Bizarre, je n'ai vu aucune notification à ce sujet. Assez différent pour sa propre réponse cependant :)
Emigna
@ Emigna bien, je veux dire, je l'ai supprimé haha.
Urne Magique Octopus
Passer la boucle enregistre un octet ÙSD¶ì.;. Pas sûr de savoir pourquoi on n'y avait pas pensé auparavant: P
Emigna
5

Haskell , 39 octets

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

Essayez-le en ligne!

Insère un symbole de nouvelle ligne avant chaque caractère qui apparaît pour la première fois, ce qui donne une chaîne séparée par une nouvelle ligne, avec une nouvelle ligne. Prévoyez lines.pour produire une liste.


Haskell , 55 octets

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

Essayez-le en ligne!

Le préfixe prend à plusieurs reprises le premier caractère plus les caractères non uniques qui le suivent.

Xnor
la source
@WheatWizard Oups, oui lines.
xnor
Peut-être voudriez-vous faire tail.linespour supprimer la chaîne vide supplémentaire maintenant que j'y pense.
Wheat Wizard
4

APL (Dyalog) , 9 octets

Merci, Erik the Outgolfer pour avoir économisé 1 octet!

⊢⊂⍨⍳∘≢∊⍳⍨

Essayez-le en ligne!

Explication:

⍳⍨: Pour chaque caractère, obtenez l'index de sa première occurrence. par exemplemississippi -> 1 2 3 3 2 3 3 2 9 9 2

⍳∘≢: La plage de 1 à la longueur de l'entrée.

: Adhésion. par exemple1 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

⊢⊂⍨: Partitionne la chaîne d'entrée avec de nouvelles partitions commençant par 1s dans le vecteur ci-dessus

H.PWiz
la source
9 octets (monadique fget monadique f∘gse comportent de la même manière)
Erik the Outgolfer
Pourquoi au lieu de =?
Adám
Au moment d'écrire ces lignes, je n'avais pas pensé que les indices seraient dans les bonnes positions. Bien qu'il soit clair qu'ils sont
H.PWiz
4

Japt , 11 octets

‰ r@=iRUbY

Testez-le en ligne!

Explication

Cela a été inspiré par la magie Octopus Urne de solution 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.
ETHproductions
la source
1
Japt a une crise d'identité ici, il s'appelle Ruby pour une raison quelconque. iRUbY!
Urne magique Octopus le
3

JavaScript (ES6), 37 octets

Enregistré 7 octets: une nouvelle ligne de premier plan était explicitement autorisée (Merci @Shaggy!)

Prend les entrées sous forme de tableau de caractères. Affiche une chaîne séparée par une nouvelle ligne.

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

Cas de test

Arnauld
la source
Les nouvelles lignes principales sont autorisées , vous pouvez donc passer à 37 octets
Shaggy
3

brainfuck, 66 octets

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

Formaté:

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

Essayez-le en ligne

La nouvelle ligne de début dans la sortie (qui n'est imprimée que si l'entrée n'est pas vide) peut être supprimée au prix de 5 octets en remplaçant le corps xde la boucle principale (la plus à l'extérieur) par .>,[x].

Mitch Schwartz
la source
2

K4 , 19 octets

Solution:

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

Exemples:

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

Explication:

8 octets est juste pour manipuler ""...

$[#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
la source
2

Python 2 , 81 74 octets

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

Essayez-le en ligne!

Barre
la source
Enregistrer deux avec la liste (définir (carte (s.find, s)))
Jonathan Allan
@JonathanAllan c'est un effet secondaire trompeur, setne maintenez pas l'ordre, contre-preuve ->s='c'*6+'a'*100+'b'
Rod
Je sais que nous ne pouvons pas compter sur cela dans les implémentations futures, mais je pense que, étant donné les entiers ordonnés, nous maintenons cet ordre dans l'ensemble en raison du hachage d'un entier étant l'entier (comme vous l'avez montré, la même chose n'est pas vraie pour d'autres objets - pouvez-vous trouver un mot qui ne fonctionne pas avec mon alternative?).
Jonathan Allan
@ JonathanAllan pas vrai non plus
Rod
Ah oui, ma conviction était fausse!
Jonathan Allan
2

Perl, 30 octets

Comprend +1pourp

Donnez votre entrée sans fin de nouvelle ligne sur STDIN. La sortie est également sans fin de ligne:

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

Si vous ne se soucient pas de tête et de queue des sauts de ligne ce 25( +3pour -pparce que le code contient ') fonctionne aussi:

#!/usr/bin/perl -p
s%%$/x!$v{$'&~v0}++%eg
Ton Hospel
la source
Bonne solution comme toujours! Selon les cas de test fournis, vous n'avez pas besoin de nommer votre hachage, vous pouvez le faire ${$&}++. Ce n'est pas aussi robuste, mais pourrait suffire à ce défi? En outre, il y a eu un consensus sur les méta qui perl -pn'ont pas besoin d'octet supplémentaire, vous devez simplement avoir l'en-tête au Perl with `-p` lieu de Perl. J'essaie de me souvenir de le faire moi-même ...
Dom Hastings
@DomHastings L'annecdote sur au plus 95 chaînes possibles implique assez fortement que 1c'est valide, auquel cas le vest nécessaire. En ce qui concerne le comptage, je suis surtout le codegolf.meta.stackexchange.com/a/7539/51507 qui est pour moi la méta-publication la plus cohérente sur le comptage de perl.
Ton Hospel
Toujours agréable d'apprendre du maître. Plus précisément, dans ce cas, &~v0pour saisir le premier caractère. Merci de rejoindre ce site et de partager votre longue expertise.
msh210
Vous pouvez utiliser Strawberry Perl, qui utilise à la "place de 'avec -e, puis vous pouvez compter -epcomme +1 plutôt que +3. (Testé.)
msh210
2

JavaScript, 61 54 52 octets

Prend les entrées sous forme de tableau de caractères.

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

L'essayer

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>

Hirsute
la source
2

R , 94 87 octets

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

Essayez-le en ligne!

Retourne une liste (éventuellement vide) de sous-chaînes.

Merci à Michael M pour avoir économisé 7 octets!

Giuseppe
la source
3
function(s,n=nchar(s),g=substring)g(s,d<-which(!duplicated(g(s,1:n,1:n))),c(d[-1]-1,n))serait plus court - et bien sûr un peu plus laid ...
Michael M
Pourquoi substringau lieu de substr?
Plannapus
@MichaelM Très sympa! Je dois encore ajouter le if(n)dedans là car substringjette une erreur pour une entrée de chaîne vide.
Giuseppe
1
@plannapus substrrenvoie un vecteur de longueur égal à sa première entrée et substringun de longueur égal à la plus longue de ses entrées.
Giuseppe
@Giuseppe: Le fait de supprimer le "if (n)" dans R 3.4.3 mappe la chaîne d'entrée vide "" à la chaîne de sortie vide "", ce qui devrait être correct (?)
Michael M
2

Stax , 8 octets

ç↓‼►▐NVh

Exécuter et déboguer en ligne

La représentation ascii du même programme est la suivante.

c{[Ii=}(m

Pour chaque caractère, il se scinde lorsque l'index du caractère actuel est la position actuelle.

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
récursif
la source
2

> <> , 22 17 14 octets

-1 octet grâce à Emigna

i:::a$1g?!o1po

Essayez-le en ligne!

Imprime une nouvelle ligne au début et à la fin.

Pour garder une trace des lettres qui sont déjà apparues, pcréez une copie du caractère à cet endroit correspondant sur la deuxième ligne et imprimez une nouvelle ligne si la valeur extraite de cette position n'était pas 1. Se termine par une erreur lorsqu'il tente d'imprimer-1

Jo King
la source
Excellent usage de g/p! 16 octets
Emigna
1

JavaScript (ES6), 68 octets

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

Prend la saisie sous forme de liste de caractères.

Cas de test:

Rick Hitchcock
la source
J'avais une solution similaire et demandé si [""]était acceptable pour le dernier cas de test. Mais ce n'est pas . :-(
Arnauld
Oh, eh bien, vous avez quand même une bien meilleure solution:)
Rick Hitchcock
1

PHP, 317 octets

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

Essayez-le en ligne!

Saurabh Chandra Patel
la source
2
Bonjour et bienvenue chez PPCG! J'ai modifié votre message au format standard et ajouté un lien à Try It Online afin que d'autres personnes puissent tester votre code. Le but de Code Golf est d’écrire le code le plus court possible, et je vois deux façons de le raccourcir, par exemple en utilisant des noms de variable plus courts et en laissant de l’espace. Vous pouvez consulter les astuces générales et les pages de astuces PHP pour d'autres idées.
Pas un arbre
1

Rouge , 79 octets

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

Essayez-le en ligne!

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
la source
1

SNOBOL4 (CSNOBOL4) , 115 91 77 octets

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

Essayez-le en ligne!

Imprime les sous-chaînes séparées par des nouvelles lignes.

Explication:

line S(for SPLIT) ne se scinde pas réellement, mais extrait le premier caractère de Net l'enregistre ( .) dans Y. D' Failleurs, ça saute à END. La correspondance ne doit échouer que lorsque Nla chaîne est vide. Ainsi, lorsque l'entrée est vide, elle saute directement vers ENDet ne génère rien.

S = S Yconcatène Ysur S.

SPAN(S)correspond avidement à une série de caractères dans Set l'envoie ( .) à OUTPUTsetting ( .) Npour les REMcaractères entrants de N(s'il en existe). Puis il revient à S.

Giuseppe
la source
1

PowerShell, 73 octets

{$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
la source
vous pouvez économiser des octets - Essayez-le en ligne!
Mazzy
1

Ruby , 65 62 58 octets

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

Essayez-le en ligne!

Un lambda acceptant une chaîne et renvoyant un tableau de chaînes.

Approche: pour chaque index, ajoutez le caractère de cet index au stableau de résultats ou à la dernière chaîne du tableau de résultats. String#indexrenvoie l'index de la première instance de l'argument.

-2 octets: Initialise en atant qu'argument splat au lieu de sa propre ligne. Merci, valeur d'encre !

-1 octet: Utiliser c=s[i]... au clieu de s[i]... s[i]. Merci, valeur d'encre !

-4 octets: utiliser .timesau lieu de.map

benj2240
la source
1

Java 8, 193 169 155 151 octets

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 octets grâce à @raznagul (pour quelque chose d'évident, je me suis un peu manqué ..)
-3 octets grâce à @OOBalance (encore pour quelque chose d'évident, je me suis égaré moi-même ..: S)

Explication:

Essayez-le en ligne.

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
la source
1
Je ne pense pas que tu aies besoin du if(l<1). Si lest 0la boucle ne doit pas être exécutée de toute façon comme 0<0est false.
Raznagul
@raznagul Je ne sais pas trop comment j'ai raté ça, mais vous avez parfaitement raison! ...>.>
Kevin Cruijssen
Vous vous couchez i=0deux fois. Vous pouvez économiser 3 octets en for(;i<l;i++)
supprimant
@OOBalance Je ne sais pas comment cela s'est passé ..: S Mais merci de l'avoir remarqué! :)
Kevin Cruijssen le