Какой второй неповторяющийся персонаж?


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
Если бы он не учитывал регистр, я бы подумал сделать это в Форт. Строковые операции - отстой на этом языке.
mbomb007

Что если мой язык не поддерживает строчные буквы?
Адам

@ Adám Используется ли другая кодовая страница? Как бы он обычно вводил строку ASCII, если он не поддерживает строчные буквы?
AdmBorkBork

1
Система, которую я имел в виду, имела 7-битную кодовую страницу; модифицированная стандартная кодовая страница, где заглавные буквы занимают строчные буквы, а прописные - для глифов. Это было сделано в старых системах APL, чтобы можно было использовать Shift для доступа к символам APL, тогда как несмещенные буквы были классическими прописными буквами.
Адам

Ответы:


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 активирует нечувствительность к регистру.
  • ! говорит Retina напечатать спички, а не считать их.
  • 2= говорит Retina напечатать только второй матч, в отличие от всех.

1
Ах, спасибо, что научил меня о 2=.
Утренняя монахиня

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. Строка «call set ...» раскрывается до «call set t =% s: D =%» и прерывается сообщением «Синтаксис команды неверен».
Меден

@meden Извините, некоторые опечатки попали в мой пост. Мертвая распродажа заключалась в том, что пост был короче, чем я говорил! Они исправлены сейчас.
Нил

3

Pyth, 16 15 байт

1 байт благодаря @ mbomb007

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

Тестирование.


2
Я даже не знаю Пита, но если ты так говоришь. : D
mbomb007

@ mbomb007 Знаешь, [1:2]хитрость.
Утренняя монахиня

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

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 говорит восстановить Monica

Еще лучше вы можете конвертировать в список и использовать индекс.ToList()[1]
aloisdg говорит: «Восстановите Монику

Это вызывает исключение для входных данных, таких как "", "AABB" и "AABBC", где во 2-й позиции нет совпадающего символа. Я думаю, что вам нужно 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) на for (;;)).

2 байта сохранены TuukkaX (изменено c ++; if (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⌶⍵
Адам

Я никогда не видел этого оператора раньше. В какой версии он работает?
Woofmao

Это называется i-beam . Это оператор во всех версиях Dyalog APL. Первоначально это была функция в старых версиях APL IBM для специальных вызовов системы IBM. Возьми? IBM - я-луч ?
Адам

Документация для вообще и для обслуживания 819 («819» - «BIg»). Попробуйте онлайн!
Адам

Ну, я узнал что-то новое. Кажется, что tryapl.org не распознает его, так что вы не против, если я просто воспользуюсь вашей ссылкой TIO?
Woofmao


1

Mathematica, 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.
Нил

Неееееет, не спецсимволы! Я должен был отредактировать свой ответ Ruby, чтобы учесть их и сейчас.
Стоимость чернил

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

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)

скрипка


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

Попробуйте онлайн!

Я определенно чувствую, что здесь можно играть в гольф. Но мне очень понравился этот вызов.

Этот ответ разбивает строку на вектор символов, изменяет их все на строчные и ставит их в таблицу (считает их). Символы, которые встречаются один раз, выбираются и сравниваются с символами в вышеупомянутом векторе, а затем возвращается второе значение true, которое выводится. Пустая строка или строка без повторяющихся символов выводит NA.






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/Enumerable . Документов пока нет. Извините, я
уберу

Вы, вероятно, должны упомянуть и связать это в теле ответа. Кроме того, в отношении byountount, консенсус заключается в том, чтобы поместить его в анонимную лямбду (так 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.