Escriba uniqchars!

41

Dada una cadena que consiste en caracteres ASCII imprimibles , produce una salida que consta de sus caracteres únicos en el orden original . En otras palabras, la salida es la misma que la entrada, excepto que un carácter se elimina si ha aparecido anteriormente.

No se pueden usar elementos integrados para encontrar elementos únicos en una matriz (por ejemplo, MATLAB tiene una uniquefunción que hace eso). La idea es hacerlo manualmente.

Más detalles:

  • Se permiten funciones o programas .
  • La entrada y la salida pueden estar en forma de argumentos de función, stdin / stdout (incluso para funciones) o una combinación de ellos.
  • Si se usan stdin o stdout, una cadena se entiende solo como la secuencia de caracteres . Si se utilizan los argumentos de funciones, puede ser necesario la secuencia de caracteres encerrada entre comillas o símbolos equivalentes que el lenguaje de programación de aplicaciones de elección para la definición de las cadenas.
  • La salida debe ser una cadena que contenga solo los caracteres únicos de la entrada. Por lo tanto, no hay saltos de línea adicionales, espacios, etc. La única excepción es: si la salida se muestra en stdout, la mayoría de las funciones de visualización agregan un final \n(para separar la cadena de lo que vendrá después). Entonces, un final \nes aceptable en stdout .
  • Si es posible, colocar un enlace a una línea intérprete / compilador para que otros puedan probar su código.

Este es el código de golf , por lo que gana el código más corto en bytes.

Algunos ejemplos , suponiendo stdin y stdout:

  1. Cadena de entrada:

    Type unique chars!
    

    Cadena de salida:

    Type uniqchars!
    
  2. Cadena de entrada

    "I think it's dark and it looks like rain", you said
    

    Cadena de salida

    "I think'sdarloe,yu
    
  3. Cadena de entrada

    3.1415926535897932384626433832795
    

    Cadena de salida

    3.14592687
    
Luis Mendo
fuente
55
Solo para verificar dos veces: ¿la regla de no construir significa que los objetos del conjunto no están permitidos?
Sp3000
@ Sp3000 Establecer objetos están permitidos. Simplemente no use una función o método (si existe) que le brinde sus elementos únicos. Y la entrada / salida debe ser cadenas, no establecer objetos
Luis Mendo
@ Sp3000 ¿Cree que sería más interesante reducir el recuento de bytes a la mitad si no se utilizan funciones establecidas? ¿O mejor no cambiar las reglas una vez que se ha establecido el desafío?
Luis Mendo
55
Creo que solo mi respuesta usa conjuntos actualmente, y no me importaría si lo cambiaras. Sin embargo, no estoy realmente seguro de que una bonificación como esa cambie mucho, por ejemplo, dudo que CJam sea factible en <6 bytes sin conjuntos. Además, no estoy seguro de dónde está la línea entre una construcción que encuentra elementos únicos y la construcción de un conjunto a partir de una serie de elementos ...
Sp3000
1
@ Sp3000 Sí, es un borde borroso. No había previsto establecer funciones. Creo que dejaré el desafío como está ahora
Luis Mendo

Respuestas:

13

GolfScript, 2 bytes

.&

o alternativamente:

.|

Publiqué esto hace un tiempo en los Consejos para jugar al golf en el hilo de GolfScript . Funciona duplicando la cadena de entrada (que el intérprete de GolfScript coloca automáticamente en la pila y que se comporta en la mayoría de los casos como una matriz de caracteres) y luego toma la intersección ( &) o unión ( |) establecida de sí misma. La aplicación de un operador de conjunto a una matriz (o cadena) contrae cualquier duplicado, pero conserva el orden de los elementos.

Ilmari Karonen
fuente
23

CJam, 3 bytes

qL|

Setwise o de la entrada con una lista vacía. Las operaciones de configuración de CJam preservan el orden de los elementos.

Pruébalo en línea

Sp3000
fuente
Supongo que esto es válido ya que los conjuntos están permitidos, pero no estoy seguro ...
Sp3000
¡Muy inteligente! Sabía que CJam sería uno de los mejores, ¡pero no esperaba solo 3 bytes!
Luis Mendo
19

C # 6, 18 + 67 = 85 bytes

Requiere esta usingdeclaración:

using System.Linq;

El método actual:

string U(string s)=>string.Concat(s.Where((x,i)=>s.IndexOf(x)==i));

Este método ahorra algunos caracteres al definir la función como lambda , que se admite en C # 6. Así es como se vería en C # pre-6 (pero sin protección):

string Unique(string input)
{
    return string.Concat(input.Where((x, i) => input.IndexOf(x) == i));
}

Cómo funciona: llamo al Wheremétodo en la cadena con una lambda con dos argumentos: que xrepresenta el elemento actual, que irepresenta el índice de ese elemento. IndexOfsiempre devuelve el primer índice del carácter pasado, por lo que si ino es igual al primer índice de x, es un carácter duplicado y no debe incluirse.

ProgramFOX
fuente
3
Sinceramente, no hubiera esperado que C # fuera tan corto. ¡Excelente trabajo!
Alex A.
Uhm Creo que debe enviar un programa completo (con static void Mainetc.).
Timwi
3
@Timwi Este desafío establece "Se permiten funciones o programas".
hvd
C # permite un enfoque más corto, también usando LINQ. He publicado una respuesta competitiva. :)
hvd
@hvd ¡Buena! +1
ProgramFOX
14

Retina , 14 bytes

+`((.).*)\2
$1

Cada línea debe ir en su propio archivo separado, o puede usar la -sbandera para leer desde un archivo.

Para explicarlo, usaremos esta versión más larga pero más simple:

+`(.)(.*)\1
$1$2

La primera línea es la expresión regular con la que coincide ( +`es la cadena de configuración que sigue ejecutándose hasta que se hayan realizado todos los reemplazos). La expresión regular busca un carácter (lo llamaremos C), seguido de cero o más caracteres arbitrarios, seguido de C. Los paréntesis indican grupos de captura, por lo que reemplazamos la coincidencia con C ( $1) y los caracteres entre ( $2), eliminando el duplicado de C.

Por ejemplo, si la cadena de entrada era unique, la primera ejecución coincidiría uniqu, con uy niqcomo $1y $2, respectivamente. Luego reemplazaría la subcadena coincidente en la entrada original con uniq, dando uniqe.

NinjaOsoMono
fuente
3
Estaba buscando una expresión regular para hacer esto; ¡No me di cuenta de que era tan corto! +1
ETHproductions
13

Perl, 21 (20 bytes + -p)

s/./!$h{$&}++&&$&/eg

Uso:

perl -pe 's/./!$h{$&}++&&$&/eg' <<< 'Type unique chars!'
Type uniqchars!
Dom Hastings
fuente
1
Podría ahorrar 1 byte negando $h{$&}y usando una lógica Y en lugar de un operador ternario:s/./!$h{$&}++&&$&/eg
kos
@kos si me hubieras preguntado, te habría dicho que lo intenté al 100% y terminé con 1s en la salida, ¡pero no es así! Gracias, actualizando!
Dom Hastings
1
Ya voté :) Creo que lo intentaste s/./$h{$&}++||$&/eg(me enamoré de eso también al principio). Es una pena porque habría sido otro byte guardado.
kos
11

Macarrones 0.0.2 , 233 bytes

set i read set f "" print map index i k v return label k set x _ set _ slice " " length index f e 1 1 set f concat f wrap x return label e set _ slice " " add _ multiply -1 x 1 1 return label v set _ unwrap slice i _ add 1 _ 1 return
  • crear lenguaje "anti-golf": verificar
  • golf de todos modos: comprobar

Este es un programa completo, que entra desde STDIN y sale en STDOUT.

Versión envuelta, por valor estético:

set i read set f "" print map index i k v return label k set x _ set _ slice "
" length index f e 1 1 set f concat f wrap x return label e set _ slice " " add
_ multiply -1 x 1 1 return label v set _ unwrap slice i _ add 1 _ 1 return

Y una versión muy "comentada" y sin golf (no hay comentarios en Macaroni, así que solo uso literales de cadena desnuda):

set input read                  "read line from STDIN, store in 'input' var"
set found ""                    "we need this for 'keep' below"
print map index input keep val  "find indeces to 'keep', map to values, print"
return

label keep
    "we're trying to determine which indeces in the string to keep. the special
     '_' variable is the current element in question, and it's also the value
     to be 'returned' (if the '_' variable is '0' or empty array after this
     label returns, the index of the element is *not* included in the output
     array; otherwise, it is"
    set x _ set _ slice
        " "
        length index found exists
        1
        1
    "now we're using 'index' again to determine whether our '_' value exists in
     the 'found' array, which is the list of letters already found. then we
     have to apply a boolean NOT, because we only want to keep values that do
     NOT exist in the 'found' array. we can 'invert' a boolean stored as an
     integer number 'b' (hence, 'length') with 'slice(' ', b, 1, 1)'--this is
     equivalent to ' '[0:1], i.e. a single-character string which is truthy, if
     'b' was falsy; otherwise, it results in an empty string if 'b' was truthy,
     which is falsy"
    set found concat found wrap x  "add the letter to the 'found' array"
return

label exists
    set _ slice
        " "
        add _ multiply -1 x
        1
        1
    "commentary on how this works: since 0 is falsy and every other number is
     truthy, we can simply subtract two values to determine whether they are
     *un*equal. then we apply a boolean NOT with the method described above"
return

label val
    set _ unwrap slice input _ add 1 _ 1  "basically 'input[_]'"
return

(¡Este es el primer programa real de macarrones (que realmente hace algo)! \ O /)

Pomo de la puerta
fuente
55
• dale al idioma un nombre divertido y apropiado: marca
Luis Mendo el
11

JavaScript ES7, 37 33 25 bytes

Enfoque bastante simple usando el operador de propagación de comprensiones de matriz ES6 Sety ES7 :

s=>[...new Set(s)].join``

22 bytes menos que el indexOfenfoque. Trabajó en un puñado de casos de prueba.

azz
fuente
Los espacios alrededor de forla expresión 's no son necesarios y que podrían hacer que sea función anónima al igual que algunas otras soluciones: s=>[for(c of Set(s))c].join``. (Pálido actualización no es 100% seguro, pero la newpalabra clave también parece innecesario.)
manatwork
No estaba seguro de las reglas con funciones anon y buena captura en el espacio.
azz
El código transpilado sin newresultado Uncaught TypeError: Constructor Set requires 'new'en Google Chrome.
azz
Disculpe mi ignorancia, pero ¿en qué punto filtra estos valores únicos? Parece que solo convierte una cadena en un conjunto en una matriz y luego une los valores que resultan en la cadena original nuevamente.
Patrick Roberts
@PatrickRoberts es la conversión a un conjunto. Un conjunto por definición no tiene duplicados
edc65
8

C # 6 - 18 + 46 = 64

using System.Linq;

y entonces

string f(string s)=>string.Concat(s.Union(s));

El Enumerable.Unionmétodo de extensión especifica que los elementos se devuelven en el orden original:

Cuando se enumera el objeto devuelto por este método, Union enumera primero y segundo en ese orden y produce cada elemento que aún no se ha entregado.

Las operaciones de configuración que no están destinadas específicamente a encontrar valores únicos parecen estar permitidas a juzgar por las otras respuestas.

hvd
fuente
Bueno, estaba pensando, string u(string s)=>String.Join("",s.Distinct());pero eso es un poco más largo.
germi
@germi Gracias. Distinct()Ya se ha utilizado una respuesta , pero se elimina porque Distinct()no está permitida en este desafío, ya que es un método diseñado específicamente para encontrar valores únicos.
hvd
Ah cierto ...
pasé por
Es s => string.Concat(s.Union(s))valido? Ese sería el delegado pasado a a Func<string, string>como argumento.
Tyler StandishMan
@TylerStandishMan Si eso es válido, esperaría que más personas lo usen, y no lo he visto antes, así que no creo que lo sea. Pero tal vez debería ser válido: esto parece algo que vale la pena revisar en Meta si está interesado.
hvd
7

JavaScript ES6, 47 bytes

f=s=>s.replace(/./g,(e,i)=>s.indexOf(e)<i?'':e)

La siguiente prueba funciona en todos los navegadores.

f=function(s){
  return s.replace(/./g,function(e,i){
    return s.indexOf(e)<i?'':e
  })
}

run=function(){document.getElementById('output').innerHTML=f(document.getElementById('input').value)};document.getElementById('run').onclick=run;run()
<input type="text" id="input" value="Type unique chars!" /><button id="run">Run</button><br />
<pre id="output"></pre>

NinjaOsoMono
fuente
¿Qué hace la <i?'':eparte?
DanTheMan
1
Es un operador ternario. Si la primera instancia de un carácter ees anterior al índice actual i, devuelve una cadena vacía, eliminando así el carácter. Si esa es la primera instancia, simplemente regresa ey no se realizan cambios.
NinjaBearMonkey
7

MATLAB, 23

 @(n)union(n,n,'stable')

Hace la "unión de conjunto" de la cadena de entrada consigo misma, usando el método 'estable' que no ordena, y luego imprime.

Esto funciona porque unionsolo devuelve valores no duplicados después de la fusión. Entonces, esencialmente, si usa unionla cadena consigo misma, primero produce una cadena como Type unique chars!Type unique chars!, y luego elimina todos los duplicados sin ordenar.

No hay necesidad de unique :)

Tom Carpenter
fuente
uniqueno permitido, lo siento! Está en la definición del desafío
Luis Mendo
Me perdí eso, no importa.
Tom Carpenter
Siguiendo la respuesta de Sp3000, ¿puedo sugerir setdiffcon la 'stable'opción?
Luis Mendo
1
¡Agradable! Y sí, puede eliminar dispporque entonces tiene una función que devuelve una cadena, que está permitida
Luis Mendo
1
También puede usar intersectcon 'stable'para lograr el mismo efecto también. Iba a escribir eso, pero dada esta respuesta, ya no es original jajaja.
rayryeng - Restablecer Monica
7

> <> , 16 bytes

i:0(?;:::1g?!o1p

> <> no tiene cadenas, por lo que utilizamos el cuadro de código. Debido a la naturaleza toroidal de> <>, lo siguiente se ejecuta en un bucle:

i         Read a char
:0(?;     Halt if EOF
:::       Push three copies of the char
1g        Get the value at (char, 1), which is 0 by default
?!o       Print the char if the value was nonzero
1p        Set the value at (char, 1) to char

Tenga en cuenta que esto utiliza el hecho de que la entrada solo contiene ASCII imprimible, ya que esto no funcionaría si ASCII 0 estuviera presente.

Sp3000
fuente
1
.......esto es brillante. Ojalá hubiera pensado en esto. Incluiré una versión Befunge de esto en mi respuesta, pero no como la principal. EDITAR: Pensándolo bien, esto no funcionaría porque Befunge no tiene un espacio de código infinito. Dangit!
El'endia Starman el
@ El'endiaStarman Creo que la respuesta de Beam también hace lo mismo, así que desafortunadamente no puedo decir que fui el primero: P
Sp3000
Ahh, sí, creo que tienes razón. Sin embargo, tu explicación es más clara.
El'endia Starman
5

Elemento , 22 19 18 bytes

_'{"(3:~'![2:`];'}

Ejemplo de entrada / salida: hello world->helo wrd

Esto funciona simplemente procesando la cadena un carácter a la vez y haciendo un seguimiento de los que ha visto antes.

_'{"(3:~'![2:`];'}
_                        input line
 '                       use as conditional
  {              }       WHILE loop
   "                     retrieve string back from control (c-) stack
    (                    split to get the first character of (remaining) string
     3:                  a total of three copies of that character
       ~                 retrieve character's hash value
        '                put on c-stack
         !               negate, gives true if undef/empty string
          [   ]          FOR loop
           2:`           duplicate and output
               ;         store character into itself
                '        put remaining string on c-stack as looping condition
PhiNotPi
fuente
4

Pitón 3, 44

r=''
for c in input():r+=c[c in r:]
print(r)

Crea la cadena de salida rcarácter por carácter, incluido el carácter cde la entrada solo si aún no lo hemos visto.

Python 2 sería 47, perdiendo 4 caracteres raw_inputy ahorrando 1 al no necesitar padres print.

xnor
fuente
El consenso ahora parece ser que puede usar inputen Python 2, por lo que puede hacer que el suyo sea un byte más corto.
mbomb007
4

APL, 3

∊∪/

Esto aplica la unión (∪) entre cada elemento del vector, obteniendo una iteración que tiene el efecto de eliminar duplicados.

Pruébelo en tryapl.org

El viejo:

~⍨\

Esto usa ~ (con argumentos invertidos, usando ⍨) aplicado entre cada elemento del argumento. El resultado es que para cada elemento, si ya está en la lista, se borra.

Moris Zucca
fuente
Nitpicking: "Y la entrada / salida deben ser cadenas", dice Luis. "Unione reduce" devuelve una matriz anidada, no una cadena. O :-)
lstefano
Tienes razón, agregando un ∊ al principio para corregir.
Moris Zucca
3

Perl, 54 27 bytes

map{$h{$_}||=print}<>=~/./g
123456789012345678901234567

Prueba:

$ echo Type unique chars! | perl -e 'map{$h{$_}||=print}<>=~/./g'
Type uniqchars!
$
Steve
fuente
1
print exists($h{$_})?"":$_$h{$_}||print
manatwork
¿SO ha insertado un unicode → char allí dejándolo roto?
Steve
1
¡usar un modificador de declaración le ahorraría algunos bytes, junto con la sugerencia de @ manatwork $h{$_}||=printy usarlo también <>=~/./gdebería ayudar a ahorrar algunos más!
Dom Hastings
1
No, lo inserté, con el significado de "cambiar a".
Manatwork
1
Cambiar a maptambién mejoraría el ahorro: map{$h{$_}||=print}<>=~/./g
manatwork
3

PHP, 72 bytes 84 bytes

<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));

Utiliza los caracteres como claves para una matriz asociativa, luego imprime las claves. El orden de los elementos de la matriz es siempre el orden de inserción.

Gracias Ismael Miguel por la str_splitsugerencia.

Fabian Schmengler
fuente
1
<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));Más corto y hace lo mismo.
Ismael Miguel
Encontrado un bucle más corto: while($c=$argv[1][$i++*1]). Esto reemplaza el todo foreach. Todo lo demás es igual
Ismael Miguel
Intenté algo similar primero pero me abstuve porque detendría a un personaje que coacciona a "falso", es decir "0". Intente "abc0def" como entrada.
Fabian Schmengler
Tienes razón al respecto. Seguramente hay una solución alternativa que no cuesta más de 2 bytes.
Ismael Miguel
3

Pyth, 7 bytes

soxzN{z

Pseudocódigo:

z = entrada

suma del índice ordenado por z en N sobre el conjunto de z.

isaacg
fuente
3

Julia, 45 42 bytes

s->(N="";[i∈N?N:N=join([N,i])for i=s];N)

Versión antigua:

s->(N={};for i=s i∈N||(N=[N,i])end;join(N))

El código construye la nueva cadena agregando nuevos caracteres en ella, luego joinlos une en una cadena adecuada al final. La nueva versión guarda algunos caracteres al iterar a través de la comprensión de la matriz. También guarda un byte usando en ?:lugar de ||(ya que elimina la necesidad de corchetes alrededor de la asignación).

Solución alternativa, 45 bytes, usando recursividad y expresiones regulares:

f=s->s!=(s=replace(s,r"(.).*\K\1",""))?f(s):s

Julia, 17 bytes

(Versión alternativa)

s->join(union(s))

Esto se usa unionbásicamente como un sustituto de unique: no considero que esta sea la respuesta "real", ya que interpreto "no usar unique" para significar "no use una sola función incorporada que tenga el efecto de devolver la única elementos".

Glen O
fuente
Tuve una idea similar pero no fue tan concisa. ¡Buen trabajo!
Alex A.
3

Java, 78 bytes

String f(char[]s){String t="";for(char c:s)t+=t.contains(c+"")?"":c;return t;}

Un bucle simple mientras se verifica la salida de caracteres ya presentes. Acepta entradas como a char[].

Geobits
fuente
3

C, 96 bytes

#include<stdio.h> 
int c,a[128];main(){while((c=getchar())-'\n')if(!a[c])a[c]=1,putchar(c);}

Esto utiliza una matriz de enteros, indexados por número de caracteres ASCII. Los caracteres solo se imprimen si ese lugar en la matriz está configurado en FALSO. Después de encontrar cada nuevo personaje, ese lugar en la matriz se establece en VERDADERO. Esto toma una línea de texto desde la entrada estándar, terminada por una nueva línea. Ignora los caracteres no ASCII.


Sin golf:

#include<stdio.h>
#include<stdbool.h>

int main(void)
{
  int i, c;
  int ascii[128];
  for (i = 0; i < 128; ++i) {
    ascii[i] = false;
  }
  while ((c = getchar()) != '\n') {
    if (ascii[c] == false) {
      ascii[c] = true;
      putchar(c);
    }
  }
  puts("\n");
  return(0);
}
musaritmia
fuente
3

C - 58

Gracias a @hvd y @AShelly por salvar un montón de personajes. Se sugirieron varias formas de hacerlo mucho más corto que el original:

// @hvd     - always copy to q but only increment q if not found
g(char*s,char*r){char*q=r;for(;*q=*s;q+=q==strchr(r,*s++));}

// @AShelly - keep a histogram of the usage of each character
h(char*s){int a[128]={0};for(;*s;s++)a[*s]++||putchar(*s);}

// @hvd     - modify in place
i(char*s){char*q=s,*p=s;for(;*q=*p;q+=q==strchr(s,*p++));}

// original version - requires -std=c99
void f(char*s,char*r){for(char*q=r;*s;s++)if(!strchr(r,*s))*q++=*s;}

Como puede ver, la modificación en el lugar parece ser la más corta (¡hasta ahora!) El programa de prueba se compila sin advertencias utilizando gcc test.c

#include <stdlib.h> // calloc
#include <string.h> // strchr
#include <stdio.h>  // puts, putchar

// 000000111111111122222222223333333333444444444455555555556666666666
// 456789012345678901234567890123456789012345678901234567890123456789

// @hvd     - always copy to q but only increment q if not found
g(char*s,char*r){char*q=r;for(;*q=*s;q+=q==strchr(r,*s++));}

// @AShelly - keep a histogram of the usage of each character
h(char*s){int a[128]={0};for(;*s;s++)a[*s]++||putchar(*s);}

// @hvd     - modify in place
i(char*s){char*q=s,*p=s;for(;*q=*p;q+=q==strchr(s,*p++));}

/* original version - commented out because it requires -std=c99
void f(char*s,char*r){for(char*q=r;*s;s++)if(!strchr(r,*s))*q++=*s;}
*/

// The test program:
int main(int argc,char*argv[]){
  char *r=calloc(strlen(argv[1]),1); // make a variable to store the result
  g(argv[1],r);                      // call the function
  puts(r);                           // print the result

  h(argv[1]);                        // call the function which prints result
  puts("");                          // print a newline

  i(argv[1]);                        // call the function (modifies in place)
  puts(argv[1]);                     // print the result
}

Gracias por toda la ayuda. Agradezco todos los consejos dados para acortar tanto!

Jerry Jeremiah
fuente
Bueno, ya que el código ya no es válida C, simplemente aceptado por los compiladores de C indulgentes: puede declarar rcomo int(y omite el int) para guardar algunos bytes: f(s,r)char*s;{...}. Pero limita su código a plataformas donde char*tiene el mismo tamaño y int, por supuesto, donde los compiladores son tan indulgentes como el suyo y el mío.
hvd
@hvd ¡Eso es malo! Estaba dispuesto a predeterminar el valor de retorno porque no lo uso. Pero eso es un poco más dudoso de lo que me gustaría ser. ¡Creo que preferiría que fuera más compatible que ir tan lejos! Gracias por traer de vuelta al lado de la luz.
Jerry Jeremiah
Puede guardar un if(x)yx?y:0
personaje
Aquí hay una función de 60 caracteres que escribe en stdout en lugar de un parámetro de matriz: f(char*s){int a[128]={0};for(;*s;s++)a[*s]++?0:putchar(*s);}
AShelly
Puede copiar incondicionalmente *q, y solo aumentar qsi el carácter apareció antes, lo que permite un poco más de relleno: void f(char*s,char*r){for(char*q=r;*q=*s;strchr(r,*s++)<q||q++);}(Tenga en cuenta que strchr(r,*s++)<qsiempre está bien definido, no hay UB allí, porque strchrno puede regresar NULLen esta versión). Excepto por el tipo de retorno, es incluso más corto que la versión de @ AShelly.
hvd
2

Ruby, 30 24 caracteres

(Código de 23 caracteres + opción de línea de comando de 1 carácter).

gsub(/./){$`[$&]?"":$&}

Ejecución de muestra:

bash-4.3$ ruby -pe 'gsub(/./){$`[$&]?"":$&}' <<< 'hello world'
helo wrd
hombre trabajando
fuente
2

CJam, 9

Lq{1$-+}/

Esto no convierte una cadena en un conjunto, pero realiza una especie de diferencia de conjunto para determinar si un carácter se encuentra en una cadena. Pruébalo en línea

Explicación:

L       push an empty array/string
q       read the input
{…}/    for each character in the input
  1$    copy the previous string
  -     subtract from the character (set difference),
         resulting in the character or empty string
  +     append the result to the string

Otra versión, 13 bytes:

Lq{_2$#)!*+}/

Esto no hace nada relacionado con los conjuntos. Pruébalo en línea

Explicación:

L       push an empty array/string
q       read the input
{…}/    for each character in the input
  _     duplicate the character
  2$    copy the previous string
  #)    find the index of the character in the string and increment it
  !     negate, resulting in 0 if the character was in the string and 1 if not
  *     repeat the character that many times
  +     append the result to the string
aditsu
fuente
2

TI-BASIC, 49 bytes

Input Str1
"sub(Str1,X,1→Y₁
Y₁(1
For(X,2,length(Str1
If not(inString(Ans,Y₁
Ans+Y₁
End
Ans

Las variables de ecuación rara vez son útiles, ya que tardan 5 bytes en almacenarse, pero Y₁son útiles aquí como el Xcarácter th de la cadena, ahorrando 3 bytes. Como no podemos agregar cadenas vacías en TI-BASIC, comenzamos la cadena con el primer carácter de Str1, luego recorremos el resto de la cadena y agregamos todos los caracteres que aún no se han encontrado.

prgmQ
?Why no empty st
rings? Because T
I...
Why noemptysrig?Bcau.
lirtosiast
fuente
2

Matlab, 46 bytes

Utiliza una función anónima, con argumentos de función como entrada y salida:

@(s)eval('s(~any(triu(bsxfun(@eq,s,s''),1)))')

(No pude hacer que esto funcione en un intérprete en línea de Octave).

Ejemplo de uso:

>> @(s)eval('s(~any(triu(bsxfun(@eq,s,s''),1)))')
ans = 
    @(s)eval('s(~any(triu(bsxfun(@eq,s,s''),1)))')

>> ans('Type unique chars!')
ans =
Type uniqchars!
Luis Mendo
fuente
esa habría sido mi idea también :) - no necesitas el ,1con any, por cierto.
Jonas
@Jonas Gracias! Aunque es difícil ver a través de ese paréntesis de paréntesis, 1es para triu (necesito eliminar la diagonal), no paraany
Luis Mendo
2

Befunge -93, 124 bytes

v
<v1p02-1
0_v#`g00: <0_@#+1::~p
 1>:1+10p2+0g-!#v_v
g `#v_10g0^       >:10g00
 ^0g 00$        <
 ^  >:,00g1+:00p1+:1+01-\0p

Pruébelo en este intérprete en línea .


Esto fue más difícil de lo que esperaba. Publicaré una explicación más completa mañana si alguien quiere que lo haga, pero aquí hay una descripción general de lo que hace mi código.

  • Los caracteres únicos vistos hasta ahora se almacenan en la primera fila, comenzando desde 2,0 y extendiéndose hacia la derecha. Esto se verifica para ver si el carácter actual es un duplicado.
  • El número de caracteres únicos vistos hasta ahora se almacena 0,0y el contador de bucle de verificación de duplicados se almacena en1,0 .
  • Cuando se ve un carácter único, se almacena en la primera fila, se imprime y el contador en 0,0 se incrementa.
  • Para evitar problemas con la lectura en los espacios presentes (ASCII 32), coloco el carácter correspondiente a -1 (realmente, 65536) en el siguiente espacio para el siguiente carácter único.
El'endia Starman
fuente
2

PHP 56 54

// 56 bytes
<?=join('',array_flip(array_flip(str_split($argv[1]))));

// 54 bytes
<?=join(!$a='array_flip',$a($a(str_split($argv[1]))));

Eliminar la respuesta de @ fschmengler usando una array_flipversión de dos segundos usa un método variable y se basa en convertir la cadena en verdadera, negarla en falso y luego volverla a la cadena vacía en el primer argumento para guardar un par de bytes en el segundo. ¡Barato!

Niet the Dark Absol
fuente
2

Haskell , 29 bytes

Una línea, anidable, sin nombre variable:

foldr(\x->(x:).filter(x/=))[]

El mismo recuento, guardado en una función denominada fcomo declaración de nivel superior:

f(x:t)=x:f[y|y<-t,x/=y];f_=[]

Tenga en cuenta que hay una optimización ligeramente engañosa que no he hecho con el espíritu de amabilidad: técnicamente todavía está permitido por las reglas de este desafío usar una codificación de entrada y salida diferente para una cadena. Al representar a cualquiera stringmediante su codificación de Church parcialmente aplicada \f -> foldr f [] string :: (a -> [b] -> [b]) -> [b](con el otro lado de la biyección proporcionada por la función ($ (:))), esto se reduce a ($ \x->(x:).filter(x/=))solo 24 caracteres.

Evité publicar la respuesta de 24 caracteres como mi respuesta oficial porque la solución anterior podría probarse en el intérprete anterior, foldr(\x->(x:).filter(x/=))[]"Type unique chars!"mientras que la solución de golf se escribiría en su lugar:

($ \x->(x:).filter(x/=))$ foldr (\x fn f->f x (fn f)) (const []) "Type unique chars!"

como una forma abreviada de la declaración literal que sería lo más loco:

($ \x->(x:).filter(x/=))$ \f->f 'T'.($f)$ \f->f 'y'.($f)$ \f->f 'p'.($f)$ \f->f 'e'.($f)$ \f->f ' '.($f)$ \f->f 'u'.($f)$ \f->f 'n'.($f)$ \f->f 'i'.($f)$ \f->f 'q'.($f)$ \f->f 'u'.($f)$ \f->f 'e'.($f)$ \f->f ' '.($f)$ \f->f 'c'.($f)$ \f->f 'h'.($f)$ \f->f 'a'.($f)$ \f->f 'r'.($f)$ \f->f 's'.($f)$ \f->f '!'.($f)$ const[]

Pero es una versión perfectamente válida de la estructura de datos representada como funciones puras. (Por supuesto, también puede usarlo \f -> foldr f [] "Type unique chars!", pero eso es presumiblemente ilegítimo ya que usa listas para almacenar realmente los datos, por lo que presumiblemente su parte plegable debe componerse en la función "respuesta", lo que lleva a más de 24 caracteres)

CR Drost
fuente