Qual é o segundo personagem que não se repete?

18

Com base nesta pergunta da Code Review

Dada uma sequência não vazia de caracteres ASCII imprimíveis, imprima o segundo caractere não repetitivo. Por exemplo, para entrada DEFD, saída F.

Entrada

Resultado

  • O segundo caractere que não se repete, ao ler da esquerda para a direita, novamente em um formato adequado.
  • O caractere de saída não diferencia maiúsculas de minúsculas.
  • Se esse caractere não existir (por exemplo, todos os caracteres se repetem), produza uma string vazia.

Regras

  • O algoritmo deve ignorar maiúsculas e minúsculas. Ou seja, De dconte como o mesmo personagem.
  • Um programa completo ou uma função são aceitáveis.
  • A sequência de entrada será garantida como não vazia (ou seja, pelo menos um caractere de comprimento).
  • A sequência de entrada é ASCII. Qualquer caractere válido pode se repetir, não apenas alfanumérico (isso inclui espaços).
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.

Exemplos

A entrada está na primeira linha, a saída está na segunda linha.

DEFD
F

FEED
D

This is an example input sentence.
x

...,,,..,,!@
@

ABCDefgHijklMNOPqrsTuVWxyz
B

AAAAAABBBBB


Thisxthis


This this.
.
AdmBorkBork
fonte
8
Se não fizesse distinção entre maiúsculas e minúsculas, consideraria fazê-lo em Forth. As operações de string são péssimas nesse idioma.
Mbomb007
E se meu idioma não suportar letras minúsculas?
Adám 03/07/19
@ Adám Utiliza uma página de código diferente? Como normalmente seria inserida uma string ASCII se não suporta letras minúsculas?
AdmBorkBork 4/16
1
O sistema que eu tinha em mente tinha uma página de código de 7 bits; uma página de código padrão modificada onde letras maiúsculas ocupam as posições em minúsculas e as posições em maiúsculas foram usadas para glifos. Isso foi feito em sistemas antigos de APL para que se pudesse usar o Shift para acessar os glifos de APL, enquanto as letras não deslocadas eram maiúsculas clássicas no estilo de codificação.
Adám 04/07/19

Respostas:

10

MATL , 11 bytes

tk&=s1=)FT)

Isso sai com um erro (permitido por padrão) se não houver um segundo caractere não repetido.

Experimente online!

Explicação

t      % Implicitly take input string. Duplicate
k      % Convert to lowercase
&=     % 2D array of equality comparisons
s      % Sum of each column
1=     % True for entries that equal 1
)      % Apply logical index to the input string to keep non-repeated characters
TF)    % Apply logical index to take 2nd element if it exists. Implicitly display 
Luis Mendo
fonte
A edição ninja ataca novamente. : P
Dennis
@Dennis Hahaha. Bem, eu acho que você vai remover um par de bytes em breve
Luis Mendo
10

Retina , 25 bytes

i!2=`(.)(?<!\1.+)(?!.*\1)

Experimente online! (A primeira linha permite executar o código em um conjunto de testes de várias entradas.)

Explicação

Esta é apenas uma única correspondência de regex, sendo a regex:

(.)(?<!\1.+)(?!.*\1)

Ou seja, combine um caractere e verifique se ele não aparece em nenhum outro lugar da entrada. O resto é configuração:

  • i ativa a distinção entre maiúsculas e minúsculas.
  • ! diz à Retina para imprimir as correspondências, em vez de contá-las.
  • 2= diz à Retina para imprimir apenas a segunda correspondência, em oposição a todas elas.
Martin Ender
fonte
1
Ah, obrigado por me ensinar sobre o 2=.
Leaky Nun
6

05AB1E, 15 12 bytes

l©v®y¢iy}}1@

Explicado

l©            # store lower case string in register
  v     }     # for each char in lower case string
   ®y¢iy      # if it occurs once in string, push it to stack
         }    # end if
          1@  # push the 2nd element from stack and implicitly display

Experimente online

Guardado 3 bytes graças a @Adnan

Emigna
fonte
Ou para 12 bytes l©v®y¢iy}}1@:).
Adnan
@Adnan: Legal! Não pensou em usar @.
Emigna
5

Python 2, 59 58 bytes

Retorna uma lista de um único caractere ou uma lista vazia, se não houver saída. (Insensibilidade estúpida a maiúsculas ...)

s=input().lower();print[c for c in s if s.count(c)<2][1:2]

Experimente online

mbomb007
fonte
Não é uma entrada válida. O usuário nunca deve ter que escapar de suas entradas.
Mbomb007
4
Claro que é. Nós fornecemos listas sobre STDIN no formato de lista do idioma. Por que as strings seriam diferentes?
Dennis
5

Gelatina , 11 bytes

Œlµḟœ-Q$Ḋḣ1

Experimente online! ou verifique todos os casos de teste .

Como funciona

Œlµḟœ-Q$Ḋḣ1  Main link. Argument: s (string)

Œl           Convert s to lowercase.
  µ          Begin a new, monadic chain. Argument: s (lowercase string)
       $     Combine the two links to the left into a monadic chain.
      Q        Unique; yield the first occurrence of each character.
    œ-         Perform multiset subtraction, removing the last occurrence of each
               character.
   ḟ         Filterfalse; keep characters that do not appear in the difference.
        Ḋ    Dequeue; remove the first character.
         ḣ1  Head 1; remove everything but the first character.
Dennis
fonte
4

Lote, 171 bytes

@echo off
set a=.
set s=%~1
:l
if "%s%"=="" exit/b
set c=%s:~0,1%
call set t=%%s:%c%=%%
if "%s:~1%"=="%t%" set a=%a%%c%
set s=%t%
if "%a:~2%"=="" goto l
echo %c%

Formulação alternativa, também 171 bytes:

@echo off
set a=.
set s=%~1
:l
if "%s%"=="" exit/b
set c=%s:~0,1%
set t=%s:~1%
call set s=%%s:%c%=%%
if "%s%"=="%t%" set a=%a%%c%
if "%a:~2%"=="" goto l
echo %c%
Neil
fonte
Não é possível fazê-lo funcionar no W2008R2. A linha "conjunto de chamadas ..." se expande para "conjunto de chamadas t =% s: D =%" e é interrompida pela mensagem "A sintaxe do comando está incorreta".
Meden
@meden Desculpe, alguns erros de digitação surgiram no meu post. O ponto morto foi que o post era mais curto do que eu disse! Eles estão consertados agora.
Neil
3

Pitão, 16 15 bytes

1 byte graças a @ mbomb007

= rz1.xhtfq1 / zTzk
= rz1: fq1 / zTz1 2

Suíte de teste.

Freira Furada
fonte
2
Eu nem conheço Pyth, mas se você diz. : D
mbomb007 01/07
@ mbomb007 Você sabe, o [1:2]truque.
Freira vazando 02/07
Você pode salvar um byte em t<…2vez de :…1 2. Você pode salvar outro byte movendo o =rz1para a sua primeira utilização, se você também alterar 1a Z(para letras minúsculas em vez de saídas com letras maiúsculas): t<fq1/zT=rzZ2.
Anders Kaseorg
3

Na verdade, 19 bytes

;╗`ù╜ùc1=`░ε;(qq1@E

Experimente online!

Explicação:

;╗`ù╜ùc1=`░ε;(qq1@E
;╗                   push a copy of input to reg0
  `ù╜ùc1=`░          [v for v in s if
   ù╜ùc1=              s.lower().count(v.lower()) == 1]
           ε;(qq     append two empty strings to the list
                1@E  element at index 1 (second element)
Mego
fonte
3

C #, 129 128 bytes

char c(string i){var s=i.Where((n,m)=>i.ToLower().Where(o=>o==Char.ToLower(n)).Count()<2).ToArray();return s.Length>1?s[1]:' ';}

funciona bem. Eu gostaria de não precisar minúsculas tudo

downrep_nation
fonte
Lança um IndexOutOfRangeException quando passo "Thisxthis" como argumento. Fora isso, acho que == 1 pode ser alterado para <2.
Yytsi
2

C # lambda com Linq, 63 bytes

s=>(s=s.ToUpper()).Where(c=>s.Count(C=>c==C)<2).Skip(1).First()
Bryce Wagner
fonte
Você deve ser capaz de substituir .Skip(1).First()por.ElementAt(1)
aloisdg diz Reinstate Monica
Mesmo melhor você pode converter a lista e usar o índice.ToList()[1]
aloisdg diz Reintegrar Monica
Isso gera uma exceção para entradas como "", "AABB" e "AABBC", onde não há um caractere correspondente na 2ª posição. Eu acho que você precisa FirstOrDefault.
Grax32
2

C #, 141 bytes

void p(){var x=Console.ReadLine().ToLower();var c=0;foreach(char i in x){if(x.Split(i).Length-1<2){if(++c==2){Console.WriteLine(i);break;}}}}

Sem interrupção (menor), 135 bytes

void p(){var x=Console.ReadLine().ToLower();var c=0;foreach(char i in x){if(x.Split(i).Length-1<2){if(++c==2){Console.WriteLine(i);}}}}

Com para (;;), 150 bytes

void p(){for(;;){var x=Console.ReadLine().ToLower();var c=0;foreach(char i in x){if(x.Split(i).Length-1<2){if(++c==2){Console.WriteLine(i);break;}}}}}

Ungolfed com comentários

void p()
{
    var x=Console.ReadLine().ToLower();//Get lowercase version of input from STDIN
    var c=0; //Create "count" integer
    foreach(char i in x){//For each char in input from STDIN
        if(x.Split(i).Length-1<2)//If current char occurs once in input from STDIN
        {
            if(++c==2){ //Add 1 to count and if count is 2
                Console.WriteLine(i); //Print result to STDOUT
                break; //Exit foreach
            } //End of IF
         } //End of IF
     } //End of FOREACH
} //End of VOID

12 bytes salvos pelo TuukkaX (altere a contagem para c).

3 bytes salvos pelo TuukkaX (altere a string para var).

4 bytes salvos pelo TuukkaX em "Com para (;;)" (alterado enquanto (verdadeiro) para para (;;)).

2 bytes salvos pelo TuukkaX (alterado c ++; if (c == 2) para if (++ c == 2)).

14 bytes salvos por Bryce Wagner (alterado x.ToCharArray () para x).

r3pear
fonte
@TuukkaX oh, sério. obrigado!
R3pear #
Bem-vindo ao PPCG! Esse é um bom primeiro post! Como as regras mencionam que as respostas para esse problema devem ser funções ou programas completos, seus códigos requerem pequenos ajustes. Você também pode salvar bytes usando em varvez de stringe tendo algo como em cvez de count.
Yytsi 01/07/16
@TuukkaX Obrigado novamente! Em breve modificarei o código e alterarei a string para var.
R3pear #
@TuukkaX Devo adicionar algo como o programa void () {} ???
R3pear #
Sim, mas dê um nome de função de um byte para salvar bytes! :)
Yytsi
2

código de máquina x86, 43 bytes

Em hexadecimal:

FC31C031C95641AC84C0740E3C6172F63C7A77F28066FFDFEBEC5EAC49740B89F751F2AE5974F44A77F1C3

A função pega um ponteiro para a sequência de entrada em (E) SI e um número inteiro em (E) DX e retorna o (E) DX-ésimo caractere não repetitivo ou zero se não houver esse caractere. Como efeito colateral, converte a string em maiúsculas.

Desmontagem:

fc             cld
31 c0          xor    eax,eax
31 c9          xor    ecx,ecx
56             push   esi
_loop0:                         ;Search for the NULL char,
41             inc    ecx       ;counting the length in the process
ac             lodsb
84 c0          test   al,al
74 0e          je     _break0   ;NULL found, break
3c 61          cmp    al,0x61   ;If char is
72 f6          jb     _loop0    ;between 'a' and 'z'
3c 7a          cmp    al,0x7a   ;convert this char
77 f2          ja     _loop0    ;to uppercase in-place
80 66 ff df    and    byte ptr [esi-0x1],0xdf
eb ec          jmp    _loop0
_break0:
5e             pop    esi       ;Reset pointer to the string
_loop:                          ;ECX=string length with NULL
ac             lodsb            ;Load next char to AL
49             dec    ecx
74 0b          je     _ret      ;End of string found, break (AL==0)
89 f7          mov    edi,esi   ;EDI points to the next char
51             push   ecx
f2 ae          repnz scasb      ;Search for AL in the rest of the string
59             pop    ecx
74 f4          je     _loop     ;ZF==1 <=> another instance found, continue
4a             dec    edx
77 f1          ja     _loop     ;If not yet the EDX-th non-rep char, continue
_ret:
c3             ret
meden
fonte
2

APL, 32 bytes

{⊃1↓⍵/⍨1=+/∘.=⍨(⎕UCS ⍵)+32×⍵∊⎕A}

Experimente || Todos os casos de teste

Explicação:

                (⎕UCS ⍵)+32×⍵∊⎕A  Add 32 to uppercase letters
            ∘.=⍨                    Make an equality matrix
          +/                        Check how many matches
    ⍵/⍨1=                           Keep elements with 1 match
  1↓                                Drop the first one
⊃                                   Return the second one

Eu estava prestes a publicá-lo com 16 bytes, mas percebi que tinha que fazer distinção entre maiúsculas e minúsculas ...

Woofmao
fonte
1
(⎕UCS ⍵)+32×⍵∊⎕A819⌶⍵
Adám
Eu nunca vi esse operador antes. Em qual versão ele funciona?
Woofmao 31/08/18
É chamado de i-beam . É um operador em todas as versões do Dyalog APL. Originalmente, era uma função nas versões antigas do APL da IBM para chamadas especiais para o sistema IBM. Pegue? IBM - i-beam ?
Adám 31/08/18
Documentação para, em geral, e para o serviço 819 ("819" ≈ "BIg"). Experimente online!
Adám 31/08/18
Bem, eu aprendi algo novo. O tryapl.org parece não reconhecer, então você se importa se eu apenas usar o seu link TIO?
Woofmao 31/08/19
1

Retina, 43 36 bytes

iM!`(.)(?<!\1.+)(?!.*\1)
!`(?<=^.¶).

Experimente online!

Freira Furada
fonte
1

Mathematica, 49 bytes

Cases[Tally@ToUpperCase@#,{_,1}][[2,1]]~Check~""&

Função anônima. Leva uma lista de caracteres como entrada. Ignore os erros gerados.

LegionMammal978
fonte
1

JavaScript (Firefox 48 ou anterior), 60 bytes

f=s=>(m=s.match(/(.).*\1/i))?f(s.replace(m[1],"","gi")):s[1]

Retorna undefinedse houver apenas zero ou um caractere não repetitivo. Funciona excluindo sem distinção entre maiúsculas e minúsculas todas as ocorrências de caracteres que aparecem mais de uma vez na cadeia. Baseia-se em uma extensão do Firefox não padrão que foi removida no Firefox 49. Versão do ES6 de 119 91 bytes:

f=s=>(m=s.match(/(.).*?(\1)(.*\1)?/i))?f((m[3]?s:s.replace(m[2],"")).replace(m[1],"")):s[1]

Procura recursivamente todos os caracteres que aparecem pelo menos duas vezes na cadeia. Se o caractere aparecer exatamente duas vezes, as duas ocorrências serão excluídas, caso contrário, somente a primeira ocorrência será excluída (as outras ocorrências serão excluídas posteriormente). Isso permite que as ocorrências tenham um caso de diferença.

Neil
fonte
Eu acredito que você pode realmente adaptar sua resposta do Firefox 48 para ser compatível com ES6, substituindo m[1]pornew RegExp(`${m[1]}`,"gi")
Value Ink
@ KevinLau-notKenny Isso não funcionaria para caracteres especiais, e me custou 33 bytes para casos especiais, levando-me até 93, infelizmente.
Neil
noooooo não os caracteres especiais! Eu tive que editar minha resposta Ruby para acomodá-las também, agora.
Value Ink
1

J, 25 bytes

(1{2{.]-.]#~1-~:)@tolower

Uso

   f =: (1{2{.]-.]#~1-~:)@tolower
   f 'DEFD'
f
   f 'FEED'
d
   f 'This is an example input sentence.'
x
   f '...,,,..,,!@'
@
   f 'ABCDefgHijklMNOPqrsTuVWxyz'
b
   f 'AAAAAABBBBB'

   f 'Thisxthis'

   f 'This this.'
.

Explicação

(1{2{.]-.]#~1-~:)@tolower  Input: s
                  tolower  Converts the string s to lowercase
              ~:           Mark the indices where the first time a char appears
            1-             Complement it
         ]                 Identity function to get s
          #~               Copy only the chars appearing more than once
      ]                    Identity function to get s
       -.                  Remove all the chars from s appearing more than once
   2{.                     Take the first 2 chars from the result (pad with empty string)
 1{                        Take the second char at index 1 and return it
milhas
fonte
1

Bash, 58 bytes

tr A-Z a-z>t
tr -dc "`fold -1<t|sort|uniq -u`"<t|cut -c2

Cuidado: Isso cria um arquivo temporário chamado t . Se já existir, será substituído.

Dennis
fonte
1

C, 174 bytes

int c(char*s){int y=128,z=256,c[384],t;memset(c,0,z*6);for(;t=toupper(*s);s++){c[t]++?c[t]-2?0:c[z+(c[y+c[z+t]]=c[y+t])]=c[z+t]:c[z]=c[y+(c[z+t]=c[z])]=t;}return c[y+c[y]];}

Esta não é a implementação mais curta, mas bastante eficiente. Em essência, ele usa a lista com vínculo duplo para manter o conjunto ordenado de caracteres candidatos e verifica a sequência de entrada apenas uma vez. Retorna o código de caractere ou zero se nenhum foi encontrado.

Uma versão pouco destruída:

int c(char*s)
{
    int y=128,z=256,c[384],t;
    //It's basically c[3][128], but with linear array the code is shorter

    memset(c,0,z*6);

    for(;t=toupper(*s);s++)
    {
        c[t]++ ?        // c[0][x] - number of char x's occurrence
            c[t] - 2 ?  // > 0
                0       // > 1 - nothing to do  
                : c[z + (c[y + c[z + t]] = c[y + t])] = c[z + t]  // == 1 - remove char from the list
            : c[z] = c[y + (c[z + t] = c[z])] = t; // == 0 - add char to the end of the list
    }
    return c[y + c[y]];
}
meden
fonte
1

C #, 143 bytes

char c(string s){var l=s.Select(o=>Char.ToLower(o)).GroupBy(x=>x).Where(n=>n.Count()<2).Select(m=>m.Key).ToList();return l.Count()>1?l[1]:' ';}
ScifiDeath
fonte
1

TSQL, 128 bytes

Golfe:

DECLARE @ varchar(99)=',,zzzbb@kkkkkkJgg'

,@i INT=99WHILE @i>1SELECT
@i-=1,@=IIF(LEN(@)>LEN(x)+1,x,@)FROM(SELECT
REPLACE(@,SUBSTRING(@,@i,1),'')x)x PRINT SUBSTRING(@,2,1)

Ungolfed:

DECLARE @ varchar(99)=',,zzzbb@kkkkkkJgg'

,@i INT=99

WHILE @i>1
  SELECT
    @i-=1,@=IIF(LEN(@)>LEN(x)+1,x,@)
  FROM
    (SELECT 
       REPLACE(@,SUBSTRING(@,@i,1),'')x
    )x

PRINT SUBSTRING(@,2,1)

Violino

t-clausen.dk
fonte
1

Ruby, 53 bytes

A entrada é STDIN, a saída é STDOUT. No Ruby, as posições fora do índice em uma matriz ou string retornam nil, que não são impressas.

String#counté uma função estranha no Ruby porque, em vez de contar o número de ocorrências para a sequência que foi passada, conta o número de ocorrências para cada letra dessa sequência. Geralmente é chato, mas podemos usá-lo para nossa vantagem neste momento. String#swapcasetroca letras maiúsculas e minúsculas.

$><<gets.chars.reject{|c|$_.count(c+c.swapcase)>1}[1]

Versão antiga que não era segura contra caracteres especiais como .- 46 bytes

$><<gets.chars.reject{|c|$_=~/#{c}.*#{c}/i}[1]
Value Ink
fonte
1

Java 8, 172 157 bytes

(String s)->{s=s.toLowerCase();for(char i=0,c;s.length()>0;s=s.replace(c+"","")){c=s.charAt(0);if(!s.matches(".*"+c+".*"+c+".*")&&++i>1)return c;}return' ';}

-15 bytes. Porra, eu era ruim em jogar golfe naquela época. ;)

Explicação:

Experimente aqui.

(String s)->{                          // Method with String parameter and character return-type
  s=s.toLowerCase();                   // Make the input-String lowercase
  for(char i=0,c;s.length()>0;         // Loop over the characters of `s`
      s=s.replace(c+"","")){           // And after every iteration, remove all occurrences of the previous iteration
    c=s.charAt(0);                     // Get the current first character
    if(!s.matches(".*"+c+".*"+c+".*")  // If it doesn't occur more than once
     &&++i>1)                          // And this was the second one we've found
      return c;                        // Return this second characters
  }                                    // End of loop
  return' ';                           // Else: return an empty character/nothing
}                                      // End of method
Kevin Cruijssen
fonte
1

R , 79 bytes

function(z){y=tolower(el(strsplit(z,"")));x=table(y);y[y%in%names(x[x==1])][2]}

Experimente online!

Eu definitivamente sinto que algo pode ser jogado aqui. Mas gostei muito desse desafio.

Essa resposta divide a string em um vetor de caracteres, altera todas para minúsculas e as apresenta (conta). Os caracteres que ocorrem uma vez são selecionados e comparados aos caracteres do vetor mencionado acima; o segundo valor verdadeiro é retornado como saída. Uma sequência vazia ou sem caracteres repetidos gera NA.

Sumner18
fonte
1

Perl 6 , 38 32 bytes

-6 bytes graças ao nwellnhof mudando .combpara um regex que não diferencia maiúsculas de minúsculas

{~grep({2>m:g:i/$^a/},.comb)[1]}

Experimente online!

Brincadeira
fonte
1
m:g:i/$^a/para 32 bytes .
Nwellnhof 01/09/19
1

K (oK) / K4 , 11 bytes

Solução:

*1_&1=#:'=_

Experimente online!

Explicação:

*1_&1=#:'=_ / the solution
          _ / convert input to lowercase
         =  / group alike characters
      #:'   / count (#:) each group
    1=      / 1 equal to length of the group?
   &        / where true
 1_         / drop the first
*           / take the first
rua
fonte
0

Perl, 75 bytes

 my$s=<>;chomp$s;my$c;for my$i(split//,$s){my$m=@{[$s=~/$i/gi]};$m<2and++$c>=2and say$i and last}
Byeonggon Lee
fonte
0

Javascript (usando a Biblioteca externa) (107 bytes)

Esmagou isso usando uma biblioteca que escrevi. Não tenho certeza se tenho que contar a declaração da variável "s", que é a string em questão.

(s)=>_.From(s).ToLookup(y=>y.toLowerCase(),z=>z).Where(g=>g.Value.Count()==1).Select(x=>x.Key).ElementAt(1)

Isso manipulará uma entrada de sequência vazia, uma entrada com apenas um caractere não repetitivo e uma entrada com mais de 2 caracteres não repetitivos

Imagem 1

applejacks01
fonte
Você tem um link para a biblioteca em questão? Além disso, como este é um código de golfe, você precisa remover um espaço em branco onde puder
Value Ink
Ei, sim, é github.com/mvegh1/Enumerable . Ainda não há documentos. Desculpe, eu vou limpar essa resposta para reduzir o espaço em branco muito
applejacks01
Você provavelmente deve mencionar e vinculá-lo no corpo da resposta. Além disso, em relação ao bytecount, o consenso é colocá-lo em um lambda anônimo (por isso s=> ...)
Valor Ink
Ok, não há problema. Eu não queria ofender ninguém vinculando ao meu código, mas mencionei que usei minha biblioteca. Eu vou atualizar a minha resposta com o lambda, obrigado por me deixar saber
applejacks01
0

Clojure, 109 bytes

#(let[s(clojure.string/lower-case %)](or(second(remove(set(map(fn[[k v]](if(> v 1)k))(frequencies s)))s))""))

Espero que exista uma maneira mais sucinta.

NikoNyrh
fonte