2番目の非反復キャラクターは何ですか?


18

コードレビューのこの質問に基づいて

印刷可能なASCII文字の空でない文字列が与えられた場合、2番目の非反復文字を出力します。たとえば、input DEFD、outputの場合F

入力

出力

  • 第二左から右に読むとき、再び適切なフォーマットで、繰り返さない文字。
  • 出力文字は大文字と小文字を区別しません。
  • そのような文字が存在しない場合(すべての文字が繰り返されるなど)、空の文字列を出力します。

ルール

  • アルゴリズムは大文字小文字を無視する必要があります。つまり、Dおよびd同じ文字としてカウントされます。
  • 完全なプログラムまたは機能のいずれかが受け入れられます。
  • 入力文字列は空でないことが保証されます(つまり、少なくとも1文字の長さ)。
  • 入力文字列はASCIIです。英数字だけではなく、任意の有効な文字を繰り返すことができます(これにはスペースが含まれます)。
  • 標準的な抜け穴は禁止されています。
  • これはので、通常のゴルフルールがすべて適用され、最短のコード(バイト単位)が勝ちます。

入力は1行目にあり、出力は2行目にあります。

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グリフにアクセスできましたが、シフトされていない文字は古典的なコーディングスタイルの大文字でした。
アダム

回答:


10

MATL、11バイト

tk&=s1=)FT)

2番目の非反復文字がない場合、これはエラー(デフォルトで許可)で終了します。

オンラインでお試しください!

説明

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
デニス

@Dennis Hahaha。まあ、私はあなたがすぐにいくつかのバイトを削除すると思います
ルイスメンドー

10

網膜、25バイト

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

オンラインでお試しください!(最初の行では、いくつかの入力のテストスイートでコードを実行できます。)

説明

これは単一の正規表現の一致であり、正規表現は次のとおりです。

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

つまり、文字を照合し、入力内のどこにも表示されないようにします。残りは設定です:

  • i 大文字と小文字を区別しないようにします。
  • ! Retinaに、カウントではなく一致を印刷するように指示します。
  • 2= Retinaに、それらのすべてではなく2番目の一致のみを印刷するように指示します。

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

オンラインで試す

@Adnanのおかげで3バイト節約


または12バイトの場合l©v®y¢iy}}1@:)。
アドナン

@アドナン:いいね!@の使用を考えていませんでした。
エミグナ

5

Pythonの2、59の 58バイト

1文字のリストを返します。出力がない場合は空のリストを返します。(愚かな大文字小文字を区別しない...)

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

@medenすみません、いくつかのタイプミスが私の投稿に忍び込みました。死んだ景品は、投稿が私が言ったよりも短いことでした!それらは現在修正されています。
ニール

3

Pyth、16 15バイト

@ mbomb007のおかげで1バイト

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

テストスイート。


2
私もPythを知りませんが、そう言うなら。:D
mbomb007

@ mbomb007ご存知のように、[1:2]トリック。
リーキー修道女

t<…2代わりにを使用してバイトを保存できます:…1 2。(大文字の出力ではなく小文字の場合)に=rz1変更1する場合は、を最初の使用に移動して別のバイトを保存できます。Zt<fq1/zT=rzZ2
アンデルスカセオルグ16

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

正常に動作します。私はすべてを小文字にする必要がなかったらいいのに


「Thisxthis」を引数として渡すと、IndexOutOfRangeExceptionがスローされます。それ以外では、== 1は<2に変更できると思います。
Yytsi

2

Linqを使用したC#ラムダ、63バイト

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

あなたが交換することができるはず.Skip(1).First().ElementAt(1)
aloisdg復活モニカ言う

リストに変換してインデックスを使用することもできます.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);}}}}

for(;;)を使用すると、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

TuukkaXによって保存された12バイト(カウントをcに変更)。

TuukkaXによって保存された3バイト(文字列をvarに変更)。

「with for(;;)」でTuukkaXによって保存された4バイト(while(true)をfor(;;)に変更)。

TuukkaXによって保存された2バイト(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

はい、ただし、バイトを節約するために1バイトの関数名を付けてください!:)
Yytsi

2

x86マシンコード、43バイト

16進数で:

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⌶⍵
アダム

私はその演算子を見たことがありません。どのバージョンで動作しますか?
ウーフマオ

これはi-beamと呼ばれます。Dyalog APLのすべてのバージョンの演算子です。もともとは、IBMシステムへの特別な呼び出しのための古いバージョンのIBM APLの関数でした。それを得る?IBM — i-beam
アダム

一般的およびサービス819( "819"≈ "BIg")のドキュメント。オンラインでお試しください!
アダム

まあ、私は何か新しいことを学びました。tryapl.orgはそれを認識していないようですので、TIOリンクを使用しても構いませんか?
ウーフマオ


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非反復文字がゼロまたは1つしかない場合に返します。大文字と小文字を区別せずに、文字列に複数回出現する文字をすべて削除することで機能します。Firefoxの49で除去して、非標準のFirefoxの拡張機能に依存している119 91バイトES6バージョン:

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

文字列に少なくとも2回現れるすべての文字を再帰的に検索します。文字が正確に2回現れる場合、両方の出現が削除されます。そうでない場合、最初の出現のみが削除されます(他の出現は後で削除されます)。これにより、オカレンスで異なるケースを使用できます。


私はあなたが実際に置き換えることにより、ES6-準拠するためにあなたのFirefox 48の答えを適応させることができると信じていm[1]new RegExp(`${m[1]}`,"gi")
バリューインク

@ KevinLau-notKennyこれは特殊文字では機能しませんが、特殊なケースを作成するのに33バイトかかり、残念ながら最大93になりました。
ニール

noooooo特殊文字ではありません!今、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

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

これは最も短いものではありませんが、非常に効率的な実装です。本質的には、二重リンクリストを使用して候補文字の順序付けられたセットを維持し、入力文字列を1回だけスキャンします。文字コードを返します。見つからない場合はゼロを返します。

少しの無料版:

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

オンラインでお試しください!

ここで何かをゴルフできると確信しています。しかし、私はこの挑戦を本当に楽しんだ。

この回答は、文字列を文字のベクトルに分割し、それらをすべて小文字に変更して、それらを表に示します(カウントします)。一度出現する文字が選択され、前述のベクトル内の文字と比較された後、真である2番目の値が出力として返されます。空の文字列、または繰り返し文字のない文字列は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)

これは、空の文字列入力、非反復文字が1つだけの入力、および非反復文字が2つ以上の入力を処理します

Image 1


問題のライブラリへのリンクはありますか?また、この空白どこのことができます。コードゴルフされ、あなたが取るなきゃ
バリューインク

ねえ、それはgithub.com/mvegh1/Enumerableです。ドキュメントはまだありません。申し訳ありませんが、私は多くの空白として減らすために、この答えをクリーンアップします
applejacks01

おそらく回答本文に記載してリンクする必要があります。また、バイトカウントに関しては、コンセンサスは匿名ラムダ(so s=> ...)に入れることです
値インク

問題ありません。私は自分のコードにリンクすることで誰かを怒らせたくはありませんでしたが、自分のライブラリを使用したことは言及しました。答えをラムダで更新します。知らせてくれてありがとう
applejacks01

0

Clojure、109バイト

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

ああ、もっと簡潔な方法があるといいのですが。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.