What's the second non-repeating character?

18

Based on this question from Code Review

Given a non-empty string of printable ASCII characters, output the second non-repeating character. For example, for input DEFD, output F.

Input

Output

  • The second character that doesn't repeat, when reading left-to-right, again in a suitable format.
  • The output character is case-insensitive.
  • If no such character exists (e.g., all characters repeat), output an empty string.

Rules

  • The algorithm should ignore case. That is, D and d count as the same character.
  • Either a full program or a function are acceptable.
  • The input string will be guaranteed non-empty (i.e., at least one character in length).
  • The input string is ASCII. Any valid character could repeat, not just alphanumeric (this includes spaces).
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.

Examples

Input is on first line, output is on second line.

DEFD
F

FEED
D

This is an example input sentence.
x

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

ABCDefgHijklMNOPqrsTuVWxyz
B

AAAAAABBBBB


Thisxthis


This this.
.

AdmBorkBork

Posted 2016-07-01T15:44:59.530

Reputation: 41 581

8If it wasn't case-insensitive, I'd consider doing it in Forth. String operations suck in that language, though. – mbomb007 – 2016-07-01T17:05:36.973

What if my language doesn't support lowercase letters? – Adám – 2016-07-03T10:32:10.877

@Adám Does it utilize a different code page? How would it normally input an ASCII string if it doesn't support lowercase letters? – AdmBorkBork – 2016-07-04T13:37:34.237

2The system I had in mind had 7-bit code page; a modified standard code page where uppercase letters occupy the lowercase positions, and the uppercase positions were used for glyphs. This was done on old APL systems so that one could use Shift to access APL glyphs, while unshifted letters were classic coding-style capitals. – Adám – 2016-07-04T13:46:25.393

Answers

10

MATL, 11 bytes

tk&=s1=)FT)

This exits with an error (allowed by default) if there is no second non-repeated character.

Try it online!

Explanation

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

Posted 2016-07-01T15:44:59.530

Reputation: 87 464

The ninja edit strikes again. :P – Dennis – 2016-07-01T16:27:03.120

@Dennis Hahaha. Well, I guess you'll remove a couple of bytes soon – Luis Mendo – 2016-07-01T17:22:25.247

10

Retina, 25 bytes

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

Try it online! (The first line enables running the code on a test suite of several inputs.)

Explanation

This is just a single regex match, the regex being:

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

That is, match a character and ensure it doesn't appear anywhere else in the input. The rest is configuration:

  • i activates case insensitivity.
  • ! tells Retina to print the matches as opposed to counting them.
  • 2= tells Retina to print only the second match as opposed to all of them.

Martin Ender

Posted 2016-07-01T15:44:59.530

Reputation: 184 808

1Ah, thanks for teaching me about the 2=. – Leaky Nun – 2016-07-01T15:58:08.903

6

05AB1E, 15 12 bytes

l©v®y¢iy}}1@

Explained

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

Try it online

Saved 3 bytes thanks to @Adnan

Emigna

Posted 2016-07-01T15:44:59.530

Reputation: 50 798

Or for 12 bytes l©v®y¢iy}}1@ :).

– Adnan – 2016-07-02T00:37:37.253

@Adnan: Nice! Didn't think of using @. – Emigna – 2016-07-02T10:59:18.233

5

Jelly, 11 bytes

Œlµḟœ-Q$Ḋḣ1

Try it online! or verify all test cases.

How it works

Œ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

Posted 2016-07-01T15:44:59.530

Reputation: 196 637

5

Python 2, 59 58 bytes

Returns a list of a single character, or an empty list if no output. (Stupid case-insensitivity...)

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

Try it online

mbomb007

Posted 2016-07-01T15:44:59.530

Reputation: 21 944

1

@mbomb007 http://meta.codegolf.stackexchange.com/a/7634

– Dennis – 2016-07-01T16:40:06.767

It's not valid input. The user should never have to escape their input. – mbomb007 – 2016-07-01T16:41:53.617

4Sure it is. We provide lists on STDIN in the language's list format. Why would strings be any different? – Dennis – 2016-07-01T16:43:50.270

4

Batch, 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%

Alternative formulation, also 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

Posted 2016-07-01T15:44:59.530

Reputation: 95 035

Can't make it to run on W2008R2. Line "call set ..." expands to "call set t=%s:D=%" and aborts with "The syntax of the command is incorrect" message. – meden – 2016-07-02T23:06:15.613

@meden Sorry, some typos crept into my post. The dead giveaway was that the post was shorter than I said it was! They're fixed now. – Neil – 2016-07-03T00:09:22.147

3

Pyth, 16 15 bytes

1 byte thanks to @mbomb007

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

Test suite.

Leaky Nun

Posted 2016-07-01T15:44:59.530

Reputation: 45 011

2I don't even know Pyth, but if you say so. :D – mbomb007 – 2016-07-01T19:26:14.413

@mbomb007 You know, the [1:2] trick. – Leaky Nun – 2016-07-02T01:20:25.280

You can save a byte with t<…2 instead of :…1 2. You can save another byte by moving the =rz1 to its first use, if you also change 1 to Z (for lowercase instead of uppercase output): t<fq1/zT=rzZ2. – Anders Kaseorg – 2016-07-04T01:23:00.110

3

Actually, 19 bytes

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

Try it online!

Explanation:

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

Posted 2016-07-01T15:44:59.530

Reputation: 32 998

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

works fine. I wish i didnt need to lowercase everything

downrep_nation

Posted 2016-07-01T15:44:59.530

Reputation: 1 152

Throws an IndexOutOfRangeException when I pass "Thisxthis" as an argument. Other than that, I think that ==1 can be changed to <2. – Yytsi – 2016-07-03T11:10:12.237

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

Without break(smallest), 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);}}}}

With for(;;), 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 with comments

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 saved by TuukkaX(change count to c).

3 bytes saved by TuukkaX(change string to var).

4 bytes saved by TuukkaX in "With for(;;)"(changed while(true) to for(;;)).

2 bytes saved by TuukkaX(changed c++;if(c==2) to if(++c==2)).

14 bytes saved by Bryce Wagner(changed x.ToCharArray() to x).

r3pear

Posted 2016-07-01T15:44:59.530

Reputation: 121

@TuukkaX oh, really. thank you! – r3pear – 2016-07-01T20:13:27.323

Welcome to PPCG! That's a nice first post! Since the rules mention that answers to this problem should either be functions or full programs, your codes require little tweaks. You can also save bytes by using var instead of string and having something like c instead of count. – Yytsi – 2016-07-01T20:15:52.823

@TuukkaX Thank you again! Shortly I'll modify the code and change string to var. – r3pear – 2016-07-01T20:17:14.503

@TuukkaX Should I add something like void program(){}??? – r3pear – 2016-07-01T20:19:35.190

Yes, but give a one byte function name to save bytes! :) – Yytsi – 2016-07-01T20:20:52.370

@TuukkaX Done. Good? – r3pear – 2016-07-01T20:23:04.887

Very good! +1. while(true) can be changed to for(;;). – Yytsi – 2016-07-01T20:23:58.067

You can just use Console.Write instead of Console.WriteLine. – Yytsi – 2016-07-01T20:27:04.197

@TuukkaX Using i+"\n" instead of i uses 5 bytes, Console.WriteLine instead of Console.Write uses 4 bytes. – r3pear – 2016-07-01T20:33:51.010

Instead of incrementing c separately, you can omit the c++ line and move the incrementation to if(++c==2).... – Yytsi – 2016-07-01T20:34:10.127

OP doesn't mention that you should have a newline character at the end of the string. – Yytsi – 2016-07-01T20:35:37.860

@TuukkaX if(++c==2) doesn't increment the variable. Or does it? – r3pear – 2016-07-01T20:36:11.337

@TuukkaX Yes, but it would look bad in the for() version. – r3pear – 2016-07-01T20:36:53.450

if(++c==2) does increment c by one before c is used and the effect stays. – Yytsi – 2016-07-01T20:38:34.040

Let us continue this discussion in chat.

– r3pear – 2016-07-01T20:42:05.650

The .ToCharArray() is completely unnecessary, surprised nobody pointed that out. – Bryce Wagner – 2016-07-02T16:39:48.600

2

C# lambda with Linq, 63 bytes

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

Bryce Wagner

Posted 2016-07-01T15:44:59.530

Reputation: 121

You should be able to replace .Skip(1).First() with .ElementAt(1) – aloisdg moving to codidact.com – 2016-07-03T13:46:24.557

Even better you can convert to list and use the index .ToList()[1] – aloisdg moving to codidact.com – 2016-07-03T13:51:23.330

This throws an exception for inputs like "", "AABB", and "AABBC", where there is not a matching character in the 2nd position. I think you need FirstOrDefault. – Grax32 – 2016-12-28T22:29:19.703

2

x86 machine code, 43 bytes

In hex:

FC31C031C95641AC84C0740E3C6172F63C7A77F28066FFDFEBEC5EAC49740B89F751F2AE5974F44A77F1C3

Function takes a pointer to the input string in (E)SI and an integer in (E)DX and returns the (E)DX-th non-repeating character or zero if there's no such character. As a side-effect it converts the string to upper case.

Disassembly:

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

Posted 2016-07-01T15:44:59.530

Reputation: 711

2

APL, 32 bytes

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

Try it || All test cases

Explanation:

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

I was about to post it with 16 bytes, but the I realized it had to be case-insensitive...

Woofmao

Posted 2016-07-01T15:44:59.530

Reputation: 211

1(⎕UCS ⍵)+32×⍵∊⎕A819⌶⍵ – Adám – 2018-08-31T07:45:06.277

I've never seen that operator before. What version does it work in? – Woofmao – 2018-08-31T17:14:48.143

It is called the i-beam. It is an operator in all versions of Dyalog APL. It was originally a function in old versions of IBM's APL for special calls to the IBM system. Get it? I-B-M — i-beam? – Adám – 2018-08-31T17:32:47.407

Documentation for in general and for service 819 ("819" ≈ "BIg"). Try it online!

– Adám – 2018-08-31T17:40:53.220

Well, I've learned something new. tryapl.org doesn't seem to recognize it, so do you mind if I just use your TIO link? – Woofmao – 2018-08-31T18:17:43.827

I'll be happy to teach you more. is disabled on TryAPL for security. You're welcome to use the link, but this may suit you better. Also, note that your solution actually fails to return empty strings when needed.

– Adám – 2018-09-01T20:32:36.800

1

R, 79 bytes

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

Try it online!

I definitely feel like something can be golfed out here. But I really enjoyed this challenge.

This answer splits the string into a vector of characters, changes them all to lower case, and tables them (counts them). Characters that occur once are selected and compared to characters within the aforementioned vector, then the second value that is true is returned as output. An empty string, or a string with no repeating characters outputs NA.

Sumner18

Posted 2016-07-01T15:44:59.530

Reputation: 1 334

1

Perl 6, 38 32 bytes

-6 bytes thanks to nwellnhof by changing .comb to a case-insensitive regex

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

Try it online!

Jo King

Posted 2016-07-01T15:44:59.530

Reputation: 38 234

1m:g:i/$^a/ for 32 bytes. – nwellnhof – 2018-09-01T13:17:35.957

1

K (oK) / K4, 11 bytes

Solution:

*1_&1=#:'=_

Try it online!

Explanation:

*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

streetster

Posted 2016-07-01T15:44:59.530

Reputation: 3 635

1

Retina, 43 36 bytes

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

Try it online!

Leaky Nun

Posted 2016-07-01T15:44:59.530

Reputation: 45 011

1

Mathematica, 49 bytes

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

Anonymous function. Takes a list of characters as input. Ignore any errors that are generated.

LegionMammal978

Posted 2016-07-01T15:44:59.530

Reputation: 15 731

1

JavaScript (Firefox 48 or earlier), 60 bytes

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

Returns undefined if there are only zero or one non-repeating characters. Works by case-insensitively deleting all occurrences of characters that appear more than once in the string. Relies on a non-standard Firefox extension that was removed in Firefox 49. 119 91 byte ES6 version:

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

Recursively searches for all characters that appear at least twice in the string. If the character appears exactly twice then both occurrences are deleted otherwise only the first occurrence is deleted (the other occurrences will be deleted later). This allows the occurrences to have a difference case.

Neil

Posted 2016-07-01T15:44:59.530

Reputation: 95 035

I believe you can actually adapt your Firefox 48 answer to be ES6-compliant by replacing m[1] with new RegExp(\${m[1]}`,"gi")` – Value Ink – 2016-07-07T01:17:58.567

@KevinLau-notKenny That wouldn't work for special characters, and it cost me 33 bytes to special-case them, taking me up to 93, unfortunately. – Neil – 2016-07-07T07:54:30.563

noooooo not the special characters! I've had to edit my Ruby answer to accommodate for them as well, now. – Value Ink – 2016-07-07T08:09:34.490

1

J, 25 bytes

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

Usage

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

Explanation

(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

miles

Posted 2016-07-01T15:44:59.530

Reputation: 15 654

1

Bash, 58 bytes

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

Caution: This creates a temporary file named t. If it already exists, it will be overwritten.

Dennis

Posted 2016-07-01T15:44:59.530

Reputation: 196 637

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

This is not the most short, but quite efficient implementation. In essence it uses double-linked list to maintain ordered set of candidate characters and scans input string just once. Returns character code or zero if none found.

A little bit ungolfed version:

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

Posted 2016-07-01T15:44:59.530

Reputation: 711

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

Posted 2016-07-01T15:44:59.530

Reputation: 151

1

TSQL, 128 bytes

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)

Fiddle

t-clausen.dk

Posted 2016-07-01T15:44:59.530

Reputation: 2 874

1

Ruby, 53 bytes

Input is STDIN, output is STDOUT. In Ruby, out-of-index positions in an array or string return nil, which is not printed.

String#count is a strange function in Ruby because instead of counting the number of occurrences for the string that was passed in, it counts the number of occurrences for each letter in that string. It's usually annoying but we can use it to our advantage this time. String#swapcase swaps upper and lower case letters.

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

Old version that wasn't safe against special characters like . - 46 bytes

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

Value Ink

Posted 2016-07-01T15:44:59.530

Reputation: 10 608

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.. Dang I was bad at golfing back then. ;)

Explanation:

Try it here.

(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

Posted 2016-07-01T15:44:59.530

Reputation: 67 575

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))""))

Ough, I hope there is a more succinct way.

NikoNyrh

Posted 2016-07-01T15:44:59.530

Reputation: 2 361

0

JavaScript, 57 bytes

v=>(v+'\0'+v).replace(/(.)(?=.*\1.*\1)|\0.*/gi,"")[1]||""

JavaScript doesn't have Regex lookbehind, so I appended a null character and another copy of the string so that I can use lookahead. I then remove the null character and all characters after it as part of the regex replace.

Grax32

Posted 2016-07-01T15:44:59.530

Reputation: 1 282

0

PowerShell, 55 Bytes

old but good challenge, deserves a PS answer.

([char[]]"$args".ToLower()|group|? Count -eq 1)[1].Name

Throws errors when there are no non-repeating chars, exits with no error or return if there is only one repeating char.

the .ToLower() cost a bit due to the case insensitivity, and using |% ToL*r actually costs bytes since you need to wrap it all in brackets before converting to a char[]

colsw

Posted 2016-07-01T15:44:59.530

Reputation: 3 195

0

PHP, 76 bytes

for($a=$argn;~$c=$a[$i++];)stripos($a,$c)<strripos($a,$c)?:$r.=$c;echo$r[1];

Try it online!

Jörg Hülsermann

Posted 2016-07-01T15:44:59.530

Reputation: 13 026

0

Java (OpenJDK 8), 133 131 bytes

s->{String t=s.toUpperCase();int[]i=t.chars().filter(c->t.indexOf(c)==t.lastIndexOf(c)).toArray();return(char)(i.length>1?i[1]:0);}

Try it online!

Bashful Beluga

Posted 2016-07-01T15:44:59.530

Reputation: 413

0

Pyth, 17 bytes

Jrz1.x.(fq/JT1J1k

Test suite

Python 3 translation:
J=input().upper()
try:
    print([T for T in J if J.count(T)==1][1])
except:
    print()

hakr14

Posted 2016-07-01T15:44:59.530

Reputation: 1 295

0

05AB1E, 9 bytes

l©ʒ®s¢}¦¬

Try it online or verify all test cases.

Explanation:

l©           # Take the lowercase input, and store it in the register
  ʒ   }      # Filter the characters by:
   ®s¢       #  Keep those with an occurrence-count in this lowercase input of exactly 1
       ¦     # Remove the first character
        ¬    # And then take the head (which we implicitly output)

Kevin Cruijssen

Posted 2016-07-01T15:44:59.530

Reputation: 67 575

0

Jelly, 15 bytes

Œlµċ@Ị¥Ðf¹ḊḢȯ“”

Try it online!

Verify all testcases. (Slightly modified to cater for all testcases)

Leaky Nun

Posted 2016-07-01T15:44:59.530

Reputation: 45 011

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

Posted 2016-07-01T15:44:59.530

Reputation: 419

0

Javascript (using external Library) (107 bytes)

Crushed this using a library I wrote. Not sure if I have to count the declaration of variable "s", which is the string in question.

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

This will handle an empty string input, an input with only one non-repeating character, and an input with 2+ non-repeating characters

Image 1

applejacks01

Posted 2016-07-01T15:44:59.530

Reputation: 989

Do you have a link to the library in question? Also, this being code golf, you gotta take out whitespace where you can – Value Ink – 2016-07-07T00:24:16.027

Hey, yeah it's https://github.com/mvegh1/Enumerable . No docs yet. Sorry, I will clean up this answer to reduce as much whitespace

– applejacks01 – 2016-07-07T00:25:56.083

You should probably mention and link it in the answer body. Also, regarding the bytecount, consensus is to put it into an anonymous lambda (so s=> ...) – Value Ink – 2016-07-07T00:41:56.677

Ok no problem. I didn't want to offend anybody by linking to my code, but I did mention I used my library. I'll update my answer with the lambda, thanks for letting me know – applejacks01 – 2016-07-07T00:45:03.403