Який другий неповторюваний персонаж?


18

Виходячи з цього питання від Code Review

Враховуючи непорожній рядок друкованих символів ASCII, виведіть другий неповторюваний символ. Наприклад, для введення DEFD, виводу F.

Вхідні дані

Вихід

  • Другий символ , який не повторюється, при читанні зліва направо, знову в потрібному форматі.
  • Вихідний символ нечутливий до регістру.
  • Якщо такого символу немає (наприклад, всі символи повторюються), виведіть порожній рядок.

Правила

  • Алгоритм повинен ігнорувати випадок. Тобто, Dі dвважають одним і тим же персонажем.
  • Прийнятна або повна програма, або функція.
  • Рядок введення буде гарантовано не порожнім (тобто, принаймні один символ у довжину).
  • Вхідний рядок - ASCII. Будь-який дійсний символ може повторюватися, не лише буквено-цифровий (сюди входять пробіли).
  • Стандартні лазівки заборонені.
  • Це тому застосовуються всі звичайні правила гольфу, і найкоротший код (у байтах) виграє.

Приклади

Вхід знаходиться на першому рядку, вихід - на другому.

DEFD
F

FEED
D

This is an example input sentence.
x

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

ABCDefgHijklMNOPqrsTuVWxyz
B

AAAAAABBBBB


Thisxthis


This this.
.

8
Якби це не було чутливим до регістру, я б подумав зробити це у Forth. Хоча струнні операції засмоктують цю мову.
mbomb007

Що робити, якщо моя мова не підтримує малі літери?
Адам

@ Adám Чи використовується інша сторінка коду? Як зазвичай вводити рядок ASCII, якщо він не підтримує малі літери?
AdmBorkBork

1
Система, яку я мав на увазі, мала 7-бітну кодову сторінку; модифікована стандартна кодова сторінка, де великі літери займають малі позиції, а великі позиції використовуються для гліфів. Це було зроблено на старих системах APL, щоб можна було використовувати Shift для доступу до гліфів APL, тоді як не змінені літери - це класичні великі літери кодування.
Adám

Відповіді:


10

MATL , 11 байт

tk&=s1=)FT)

Це завершується помилкою (дозволено за замовчуванням), якщо немає другого неповторного символу.

Спробуйте в Інтернеті!

Пояснення

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 

Редагування ніндзя знову вражає. : P
Денніс

@Денніс Хахаха. Ну, напевно, ви скоро видалите пару байт
Луїс Мендо

10

Сітківка , 25 байт

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

Спробуйте в Інтернеті! (Перший рядок дозволяє запустити код на тестовому наборі з декількох входів.)

Пояснення

Це лише одна відповідність регулярного вираження, при цьому регулярний вираз:

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

Тобто, підберіть відповідність символу та переконайтеся, що він не з’являється більше ніде у вводі. Решта - конфігурація:

  • i активує нечутливість випадку.
  • ! говорить Ретіні друкувати сірники, а не рахувати їх.
  • 2= говорить Ретіні надрукувати лише другий матч на відміну від усіх.

1
А, дякую, що ви навчали мене про 2=.
Leaky Nun

6

05AB1E, 15 12 байт

l©v®y¢iy}}1@

Пояснив

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

Спробуйте в Інтернеті

Збережено 3 байти завдяки @Adnan


Або на 12 байт l©v®y¢iy}}1@:).
Аднан

@Adnan: Приємно! Не думав використовувати @.
Емінья

5

Python 2, 59 58 байт

Повертає список одного символу або порожнього списку, якщо виводу немає. (Дурна нечутливість до випадку ...)

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

Спробуйте в Інтернеті



Неправильний ввід. Користувачеві ніколи не слід уникати своїх даних.
mbomb007

4
Звичайно, це так. Ми надаємо списки на STDIN у форматі списку мови. Чому б рядки були різними?
Денніс

5

Желе , 11 байт

Œlµḟœ-Q$Ḋḣ1

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Як це працює

Œ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

Пакетна, 171 байт

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

Альтернативна рецептура, також 171 байт:

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

Неможливо змусити його працювати на W2008R2. Рядок "набір викликів ..." розширюється на "набір викликів t =% s: D =%" і перериває повідомлення "Синтаксис команди невірний".
меден

@meden Вибачте, деякі помилки прокралися до моєї публікації. Мертвий подарунок полягав у тому, що посада була коротшою, ніж я сказав, що це було! Вони зараз виправлені.
Ніл

3

Pyth, 16 15 байт

1 байт завдяки @ mbomb007

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

Тестовий набір.


2
Я навіть не знаю Піта, але якщо ти так кажеш. : D
mbomb007

@ mbomb007 Ви знаєте, [1:2]фокус.
Leaky Nun

Ви можете зберегти байт за допомогою, t<…2а не :…1 2. Ви можете зберегти інші байти, переміщаючи =rz1його перше використання, якщо ви також змінити 1на Z(для нижнього регістра замість верхнього регістру виходу): t<fq1/zT=rzZ2.
Anders Kaseorg

3

Власне, 19 байт

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

Спробуйте в Інтернеті!

Пояснення:

;╗`ù╜ù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 байт

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

працює чудово. Я б хотів, щоб я не мав потребу в регістрі всього


Викидає IndexOutOfRangeException, коли я передаю "Thisxthis" як аргумент. Крім цього, я думаю, що == 1 можна змінити на <2.
Yytsi

2

C # лямбда з Linq, 63 байти

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

Ви повинні бути в змозі замінити .Skip(1).First()з.ElementAt(1)
aloisdg переходу до codidact.com

Ще краще ви можете конвертувати в список та використовувати індекс.ToList()[1]
aloisdg переходить на codidact.com

Це викидає винятки для входів, таких як "", "AABB" та "AABBC", де у другій позиції немає відповідного символу. Я думаю, що вам потрібен FirstOrDefault.
Grax32

2

C #, 141 байт

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

Без перерви (найменший), 135 байт

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

З для (;;), 150 байт

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

Безголовка з коментарями

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 байтів, збережених TuukkaX (кількість змін на c).

3 байти, збережені TuukkaX (змініть рядок на var).

4 байти, збережені TuukkaX у "With for (;;)" (змінено в той час, коли (true) to for (;;)).

2 байти, збережені TuukkaX (змінено c ++; якщо (c == 2) на if (++ c == 2)).

14 байт, збережених Брайсом Вагнером (змінено x.ToCharArray () на x).


@TuukkaX о, справді. Дякую!
r3pear

Ласкаво просимо до PPCG! Це хороший перший пост! Оскільки правила згадують, що відповіді на цю проблему мають бути або функціями, або повноцінними програмами, ваші коди потребують невеликих змін. Ви також можете зберегти байти, використовуючи varзамість того , щоб stringі мати що - щось подібне , cзамістьcount .
Yytsi

@TuukkaX Дякую ще раз! Незабаром я зміню код і зміню рядок на var.
r3pear

@TuukkaX Чи варто додати щось на зразок void program () {} ???
r3pear

Так, але дайте ім’я однієї байтової функції для збереження байтів! :)
Yytsi

2

машинний код x86, 43 байти

У шістнадцятковій формі:

FC31C031C95641AC84C0740E3C6172F63C7A77F28066FFDFEBEC5EAC49740B89F751F2AE5974F44A77F1C3

Функція бере вказівник на рядок введення в (E) SI і ціле число в (E) DX і повертає (E) DX-й не повторюваний символ або нуль, якщо такого символу немає. Як побічний ефект він перетворює рядок у верхній регістр.

Розбирання:

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 байти

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

Спробуйте || Усі тестові справи

Пояснення:

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

Я збирався розмістити його з 16 байтами, але зрозумів, що це повинно бути нечутливим до регістру ...


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

Я ніколи раніше не бачив цього оператора. У якій версії він працює?
Woofmao

Його називають i-променем . Це оператор у всіх версіях Dyalog APL. Спочатку це була функція у старих версіях APL IBM для спеціальних викликів до системи IBM. Отримаєте? IBM - i-промінь ?
Adám


Ну, я дізнався щось нове. tryapl.org, схоже, не розпізнає це, тож ви не заперечуєте, якщо я просто використовую ваше посилання TIO?
Woofmao


1

Математика, 49 байт

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

Анонімна функція. Візьме список символів як вхідний. Ігноруйте всі генеровані помилки.


1

JavaScript (Firefox 48 або новіші версії), 60 байт

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

Повертається, undefinedякщо є лише нуль або один не повторюваний символ. Працює за допомогою нечутливого до випадку видалення всіх подій символів, які з’являються не один раз у рядку. Покладається на нестандартне розширення Firefox, яке було видалено у Firefox 49. 119 91 байт ES6 версія:

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

Рекурсивно шукає всі символи, що з’являються щонайменше двічі в рядку. Якщо символ з'являється рівно двічі, обидва випадки видаляються, інакше видаляється лише перше явище (інші випадки буде видалено пізніше). Це дозволяє мати випадки різниці.


Я вважаю , що ви можете адаптувати свій Firefox 48 відповіді будуть ES6-сумісної заміни m[1]зnew RegExp(`${m[1]}`,"gi")
Value Ink

@ KevinLau-notKenny Це не працювало б для особливих персонажів, і коштувало мені 33 байтів, щоб надати їм особливий випадок, на жаль, до 93, на жаль.
Ніл

noooooo не спеціальні символи! Мені довелося відредагувати свою відповідь Рубі, щоб їх також вмістити.
Значення чорнила

1

J, 25 байт

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

Використання

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

Пояснення

(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

Баш, 58 байт

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

Попередження: При цьому створюється тимчасовий файл з назвою t . Якщо вона вже існує, вона буде перезаписана.


1

C, 174 байти

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

Це не найкоротша, але досить ефективна реалізація. По суті, він використовує подвійний зв'язаний список, щоб підтримувати впорядкований набір символів-кандидатів та сканує рядок введення лише один раз. Повертає код символу або нуль, якщо його не знайдено.

Трохи незворушена версія:

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 байти

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 байт

Гольф:

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)

Безголівки:

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)

Скрипка


1

Рубін, 53 байти

Вхід STDIN, вихід STDOUT. У Ruby позиції поза індексу в масиві або рядку повертаються nil, що не друкується.

String#countє дивною функцією в Ruby, оскільки замість того, щоб рахувати кількість подій для переданої рядка, вона рахує кількість входжень для кожної літери в цьому рядку. Зазвичай це дратує, але ми можемо використати це на нашу користь цього разу. String#swapcaseміняє великі і малі літери.

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

Стара версія, яка не була безпечною для спеціальних символів на кшталт .- 46 байт

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

1

Java 8, 172 157 байт

(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 байт .. Данг мені тоді було погано в гольфі. ;)

Пояснення:

Спробуйте тут.

(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 байт

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

Спробуйте в Інтернеті!

Я напевно відчуваю, що щось тут можна пограти в гольф. Але мені дуже сподобався цей виклик.

Ця відповідь розбиває рядок на вектор символів, змінює їх на малі регістри та таблиць їх (рахує їх). Символи, що виникають один раз, вибираються та порівнюються із символами в межах згаданого вектора, тоді друге значення, що відповідає дійсності, повертається як вихід. Порожній рядок або рядок без повторюваних символів виводить NA.





0

Perl, 75 байт

 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 (за допомогою зовнішньої бібліотеки) (107 байт)

Розчавив це за допомогою бібліотеки, яку я написав. Не впевнений, чи потрібно мені рахувати декларацію змінної "s", що є рядком, про який йдеться.

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

Це буде обробляти порожній рядок, вхід із лише одним символом, що повторюється, та вхід із 2+ символами, що не повторюються

Зображення 1


Чи є у вас посилання на відповідну бібліотеку? Також, маючи на увазі гольф з кодом, ви повинні взяти пробіли, де можна
Value Ink

Гей, так, це github.com/mvegh1/ незліченна кількість . Документів поки немає. Вибачте, я
очищу

Вам, мабуть, слід згадати і зв’язати це в тілі відповідей. Крім того, щодо облікового запису, консенсус полягає в тому, щоб він став анонімним лямбда (так s=> ...)
Value Ink

Без проблем. Я не хотів нікого ображати, посилаючись на свій код, але я згадав, що використовував свою бібліотеку. Я
оновлю

0

Clojure, 109 байт

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

Ой, сподіваюся, є більш складний спосіб.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.