Digite uniqchars!


41

Dada uma sequência que consiste em caracteres ASCII imprimíveis , produza uma saída que consiste em seus caracteres exclusivos na ordem original . Em outras palavras, a saída é a mesma que a entrada, exceto que um caractere é removido se ele tiver aparecido anteriormente.

Nenhum componente interno para localizar elementos exclusivos em uma matriz pode ser usado (por exemplo, o MATLAB possui uma uniquefunção que faz isso). A ideia é fazê-lo manualmente.

Detalhes adicionais:

  • De qualquer funções ou programas são permitidos.
  • A entrada e a saída podem estar na forma de argumentos de função, stdin / stdout (mesmo para funções) ou uma mistura deles.
  • Se stdin ou stdout forem usados, uma string será entendida apenas como a sequência de caracteres . Se forem usados argumentos de função, a seqüência de caracteres podem precisar de ser fechado entre aspas ou símbolos equivalentes que a linguagem de programação de usos de escolha para definir strings.
  • A saída deve ser uma sequência contendo apenas os caracteres exclusivos da entrada. Portanto, não há quebras de linha extras, espaços etc. A única exceção é: se a saída for exibida no stdout, a maioria das funções de exibição adicionará um final \n(para separar a string do que virá a seguir). Portanto, um final \né aceitável no stdout .
  • Se possível, poste um link em um intérprete / compilador on - line para que outros possam experimentar seu código.

Este é o código golf , pelo que o código mais curto em bytes vence.

Alguns exemplos , assumindo stdin e stdout:

  1. String de entrada:

    Type unique chars!
    

    Cadeia de saída:

    Type uniqchars!
    
  2. String de entrada

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

    String de saída

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

    3.1415926535897932384626433832795
    

    String de saída

    3.14592687
    

5
Apenas para verificar: a regra no builtins significa que os objetos definidos não são permitidos?
Sp3000 4/15

@ Sp3000 Objetos definidos são permitidos. Apenas não use uma função ou método (se existir) que fornece seus elementos exclusivos. E de entrada / saída deve ser cordas, não definidos tobjects
Luis Mendo

@ Sp3000 Você acha que seria mais interessante reduzir a contagem de bytes pela metade se nenhuma função definida for usada? Ou melhor, não mudar as regras depois que o desafio for definido?
Luis Mendo

5
Acho que apenas minha resposta usa conjuntos atualmente e não me importaria se você a alterasse. No entanto, não tenho certeza se um bônus como esse mudaria muito, por exemplo, duvido que o CJam seja possível em <6 bytes sem conjuntos. Além disso, eu não tenho certeza de onde a linha entre um builtin que encontra elementos únicos, e construir um conjunto de um número de elementos ...
SP3000

11
@ Sp3000 Sim, é uma borda borrada. Eu não tinha previsto funções definidas. Acho que vou deixar o desafio como é agora
Luis Mendo

Respostas:


13

GolfScript, 2 bytes

.&

ou alternativamente:

.|

Eu publiquei isso há um tempo atrás no tópico Dicas para jogar golfe no GolfScript . Ele funciona duplicando a sequência de entrada (que é colocada na pilha automaticamente pelo intérprete GolfScript e que se comporta da maioria das maneiras como uma matriz de caracteres) e, em seguida, levando consigo a interseção ( &) ou união ( |) definida . A aplicação de um operador set a uma matriz (ou sequência) reduz as duplicatas, mas preserva a ordem dos elementos.


23

CJam, 3 bytes

qL|

Setwise ou da entrada com uma lista vazia. As operações de conjunto CJam preservam a ordem dos elementos.

Experimente online


Estou assumindo que isso é válido, pois os conjuntos são permitidos, mas não tenho certeza ...
Sp3000 4/15

Muito esperto! Eu sabia que o CJam seria um dos melhores, mas não esperava apenas 3 bytes!
Luis Mendo

19

C # 6, 18 + 67 = 85 bytes

Requer esta usingdeclaração:

using System.Linq;

O método real:

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

Esse método salva alguns caracteres definindo a função como um lambda , suportado no C # 6. É assim que ficaria no C # pré-6 (mas não destruído):

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

Como funciona: chamo o Wheremétodo na string com um lambda com dois argumentos: xrepresentando o elemento atual, irepresentando o índice desse elemento. IndexOfsempre retorna o primeiro índice do caractere passado para ele; portanto, se inão for igual ao primeiro x, é um caractere duplicado e não deve ser incluído.


3
Sinceramente, eu não esperava que o C # fosse tão curto. Excelente trabalho!
Alex A.

Uhm. Eu acho que você deve enviar um programa completo (com static void Mainetc.).
Timwi #

3
@ Timwi Este desafio declara "Funções ou programas são permitidos".
hvd 5/10

O C # permite uma abordagem mais curta, também usando o LINQ. Eu postei uma resposta concorrente. :)
hvd

@hvd Nice one! 1
ProgramFOX

14

Retina , 14 bytes

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

Cada linha deve ter seu próprio arquivo separado, ou você pode usar o -ssinalizador para ler um arquivo.

Para explicar, usaremos esta versão mais longa, porém mais simples:

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

A primeira linha é o regex com o qual corresponder ( +`é a cadeia de configuração que continua em execução até que todas as substituições tenham sido feitas). A regex procura um caractere (vamos chamá-lo de C), seguido por zero ou mais caracteres arbitrários, seguido por C. Os parênteses indicam grupos de captura, portanto substituímos a correspondência por C ( $1) e os caracteres entre ( $2), removendo a duplicata de C.

Por exemplo, se a sequência de entrada fosse unique, a primeira execução corresponderia uniqucom ue niqcomo $1e $2, respectivamente. Em seguida, substituiria a substring correspondente na entrada original por uniq, dando uniqe.


3
Eu estava procurando por um regex para fazer isso; Eu não sabia que era tão curto! +1
ETHproductions

13

Perl, 21 (20 bytes + -p)

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

Uso:

perl -pe 's/./!$h{$&}++&&$&/eg' <<< 'Type unique chars!'
Type uniqchars!

11
Você poderia economizar 1 byte negando $h{$&}e usando uma lógica E em vez de um operador ternário:s/./!$h{$&}++&&$&/eg
kos

@ kos se você tivesse me perguntado, eu teria dito que eu 100% tentei isso e acabei com 1s na saída, mas não! Obrigado, atualizando!
Dom Hastings

11
Voto a favor já :) Acho que você tentou s/./$h{$&}++||$&/eg(eu me apaixonei por isso também no começo). Vergonha, porque isso teria sido outro byte salvo.
kos

11

Macarrão 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
  • criar linguagem "anti-golfe": verifique
  • jogue de qualquer maneira: verifique

Este é um programa completo, que insere STDIN e sai em STDOUT.

Versão embrulhada, para 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

E uma versão fortemente "comentada" e não-golfada (não há comentários em Macarrão, então eu apenas uso literais de string nua):

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 é o primeiro programa de macarrão real (que realmente faz alguma coisa)! \ O /)


5
• dê ao idioma um nome engraçado e apropriado: check
Luis Mendo

11

JavaScript ES7, 37 33 25 bytes

Abordagem bastante simples usando o operador de espalhamento de compreensão ES6 Sete ES7 Array :

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

22 bytes a menos que a indexOfabordagem. Trabalhou em vários casos de teste.


Os espaços em torno forexpressão 's não são necessários e você pode torná-lo função anônima como algumas outras soluções fiz: s=>[for(c of Set(s))c].join``. (Pálido atualização: não 100% de certeza, mas a newpalavra-chave parece também desnecessário.)
manatwork

Não tinha certeza das regras com funções anon, e boa captura do espaço.
Zz5

Código transpilado sem newresultado Uncaught TypeError: Constructor Set requires 'new'no Google Chrome.
azz

Por favor, desculpe minha ignorância, mas em que momento isso filtra valores únicos? Parece que apenas converte uma string em um conjunto em uma matriz e junta os valores que resultam na string original novamente.
Patrick Roberts

@PatrickRoberts é a conversão para um conjunto. Um conjunto, por definição, não tem dupluicates
edc65

8

C # 6 - 18 + 46 = 64

using System.Linq;

e depois

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

O Enumerable.Unionmétodo de extensão especifica que os elementos são retornados na ordem original:

Quando o objeto retornado por esse método é enumerado, o Union enumera primeiro e segundo nessa ordem e gera cada elemento que ainda não foi produzido.

Operações definidas que não se destinam especificamente a encontrar valores únicos parecem ser permitidas a julgar pelas outras respostas.


Legal, eu estava pensando, string u(string s)=>String.Join("",s.Distinct());mas isso é um pouco mais.
Germi #

@germi Obrigado. Já houve uma resposta usando Distinct(), mas ela foi excluída porque Distinct()não é permitida neste desafio, pois é um método especificamente destinado a encontrar valores únicos.
hvd

Ah certo ... negligenciei esse bit;) #
315

É s => string.Concat(s.Union(s))válido? Esse seria o delegado passado para a Func<string, string>como argumento.
usar o seguinte código

@TylerStandishMan Se isso for válido, eu esperaria que mais pessoas fizessem uso dele, e eu nunca vi isso antes, então acho que não. Mas talvez deva ser válido - isso parece algo que vale a pena conferir no Meta, se você estiver interessado.
hvd 28/09

7

JavaScript ES6, 47 bytes

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

O teste abaixo funciona em todos os 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>


O que a <i?'':epeça faz?
DanTheMan

11
É um operador ternário. Se a primeira instância de um caractere eestiver antes do índice atual i, ele retornará uma string vazia, livrando-se assim do caractere. Se essa for a primeira instância, ela simplesmente retorna ee nenhuma alteração é feita.
NinjaBearMonkey

7

MATLAB, 23

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

Faz a "união de conjunto" da string de entrada consigo mesma, usando o método 'stable' que não classifica e depois imprime.

Isso funciona porque unionretorna apenas valores não duplicados após a mesclagem. Então, basicamente, se você unionusar a string em si mesma, ela produzirá uma string como Type unique chars!Type unique chars!e depois removerá todas as duplicatas sem classificação.

Não há necessidade de unique:)


uniquenão é permitido, desculpe! Está na definição de desafio
Luis Mendo

Perdeu isso, não importa.
Tom Carpenter

Seguindo a resposta do Sp3000, posso sugerir setdiffcom a 'stable'opção?
Luis Mendo

11
Agradável! E sim, você pode remover dispporque, em seguida, você tem uma função que retorna uma string, o que é permitido
Luis Mendo

11
Você também pode usar intersectcom 'stable'para obter o mesmo efeito. Eu ia escrever isso, mas, dada essa resposta, não é mais original, lol.
rayryeng - Restabelece Monica 4/15

7

> <> , 16 bytes

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

> <> não tem strings, então usamos o codebox. Devido à natureza toroidal de> <>, o seguinte é executado em um loop:

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

Observe que isso usa o fato de que a entrada contém apenas ASCII imprimível, pois isso não funcionaria se o ASCII 0 estivesse presente.


11
.......isto é brilhante. Eu gostaria de ter pensado nisso. Vou incluir uma versão Befunge disso na minha resposta, mas não como a principal. EDIT: Pensando bem, isso não funcionaria porque o Befunge não possui um espaço de código infinito. Dangit!
El'endia Starman

@ El'endiaStarman Eu acho que a resposta feixe também faz a mesma coisa, por isso, infelizmente, eu não posso dizer que foi o primeiro: P
SP3000

Ahh, sim, acho que você está certo. Sua explicação é mais clara.
El'endia Starman


5

Elemento , 22 19 18 bytes

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

Exemplo de entrada / saída: hello world->helo wrd

Isso funciona simplesmente processando a string, um caractere de cada vez, e acompanhando quais já foram vistas 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


4

Python 3, 44

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

Constrói a string de saída rcaractere por caractere, incluindo o caractere cda entrada apenas se ainda não o tivermos visto.

O Python 2 seria 47, perdendo 4 caracteres raw_inpute economizando 1 em não precisar de parers print.


O consenso agora parece ser o de que você pode usar inputno Python 2, para tornar o seu byte mais curto.
mbomb007

4

APL, 3

∊∪/

Isso aplica a união (∪) entre cada elemento do vetor, obtendo uma iteração que tem o efeito de remover duplicatas.

Teste em tryapl.org

Antigo:

~⍨\

Isso usa ~ (com argumentos invertidos, usando ⍨) aplicado entre cada elemento do argumento. O resultado é que, para cada elemento, se já estiver na lista, ele será apagado.


Nitpicking: "E entrada / saída devem ser strings", diz Luis. "Unione reduzir" retorna uma matriz aninhada, não uma string. O :-)
lstefano 28/06

Você está certo, adicionando um ∊ no começo para corrigir.
Moris Zucca

3

Perl, 54 27 bytes

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

Teste:

$ echo Type unique chars! | perl -e 'map{$h{$_}||=print}<>=~/./g'
Type uniqchars!
$

11
print exists($h{$_})?"":$_$h{$_}||print
manatwork

O SO inseriu um unicode → char lá, tornando-o quebrado?
Steve

11
o uso de um modificador de instrução pouparia alguns bytes, juntamente com a sugestão de @ manatwork, $h{$_}||=printe o uso <>=~/./gtambém ajudaria a economizar um pouco mais!
Dom Hastings

11
Não, eu o inseri, com o significado de "alterar para".
Manatwork

11
Mudar para maptambém melhoraria a economia: 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));

Usa os caracteres como chaves para uma matriz associativa e depois imprime as chaves. A ordem dos elementos da matriz é sempre a ordem de inserção.

Obrigado Ismael Miguel pela str_splitsugestão.


11
<?foreach(str_split($argv[1])as$c)$a[$c]=0;echo join('',array_keys($a));Mais curto e faz o mesmo.
Ismael Miguel

Encontrado um ciclo mais curto: while($c=$argv[1][$i++*1]). Isso substitui o todo foreach. Tudo o resto é igual
Ismael Miguel

Eu tentei algo semelhante primeiro, mas me abstive disso, porque ele iria parar em um personagem que obriga a "falso", ie "0". Tente "abc0def" como entrada.
Fabian Schmengler

Você está certo sobre isso. Surly, há uma solução alternativa para isso que não custa mais de 2 bytes.
Ismael Miguel

3

Pitão, 7 bytes

soxzN{z

Pseudo-código:

z = entrada

soma do índice de ordenação em z de N sobre o conjunto de z.


3

Julia, 45 42 bytes

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

Versão antiga:

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

O código constrói a nova sequência de caracteres, acrescentando novos caracteres a ela e, em seguida, joinos reúne em uma sequência adequada no final. A nova versão salva alguns caracteres iterando através da compreensão do array. Também salva um byte usando em ?:vez de ||(pois elimina a necessidade de colchetes em torno da atribuição).

Solução alternativa, 45 bytes, usando recursão e regex:

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

Julia, 17 bytes

(Versão alternativa)

s->join(union(s))

Isso usa unionbasicamente como um substituto para unique- eu não considero a resposta "real", pois interpreto "não use unique" para significar "não use uma única função interna que tenha o efeito de retornar o único elementos ".


Eu tive uma ideia semelhante, mas não foi tão concisa. Bom trabalho!
Alex A.

3

Java, 78 bytes

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

Um loop simples ao verificar a saída quanto a caracteres já presentes. Aceita entrada como a char[].


3

C, 96 bytes

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

Isso usa uma matriz de números inteiros, indexados pelo número de caracteres ASCII. Os caracteres são impressos apenas se esse local na matriz estiver definido como FALSE. Depois que cada novo caractere é encontrado, o local na matriz é definido como TRUE. Isso pega uma linha de texto da entrada padrão, terminada por uma nova linha. Ele ignora caracteres não ASCII.


Ungolfed:

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

3

C - 58

Agradecemos a @hvd e @AShelly por salvar um monte de personagens. Sugeriram várias maneiras de torná-lo muito mais curto que o 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 você pode ver, a modificação no local parece ser a mais curta (até agora!) O programa de teste é compilado sem avisos usando 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
}

Obrigado por toda a ajuda. Agradeço todos os conselhos dados para encurtar tanto!


Bem, desde que o seu código já não é válido C, apenas aceito por compiladores C branda: você pode declarar rcomo int(e omitir a int) para salvar alguns bytes: f(s,r)char*s;{...}. Mas limita seu código a plataformas onde char*é do mesmo tamanho inte, é claro, onde os compiladores são tão brandos quanto o seu e o meu.
hvd

@hvd Isso é mau! Eu estava disposto a usar como padrão o valor de retorno porque não o uso. Mas isso é um pouco mais desonesto do que eu gostaria de ser. Acho que prefiro torná-lo compatível, em vez de ir tão longe! Obrigado por trazer de volta ao lado da luz.
Jerry Jeremiah

Você pode salvar um caractere substituindo if(x)yporx?y:0
ugoren

Aqui está uma função de 60 de char que escreve na saída padrão em vez de um parâmetro de matriz: f(char*s){int a[128]={0};for(;*s;s++)a[*s]++?0:putchar(*s);}
AShelly

Você pode copiar incondicionalmente *qe incrementar apenas qse o personagem aparecer mais cedo, permitindo um pouco mais de compilação: void f(char*s,char*r){for(char*q=r;*q=*s;strchr(r,*s++)<q||q++);}(Observe que strchr(r,*s++)<qsempre está bem definido, não há UB lá, porque strchrnão pode retornar NULLnesta versão.) Exceto pelo tipo de retorno, é ainda mais curto que a versão do @ AShelly.
hvd

2

Ruby, 30 24 caracteres

(Código de 23 caracteres + opção de linha de comando de 1 caractere.)

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

Exemplo de execução:

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

2

CJam, 9

Lq{1$-+}/

Isso não converte uma string em um conjunto, mas executa um tipo de diferença de conjunto para determinar se um caractere é encontrado em uma string. Experimente online

Explicação:

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

Outra versão, 13 bytes:

Lq{_2$#)!*+}/

Isso não faz nada relacionado a conjuntos. Experimente online

Explicação:

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

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

As variáveis ​​da equação raramente são úteis, pois levam 5 bytes para armazenar, mas são Y₁úteis aqui como o Xcaractere da string, economizando 3 bytes. Como não podemos adicionar cadeias de caracteres vazias no TI-BASIC, iniciamos a cadeia com o primeiro caractere de Str1, depois percorremos o restante da cadeia, adicionando todos os caracteres que ainda não foram encontrados.

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

2

Matlab, 46 bytes

Ele usa uma função anônima, com argumentos de função como entrada e saída:

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

(Não consegui fazer isso funcionar em um intérprete on-line do Octave.)

Exemplo 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!

essa teria sido minha ideia também :) - você não precisa do ,1with any, btw.
Jonas

@Jonas Thanks! Alrhough é difícil ver através dessa confusão de parênteses, o 1é para triu (eu preciso remover a diagonal), não 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

Teste-o neste intérprete online .


Isso foi mais difícil do que eu esperava. Vou postar uma explicação mais completa amanhã, se alguém quiser, mas aqui está uma visão geral do que meu código faz.

  • Os caracteres únicos vistos até agora são armazenados na primeira linha, começando 2,0e se estendendo para a direita. Isso é verificado para ver se o caractere atual é uma duplicata.
  • O número de caracteres únicos vistos até agora é armazenado 0,0e o contador de loop de verificação de duplicação é armazenado 1,0.
  • Quando um caractere exclusivo é visto, ele é armazenado na primeira linha, impresso e o contador de entrada 0,0é incrementado.
  • Para evitar problemas com a leitura nos espaços presentes (ASCII 32), coloquei o caractere correspondente a -1 (realmente, 65536) no próximo slot para o próximo caractere exclusivo.

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]))));

Afastar a resposta do @ fschmengler usando a array_flipversão duas vezes segunda usa o método variável e depende da conversão da string para true, negando-a como false, e depois convertendo-a de volta para a string vazia no primeiro argumento para salvar alguns bytes no segundo. Barato!


2

Haskell , 29 bytes

Linha única aninhada e sem nome de variável:

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

Mesma contagem, salva em uma função nomeada fcomo uma declaração de nível superior:

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

Observe que há uma otimização pouco trapaceira que eu não fiz no espírito de gentileza: tecnicamente ainda é permitido pelas regras deste desafio usar uma codificação de entrada e saída diferente para uma string. Ao representar qualquer um stringpor sua codificação parcialmente aplicada da Igreja \f -> foldr f [] string :: (a -> [b] -> [b]) -> [b](com o outro lado da bijeção fornecida pela função ($ (:))), isso diminui para ($ \x->(x:).filter(x/=))apenas 24 caracteres.

Evitei postar a resposta de 24 caracteres como minha resposta oficial, porque a solução acima poderia ser tentada no intérprete acima como se foldr(\x->(x:).filter(x/=))[]"Type unique chars!"a solução golfed fosse escrita:

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

como uma abreviação para a declaração literal que seria a mais insana:

($ \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[]

Mas é uma versão perfeitamente válida da estrutura de dados representada como funções puras. (Claro, você também pode usar \f -> foldr f [] "Type unique chars!", mas isso é presumivelmente ilegítimo, pois usa listas para realmente armazenar os dados; portanto, sua parte foldr deve ser presumivelmente composta na função "resposta", com mais de 24 caracteres.)

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.