Ajouter et effacer

14

Étant donné une ligne composée uniquement de lettres, procédez comme suit:

  • Vous conservez une chaîne vide au début.
  • Si le caractère d'entrée suivant se trouve dans la chaîne, supprimez-le de la chaîne.
  • Si le caractère d'entrée suivant n'est pas dans la chaîne, ajoutez-le à la chaîne.

Affiche l'état final de la chaîne.

Vous pouvez supposer en toute sécurité que l'entrée comprend au moins un caractère (c'est-à-dire non vide), mais rien ne garantit que la sortie n'est pas vide.

Pseudocode (n'hésitez pas à jouer au golf):

str = EMPTY
for each character ch in input
  if ch exists in str
    remove all ch from str
  else
    append ch to str
print str

L'entrée correspond à l'expression régulière ^[A-Za-z]+$.

Exemples de cas de test:

ABCDBCCBE -> ADCBE
ABCXYZCABXAYZ -> A
aAABBbAbbB -> aAbB
GG -> (empty)

L'entrée peut être donnée de n'importe quelle manière applicable, mais elle doit être traitée comme une chaîne, et la même chose pour la sortie. Le programme ne doit pas quitter avec une erreur.

Le programme le plus court dans chaque langue gagne!

Extra (Facultatif): Veuillez expliquer comment fonctionne votre programme. Je vous remercie.

iBug
la source
La ligne peut-elle être vide?
user202729
1
@ user202729 Non. J'ai un peu changé (cela n'invalide aucune réponse) donc l'entrée n'est jamais vide.
iBug
1
Alors , pourquoi avez - vous rejetez la suggestion de modifier de ais523 (lien) ?
user202729

Réponses:

10

Haskell , 44 42 octets

foldl(#)""
s#x|z<-filter(/=x)s=z++[x|z==s]

Essayez-le en ligne! Edit: -2 octets grâce à Zgarb!

Explication:

La deuxième ligne définit une fonction (#)qui prend une chaîne set un caractère xet effectue la suppression ou l'ajout. Ceci est réalisé en filtering sur chaque occurrence de xin s, résultant en la chaîne z. Si xne se produit pas danss , alors zest égal à set z++[x|z==s]renvoie la chaîne d'origine avec en xannexe. Sinon, [x|z==s]renvoie la chaîne vide et seule la chaîne filtrée est renvoyée.

foldl(#)""est une fonction anonyme qui prend une chaîne et ajoute un caractère après l'autre la chaîne initialement vide ""avec la fonction(#) .

Laikoni
la source
2
42 octets en réutilisant le filtre.
Zgarb
9

Gelée , 3 octets

œ^/

Essayez-le en ligne!

Programme complet.

Erik le Outgolfer
la source
Pourquoi ça œ^/ne suffit pas?
Jonathan Allan
@JonathanAllan Le programme ne doit pas quitter avec une erreur.
Erik the Outgolfer
the input is never emptyEh bien, maintenant ça marche.
user202729
8

J , 21 19 octets

#~~:&.|.(2|*)1#.=/~

Comment ça fonctionne:

=/~ - fait un tableau d'égalité des caractères dans la chaîne:

   a =. 'ABCXYZCABXAYZ'
   ]b =: =/~ a 
1 0 0 0 0 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 1
0 0 1 0 0 0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 1 0 0 1 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 1

1#. - somme de chaque ligne par conversion en base 1 (combien de fois la lettre apparaît)

   ]c =: 1#. b
3 2 2 2 2 2 2 3 2 2 3 2 2

~:&.|- inverser, puis appliquer nub tamis (est le caractère unique) et inverser à nouveau. Ainsi je retrouve les dernières occurrences des caractères de la chaîne:

   ]d =. ~:&.|. a
0 0 0 0 0 0 1 0 1 1 1 1 1

* - multiplie le compte par 1 pour la dernière position du caractère dans la chaîne, par 0 sinon, calculé par ce qui précède ~:&.|

   ]e =. c * d
0 0 0 0 0 0 2 0 2 2 3 2 2

2| - modulo 2 (met à 0 les positions des caractères qui ont même compté):

   ]f =. 2| e 
0 0 0 0 0 0 0 0 0 0 1 0 0

#~- copier l'argument de droite, l'argument de gauche. fois (~ inverse les endroits des args)

]f # a A

Essayez-le en ligne!

Galen Ivanov
la source
6

Brainfuck, 95 octets

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

Essayez-le en ligne

Comment ça fonctionne

, Gets first input
[ Starts loop
    <<< Go to start of string
    [ Loop over the string
        [->+>>>+<<<<] Duplicates the current char of the string
        >>>[-<+<->>] Duplicates and subtracts the inputted char from the duplicate of the string char
        <<[[-]<] If the char is different to the input, remove the difference
        > If the char is the same
        [
            [-]>>[-]>[[-<+>]>]<<[<]<< Remove the char from the string and sets the inputted char to 0
        ]
        << Moves to the next char of the string
    ]
    >>>[->+<] adds the inputted char to the string
    >>[>]>>, gets the next input
]
<<<[.<] prints the string
Jo King
la source
4

Haskell , 47 octets

Un autre dégage la poussière grâce à Bruce Forte.

import Data.List
foldl1(\x y->union(x\\y)$y\\x)

Essayez-le en ligne!

Prend une liste de chaînes.

La différence symétrique est ennuyeuse ...

totalement humain
la source
++enregistre 2 octets de plus unionavec cette méthode.
Ørjan Johansen
2

R , 92 84 77 octets

for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='')

Essayez-le en ligne!

-15 octets grâce à djhurio

Explication

djhurio a fourni une excellente réponse R en évitant une forboucle - comme le font instinctivement les programmeurs R (moi y compris). Voici une réponse R qui utilise une forboucle (et économise quelques octets dans le processus).

  • x=scan(,''); - affecter l'entrée dans la variable x
  • y=''; - créer une chaîne vide dans une variable appelée y
  • for(i in el(strsplit(x,'')))- pour chaque caractère idansx
  • y=c(y[y!=i],if(!i%in%y)i)- attribuer à ychaque élément de ce yqui n'est pas égal à i, en ajoutant isi in'était pas déjà dansy
  • cat(y,sep='')- imprimer les éléments de ysans espace entre eux

Remarque

Si vous cliquez sur le lien TIO ci-dessus, vous le trouverez dans l'en-tête library(methods); c'est pour faire face à l'erreur que djhurio a connue concernant la el()fonction - la fonction est fournie par le methodspackage, qui, dans n'importe quelle version de R que j'ai utilisée, est chargé par défaut, mais pour une raison quelconque, il ne l'est pas par TIO. Si library(methods)est supprimé de l'en-tête et unlistest remplacé par el, je gagne quatre octets, mais il en serait de même pour djhurio , en plaçant nos nombres d' octets à 96 88 et 99 respectivement.

duckmayr
la source
Joli. Jamais pensé pour la boucle sera plus courte. Vous pouvez le raccourcir encore plus en omettant l'instruction else for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='').
djhurio
@djhurio - Je sais, ce n'est presque jamais le cas dans R une boucle va aider avec quoi que ce soit. Concernant votre suggestion: Excellente idée! La suggestion est maintenant incorporée dans la réponse.
duckmayr
1
@djhurio - assez juste; J'étais trop occupé à regarder la différence introduite en omettant la déclaration else Je ne voyais pas comment vous aviez changé le début. Modification maintenant. Bon travail!
duckmayr
1
@djhurio @duckmayr, il existe une solution de 73 octets qui utilise essentiellement cette solution et utilise une approche légèrement différente pour extraire les caractères. Je n'avais pas vraiment envie de le poster comme une réponse séparée. Notez également qu'il ...[[1]]est plus long el(...)mais plus court que unlist(...), à condition qu'il ...s'agisse d'une liste de longueur 1.
Giuseppe
1
grattez cela, j'ai trouvé une réponse de 70 bye car 0c'est le nulcaractère et est converti en chaîne vide.
Giuseppe
2

MATL , 6 octets

vi"@X~

Ne fonctionne pas dans l'environnement TIO, mais fonctionne bien sur l'implémentation MATLAB, et grâce à un nouveau patch, vous pouvez l'essayer sur MATL Online

X~égal setxorou différence symétrique, qui fait exactement ce que le défi demande. Le reste fait simplement une boucle sur l'entrée i"@et commence avec une chaîne vide en concaténant la pile entière qui est vide au début (merci Luis Mendo).

Sanchises
la source
2

Python 2 , 56 octets

-2 octets grâce à xnor. -3 octets grâce aux ovs.

lambda s:reduce(lambda a,c:a.replace(c,'')+c[c in a:],s)

Essayez-le en ligne!

Je viens de jouer au pseudocode. : P

totalement humain
la source
1
Enregistrer 2 octets: s=(s+c).replace(c,c[c in s:]).
2017
@xnor C'est du golf de base exécuté très intelligemment. Merci!
2017 totalement humain
1
-1 octet :s=s.replace(c,'')+c[c in s:]
ovs
1
56 octets en utilisant réduire
ovs
1

JavaScript (ES6), 60 octets

s=>[...s].map(c=>s=s.match(c)?s.split(c).join``:s+c,s='')&&s

Cas de test

Arnauld
la source
J'ai porté la réponse Retina de @ MartinEnder et ce n'était que de 45 octets ...
Neil
1

q , 38 octets

""{$[y in x;except;,][x;y]}/
skeevey
la source
1

APL + WIN, 19 octets

Logique similaire à la solution J de Galen.

(2|+⌿⌽<\⌽c∘.=c)/c←⎕     
Graham
la source
1

Wolfram Language (Mathematica) , 36 octets

#//.{a___,x_,b___,x_,c___}:>{a,b,c}&

Essayez-le en ligne!

Prend l'entrée et la sortie sous forme de liste de caractères.

Comment ça fonctionne

Utilise //.(alias ReplaceRepeated) pour rechercher deux caractères répétés et supprimer les deux, jusqu'à ce qu'il n'y ait plus de caractères répétés. Si le caractère apparaît plus de deux fois, Mathematica supprimera toujours les deux premières occurrences. Donc, si un personnage se produit un nombre impair de fois, sa dernière instance sera toujours celle qui survivra.

Misha Lavrov
la source
1

Prolog 81 octets

a([],O,O).
a([I|J],K,O):-delete(K,I,F),(K=F->append(K,[I],M),a(J,M,O);a(J,F,O)).

Version non obscurcie:

append_and_eraze([], Output, Output).
append_and_eraze([I | Input], Interim, Output) :-
    delete(Interim, I, Filtered),
    ( Interim = Filtered ->
      append(Interim, [I], Interim1),
      append_and_eraze(Input, Interim1, Output)
    ;
    append_and_eraze(Input, Filtered, Output)
    ).
  1. delete/3 s'assure que son troisième argument s'unifie avec son premier argument, avec toutes les instances du deuxième argument supprimées.
  2. Si ceux-ci s'avèrent être les mêmes, nous ajoutons l'élément (il n'a pas été supprimé).
  3. append/3 selon son nom, ajoute un élément à la liste.
  4. Nous revenons sur les éléments de l'entrée jusqu'à ce que nous atteignions la [](liste vide), moment auquel le résultat intermédiaire s'unifiera avec le résultat souhaité.

Tester:

?- append_and_eraze(`ABCDBCCBE`, [], X), string_codes(Y, X).
X = [65, 68, 67, 66, 69],
Y = "ADCBE".

?- append_and_eraze(`ABCXYZCABXAYZ`, [], X), string_codes(Y, X).
X = [65],
Y = "A".

?- append_and_eraze(`aAABBbAbbB`, [], X), string_codes(Y, X).
X = [97, 65, 98, 66],
Y = "aAbB".

?- append_and_eraze(`GG`, [], X), string_codes(Y, X).
X = [],
Y = "".

Certains Prologs traitent les chaînes entre guillemets doubles comme des listes, SWI peut être configuré pour faire de même, mais pour des raisons de simplicité, j'ai utilisé string_codes/2pour formater la sortie correctement.

wvxvw
la source
1

R , 84 octets

y=el(strsplit(scan(,""),""));cat(unique(y[colSums(outer(y,y,"=="))%%2>0],,T),sep="")

Essayez-le en ligne!

Une autre solution, mais il y a de meilleures réponses R ici.

R , 88 octets

z=table(y<-el(strsplit(scan(,""),"")));cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="")

Essayez-le en ligne!

Merci à Giuseppe pour -7 octets!

Il y a une réponse plus courte de duckmayr .

  1. scan(,"") lire l'entrée de stdin.
  2. y<-el(strsplit(scan(,""),""))diviser l'entrée par caractères et l'enregistrer sous y.
  3. z=table(y<-el(strsplit(scan(,""),"")))calculer les fréquences de chaque caractère et enregistrer la table résultante sous z;
  4. unique(y,,T) prenez des personnages uniques du côté droit.
  5. names(z[!z%%2]) sélectionner uniquement les nombres pairs et extraire les noms.
  6. setdiff(unique(y,,T),names(z[!z%%2])) supprimer des caractères avec un nombre pair.
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") imprimer la sortie.
djhurio
la source
La raison de votre erreur el()vient du methodspaquet, qui, bien que généralement chargé par défaut, ne l'est pas par TIO (discuté dans ma réponse ci-dessous)
duckmayr
pourquoi utilisez-vous rev(unique(rev(y)))? Ne fonctionnerait pas simplement unique(y)? ooohhh attends je vois, tu veux les personnages uniques de droite à gauche. Dans ce cas unique(y,,T)(le réglage fromLast=T) sera de 88 octets .
Giuseppe
0

Alice , 9 octets

/X&@
\io/

Essayez-le en ligne!

Explication

Fondamentalement, un port de la réponse d' Erik . Mis à part un peu de redirection IP, le code est vraiment juste:

i&Xo@

qui fait:

i   Read all input.
&X  Fold symmetric multiset difference over the input.
o   Output the result.
@   Terminate.
Martin Ender
la source
0

APL (Dyalog) , 16 octets

{(,⍨~∩)/⍣(≢⍵)⊖⍵}

Essayez-le en ligne!

Si des erreurs avaient été autorisées, cela aurait été de 9 octets:

(,⍨~∩)/∘⊖
Erik le Outgolfer
la source
Qu'entendez-vous par erreurs?
FrownyFrog
@FrownyFrog La version 9 octets lancerait un DOMAIN ERRORsi la chaîne est vide, car (,⍨~∩)n'a pas d'élément d'identité prédéfini.
Erik the Outgolfer
0

Rubis , 53 octets

->s{s.reverse.uniq.select{|c|s.count(c)%2>0}.reverse}

Essayez-le en ligne!

L'entrée et la sortie sont toutes deux un tableau de caractères. Testez les appels de code .charset .joinpour plus de commodité.

Explication

Utilise le fait que les lettres de la chaîne résultante apparaissent un nombre impair de fois et dans l'ordre de droite à gauche.

->s{                # lambda function taking char-array argument
    s.reverse           # reverse the input
    .uniq               # get unique characters
    .select{|c|         # select only those which...
        s.count(c)%2>0      # appear in the input array an odd number of times
    }.reverse           # reverse back and return
}
Justin Mariner
la source
0

Pyth, 13 octets

{_xD_Qf%/QT2Q

Prend en entrée la liste des caractères. Testez-le!

      f     Q            (f)ilter input (Q)
        /QT              On how many times (/) each character (T) appears in the 
                           input (Q)
       %   2             Only allow odd numbers of occurences (when x % 2 = 1)
 _xD_Q                   Sort (D) descending (the first _) by the location (x) of 
                           the last (the second _) inde(x) of the target character
                           in the input (Q)
{                        Remove duplicates
Steven H.
la source
0

Röda , 34 octets

{a=[]a-=_ if[_1 in a]else a+=_1;a}

Essayez-le en ligne!

Il s'agit d'une traduction directe du pseudocode. Il traite l'entrée et la sortie comme des flux de caractères.

Explication:

{                    /* Anonymous function                   */
    a=[]             /* initialize a                         */
                     /* For each character _1 in the stream: */
    a-=_ if[_1 in a] /*  Remove it from a if a contains it   */
    else a+=_1;      /*  Otherwise append it to a            */
    a                /* Push characters in a to the stream   */
}
fergusq
la source
0

Python 3 , 73 octets

Pas le plus court, mais j'aime cette approche.

lambda s:''.join(c*(s.count(c)%2)*(i==s.rfind(c))for i,c in enumerate(s))

Essayez-le en ligne!

Boucle dans la chaîne, en ne gardant que les caractères où:

  • (s.count(c)%2) == 0 - Le personnage apparaît un nombre pair de fois.
  • (i==s.rfind(c)) - L'index actuel est la dernière apparition du personnage en question.
FlipTack
la source
0

REXX , 102 octets

a=arg(1)
s=''
do while a>''
  b=right(a,1)
  if countstr(b,a)//2 then s=b||s
  a=changestr(b,a,'')
  end
say s

Essayez-le en ligne!

Comment cela fonctionne: Prenez la lettre la plus à droite, voyez si le nombre d'occurrences est pair ou impair (qui se double également d'une valeur de vérité) et s'il est impair, ajoutez-le à la chaîne de sortie. Supprimez ensuite toutes les occurrences de la lettre de la chaîne d'entrée. Répétez jusqu'à ce que l'entrée soit épuisée.

idrougge
la source
0

Java 8, 93 octets

Un lambda de Stringà String. Juste une implémentation du pseudocode dans la question.

s->{String o="";for(char c:s.toCharArray())o=o.indexOf(c)<0?o+c:o.replace(c+"","");return o;}

Essayez-le en ligne

Java 8, 182 octets

Voici un autre lambda du même type qui utilise des flux! C'est probablement plus efficace.

s->s.join("",s.chars().mapToObj(c->(char)c+"").filter(c->s.replaceAll("[^"+c+"]","").length()%2>0).distinct().sorted((c,d)->s.lastIndexOf(c)-s.lastIndexOf(d)).toArray(String[]::new))

Essayez-le en ligne

Non golfé

s ->
    s.join(
        "",
        s.chars()
            .mapToObj(c -> (char) c + "")
            .filter(c -> s.replaceAll("[^" + c + "]", "").length() % 2 < 0)
            .distinct()
            .sorted((c, d) -> s.lastIndexOf(c) - s.lastIndexOf(d))
            .toArray(String[]::new)
    )
Jakob
la source
0

R , 70 octets

function(s){for(i in utf8ToInt(s))F=c(F[F!=i],i*!i%in%F);intToUtf8(F)}

Essayez-le en ligne!

J'ai été encouragé par djhurio à publier cette solution; La réponse de djhurio peut être trouvée ici .

Cela utilise la même idée que la réponse de duckmayr , mais il exploite une approche numérique en convertissant la chaîne en ses points de code plutôt que de la diviser en caractères, et est une fonction plutôt qu'un programme complet afin qu'il puisse retourner la nouvelle chaîne plutôt que d'imprimer sur stdout .

function(s) {
 for(i in utf8ToInt(s))           # convert string to codepoints and iterate over it
  F=c(F[F!=i],                    # remove duplicates and append
      i*!i%in%F)                  # 0 if in F, i otherwise
 intToUtf8(F)                     # collapse from codepoints to string
}

Une observation importante est celle qui Fest initialisée à FALSEou 0et utf8ToInt(0)=="", donc cela réussira pour la chaîne vide ainsi que pour réduire correctement les points de code.

Giuseppe
la source
0

PHP, 71 + 1 octets

while(~$c=$argn[$i++])$s=strstr($s,$c)?strtr($s,[$c=>""]):$s.$c;echo$s;

Exécuter en tant que pipe avec -nRou l' essayer en ligne .

Titus
la source
0

Python 3.6 , 69 octets

lambda a:"".join({c:1 for c in a[::-1] if a.count(c)%2}.keys())[::-1]

Essayez-le en ligne!

L'ordre d'insertion des dictés est conservé dans Python 3.6.

user285259
la source
0

SNOBOL4 (CSNOBOL4) , 97 95 octets

	S =INPUT
N	S LEN(1) . C REM . S :F(O)
	O C :S(R)
	O =O C :(N)
R	O C =:S(R)F(N)
O	OUTPUT =O
END

Essayez-le en ligne!

	S =INPUT			;* read input
N	S LEN(1) . C REM . S :F(O)	;* take the first character of S and assign it to C,
					;* assign the remainder to S, and if S has no characters left, goto O
	O C :S(R)			;* if C matches anything in O, goto R, otherwise go to next line
	O =O C :(N)			;* append C to O and goto N
R	O C =:S(R)F(N)			;* as long as C matches O, replace it with ''
					;* (unassigned variables default to the null string)
					;* then goto N once it fails to match
O	OUTPUT =O			;* output the string
END					;* terminate the program
Giuseppe
la source