Qual è il secondo personaggio che non si ripete?


18

Sulla base di questa domanda da Code Review

Data una stringa non vuota di caratteri ASCII stampabili, genera il secondo carattere non ripetuto. Ad esempio, per input DEFD, output F.

Ingresso

Produzione

  • Il secondo carattere che non si ripete, quando si legge da sinistra a destra, di nuovo in un formato adatto.
  • Il carattere di output non fa distinzione tra maiuscole e minuscole.
  • Se non esiste tale carattere (ad esempio, tutti i caratteri si ripetono), emette una stringa vuota.

Regole

  • L'algoritmo dovrebbe ignorare il caso. Cioè De dconta come lo stesso personaggio.
  • È accettabile un programma completo o una funzione.
  • La stringa di input sarà garantita non vuota (ovvero almeno un carattere di lunghezza).
  • La stringa di input è ASCII. Qualsiasi carattere valido può essere ripetuto, non solo alfanumerico (inclusi gli spazi).
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

Esempi

L'ingresso è sulla prima riga, l'output è sulla seconda riga.

DEFD
F

FEED
D

This is an example input sentence.
x

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

ABCDefgHijklMNOPqrsTuVWxyz
B

AAAAAABBBBB


Thisxthis


This this.
.

8
Se non fosse sensibile al maiuscolo / minuscolo, prenderei in considerazione la possibilità di farlo a Forth. Tuttavia, le operazioni sulle stringhe fanno schifo in quella lingua.
mbomb007,

Cosa succede se la mia lingua non supporta le lettere minuscole?
Adám,

@Adám Utilizza una tabella codici diversa? Come normalmente inserisce una stringa ASCII se non supporta le lettere minuscole?
AdmBorkBork,

1
Il sistema che avevo in mente aveva una tabella codici a 7 bit; una tabella codici standard modificata in cui le lettere maiuscole occupano le posizioni minuscole e le posizioni maiuscole sono state utilizzate per glifi. Ciò è stato fatto su vecchi sistemi APL in modo da poter usare Shift per accedere ai glifi APL, mentre le lettere non spostate erano maiuscole in stile classico.
Adám,

Risposte:


10

MATL , 11 byte

tk&=s1=)FT)

Questo si chiude con un errore (consentito per impostazione predefinita) se non esiste un secondo carattere non ripetuto.

Provalo online!

Spiegazione

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 

La modifica del ninja colpisce ancora. : P
Dennis,

@Dennis Hahaha. Bene, immagino che presto rimuoverai un paio di byte
Luis Mendo,

10

Retina , 25 byte

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

Provalo online! (La prima riga consente di eseguire il codice su una suite di test con più input.)

Spiegazione

Questa è solo una singola corrispondenza regex, essendo la regex:

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

Ossia, abbina un personaggio e assicurati che non appaia in nessun altro punto dell'input. Il resto è configurazione:

  • i attiva l'insensibilità al caso.
  • ! dice a Retina di stampare le partite invece di contarle.
  • 2= dice a Retina di stampare solo la seconda partita invece di tutte.

1
Ah, grazie per avermi insegnato sul 2=.
Leaky Nun,

6

05AB1E, 15 12 byte

l©v®y¢iy}}1@

spiegato

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

Provalo online

Salvato 3 byte grazie a @Adnan


O per 12 byte l©v®y¢iy}}1@:).
Adnan,

@Adnan: bello! Non ho pensato di usare @.
Emigna,

5

Python 2, 59 58 byte

Restituisce un elenco di un singolo carattere o un elenco vuoto se non viene prodotto alcun output. (Stupida insensibilità al maiuscolo ...)

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

Provalo online



Non è un input valido. L'utente non dovrebbe mai dover sfuggire al proprio input.
mbomb007,

4
Certo che lo e. Forniamo elenchi su STDIN nel formato elenco delle lingue. Perché le stringhe dovrebbero essere diverse?
Dennis,

5

Gelatina , 11 byte

Œlµḟœ-Q$Ḋḣ1

Provalo online! o verifica tutti i casi di test .

Come funziona

Œ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.

4

Lotto, 171 byte

@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%

Formulazione alternativa, anche 171 byte:

@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%

Impossibile farlo funzionare su W2008R2. La riga "call set ..." si espande in "call set t =% s: D =%" e si interrompe con il messaggio "La sintassi del comando non è corretta".
data

@meden Siamo spiacenti, alcuni errori di battitura sono entrati nel mio post. L'omaggio morto era che la posta era più corta di quanto dicessi! Sono riparati ora.
Neil,

3

Pyth, 16 15 byte

1 byte grazie a @ mbomb007

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

Suite di test.


2
Non conosco nemmeno Pyth, ma se lo dici tu. : D
mbomb007,

@ mbomb007 Sai, il [1:2]trucco.
Leaky Nun,

È possibile salvare un byte con t<…2invece di :…1 2. È possibile salvare un altro byte spostando il =rz1suo primo utilizzo, se si cambia anche 1a Z(per minuscolo invece di uscita maiuscolo): t<fq1/zT=rzZ2.
Anders Kaseorg,

3

In realtà, 19 byte

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

Provalo online!

Spiegazione:

;╗`ù╜ù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)

3

C #, 129 128 byte

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]:' ';}

funziona bene. Vorrei non aver bisogno di minuscole tutto


Genera IndexOutOfRangeException quando passo "Thisxthis" come argomento. Oltre a ciò, penso che == 1 possa essere modificato in <2.
Yytsi,

2

C # lambda con Linq, 63 byte

s=>(s=s.ToUpper()).Where(c=>s.Count(C=>c==C)<2).Skip(1).First()

Dovresti essere in grado di sostituire .Skip(1).First()con.ElementAt(1)
aloisdg dice Reinstate Monica il

Ancora meglio è possibile convertire in elenco e utilizzare l'indice.ToList()[1]
aloisdg dice Reinstate Monica

Ciò genera un'eccezione per input come "", "AABB" e "AABBC", dove non c'è un carattere corrispondente nella seconda posizione. Penso che tu abbia bisogno di FirstOrDefault.
Grax32,

2

C #, 141 byte

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

Senza interruzione (il più piccolo), 135 byte

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

Con per (;;), 150 byte

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

Non rigato di commenti

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 byte salvati da TuukkaX (modifica il conteggio in c).

3 byte salvati da TuukkaX (cambia la stringa in var).

4 byte salvati da TuukkaX in "With for (;;)" (modificato da (true) a for (;;)).

2 byte salvati da TuukkaX (modificato c ++; if (c == 2) in if (++ c == 2)).

14 byte salvati da Bryce Wagner (modificato x.ToCharArray () in x).


@TuukkaX oh, davvero. grazie!
r3pear,

Benvenuti in PPCG! Questo è un bel primo post! Poiché le regole menzionano che le risposte a questo problema dovrebbero essere funzioni o programmi completi, i tuoi codici richiedono piccole modifiche. Puoi anche salvare byte usando varinvece di stringe avendo qualcosa di simile cinvece di count.
Yytsi,

@TuukkaX Grazie ancora! Tra poco modificherò il codice e cambierò stringa in var.
r3pear,

@TuukkaX Dovrei aggiungere qualcosa come il programma void () {} ???
r3pear,

Sì, ma dai un nome di funzione a un byte per salvare i byte! :)
Yytsi

2

codice macchina x86, 43 byte

In esadecimale:

FC31C031C95641AC84C0740E3C6172F63C7A77F28066FFDFEBEC5EAC49740B89F751F2AE5974F44A77F1C3

La funzione prende un puntatore alla stringa di input in (E) SI e un numero intero in (E) DX e restituisce il (E) DX-esimo carattere non ripetuto o zero se non esiste tale carattere. Come effetto collaterale converte la stringa in maiuscolo.

Smontaggio:

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

2

APL, 32 byte

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

Provalo || Tutti i casi di test

Spiegazione:

                (⎕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

Stavo per pubblicarlo con 16 byte, ma mi sono reso conto che doveva fare distinzione tra maiuscole e minuscole ...


1
(⎕UCS ⍵)+32×⍵∊⎕A819⌶⍵
Adám,

Non avevo mai visto quell'operatore prima d'ora. In quale versione funziona?
Woofmao,

Si chiama i-beam . È un operatore in tutte le versioni di Dyalog APL. Originariamente era una funzione nelle vecchie versioni dell'APL di IBM per chiamate speciali al sistema IBM. Prendilo? IBM - i-beam ?
Adám,

Documentazione per in generale e per il servizio 819 ("819" ≈ "BIg"). Provalo online!
Adám,

Bene, ho imparato qualcosa di nuovo. tryapl.org non sembra riconoscerlo, quindi ti dispiace se uso solo il tuo link TIO?
Woofmao,


1

Mathematica, 49 byte

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

Funzione anonima. Accetta un elenco di caratteri come input. Ignora eventuali errori generati.


1

JavaScript (Firefox 48 o precedente), 60 byte

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

Restituisce undefinedse ci sono solo zero o un carattere non ripetuto. Funziona eliminando senza distinzione tra maiuscole e minuscole tutte le ricorrenze di caratteri che compaiono più di una volta nella stringa. Si basa su un'estensione non standard di Firefox che è stata rimossa in Firefox 49. 119 Versione ES6 a 91 byte:

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

Cerca ricorsivamente tutti i caratteri che compaiono almeno due volte nella stringa. Se il carattere appare esattamente due volte, entrambe le occorrenze vengono eliminate, altrimenti viene eliminata solo la prima occorrenza (le altre occorrenze verranno eliminate in seguito). Ciò consente alle ricorrenze di avere un caso di differenza.


Credo che tu possa effettivamente adattare la tua risposta di Firefox 48 alla conformità ES6 sostituendola m[1]connew RegExp(`${m[1]}`,"gi")
Value Ink

@ KevinLau-notKenny Che non avrebbe funzionato per personaggi speciali, e mi è costato 33 byte nel caso speciale, portandomi fino a 93, sfortunatamente.
Neil,

noooooo non i personaggi speciali! Ho dovuto modificare la mia risposta di Ruby per adattarmi anche a loro, ora.
Value Ink

1

J, 25 byte

(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.'
.

Spiegazione

(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

1

Bash, 58 byte

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

Attenzione: questo crea un file temporaneo chiamato t . Se esiste già, verrà sovrascritto.


1

C, 174 byte

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

Questa non è l'implementazione più breve, ma abbastanza efficiente. In sostanza utilizza un elenco a doppio collegamento per mantenere l'insieme ordinato di caratteri candidati e scansiona la stringa di input una sola volta. Restituisce il codice carattere o zero se non ne viene trovato nessuno.

Versione un po 'ungolfed:

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

1

C #, 143 byte

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]:' ';}

1

TSQL, 128 byte

golfed:

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


1

Rubino, 53 byte

L'ingresso è STDIN, l'uscita è STDOUT. In Ruby, vengono restituite posizioni fuori indice in un array o in una stringa nil, che non viene stampato.

String#countè una strana funzione in Ruby perché invece di contare il numero di occorrenze per la stringa che è stata passata, conta il numero di occorrenze per ogni lettera in quella stringa. Di solito è fastidioso ma questa volta possiamo usarlo a nostro vantaggio. String#swapcasescambia lettere maiuscole e minuscole.

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

Vecchia versione che non era sicura contro caratteri speciali come .- 46 byte

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

1

Java 8, 172 157 byte

(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 byte .. Dang All'epoca ero un cattivo giocatore di golf. ;)

Spiegazione:

Provalo qui.

(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

1

R , 79 byte

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

Provalo online!

Sicuramente sento che si può giocare a golf qui. Ma mi è davvero piaciuta questa sfida.

Questa risposta divide la stringa in un vettore di caratteri, li cambia tutti in lettere minuscole e li classifica (li conta). I caratteri che si presentano una volta vengono selezionati e confrontati con i caratteri all'interno del vettore sopra menzionato, quindi il secondo valore vero viene restituito come output. Una stringa vuota o una stringa senza caratteri ripetitivi genera NA.



1

K (oK) / K4 , 11 byte

Soluzione:

*1_&1=#:'=_

Provalo online!

Spiegazione:

*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


0

Perl, 75 byte

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

0

Javascript (utilizzando una libreria esterna) (107 byte)

Ho schiacciato questo usando una libreria che ho scritto. Non sono sicuro se devo contare la dichiarazione della variabile "s", che è la stringa in questione.

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

Questo gestirà un input di stringa vuoto, un input con un solo carattere non ripetuto e un input con 2+ caratteri non ripetitivi

Immagine 1


Hai un link alla libreria in questione? Inoltre, essendo questo il golf del codice, devi eliminare gli spazi bianchi dove puoi
Value Ink

Ehi, sì, è github.com/mvegh1/Enumerable . Nessun documento ancora. Mi dispiace, pulirò questa risposta per ridurre lo spazio bianco
applejacks01

Probabilmente dovresti menzionarlo e collegarlo nel corpo della risposta. Inoltre, per quanto riguarda il Bytecount, il consenso è quello di metterlo in un lambda anonimo (quindi s=> ...)
Value Ink

Ok nessun problema. Non volevo offendere nessuno collegandomi al mio codice, ma ho menzionato che ho usato la mia libreria. Aggiornerò la mia risposta con la lambda, grazie per avermelo fatto sapere
applejacks01

0

Clojure, 109 byte

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

Ough, spero che ci sia un modo più conciso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.