I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Determine if a string has all unique characters

Determine if a string has all unique characters
You are encouraged to solve this task according to the task description, using any language you may know.

Given a character string   (which may be empty, or have a length of zero characters):

•   create a function/procedure/routine to:
•   determine if all the characters in the string are unique
•   indicate if or which character is duplicated and where
•   display each string and its length   (as the strings are being examined)
•   a zero─length (empty) string shall be considered as unique
•   process the strings from left─to─right
•   if       unique,   display a message saying such
•   if not unique,   then:
•   display a message saying such
•   display what character is duplicated
•   only the 1st non─unique character need be displayed
•   display where "both" duplicated characters are in the string
•   the above messages can be part of a single message
•   display the hexadecimal value of the duplicated character

Use (at least) these five test values   (strings):

•   a string of length     0   (an empty string)
•   a string of length     1   which is a single period   (.)
•   a string of length     6   which contains:   abcABC
•   a string of length     7   which contains a blank in the middle:   XYZ  ZYX
•   a string of length   36   which   doesn't   contain the letter "oh":
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ

`with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;with Ada.Text_IO; use Ada.Text_IO;procedure Test_All_Chars_Unique is   procedure All_Chars_Unique (S : in String) is   begin      Put_Line ("Input = """ & S & """, length =" & S'Length'Image);      for I in S'First .. S'Last - 1 loop         for J in I + 1 .. S'Last loop            if S(I) = S(J) then               Put (" First duplicate at positions" & I'Image &                    " and" & J'Image & ", character = '" & S(I) &                    "', hex = ");               Put (Character'Pos (S(I)), Width => 0, Base => 16);               New_Line;               return;            end if;         end loop;      end loop;      Put_Line (" All characters are unique.");   end All_Chars_Unique;begin   All_Chars_Unique ("");   All_Chars_Unique (".");   All_Chars_Unique ("abcABC");   All_Chars_Unique ("XYZ ZYX");   All_Chars_Unique ("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");end Test_All_Chars_Unique; `
Output:
```Input = "", length = 0
All characters are unique.
Input = ".", length = 1
All characters are unique.
Input = "abcABC", length = 6
All characters are unique.
Input = "XYZ ZYX", length = 7
First duplicate at positions 1 and 7, character = 'X', hex = 16#58#
Input = "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ", length = 36
First duplicate at positions 10 and 25, character = '0', hex = 16#30#```

## ALGOL 68

`BEGIN    # mode to hold the positions of duplicate characters in a string      #    MODE DUPLICATE = STRUCT( INT original, first duplicate );     # finds the first non-unique character in s and returns its position  #    # and the position of the original character in a DUPLICATE           #    # if all characters in s are uniue, returns LWB s - 1, UPB s + 1      #    PROC first duplicate position = ( STRING s )DUPLICATE:    BEGIN        BOOL all unique := TRUE;        INT  o pos      := LWB s - 1;        INT  d pos      := UPB s + 1;        FOR i FROM LWB s TO UPB s WHILE all unique DO            FOR j FROM i + 1 TO UPB s WHILE all unique DO                IF NOT ( all unique := s[ i ] /= s[ j ] ) THEN                    o pos := i;                    d pos := j                FI            OD        OD;        DUPLICATE( o pos, d pos )    END # first duplicate position # ;    # task test cases                                                     #    []STRING tests = ( "", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" );    FOR t pos FROM LWB tests TO UPB tests DO        IF  STRING s    = tests[ t pos ];            DUPLICATE d = first duplicate position( s );            print( ( "<<<", s, ">>> (length ", whole( ( UPB s + 1 ) - LWB s, 0 ), "): " ) );            original OF d < LWB s        THEN            print( ( " all characters are unique", newline ) )        ELSE            # have at least one duplicate #            print( ( " first duplicate character: """, s[ original OF d ], """"                   , " at: ", whole( original OF d, 0 ), " and ", whole( first duplicate OF d, 0 )                   , newline                   )                 )        FI    ODEND`
Output:
```<<<>>> (length 0):  all characters are unique
<<<.>>> (length 1):  all characters are unique
<<<abcABC>>> (length 6):  all characters are unique
<<<XYZ ZYX>>> (length 7):  first duplicate character: "X" at: 1 and 7
<<<1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ>>> (length 36):  first duplicate character: "0" at: 10 and 25
```

## AppleScript

Following AppleScript's convention of one-based indices:

Translation of: Python
Translation of: JavaScript
`use AppleScript version "2.4"use framework "Foundation"use scripting additions on run    script showSource        on |λ|(s)            quoted("'", s) & " (" & length of s & ")"        end |λ|    end script     script showDuplicate        on |λ|(mb)            script go                on |λ|(tpl)                    set {c, ixs} to tpl                    quoted("'", c) & " at " & intercalate(", ", ixs)                end |λ|            end script            maybe("None", go, mb)        end |λ|    end script     fTable("Indices (1-based) of any duplicated characters:\n", ¬        showSource, showDuplicate, ¬        duplicatedCharIndices, ¬        {"", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"})end run  ------------------CHARACTER DUPLICATIONS------------------- -- duplicatedCharIndices :: String -> Maybe (Char, [Int])on duplicatedCharIndices(s)    script positionRecord        on |λ|(dct, c, i)            set k to (id of c) as string            script additional                on |λ|(xs)                    insertDict(k, xs & i, dct)                end |λ|            end script            maybe(insertDict(k, {i}, dct), additional, lookupDict(k, dct))        end |λ|    end script     script firstDuplication        on |λ|(sofar, idxs)            set {iCode, xs} to idxs            if 1 < length of xs then                script earliest                    on |λ|(kxs)                        if item 1 of xs < (item 1 of (item 2 of kxs)) then                            Just({chr(iCode), xs})                        else                            sofar                        end if                    end |λ|                end script                maybe(Just({chr(iCode), xs}), earliest, sofar)            else                sofar            end if        end |λ|    end script     foldl(firstDuplication, Nothing(), ¬        assocs(foldl(positionRecord, {name:""}, chars(s))))end duplicatedCharIndices  --------------------------GENERIC-------------------------- -- Just :: a -> Maybe aon Just(x)    -- Constructor for an inhabited Maybe (option type) value.    -- Wrapper containing the result of a computation.    {type:"Maybe", Nothing:false, Just:x}end Just -- Nothing :: Maybe aon Nothing()    -- Constructor for an empty Maybe (option type) value.    -- Empty wrapper returned where a computation is not possible.    {type:"Maybe", Nothing:true}end Nothing -- Tuple (,) :: a -> b -> (a, b)on Tuple(a, b)    -- Constructor for a pair of values, possibly of two different types.    {type:"Tuple", |1|:a, |2|:b, length:2}end Tuple -- assocs :: Map k a -> [(k, a)]on assocs(m)    script go        on |λ|(k)            set mb to lookupDict(k, m)            if true = |Nothing| of mb then                {}            else                {{k, |Just| of mb}}            end if        end |λ|    end script    concatMap(go, keys(m))end assocs -- keys :: Dict -> [String]on keys(rec)    (current application's ¬        NSDictionary's dictionaryWithDictionary:rec)'s allKeys() as listend keys -- chr :: Int -> Charon chr(n)    character id nend chr -- chars :: String -> [Char]on chars(s)    characters of send chars -- compose (<<<) :: (b -> c) -> (a -> b) -> a -> con compose(f, g)    script        property mf : mReturn(f)        property mg : mReturn(g)        on |λ|(x)            mf's |λ|(mg's |λ|(x))        end |λ|    end scriptend compose -- concatMap :: (a -> [b]) -> [a] -> [b]on concatMap(f, xs)    set lng to length of xs    set acc to {}    tell mReturn(f)        repeat with i from 1 to lng            set acc to acc & (|λ|(item i of xs, i, xs))        end repeat    end tell    return accend concatMap -- enumFromTo :: Int -> Int -> [Int]on enumFromTo(m, n)    if m ≤ n then        set lst to {}        repeat with i from m to n            set end of lst to i        end repeat        lst    else        {}    end ifend enumFromTo -- foldl :: (a -> b -> a) -> a -> [b] -> aon foldl(f, startValue, xs)    tell mReturn(f)        set v to startValue        set lng to length of xs        repeat with i from 1 to lng            set v to |λ|(v, item i of xs, i, xs)        end repeat        return v    end tellend foldl -- fst :: (a, b) -> aon fst(tpl)    if class of tpl is record then        |1| of tpl    else        item 1 of tpl    end ifend fst -- fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> Stringon fTable(s, xShow, fxShow, f, xs)    set ys to map(xShow, xs)    set w to maximum(map(my |length|, ys))    script arrowed        on |λ|(a, b)            justifyRight(w, space, a) & " -> " & b        end |λ|    end script    s & linefeed & unlines(zipWith(arrowed, ¬        ys, map(compose(fxShow, f), xs)))end fTable -- insertDict :: String -> a -> Dict -> Dicton insertDict(k, v, rec)    tell current application        tell dictionaryWithDictionary_(rec) of its NSMutableDictionary            its setValue:v forKey:(k as string)            it as record        end tell    end tellend insertDict -- intercalate :: String -> [String] -> Stringon intercalate(delim, xs)    set {dlm, my text item delimiters} to ¬        {my text item delimiters, delim}    set str to xs as text    set my text item delimiters to dlm    strend intercalate -- justifyRight :: Int -> Char -> String -> Stringon justifyRight(n, cFiller, strText)    if n > length of strText then        text -n thru -1 of ((replicate(n, cFiller) as text) & strText)    else        strText    end ifend justifyRight -- length :: [a] -> Inton |length|(xs)    set c to class of xs    if list is c or string is c then        length of xs    else        (2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)    end ifend |length| -- lookupDict :: a -> Dict -> Maybe bon lookupDict(k, dct)    -- Just the value of k in the dictionary,    -- or Nothing if k is not found.    set ca to current application    set v to (ca's NSDictionary's dictionaryWithDictionary:dct)'s objectForKey:k    if missing value ≠ v then        Just(item 1 of ((ca's NSArray's arrayWithObject:v) as list))    else        Nothing()    end ifend lookupDict -- map :: (a -> b) -> [a] -> [b]on map(f, xs)    -- The list obtained by applying f    -- to each element of xs.    tell mReturn(f)        set lng to length of xs        set lst to {}        repeat with i from 1 to lng            set end of lst to |λ|(item i of xs, i, xs)        end repeat        return lst    end tellend map -- maximum :: Ord a => [a] -> aon maximum(xs)    script        on |λ|(a, b)            if a is missing value or b > a then                b            else                a            end if        end |λ|    end script     foldl(result, missing value, xs)end maximum -- maybe :: b -> (a -> b) -> Maybe a -> bon maybe(v, f, mb)    -- The 'maybe' function takes a default value, a function, and a 'Maybe'    -- value.  If the 'Maybe' value is 'Nothing', the function returns the    -- default value.  Otherwise, it applies the function to the value inside    -- the 'Just' and returns the result.    if Nothing of mb then        v    else        tell mReturn(f) to |λ|(Just of mb)    end ifend maybe -- min :: Ord a => a -> a -> aon min(x, y)    if y < x then        y    else        x    end ifend min -- mReturn :: First-class m => (a -> b) -> m (a -> b)on mReturn(f)    -- 2nd class handler function lifted into 1st class script wrapper.     if script is class of f then        f    else        script            property |λ| : f        end script    end ifend mReturn -- quoted :: Char -> String -> Stringon quoted(c, s)    -- string flanked on both sides    -- by a specified quote character.    c & s & cend quoted -- Egyptian multiplication - progressively doubling a list, appending-- stages of doubling to an accumulator where needed for binary -- assembly of a target length-- replicate :: Int -> a -> [a]on replicate(n, a)    set out to {}    if 1 > n then return out    set dbl to {a}     repeat while (1 < n)        if 0 < (n mod 2) then set out to out & dbl        set n to (n div 2)        set dbl to (dbl & dbl)    end repeat    return out & dblend replicate -- take :: Int -> [a] -> [a]-- take :: Int -> String -> Stringon take(n, xs)    set c to class of xs    if list is c then        if 0 < n then            items 1 thru min(n, length of xs) of xs        else            {}        end if    else if string is c then        if 0 < n then            text 1 thru min(n, length of xs) of xs        else            ""        end if    else if script is c then        set ys to {}        repeat with i from 1 to n            set v to |λ|() of xs            if missing value is v then                return ys            else                set end of ys to v            end if        end repeat        return ys    else        missing value    end ifend take -- unlines :: [String] -> Stringon unlines(xs)    -- A single string formed by the intercalation    -- of a list of strings with the newline character.    set {dlm, my text item delimiters} to ¬        {my text item delimiters, linefeed}    set str to xs as text    set my text item delimiters to dlm    strend unlines -- zip :: [a] -> [b] -> [(a, b)]on zip(xs, ys)    zipWith(Tuple, xs, ys)end zip -- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]on zipWith(f, xs, ys)    set lng to min(|length|(xs), |length|(ys))    if 1 > lng then return {}    set xs_ to take(lng, xs) -- Allow for non-finite    set ys_ to take(lng, ys) -- generators like cycle etc    set lst to {}    tell mReturn(f)        repeat with i from 1 to lng            set end of lst to |λ|(item i of xs_, item i of ys_)        end repeat        return lst    end tellend zipWith`
Output:
```Indices (1-based) of any duplicated characters:

'' (0) -> None
'.' (1) -> None
'abcABC' (6) -> None
'XYZ ZYX' (7) -> 'X' at 1, 7
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (36) -> '0' at 10, 25```

## AWK

` # syntax: GAWK -f DETERMINE_IF_A_STRING_HAS_ALL_UNIQUE_CHARACTERS.AWKBEGIN {    for (i=0; i<=255; i++) { ord_arr[sprintf("%c",i)] = i } # build array[character]=ordinal_value    n = split(",.,abcABC,XYZ ZYX,1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",arr,",")    for (i in arr) {      width = max(width,length(arr[i]))    }    width += 2    fmt = "| %-*s | %-6s | %-10s | %-8s | %-3s | %-9s |\n"    head1 = head2 = sprintf(fmt,width,"string","length","all unique","1st diff","hex","positions")    gsub(/[^|\n]/,"-",head1)    printf(head1 head2 head1) # column headings    for (i=1; i<=n; i++) {      main(arr[i])    }    printf(head1) # column footing    exit(0)}function main(str,  c,hex,i,leng,msg,position1,position2,tmp_arr) {    msg = "yes"    leng = length(str)    for (i=1; i<=leng; i++) {      c = substr(str,i,1)      if (c in tmp_arr) {        msg = "no"        first_diff = "'" c "'"        hex = sprintf("%2X",ord_arr[c])        position1 = index(str,c)        position2 = i        break      }      tmp_arr[c] = ""    }    printf(fmt,width,"'" str "'",leng,msg,first_diff,hex,position1 " " position2)}function max(x,y) { return((x > y) ? x : y) } `
Output:
```|----------------------------------------|--------|------------|----------|-----|-----------|
| string                                 | length | all unique | 1st diff | hex | positions |
|----------------------------------------|--------|------------|----------|-----|-----------|
| ''                                     | 0      | yes        |          |     |           |
| '.'                                    | 1      | yes        |          |     |           |
| 'abcABC'                               | 6      | yes        |          |     |           |
| 'XYZ ZYX'                              | 7      | no         | 'Z'      | 5A  | 3 5       |
| '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' | 36     | no         | '0'      | 30  | 10 25     |
|----------------------------------------|--------|------------|----------|-----|-----------|
```

## C

In interactive mode, strings with spaces have to be enclosed in double quotes ("")

` #include<stdbool.h>#include<string.h>#include<stdlib.h>#include<stdio.h> typedef struct positionList{    int position;    struct positionList *next;}positionList; typedef struct letterList{    char letter;    int repititions;    positionList* positions;    struct letterList *next;}letterList; letterList* letterSet;bool duplicatesFound = false; void checkAndUpdateLetterList(char c,int pos){    bool letterOccurs = false;    letterList *letterIterator,*newLetter;    positionList *positionIterator,*newPosition;     if(letterSet==NULL){        letterSet = (letterList*)malloc(sizeof(letterList));        letterSet->letter = c;        letterSet->repititions = 0;         letterSet->positions = (positionList*)malloc(sizeof(positionList));        letterSet->positions->position = pos;        letterSet->positions->next = NULL;         letterSet->next = NULL;    }     else{        letterIterator = letterSet;         while(letterIterator!=NULL){            if(letterIterator->letter==c){                letterOccurs = true;                duplicatesFound = true;                 letterIterator->repititions++;                positionIterator = letterIterator->positions;                 while(positionIterator->next!=NULL)                    positionIterator = positionIterator->next;                 newPosition = (positionList*)malloc(sizeof(positionList));                newPosition->position = pos;                newPosition->next = NULL;                 positionIterator->next = newPosition;            }            if(letterOccurs==false && letterIterator->next==NULL)                break;            else                letterIterator = letterIterator->next;        }         if(letterOccurs==false){            newLetter = (letterList*)malloc(sizeof(letterList));            newLetter->letter = c;             newLetter->repititions = 0;             newLetter->positions = (positionList*)malloc(sizeof(positionList));            newLetter->positions->position = pos;            newLetter->positions->next = NULL;             newLetter->next = NULL;             letterIterator->next = newLetter;        }     }} void printLetterList(){    positionList* positionIterator;    letterList* letterIterator = letterSet;     while(letterIterator!=NULL){        if(letterIterator->repititions>0){            printf("\n'%c' (0x%x) at positions :",letterIterator->letter,letterIterator->letter);             positionIterator = letterIterator->positions;             while(positionIterator!=NULL){                printf("%3d",positionIterator->position + 1);                positionIterator = positionIterator->next;            }        }         letterIterator = letterIterator->next;    }    printf("\n");} int main(int argc,char** argv){    int i,len;     if(argc>2){        printf("Usage : %s <Test string>\n",argv);        return 0;    }     if(argc==1||strlen(argv)==1){        printf("\"%s\" - Length %d - Contains only unique characters.\n",argc==1?"":argv,argc==1?0:1);        return 0;    }     len = strlen(argv);     for(i=0;i<len;i++){        checkAndUpdateLetterList(argv[i],i);    }     printf("\"%s\" - Length %d - %s",argv,len,duplicatesFound==false?"Contains only unique characters.\n":"Contains the following duplicate characters :");     if(duplicatesFound==true)        printLetterList();     return 0;} `

Output, test strings from the task Determine_if_a_string_has_all_the_same_characters are also included :

```[email protected]:~/doodles\$ ./a.out
"" - Length 0 - Contains only unique characters.
[email protected]:~/doodles\$ ./a.out .
"." - Length 1 - Contains only unique characters.
[email protected]:~/doodles\$ ./a.out abcABC
"abcABC" - Length 6 - Contains only unique characters.
[email protected]:~/doodles\$ ./a.out "XYZ YZX"
"XYZ YZX" - Length 7 - Contains the following duplicate characters :
'X' (0x58) at positions :  1  7
'Y' (0x59) at positions :  2  5
'Z' (0x5a) at positions :  3  6
abhishek_ghosh[email protected]:~/doodles\$ ./a.out 1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" - Length 36 - Contains the following duplicate characters :
'0' (0x30) at positions : 10 25
[email protected]:~/doodles\$ ./a.out "   "
"   " - Length 3 - Contains the following duplicate characters :
' ' (0x20) at positions :  1  2  3
[email protected]:~/doodles\$ ./a.out 2
"2" - Length 1 - Contains only unique characters.
[email protected]:~/doodles\$ ./a.out 333
"333" - Length 3 - Contains the following duplicate characters :
'3' (0x33) at positions :  1  2  3
[email protected]:~/doodles\$ ./a.out .55
".55" - Length 3 - Contains the following duplicate characters :
'5' (0x35) at positions :  2  3
[email protected]:~/doodles\$ ./a.out tttTTT
"tttTTT" - Length 6 - Contains the following duplicate characters :
't' (0x74) at positions :  1  2  3
'T' (0x54) at positions :  4  5  6
[email protected]:~/doodles\$ ./a.out "4444 444k"
"4444 444k" - Length 9 - Contains the following duplicate characters :
'4' (0x34) at positions :  1  2  3  4  6  7  8
```

## C#

`using System;using System.Linq; public class Program{    static void Main    {        string[] input = {"", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"};        foreach (string s in input) {            Console.WriteLine(\$"\"{s}\" (Length {s.Length}) " +                string.Join(", ",                    s.Select((c, i) => (c, i))                    .GroupBy(t => t.c).Where(g => g.Count() > 1)                    .Select(g => \$"'{g.Key}' (0X{(int)g.Key:X})[{string.Join(", ", g.Select(t => t.i))}]")                    .DefaultIfEmpty("All characters are unique.")                )            );        }    }}`
Output:
```"" (Length 0) All characters are unique.
"." (Length 1) All characters are unique.
"abcABC" (Length 6) All characters are unique.
"XYZ ZYX" (Length 7) 'X'(0X58) [0, 6], 'Y'(0X59) [1, 5], 'Z'(0X5A) [2, 4]
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (Length 36) '0'(0X30) [9, 24]
```

## C++

`#include <iostream>#include <string> void string_has_repeated_character(const std::string& str) {    size_t len = str.length();    std::cout << "input: \"" << str << "\", length: " << len << '\n';    for (size_t i = 0; i < len; ++i) {        for (size_t j = i + 1; j < len; ++j) {            if (str[i] == str[j]) {                std::cout << "String contains a repeated character.\n";                std::cout << "Character '" << str[i]                    << "' (hex " << std::hex << static_cast<unsigned int>(str[i])                    << ") occurs at positions " << std::dec << i + 1                    << " and " << j + 1 << ".\n\n";                return;            }        }    }    std::cout << "String contains no repeated characters.\n\n";} int main() {    string_has_repeated_character("");    string_has_repeated_character(".");    string_has_repeated_character("abcABC");    string_has_repeated_character("XYZ ZYX");    string_has_repeated_character("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");    return 0;}`
Output:
```input: "", length: 0
String contains no repeated characters.

input: ".", length: 1
String contains no repeated characters.

input: "abcABC", length: 6
String contains no repeated characters.

input: "XYZ ZYX", length: 7
String contains a repeated character.
Character 'X' (hex 58) occurs at positions 1 and 7.

input: "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ", length: 36
String contains a repeated character.
Character '0' (hex 30) occurs at positions 10 and 25.

```

## Clojure

` (defn uniq-char-string [s]  (let [len (count s)]    (if (= len (count (set s)))      (println (format "All %d chars unique in: '%s'" len s))      (loop [prev-chars #{}             idx   0             chars (vec s)]        (let [c (first chars)]          (if (contains? prev-chars c)            (println (format "'%s' (len: %d) has '%c' duplicated at idx: %d"                             s len c idx))            (recur (conj prev-chars c)                   (inc idx)                   (rest chars)))))))) `
Output:
```All 0 chars unique in: ''
All 1 chars unique in: '.'
All 6 chars unique in: 'abcABC'
'XYZ ZYX' (len: 7) has 'Z' duplicated at idx: 4
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (len: 36) has '0' duplicated at idx: 24
All 4 chars unique in: 'asdf'
'asdfas' (len: 6) has 'a' duplicated at idx: 4
'foofoo' (len: 6) has 'o' duplicated at idx: 2
'foOfoo' (len: 6) has 'f' duplicated at idx: 3
```

## Common Lisp

`;; * Loading the iterate library(eval-when (:compile-toplevel :load-toplevel)  (ql:quickload '("iterate"))) ;; * The package definition(defpackage :unique-string  (:use :common-lisp :iterate))(in-package :unique-string) ;; * The test strings(defparameter test-strings  '("" "." "abcABC" "XYZ ZYX" "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")) ;; * The function(defun unique-string (string)  "Returns T if STRING has all unique characters."  (iter    (with hash = (make-hash-table :test #'equal))    (with len = (length string))    (with result = T)    (for char in-string string)    (for pos  from 0)    (initially (format t "String ~a of length ~D~%" string len))    (if #1=(gethash char hash)        ;; The character was seen before        (progn          (format t                  " --> Non-unique character ~c #X~X found at position ~D,                  before ~D ~%" char (char-code char) pos #1#)          (setf result nil))        ;; The character was not seen before, saving its position        (setf #1# pos))    (finally (when result               (format t " --> All characters are unique~%"))             (return result)))) (mapcar #'unique-string test-strings)`
Output:
```String  of length 0
--> All characters are unique
String . of length 1
--> All characters are unique
String abcABC of length 6
--> All characters are unique
String XYZ ZYX of length 7
--> Non-unique character Z #X5A found at position 4,
before 2
--> Non-unique character Y #X59 found at position 5,
before 1
--> Non-unique character X #X58 found at position 6,
before 0
String 1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ of length 36
--> Non-unique character 0 #X30 found at position 24,
before 9```

## D

Translation of: C++
`import std.stdio; void uniqueCharacters(string str) {    writefln("input: `%s`, length: %d", str, str.length);    foreach (i; 0 .. str.length) {        foreach (j; i + 1 .. str.length) {            if (str[i] == str[j]) {                writeln("String contains a repeated character.");                writefln("Character '%c' (hex %x) occurs at positions %d and %d.", str[i], str[i], i + 1, j + 1);                writeln;                return;            }        }    }    writeln("String contains no repeated characters.");    writeln;} void main() {    uniqueCharacters("");    uniqueCharacters(".");    uniqueCharacters("abcABC");    uniqueCharacters("XYZ ZYX");    uniqueCharacters("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");}`
Output:
```input: ``, length: 0
String contains no repeated characters.

input: `.`, length: 1
String contains no repeated characters.

input: `abcABC`, length: 6
String contains no repeated characters.

input: `XYZ ZYX`, length: 7
String contains a repeated character.
Character 'X' (hex 58) occurs at positions 1 and 7.

input: `1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ`, length: 36
String contains a repeated character.
Character '0' (hex 30) occurs at positions 10 and 25.```

## F#

` // Determine if a string has all unique characters. Nigel Galloway: June 9th., 2020let fN (n:string)=n.ToCharArray()|>Array.mapi(fun n g->(n,g))|>Array.groupBy(fun (_,n)->n)|>Array.filter(fun(_,n)->n.Length>1) let allUnique n=match fN n with                 g when g.Length=0->printfn "All charcters in <<<%s>>> (length %d) are unique" n n.Length                |g->Array.iter(fun(n,g)->printf "%A is repeated at positions" n; Array.iter(fun(n,_)->printf " %d" n)g;printf " ")g                    printfn "in <<<%s>>> (length %d)" n n.Length allUnique ""allUnique "."allUnique "abcABC"allUnique "XYZ ZYX"allUnique "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" `
Output:
```All charcters in <<<>>> (length 0) are unique
All charcters in <<<.>>> (length 1) are unique
All charcters in <<<abcABC>>> (length 6) are unique
'X' is repeated at positions 0 6 'Y' is repeated at positions 1 5 'Z' is repeated at positions 2 4 in <<<XYZ ZYX>>> (length 7)
'0' is repeated at positions 9 24 in <<<1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ>>> (length 36)
```

## Factor

`USING: formatting fry generalizations io kernel math.parsersequences sets ; : repeated ( elt seq -- )    [ dup >hex over ] dip indices first2    "  '%c' (0x%s) at indices %d and %d.\n" printf ; : uniqueness-report ( str -- )    dup dup length "%u — length %d — contains " printf    [ duplicates ] keep over empty?    [ 2drop "all unique characters." print ]    [ "repeated characters:" print '[ _ repeated ] each ] if ; """.""abcABC""XYZ ZYX""1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"[ uniqueness-report nl ] 5 napply`
Output:
```"" — length 0 — contains all unique characters.

"." — length 1 — contains all unique characters.

"abcABC" — length 6 — contains all unique characters.

"XYZ ZYX" — length 7 — contains repeated characters:
'Z' (0x5a) at indices 2 and 4.
'Y' (0x59) at indices 1 and 5.
'X' (0x58) at indices 0 and 6.

"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" — length 36 — contains repeated characters:
'0' (0x30) at indices 9 and 24.
```

## Go

`package main import "fmt" func analyze(s string) {    chars := []rune(s)    le := len(chars)    fmt.Printf("Analyzing %q which has a length of %d:\n", s, le)    if le > 1 {        for i := 0; i < le-1; i++ {            for j := i + 1; j < le; j++ {                if chars[j] == chars[i] {                    fmt.Println("  Not all characters in the string are unique.")                    fmt.Printf("  %q (%#x) is duplicated at positions %d and %d.\n\n", chars[i], i+1, j+1)                    return                }            }        }    }    fmt.Println("  All characters in the string are unique.\n")} func main() {    strings := []string{        "",        ".",        "abcABC",        "XYZ ZYX",        "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",        "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",        "hétérogénéité",        "🎆🎃🎇🎈",        "😍😀🙌💃😍🙌",        "🐠🐟🐡🦈🐬🐳🐋🐡",    }    for _, s := range strings {        analyze(s)    }}`
Output:
```Analyzing "" which has a length of 0:
All characters in the string are unique.

Analyzing "." which has a length of 1:
All characters in the string are unique.

Analyzing "abcABC" which has a length of 6:
All characters in the string are unique.

Analyzing "XYZ ZYX" which has a length of 7:
Not all characters in the string are unique.
'X' (0x58) is duplicated at positions 1 and 7.

Analyzing "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" which has a length of 36:
Not all characters in the string are unique.
'0' (0x30) is duplicated at positions 10 and 25.

Analyzing "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" which has a length of 39:
Not all characters in the string are unique.
'0' (0x30) is duplicated at positions 1 and 11.

Analyzing "hétérogénéité" which has a length of 13:
Not all characters in the string are unique.
'é' (0xe9) is duplicated at positions 2 and 4.

Analyzing "🎆🎃🎇🎈" which has a length of 4:
All characters in the string are unique.

Analyzing "😍😀🙌💃😍🙌" which has a length of 6:
Not all characters in the string are unique.
'😍' (0x1f60d) is duplicated at positions 1 and 5.

Analyzing "🐠🐟🐡🦈🐬🐳🐋🐡" which has a length of 8:
Not all characters in the string are unique.
'🐡' (0x1f421) is duplicated at positions 3 and 8.
```

`import Data.List (groupBy, intersperse, sort, transpose)import Data.Char (ord, toUpper)import Numeric (showHex) hexFromChar :: Char -> StringhexFromChar c = map toUpper \$ showHex (ord c) "" string :: String -> Stringstring xs = ('\"' : xs) ++ "\"" char :: Char -> Stringchar c = ['\'', c, '\''] size :: String -> Stringsize = show . length positions :: (Int, Int) -> Stringpositions (a, b) = show a ++ " " ++ show b forTable :: String -> [String]forTable xs = string xs : go (allUnique xs)  where    go Nothing = [size xs, "yes", "", "", ""]    go (Just (u, ij)) = [size xs, "no", char u, hexFromChar u, positions ij] showTable :: Bool -> Char -> Char -> Char -> [[String]] -> StringshowTable _ _ _ _ [] = []showTable header ver hor sep contents =  unlines \$  hr :  (if header     then z : hr : zs     else intersperse hr zss) ++  [hr]  where    vss = map (map length) contents    ms = map maximum (transpose vss) :: [Int]    hr = concatMap (\n -> sep : replicate n hor) ms ++ [sep]    top = replicate (length hr) hor    bss = map (map (`replicate` ' ') . zipWith (-) ms) vss    zss@(z:zs) =      zipWith        (\us bs -> concat (zipWith (\x y -> (ver : x) ++ y) us bs) ++ [ver])        contents        bss table xs =  showTable    True    '|'    '-'    '+'    (["string", "length", "all unique", "1st diff", "hex", "positions"] :     map forTable xs) allUnique  :: (Ord b, Ord a, Num b, Enum b)  => [a] -> Maybe (a, (b, b))allUnique xs = go . groupBy (\(x, _) (y, _) -> x == y) . sort . zip xs \$ [0 ..]  where    go [] = Nothing    go ([_]:us) = go us    go (((u, i):(_, j):_):_) = Just (u, (i, j)) main :: IO ()main =  putStrLn \$  table ["", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]`
Output:
```+--------------------------------------+------+----------+--------+---+---------+
|string                                |length|all unique|1st diff|hex|positions|
+--------------------------------------+------+----------+--------+---+---------+
|""                                    |0     |yes       |        |   |         |
|"."                                   |1     |yes       |        |   |         |
|"abcABC"                              |6     |yes       |        |   |         |
|"XYZ ZYX"                             |7     |no        |'X'     |58 |0 6      |
|"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"|36    |no        |'0'     |30 |9 24     |
+--------------------------------------+------+----------+--------+---+---------+```

Alternatively, defining a duplicatedCharIndices function in terms of sortOn, groupBy, and filter:

`import Data.List (groupBy, intercalate, sortOn)import Control.Arrow ((&&&))import Data.Function (on)import Numeric (showHex)import Data.Char (ord) duplicatedCharIndices :: String -> Maybe (Char, [Int])duplicatedCharIndices s  | null duplicates = Nothing  | otherwise =    Just \$ ((snd . head) &&& fmap fst) (head (sortOn (fst . head) duplicates))  where    duplicates =      filter ((1 <) . length) \$      groupBy (on (==) snd) \$ sortOn snd \$ zip [0 ..] s ---------------------------TEST----------------------------main :: IO ()main =  putStrLn \$  fTable    "First duplicated character, if any:"    ((++) <\$> show <*> ((" (" ++) . (++ ")") . show . length))    (maybe       "None"       (\(c, ixs) ->           unwords             [ show c             , "(0x" ++ showHex (ord c) ") at"             , intercalate ", " (show <\$> ixs)             ]))    duplicatedCharIndices    ["", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"] --------------------------DISPLAY--------------------------fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> StringfTable s xShow fxShow f xs =  let rjust n c = drop . length <*> (replicate n c ++)      w = maximum (length . xShow <\$> xs)  in unlines \$     s : fmap (((++) . rjust w ' ' . xShow) <*> ((" -> " ++) . fxShow . f)) xs`
Output:
```First duplicated character, if any:
"" (0) -> None
"." (1) -> None
"abcABC" (6) -> None
"XYZ ZYX" (7) -> 'X' (0x58) at 0, 6
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (36) -> '0' (0x30) at 9, 24```

Or, as an alternative to grouping and sorting – folding a string down to a Map of indices:

`import qualified Safe as Simport qualified Data.Map.Strict as Mimport Data.List (intercalate, foldl') --'import Data.Ord (comparing)import Numeric (showHex)import Data.Char (ord) duplicatedCharIndices :: String -> Maybe (Char, [Int])duplicatedCharIndices xs =  S.minimumByMay    (comparing (head . snd))    (M.toList       (M.filter          ((1 <) . length)          (foldl' --'             (\a (i, c) -> M.insert c (maybe [i] (++ [i]) (M.lookup c a)) a)             M.empty             (zip [0 ..] xs)))) -- OR, fusing filter, toList, and minimumByMay down to a single fold:duplicatedCharIndices_ :: String -> Maybe (Char, [Int])duplicatedCharIndices_ xs =  M.foldrWithKey    go    Nothing    (foldl' --'       (\a (i, c) -> M.insert c (maybe [i] (++ [i]) (M.lookup c a)) a)       M.empty       (zip [0 ..] xs))  where    go k [_] mb = mb -- Unique    go k xs Nothing = Just (k, xs) -- Duplicated    go k xs@(x:_) (Just (c, ys@(y:_)))      | x < y = Just (k, xs) -- Earlier duplication      | otherwise = Just (c, ys) ---------------------------TEST----------------------------main :: IO ()main =  putStrLn \$  fTable    "First duplicated character, if any:"    ((++) <\$> show <*> ((" (" ++) . (++ ")") . show . length))    (maybe       "None"       (\(c, ixs) ->           unwords             [ show c             , "(0x" ++ showHex (ord c) ") at"             , intercalate ", " (show <\$> ixs)             ]))    duplicatedCharIndices_    ["", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"] --------------------------DISPLAY--------------------------fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> StringfTable s xShow fxShow f xs =  unlines \$  s : fmap (((++) . rjust w ' ' . xShow) <*> ((" -> " ++) . fxShow . f)) xs  where    rjust n c = drop . length <*> (replicate n c ++)    w = maximum (length . xShow <\$> xs)`
Output:
```First duplicated character, if any:
"" (0) -> None
"." (1) -> None
"abcABC" (6) -> None
"XYZ ZYX" (7) -> 'X' (0x58) at 0, 6
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (36) -> '0' (0x30) at 9, 24```

## J

Quotes surround the literals to make the computed one-at-a-time results present well in the combined table.

` rc_unique=: monad define string=. '"' , y , '"' self_classification=. = y  NB. deprecated- consumes space proportional to the squared tally of y  (*: # y) is_unique=. self_classification =&# y if. is_unique do.  (# y) ; string ; 'unique' else.  duplicate_masks=. (#~ (1 < +/"1)) self_classification  duplicate_characters=. ~. y #~ +./ duplicate_masks  ASCII_values_of_duplicates=. a. i. duplicate_characters  markers=. duplicate_masks { ' ^'  A=. (# y) ; string , ' ' ,. markers  B=. 'duplicate' , ASCII_values_of_duplicates ('<' , (#~ 31&<)~ , '> ASCII ' , ":@:[)"0 duplicate_characters  A , < B end.) `

Tests include those of the C example and a pair of MS-DOS line terminations.

```   (;:'length string analysis') , rc_unique;._2';.;abcABC;XYZ YZX;1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ;   ;2;333;.55;tttTTT;4444 444k;',(4\$CRLF),';'
┌──────┬──────────────────────────────────────┬─────────────┐
│length│string                                │analysis     │
├──────┼──────────────────────────────────────┼─────────────┤
│0     │""                                    │unique       │
├──────┼──────────────────────────────────────┼─────────────┤
│1     │"."                                   │unique       │
├──────┼──────────────────────────────────────┼─────────────┤
│6     │"abcABC"                              │unique       │
├──────┼──────────────────────────────────────┼─────────────┤
│7     │"XYZ YZX"                             │duplicate    │
│      │ ^     ^                              │<X> ASCII 88 │
│      │  ^  ^                                │<Y> ASCII 89 │
│      │   ^  ^                               │<Z> ASCII 90 │
├──────┼──────────────────────────────────────┼─────────────┤
│36    │"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"│duplicate    │
│      │          ^              ^            │<0> ASCII 48 │
├──────┼──────────────────────────────────────┼─────────────┤
│3     │"   "                                 │duplicate    │
│      │ ^^^                                  │< > ASCII 32 │
├──────┼──────────────────────────────────────┼─────────────┤
│1     │"2"                                   │unique       │
├──────┼──────────────────────────────────────┼─────────────┤
│3     │"333"                                 │duplicate    │
│      │ ^^^                                  │<3> ASCII 51 │
├──────┼──────────────────────────────────────┼─────────────┤
│3     │".55"                                 │duplicate    │
│      │  ^^                                  │<5> ASCII 53 │
├──────┼──────────────────────────────────────┼─────────────┤
│6     │"tttTTT"                              │duplicate    │
│      │ ^^^                                  │<t> ASCII 116│
│      │    ^^^                               │<T> ASCII 84 │
├──────┼──────────────────────────────────────┼─────────────┤
│9     │"4444 444k"                           │duplicate    │
│      │ ^^^^ ^^^                             │<4> ASCII 52 │
├──────┼──────────────────────────────────────┼─────────────┤
│4     │"    "                                │duplicate    │
│      │ ^ ^                                  │<> ASCII 13  │
│      │  ^ ^                                 │<> ASCII 10  │
└──────┴──────────────────────────────────────┴─────────────┘
```

More uniqueness tests with performance comparison

` NB. unique_index answers "Do the left and right indexes match?"unique_index=: (i. -: i:)~assert 0 1 -: 2 unique_index\0 0 1 NB. unique_set answers "Are lengths of the nub and original equal?"unique_set=: -:&# ~.assert 0 1 -: _2 unique_set\'aab' NB. unique_nubsieve answers "Are the items unique?"unique_nubsieve=: 0 [email protected]:e. ~:assert 0 1 -: _2 unique_nubsieve\'aab' Note'compared to nubsieve'  the index method takes 131% longer and 15 times additional memory  the set formation method 15% longer and uses 7 times additional memory.) `

## Java

` import java.util.HashMap;import java.util.Map; //  Title:  Determine if a string has all unique characters public class StringUniqueCharacters {     public static void main(String[] args) {        System.out.printf("%-40s  %2s  %10s  %8s  %s  %s%n", "String", "Length", "All Unique", "1st Diff", "Hex", "Positions");        System.out.printf("%-40s  %2s  %10s  %8s  %s  %s%n", "------------------------", "------", "----------", "--------", "---", "---------");        for ( String s : new String[] {"", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"} ) {            processString(s);        }    }       private static void processString(String input) {        Map<Character,Integer> charMap = new HashMap<>();         char dup = 0;        int index = 0;        int pos1 = -1;        int pos2 = -1;        for ( char key : input.toCharArray() ) {            index++;            if ( charMap.containsKey(key) ) {                dup = key;                pos1 = charMap.get(key);                pos2 = index;                break;            }            charMap.put(key, index);        }        String unique = dup == 0 ? "yes" : "no";        String diff = dup == 0 ? "" : "'" + dup + "'";        String hex = dup == 0 ? "" : Integer.toHexString(dup).toUpperCase();        String position = dup == 0 ? "" : pos1 + " " + pos2;        System.out.printf("%-40s  %-6d  %-10s  %-8s  %-3s  %-5s%n", input, input.length(), unique, diff, hex, position);    } } `
Output:
```String                                    Length  All Unique  1st Diff  Hex  Positions
------------------------                  ------  ----------  --------  ---  ---------
0       yes
.                                         1       yes
abcABC                                    6       yes
XYZ ZYX                                   7       no          'Z'       5A   3 5
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ      36      no          '0'       30   10 25
```

## JavaScript

`(() => {    'use strict';     // duplicatedCharIndices :: String -> Maybe (Char, [Int])    const duplicatedCharIndices = s => {        const            duplicates = filter(g => 1 < g.length)(                groupBy(on(eq)(snd))(                    sortOn(snd)(                        zip(enumFrom(0))(chars(s))                    )                )            );        return 0 < duplicates.length ? Just(            fanArrow(compose(snd, fst))(map(fst))(                sortOn(compose(fst, fst))(                    duplicates                )            )        ) : Nothing();    };     // ------------------------TEST------------------------    const main = () =>        console.log(            fTable('First duplicated character, if any:')(                s => `'\${s}' (\${s.length})`            )(maybe('None')(tpl => {                const [c, ixs] = Array.from(tpl);                return `'\${c}' (0x\${showHex(ord(c))}) at \${ixs.join(', ')}`            }))(duplicatedCharIndices)([                "", ".", "abcABC", "XYZ ZYX",                "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"            ])        );      // -----------------GENERIC FUNCTIONS------------------     // Just :: a -> Maybe a    const Just = x => ({        type: 'Maybe',        Nothing: false,        Just: x    });     // Nothing :: Maybe a    const Nothing = () => ({        type: 'Maybe',        Nothing: true,    });     // Tuple (,) :: a -> b -> (a, b)    const Tuple = a => b => ({        type: 'Tuple',        '0': a,        '1': b,        length: 2    });     // chars :: String -> [Char]    const chars = s => s.split('');     // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c    const compose = (...fs) =>        x => fs.reduceRight((a, f) => f(a), x);     // enumFrom :: Enum a => a -> [a]    function* enumFrom(x) {        let v = x;        while (true) {            yield v;            v = 1 + v;        }    }     // eq (==) :: Eq a => a -> a -> Bool    const eq = a => b => a === b;     // fanArrow (&&&) :: (a -> b) -> (a -> c) -> (a -> (b, c))    const fanArrow = f =>        // Compose a function from a simple value to a tuple of        // the separate outputs of two different functions.        g => x => Tuple(f(x))(g(x));     // filter :: (a -> Bool) -> [a] -> [a]    const filter = f => xs => xs.filter(f);     // fst :: (a, b) -> a    const fst = tpl => tpl;     // fTable :: String -> (a -> String) -> (b -> String)    //                      -> (a -> b) -> [a] -> String    const fTable = s => xShow => fxShow => f => xs => {        // Heading -> x display function ->        //           fx display function ->        //    f -> values -> tabular string        const            ys = xs.map(xShow),            w = Math.max(...ys.map(length));        return s + '\n' + zipWith(            a => b => a.padStart(w, ' ') + ' -> ' + b        )(ys)(            xs.map(x => fxShow(f(x)))        ).join('\n');    };     // groupBy :: (a -> a -> Bool) -> [a] -> [[a]]    const groupBy = fEq =>        // Typical usage: groupBy(on(eq)(f), xs)        xs => 0 < xs.length ? (() => {            const                tpl = xs.slice(1).reduce(                    (gw, x) => {                        const                            gps = gw,                            wkg = gw;                        return fEq(wkg)(x) ? (                            Tuple(gps)(wkg.concat([x]))                        ) : Tuple(gps.concat([wkg]))([x]);                    },                    Tuple([])([xs])                );            return tpl.concat([tpl])        })() : [];     // length :: [a] -> Int    const length = xs =>        // Returns Infinity over objects without finite length.        // This enables zip and zipWith to choose the shorter        // argument when one is non-finite, like cycle, repeat etc        (Array.isArray(xs) || 'string' === typeof xs) ? (            xs.length        ) : Infinity;     // map :: (a -> b) -> [a] -> [b]    const map = f => xs =>        (Array.isArray(xs) ? (            xs        ) : xs.split('')).map(f);     // maybe :: b -> (a -> b) -> Maybe a -> b    const maybe = v =>        // Default value (v) if m is Nothing, or f(m.Just)        f => m => m.Nothing ? v : f(m.Just);     // on :: (b -> b -> c) -> (a -> b) -> a -> a -> c    const on = f =>        g => a => b => f(g(a))(g(b));     // ord :: Char -> Int    const ord = c => c.codePointAt(0);     // showHex :: Int -> String    const showHex = n =>        n.toString(16);     // snd :: (a, b) -> b    const snd = tpl => tpl;     // sortOn :: Ord b => (a -> b) -> [a] -> [a]    const sortOn = f =>        // Equivalent to sortBy(comparing(f)), but with f(x)        // evaluated only once for each x in xs.        // ('Schwartzian' decorate-sort-undecorate).        xs => xs.map(            x => [f(x), x]        ).sort(            (a, b) => a < b ? -1 : (a > b ? 1 : 0)        ).map(x => x);     // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n => xs =>        'GeneratorFunction' !== xs.constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat.apply([], Array.from({            length: n        }, () => {            const x = xs.next();            return x.done ? [] : [x.value];        }));     // uncurry :: (a -> b -> c) -> ((a, b) -> c)    const uncurry = f =>        (x, y) => f(x)(y)     // zip :: [a] -> [b] -> [(a, b)]    const zip = xs => ys => {        const            lng = Math.min(length(xs), length(ys)),            vs = take(lng)(ys);        return take(lng)(xs)            .map((x, i) => Tuple(x)(vs[i]));    };     // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]    const zipWith = f =>        xs => ys => {            const                lng = Math.min(length(xs), length(ys)),                vs = take(lng)(ys);            return take(lng)(xs)                .map((x, i) => f(x)(vs[i]));        };     // MAIN ---    return main();})();`
Output:
```First duplicated character, if any:
'' (0) -> None
'.' (1) -> None
'abcABC' (6) -> None
'XYZ ZYX' (7) -> 'X' (0x58) at 0, 6
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (36) -> '0' (0x30) at 9, 24```

Or, as an alternative to sorting and grouping – folding a string down to a dictionary of indices:

`(() => {    'use strict';     // duplicatedCharIndices :: String -> Maybe (Char, [Int])    const duplicatedCharIndices = s =>        minimumByMay(            comparing(compose(fst, snd))        )(filter(x => 1 < x.length)(            Object.entries(                s.split('').reduce(                    (a, c, i) => Object.assign(a, {                        [c]: (a[c] || []).concat(i)                    }), {}                )            )        ));     // ------------------------TEST------------------------    const main = () =>        console.log(            fTable('First duplicated character, if any:')(                s => `'\${s}' (\${s.length    })`            )(maybe('None')(tpl => {                const [c, ixs] = Array.from(tpl);                return `'\${c}' (0x\${showHex(ord(c))}) at \${ixs.join(', ')}`            }))(duplicatedCharIndices)([                "", ".", "abcABC", "XYZ ZYX",                "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"            ])        );      // -----------------GENERIC FUNCTIONS------------------     // Just :: a -> Maybe a    const Just = x => ({        type: 'Maybe',        Nothing: false,        Just: x    });     // Nothing :: Maybe a    const Nothing = () => ({        type: 'Maybe',        Nothing: true,    });     // Tuple (,) :: a -> b -> (a, b)    const Tuple = a => b => ({        type: 'Tuple',        '0': a,        '1': b,        length: 2    });     // chars :: String -> [Char]    const chars = s => s.split('');     // comparing :: (a -> b) -> (a -> a -> Ordering)    const comparing = f =>        x => y => {            const                a = f(x),                b = f(y);            return a < b ? -1 : (a > b ? 1 : 0);        };     // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c    const compose = (...fs) =>        x => fs.reduceRight((a, f) => f(a), x);     // enumFrom :: Enum a => a -> [a]    function* enumFrom(x) {        let v = x;        while (true) {            yield v;            v = 1 + v;        }    }     // filter :: (a -> Bool) -> [a] -> [a]    const filter = f => xs => xs.filter(f);     // fst :: (a, b) -> a    const fst = tpl => tpl;     // fTable :: String -> (a -> String) -> (b -> String)    //                      -> (a -> b) -> [a] -> String    const fTable = s => xShow => fxShow => f => xs => {        // Heading -> x display function ->        //           fx display function ->        //    f -> values -> tabular string        const            ys = xs.map(xShow),            w = Math.max(...ys.map(length));        return s + '\n' + zipWith(            a => b => a.padStart(w, ' ') + ' -> ' + b        )(ys)(            xs.map(x => fxShow(f(x)))        ).join('\n');    };     // length :: [a] -> Int    const length = xs =>        // Returns Infinity over objects without finite length.        // This enables zip and zipWith to choose the shorter        // argument when one is non-finite, like cycle, repeat etc        (Array.isArray(xs) || 'string' === typeof xs) ? (            xs.length        ) : Infinity;     // maybe :: b -> (a -> b) -> Maybe a -> b    const maybe = v =>        // Default value (v) if m is Nothing, or f(m.Just)        f => m => m.Nothing ? v : f(m.Just);     // minimumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a    const minimumByMay = f =>        xs => xs.reduce((a, x) =>            a.Nothing ? Just(x) : (                f(x)(a.Just) < 0 ? Just(x) : a            ), Nothing());     // ord :: Char -> Int    const ord = c => c.codePointAt(0);     // showHex :: Int -> String    const showHex = n =>        n.toString(16);     // snd :: (a, b) -> b    const snd = tpl =>        tpl;     // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = n =>        xs => 'GeneratorFunction' !== xs.constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat.apply([], Array.from({            length: n        }, () => {            const x = xs.next();            return x.done ? [] : [x.value];        }));     // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]    const zipWith = f =>        xs => ys => {            const                lng = Math.min(length(xs), length(ys)),                vs = take(lng)(ys);            return take(lng)(xs)                .map((x, i) => f(x)(vs[i]));        };     // MAIN ---    return main();})();`
Output:
```First duplicated character, if any:
'' (0) -> None
'.' (1) -> None
'abcABC' (6) -> None
'XYZ ZYX' (7) -> 'X' (0x58) at 0, 6
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (36) -> '0' (0x30) at 9, 24```

## Julia

`arr(s) = [c for c in s]alldup(a) = filter(x -> length(x) > 1, [findall(x -> x == a[i], a) for i in 1:length(a)])firstduplicate(s) = (a = arr(s); d = alldup(a); isempty(d) ? nothing : first(d)) function testfunction(strings)    println("String                            | Length | All Unique | First Duplicate | Positions\n" *            "-------------------------------------------------------------------------------------")    for s in strings        n = firstduplicate(s)        a = arr(s)        println(rpad(s, 38), rpad(length(s), 11), n == nothing ? "yes" :                rpad("no               \$(a[n])", 26) * rpad(n, 4) * "\$(n)")    endend testfunction(["",".","abcABC","XYZ ZYX","1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ", "hétérogénéité","🎆🎃🎇🎈","😍😀🙌💃😍🙌","🐠🐟🐡🦈🐬🐳🐋🐡",]) `
Output:
```String                            | Length | All Unique | First Duplicate (Hex) | Positions
-------------------------------------------------------------------------------------------
0          yes
.                                     1          yes
abcABC                                6          yes
XYZ ZYX                               7          no             X  (58)            1   7
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ  36         no             0  (30)            10  25
hétérogénéité                         13         no             é  (e9)            2   4
🎆🎃🎇🎈                             4          yes
😍😀🙌💃😍🙌                        6          no           😍  (1f60d)         1   5
🐠🐟🐡🦈🐬🐳🐋🐡                   8          no           🐡  (1f421)         3   8
```

## Kotlin

Translation of: Java
`import java.util.HashMap fun main() {    System.out.printf("%-40s  %2s  %10s  %8s  %s  %s%n", "String", "Length", "All Unique", "1st Diff", "Hex", "Positions")    System.out.printf("%-40s  %2s  %10s  %8s  %s  %s%n", "------------------------", "------", "----------", "--------", "---", "---------")    for (s in arrayOf("", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")) {        processString(s)    }} private fun processString(input: String) {    val charMap: MutableMap<Char, Int?> = HashMap()    var dup = 0.toChar()    var index = 0    var pos1 = -1    var pos2 = -1    for (key in input.toCharArray()) {        index++        if (charMap.containsKey(key)) {            dup = key            pos1 = charMap[key]!!            pos2 = index            break        }        charMap[key] = index    }    val unique = if (dup.toInt() == 0) "yes" else "no"    val diff = if (dup.toInt() == 0) "" else "'\$dup'"    val hex = if (dup.toInt() == 0) "" else Integer.toHexString(dup.toInt()).toUpperCase()    val position = if (dup.toInt() == 0) "" else "\$pos1 \$pos2"    System.out.printf("%-40s  %-6d  %-10s  %-8s  %-3s  %-5s%n", input, input.length, unique, diff, hex, position)}`
Output:
```String                                    Length  All Unique  1st Diff  Hex  Positions
------------------------                  ------  ----------  --------  ---  ---------
0       yes
.                                         1       yes
abcABC                                    6       yes
XYZ ZYX                                   7       no          'Z'       5A   3 5
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ      36      no          '0'       30   10 25```

## Lua

Using regular expressions. The '-' in the pattern's '.-' is the "lazy" or "reluctant" repetition qualifier; the usual '.*' would caused pattern to match, in the first example below, the substring "cocc" instead of "coc".

`local find, format = string.find, string.formatlocal function printf(fmt, ...) print(format(fmt,...)) end local pattern = '(.).-%1' -- '(.)' .. '.-' .. '%1' function report_dup_char(subject)    local pos1, pos2, char = find(subject, pattern)     local prefix = format('"%s" (%d)', subject, #subject)    if pos1 then        local byte = char:byte()        printf("%s: '%s' (0x%02x) duplicates at %d, %d", prefix, char, byte, pos1, pos2)    else        printf("%s: no duplicates", prefix)    endend local show = report_dup_charshow('coccyx')show('')show('.')show('abcABC')show('XYZ ZYX')show('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ') `
Output:
```"coccyx" (6): 'c' (0x63) duplicates at 1, 3
"" (0): no duplicates
"." (1): no duplicates
"abcABC" (6): no duplicates
"XYZ ZYX" (7): 'X' (0x58) duplicates at 1, 7
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (36): '0' (0x30) duplicates at 10, 25```

## Nanoquery

`def analyze(s)        s = str(s)        println "Examining [" + s + "] which has a length of " + str(len(s)) + ":"         if len(s) < 2                println "\tAll characters in the string are unique."                return        end         seen = list()        for i in range(0, len(s) - 2)                if s[i] in seen                        println "\tNot all characters in the string are unique."                        println "\t'" + s[i] + "' " + format("(0x%x)", ord(s[i])) +\                                " is duplicated at positions " + str(i + 1) + " and " +\                                str(s.indexOf(s[i]) + 1)                        return                end                seen.append(s[i])        end         println "\tAll characters in the string are unique."end tests = {"", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"}for s in tests        analyze(s)end`
Output:
```Examining [] which has a length of 0:
All characters in the string are unique.
Examining [.] which has a length of 1:
All characters in the string are unique.
Examining [abcABC] which has a length of 6:
All characters in the string are unique.
Examining [XYZ ZYX] which has a length of 7:
Not all characters in the string are unique.
'Z' (0x5a) is duplicated at positions 5 and 3
Examining [1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ] which has a length of 36:
Not all characters in the string are unique.
'0' (0x30) is duplicated at positions 25 and 10```

## Perl

`use strict;use warnings;use feature 'say';use utf8;binmode(STDOUT, ':utf8');use List::AllUtils qw(uniq);use Unicode::UCD 'charinfo'; for my \$str (    '',    '.',    'abcABC',    'XYZ ZYX',    '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ',    '01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X',    'Δ👍👨👍Δ',    'ΔδΔ̂ΔΛ',) {    my @S;    push @S, \$1 while \$str =~ /(\X)/g;    printf qq{\n"\$str" (length: %d) has }, scalar @S;    if (@S != uniq @S ) {        say "duplicated characters:";        my %P;        push @{ \$P{\$S[\$_]} }, 1+\$_ for 0..\$#S;        for my \$k (sort keys %P) {            next unless @{\$P{\$k}} > 1;            printf "'%s' %s (0x%x) in positions: %s\n", \$k, charinfo(ord \$k)->{'name'}, ord(\$k), join ', ', @{\$P{\$k}};        }    } else {        say "no duplicated characters."    }}`
Output:
```"" (length: 0) has no duplicated characters.

"." (length: 1) has no duplicated characters.

"abcABC" (length: 6) has no duplicated characters.

"XYZ ZYX" (length: 7) has duplicated characters:
'X' LATIN CAPITAL LETTER X (0x58) in positions: 1, 7
'Y' LATIN CAPITAL LETTER Y (0x59) in positions: 2, 6
'Z' LATIN CAPITAL LETTER Z (0x5a) in positions: 3, 5

"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length: 36) has duplicated characters:
'0' DIGIT ZERO (0x30) in positions: 10, 25

"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" (length: 39) has duplicated characters:
'0' DIGIT ZERO (0x30) in positions: 1, 11, 26, 38
'X' LATIN CAPITAL LETTER X (0x58) in positions: 35, 39

"Δ👍👨👍Δ" (length: 5) has duplicated characters:
'Δ' GREEK CAPITAL LETTER DELTA (0x394) in positions: 1, 5
'👍' THUMBS UP SIGN (0x1f44d) in positions: 2, 4

"ΔδΔ̂ΔΛ" (length: 5) has duplicated characters:
'Δ' GREEK CAPITAL LETTER DELTA (0x394) in positions: 1, 4```

## Phix

As with Determine_if_a_string_has_all_the_same_characters#Phix, you can use utf8_to_utf32() when needed.

`procedure all_uniq(sequence s)    string msg = "all characters are unique"    for i=1 to length(s) do        integer si = s[i],                r = find(si,s,i+1) -- (or maybe rfind(si,s,i-1))        if r then            msg = sprintf(`first duplicate character "%c"(#%02x) at positions %d and %d`,{si,si,i,r})            exit        end if    end for    printf(1,"\"%s\" (length %d): %s\n",{s,length(s),msg})end procedure constant tests = {"",".","abcABC","XYZ ZYX","1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"}for i=1 to length(tests) do all_uniq(tests[i]) end for`
Output:
```"" (length 0): all characters are unique
"." (length 1): all characters are unique
"abcABC" (length 6): all characters are unique
"XYZ ZYX" (length 7): first duplicate character "X"(#58) at positions 1 and 7
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length 36): first duplicate character "0"(#30) at positions 10 and 25
```

## PicoLisp

`(de burn (Lst)   (let P 0      (by         '((A)            (set A (inc 'P))            (put A 'P (char A)) )         group         Lst ) ) )(de first (Lst)   (mini      '((L)         (nand            (cdr L)            (apply min (mapcar val L)) ) )      Lst ) )(de uniq? (Str)   (let M (first (burn (chop Str)))      (ifn M         (prinl Str " (length " (length Str) "): all characters are unique")         (prin            Str " (length " (length Str) "): first duplicate character "            (car M)            " at positions " )         (println (mapcar val M)) ) ) )(uniq?)(uniq? ".")(uniq? "abcABC")(uniq? "XYZ ZYX")(uniq? "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")`
Output:
``` (length 0): all characters are unique
. (length 1): all characters are unique
abcABC (length 6): all characters are unique
XYZ ZYX (length 7): first duplicate character X at positions (1 7)
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ (length 36): first duplicate character 0 at positions (10 25)
```

## Prolog

`report_duplicates(S) :-	duplicates(S, Dups),			format('For value "~w":~n', S),	report(Dups),	nl. report(Dups) :-	maplist(only_one_position, Dups),	format('    All characters are unique~n'). report(Dups) :-	exclude(only_one_position, Dups, [c(Char,Positions)|_]),	reverse(Positions, PosInOrder),	atomic_list_concat(PosInOrder, ', ', PosAsList),	format('    The character ~w is non unique at ~p~n', [Char, PosAsList]).	 only_one_position(c(_,[_])).	 duplicates(S, Count) :- 	atom_chars(S, Chars), 	char_count(Chars, 0, [], Count). char_count([], _, C, C).char_count([C|T], Index, Counted, Result) :-	select(c(C,Positions), Counted, MoreCounted),	succ(Index, Index1),	char_count(T, Index1, [c(C,[Index|Positions])|MoreCounted], Result).char_count([C|T], Index, Counted, Result) :-	\+ member(c(C,_), Counted),	succ(Index, Index1),	char_count(T, Index1, [c(C,[Index])|Counted], Result). test :-	report_duplicates('').test :-	report_duplicates('.').test :-	report_duplicates('abcABC').test :-	report_duplicates('XYZ ZYX').test :-	report_duplicates('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ').`
Output:
```?- forall(test, true).
For value "":
All characters are unique

For value ".":
All characters are unique

For value "abcABC":
All characters are unique

For value "XYZ ZYX":
The character X is non unique at '0, 6'

For value "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ":
The character 0 is non unique at '9, 24'

true.

?-```

## Python

### Functional

Defined in terms of itertools.groupby:

`'''Determine if a string has all unique characters''' from itertools import groupby  # duplicatedCharIndices :: String -> Maybe (Char, [Int])def duplicatedCharIndices(s):    '''Just the first duplicated character, and       the indices of its occurrence, or       Nothing if there are no duplications.    '''    def go(xs):        if 1 < len(xs):            duplicates = list(filter(lambda kv: 1 < len(kv), [                (k, list(v)) for k, v in groupby(                    sorted(xs, key=swap),                    key=snd                )            ]))            return Just(second(fmap(fst))(                sorted(                    duplicates,                    key=lambda kv: kv                )            )) if duplicates else Nothing()        else:            return Nothing()    return go(list(enumerate(s)))  # TEST ----------------------------------------------------# main :: IO ()def main():    '''Test over various strings.'''     def showSample(s):        return repr(s) + ' (' + str(len(s)) + ')'     def showDuplicate(cix):        c, ix = cix        return repr(c) + (            ' (' + hex(ord(c)) + ') at ' + repr(ix)        )     print(        fTable('First duplicated character, if any:')(            showSample        )(maybe('None')(showDuplicate))(duplicatedCharIndices)([            '', '.', 'abcABC', 'XYZ ZYX',            '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'        ])    )  # FORMATTING ---------------------------------------------- # fTable :: String -> (a -> String) -># (b -> String) -> (a -> b) -> [a] -> Stringdef fTable(s):    '''Heading -> x display function -> fx display function ->       f -> xs -> tabular string.    '''    def go(xShow, fxShow, f, xs):        ys = [xShow(x) for x in xs]        w = max(map(len, ys))        return s + '\n' + '\n'.join(map(            lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),            xs, ys        ))    return lambda xShow: lambda fxShow: lambda f: lambda xs: go(        xShow, fxShow, f, xs    )  # GENERIC ------------------------------------------------- # Just :: a -> Maybe adef Just(x):    '''Constructor for an inhabited Maybe (option type) value.       Wrapper containing the result of a computation.    '''    return {'type': 'Maybe', 'Nothing': False, 'Just': x}  # Nothing :: Maybe adef Nothing():    '''Constructor for an empty Maybe (option type) value.       Empty wrapper returned where a computation is not possible.    '''    return {'type': 'Maybe', 'Nothing': True}  # fmap :: (a -> b) -> [a] -> [b]def fmap(f):    '''fmap over a list.       f lifted to a function over a list.    '''    return lambda xs: [f(x) for x in xs]  # fst :: (a, b) -> adef fst(tpl):    '''First member of a pair.'''    return tpl  # head :: [a] -> adef head(xs):    '''The first element of a non-empty list.'''    return xs if isinstance(xs, list) else next(xs)  # maybe :: b -> (a -> b) -> Maybe a -> bdef maybe(v):    '''Either the default value v, if m is Nothing,       or the application of f to x,       where m is Just(x).    '''    return lambda f: lambda m: v if (        None is m or m.get('Nothing')    ) else f(m.get('Just'))  # second :: (a -> b) -> ((c, a) -> (c, b))def second(f):    '''A simple function lifted to a function over a tuple,       with f applied only to the second of two values.    '''    return lambda xy: (xy, f(xy))  # snd :: (a, b) -> bdef snd(tpl):    '''Second member of a pair.'''    return tpl  # swap :: (a, b) -> (b, a)def swap(tpl):    '''The swapped components of a pair.'''    return (tpl, tpl)  # MAIN ---if __name__ == '__main__':    main()`
Output:
```First duplicated character, if any:
'' (0) -> None
'.' (1) -> None
'abcABC' (6) -> None
'XYZ ZYX' (7) -> 'X' (0x58) at [0, 6]
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (36) -> '0' (0x30) at [9, 24]```

Or, as an alternative to sorting and grouping, folding a string down to a dictionary with reduce:

`'''Determine if a string has all unique characters''' from functools import reduce  # duplicatedCharIndices :: String -> Maybe (Char, [Int])def duplicatedCharIndices(s):    '''Just the first duplicated character, and       the indices of its occurrence, or       Nothing if there are no duplications.    '''    def go(dct, ic):        i, c = ic        return dict(            dct,            **{c: dct[c] + [i] if c in dct else [i]}        )    duplicates = [        (k, v) for (k, v)        in reduce(go, enumerate(s), {}).items()        if 1 < len(v)    ]    return Just(        min(duplicates, key=compose(head, snd))    ) if duplicates else Nothing()  # And another alternative here would be to fuse the 1 < len(v)# filtering, and the min() search for the earliest duplicate,# down to a single `earliestDuplication` fold: # duplicatedCharIndices_ :: String -> Maybe (Char, [Int])def duplicatedCharIndices_(s):    '''Just the first duplicated character, and       the indices of its occurrence, or       Nothing if there are no duplications.    '''    def positionRecord(dct, ic):        i, c = ic        return dict(            dct,            **{c: dct[c] + [i] if c in dct else [i]}        )     def earliestDuplication(sofar, charPosns):        c, indices = charPosns        return (            maybe(Just((c, indices)))(                lambda kxs: Just((c, indices)) if (                    # Earlier duplication ?                    indices < kxs                ) else sofar            )(sofar)        ) if 1 < len(indices) else sofar     return reduce(        earliestDuplication,        reduce(            positionRecord,            enumerate(s),            {}        ).items(),        Nothing()    )  # TEST ----------------------------------------------------# main :: IO ()def main():    '''Test over various strings.'''     def showSample(s):        return repr(s) + ' (' + str(len(s)) + ')'     def showDuplicate(cix):        c, ix = cix        return repr(c) + (            ' (' + hex(ord(c)) + ') at ' + repr(ix)        )     print(        fTable('First duplicated character, if any:')(            showSample        )(maybe('None')(showDuplicate))(duplicatedCharIndices_)([            '', '.', 'abcABC', 'XYZ ZYX',            '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'        ])    )  # FORMATTING ---------------------------------------------- # fTable :: String -> (a -> String) -># (b -> String) -> (a -> b) -> [a] -> Stringdef fTable(s):    '''Heading -> x display function -> fx display function ->       f -> xs -> tabular string.    '''    def go(xShow, fxShow, f, xs):        ys = [xShow(x) for x in xs]        w = max(map(len, ys))        return s + '\n' + '\n'.join(map(            lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),            xs, ys        ))    return lambda xShow: lambda fxShow: lambda f: lambda xs: go(        xShow, fxShow, f, xs    )  # GENERIC ------------------------------------------------- # Just :: a -> Maybe adef Just(x):    '''Constructor for an inhabited Maybe (option type) value.       Wrapper containing the result of a computation.    '''    return {'type': 'Maybe', 'Nothing': False, 'Just': x}  # Nothing :: Maybe adef Nothing():    '''Constructor for an empty Maybe (option type) value.       Empty wrapper returned where a computation is not possible.    '''    return {'type': 'Maybe', 'Nothing': True}  # compose :: ((a -> a), ...) -> (a -> a)def compose(*fs):    '''Composition, from right to left,       of a series of functions.    '''    return lambda x: reduce(        lambda a, f: f(a),        fs[::-1], x    )  # head :: [a] -> adef head(xs):    '''The first element of a non-empty list.'''    return xs if isinstance(xs, list) else next(xs)  # maybe :: b -> (a -> b) -> Maybe a -> bdef maybe(v):    '''Either the default value v, if m is Nothing,       or the application of f to x,       where m is Just(x).    '''    return lambda f: lambda m: v if (        None is m or m.get('Nothing')    ) else f(m.get('Just'))  # snd :: (a, b) -> bdef snd(tpl):    '''Second member of a pair.'''    return tpl  # MAIN ---if __name__ == '__main__':    main()`
Output:
```First duplicated character, if any:
'' (0) -> None
'.' (1) -> None
'abcABC' (6) -> None
'XYZ ZYX' (7) -> 'X' (0x58) at [0, 6]
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (36) -> '0' (0x30) at [9, 24]```

### Using regular expression

The second part of the pattern uses the '*?' match qualifier, which makes the match "lazy" or "reluctant". '.*' instead of '.*?' would have matched the substring "cocc" instead of "coc" in the first example below. Tested with Python 3.7.

`import re pattern = '(.)' + '.*?' + r'\1' def find_dup_char(subject):    match = re.search(pattern, subject)    if match:        return match.groups(0), match.start(0), match.end(0) def report_dup_char(subject):    dup = find_dup_char(subject)    prefix = f'"{subject}" ({len(subject)})'    if dup:        ch, pos1, pos2 = dup        print(f"{prefix}: '{ch}' (0x{ord(ch):02x}) duplicates at {pos1}, {pos2-1}")    else:        print(f"{prefix}: no duplicate characters") show = report_dup_charshow('coccyx')show('')show('.')show('abcABC')show('XYZ ZYX')show('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ') `
Output:
```"coccyx" (6): 'c' (0x63) duplicates at 0, 2
"" (0): no duplicate characters
"." (1): no duplicate characters
"abcABC" (6): no duplicate characters
"XYZ ZYX" (7): 'X' (0x58) duplicates at 0, 6
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (36): '0' (0x30) duplicates at 9, 24
```

## Raku

(formerly Perl 6)

Works with: Rakudo version 2019.07.1

Raku works with unicode natively and handles combining characters and multi-byte emoji correctly. In the last string, notice the the length is correctly shown as 11 characters and that the delta with a combining circumflex in position 6 is not the same as the deltas without in positions 5 & 9.

`  -> \$str {    my \$i = 0;    print "\n{\$str.perl} (length: {\$str.chars}), has ";    my %m;    %m{\$_}.push: ++\$i for \$str.comb;    if any(%m.values) > 1 {        say "duplicated characters:";        say "'{.key}' ({.key.uninames}; hex ordinal: {(.key.ords).fmt: "0x%X"})" ~        " in positions: {.value.join: ', '}" for %m.grep( *.value > 1 ).sort( *.value );    } else {        say "no duplicated characters."    }} for    '',    '.',    'abcABC',    'XYZ ZYX',    '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ',    '01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X',    '🦋🙂👨‍👩‍👧‍👦🙄ΔΔ̂ 🦋Δ👍👨‍👩‍👧‍👦'`
Output:
```"" (length: 0), has no duplicated characters.

"." (length: 1), has no duplicated characters.

"abcABC" (length: 6), has no duplicated characters.

"XYZ ZYX" (length: 7), has duplicated characters:
'X' (LATIN CAPITAL LETTER X; hex ordinal: 0x58) in positions: 1, 7
'Y' (LATIN CAPITAL LETTER Y; hex ordinal: 0x59) in positions: 2, 6
'Z' (LATIN CAPITAL LETTER Z; hex ordinal: 0x5A) in positions: 3, 5

"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length: 36), has duplicated characters:
'0' (DIGIT ZERO; hex ordinal: 0x30) in positions: 10, 25

"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" (length: 39), has duplicated characters:
'0' (DIGIT ZERO; hex ordinal: 0x30) in positions: 1, 11, 26, 38
'X' (LATIN CAPITAL LETTER X; hex ordinal: 0x58) in positions: 35, 39

"🦋🙂👨‍👩‍👧‍👦🙄ΔΔ̂ 🦋Δ👍👨‍👩‍👧‍👦" (length: 11), has duplicated characters:
'🦋' (BUTTERFLY; hex ordinal: 0x1F98B) in positions: 1, 8
'👨‍👩‍👧‍👦' (MAN ZERO WIDTH JOINER WOMAN ZERO WIDTH JOINER GIRL ZERO WIDTH JOINER BOY; hex ordinal: 0x1F468 0x200D 0x1F469 0x200D 0x1F467 0x200D 0x1F466) in positions: 3, 11
'Δ' (GREEK CAPITAL LETTER DELTA; hex ordinal: 0x394) in positions: 5, 9
```

## REXX

`/*REXX pgm determines if a string is comprised of all unique characters (no duplicates).*/@.=                                              /*assign a default for the  @.  array. */parse arg @.1                                    /*obtain optional argument from the CL.*/if @.1=''  then do;   @.1=                       /*Not specified?  Then assume defaults.*/                      @.2= .                      @.3= 'abcABC'                      @.4= 'XYZ ZYX'                      @.5= '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'                end      do j=1;  if j\==1  &  @.j==''  then leave   /*String is null & not j=1?  We're done*/     say copies('─', 79)                         /*display a separator line  (a fence). */     say 'Testing for the string (length' length(@.j)"): "   @.j     say     dup= isUnique(@.j)     say 'The characters in the string'   word("are aren't", 1 + (dup>0) )  'all unique.'     if dup==0  then iterate     ?= substr(@.j, dup, 1)     say 'The character '  ?  " ('"c2x(?)"'x)  at position "  dup ,                                 ' is repeated at position '  pos(?, @.j, dup+1)     end   /*j*/exit                                             /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/isUnique: procedure; parse arg x                          /*obtain the character string.*/                       do k=1  to length(x) - 1           /*examine all but the last.   */                       p= pos( substr(x, k, 1), x, k + 1) /*see if the Kth char is a dup*/                       if p\==0  then return k            /*Find a dup? Return location.*/                       end   /*k*/          return 0                                        /*indicate all chars unique.  */`
output   when using the internal defaults
```───────────────────────────────────────────────────────────────────────────────
Testing for the string (length 0):

The characters in the string are all unique.
───────────────────────────────────────────────────────────────────────────────
Testing for the string (length 1):  .

The characters in the string are all unique.
───────────────────────────────────────────────────────────────────────────────
Testing for the string (length 6):  abcABC

The characters in the string are all unique.
───────────────────────────────────────────────────────────────────────────────
Testing for the string (length 7):  XYZ ZYX

The characters in the string aren't all unique.
The character  X  ('58'x)  at position  1  is repeated at position  7
───────────────────────────────────────────────────────────────────────────────
Testing for the string (length 36):  1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ

The characters in the string aren't all unique.
The character  0  ('30'x)  at position  10  is repeated at position  25
```

## Ruby

`strings = ["",        ".",        "abcABC",        "XYZ ZYX",        "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",        "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",        "hétérogénéité",        "🎆🎃🎇🎈",        "😍😀🙌💃😍🙌",        "🐠🐟🐡🦈🐬🐳🐋🐡",] strings.each do |str|  seen = {}  print "#{str.inspect} (size #{str.size}) "  res = "has no duplicates." #may change  str.chars.each_with_index do |c,i|    if seen[c].nil?       seen[c] = i    else      res =  "has duplicate char #{c} (#{'%#x' % c.ord}) on #{seen[c]} and #{i}."      break    end  end  puts resend `
Output:
```"" (size 0) has no duplicates.
"." (size 1) has no duplicates.
"abcABC" (size 6) has no duplicates.
"XYZ ZYX" (size 7) has duplicate char Z (0x5a) on 2 and 4.
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (size 36) has duplicate char 0 (0x30) on 9 and 24.
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" (size 39) has duplicate char 0 (0x30) on 0 and 10.
"hétérogénéité" (size 13) has duplicate char é (0xe9) on 1 and 3.
"🎆🎃🎇🎈" (size 4) has no duplicates.
"😍😀🙌💃😍🙌" (size 6) has duplicate char 😍 (0x1f60d) on 0 and 4.
"🐠🐟🐡🦈🐬🐳🐋🐡" (size 8) has duplicate char 🐡 (0x1f421) on 2 and 7.
```

## Sidef

`func index_duplicates(str) {    gather {        for k,v in (str.chars.kv) {            var i = str.index(v, k+1)            take([k, i]) if (i != -1)        }    }} var strings = [    "", ".", "abcABC", "XYZ ZYX",    "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",    "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",    "hétérogénéité", "🎆🎃🎇🎈", "😍😀🙌💃😍🙌",    "🐠🐟🐡🦈🐬🐳🐋🐡"] strings.each {|str|    print "\n'#{str}' (size: #{str.len}) "    var dups = index_duplicates(str)    say "has duplicated characters:" if dups    for i,j in (dups) {        say "#{str[i]} (#{'%#x' % str[i].ord}) in positions: #{i}, #{j}"    }    say "has no duplicates." if !dups}`
Output:
```'' (size: 0) has no duplicates.

'.' (size: 1) has no duplicates.

'abcABC' (size: 6) has no duplicates.

'XYZ ZYX' (size: 7) has duplicated characters:
X (0x58) in positions: 0, 6
Y (0x59) in positions: 1, 5
Z (0x5a) in positions: 2, 4

'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (size: 36) has duplicated characters:
0 (0x30) in positions: 9, 24

'01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X' (size: 39) has duplicated characters:
0 (0x30) in positions: 0, 10
0 (0x30) in positions: 10, 25
0 (0x30) in positions: 25, 37
X (0x58) in positions: 34, 38

'hétérogénéité' (size: 13) has duplicated characters:
é (0xe9) in positions: 1, 3
t (0x74) in positions: 2, 11
é (0xe9) in positions: 3, 7
é (0xe9) in positions: 7, 9
é (0xe9) in positions: 9, 12

'🎆🎃🎇🎈' (size: 4) has no duplicates.

'😍😀🙌💃😍🙌' (size: 6) has duplicated characters:
😍 (0x1f60d) in positions: 0, 4
🙌 (0x1f64c) in positions: 2, 5

'🐠🐟🐡🦈🐬🐳🐋🐡' (size: 8) has duplicated characters:
🐡 (0x1f421) in positions: 2, 7
```

## Tcl

`package require Tcl 8.6 ; # For binary encode array set yesno {1 Yes 2 No} set test {    {}    {.}    {abcABC}    {XYZ ZYX}    {1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ}    {hétérogénéité}} # Loop through test stringsforeach str \$test {    set chars [dict create] ; # init dictionary    set num_chars 1 ; # In case of empty string     # Loop through characters in string    for {set i 0} {\$i < [string length \$str]} {incr i} {        set c [string index \$str \$i] ; # get char at index        dict lappend chars \$c \$i ; # add index to a running list for key=char        set indexes [dict get \$chars \$c] ; # get the whole running list        set num_chars [llength \$indexes] ; # count the # of indexes        if {\$num_chars > 1} {            break ; # Found a duplicate, break out of the loop        }    }     # Handle Output    puts [format "Tested: %38s (len: %2d). All unique? %3s. " \              "'\$str'" [string length \$str] \$yesno(\$num_chars)]    if {\$num_chars > 1} {        puts [format " --> Character '%s' (hex: 0x%s) reappears at indexes: %s." \                  \$c [binary encode hex \$c] \$indexes]    }} `
Output:
```Tested:                                     '' (len:  0). All unique? Yes.
Tested:                                    '.' (len:  1). All unique? Yes.
Tested:                               'abcABC' (len:  6). All unique? Yes.
Tested:                              'XYZ ZYX' (len:  7). All unique?  No.
--> Character 'Z' (hex: 0x5a) reappears at indexes: 2 4.
Tested: '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (len: 36). All unique?  No.
--> Character '0' (hex: 0x30) reappears at indexes: 9 24.
Tested:                        'hétérogénéité' (len: 13). All unique?  No.
--> Character 'é' (hex: 0xe9) reappears at indexes: 1 3.
```

## Visual Basic .NET

Translation of: C#
`Module Module1     Sub Main()        Dim input() = {"", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"}        For Each s In input            Console.WriteLine(\$"'{s}' (Length {s.Length}) " + String.Join(", ", s.Select(Function(c, i) (c, i)).GroupBy(Function(t) t.c).Where(Function(g) g.Count() > 1).Select(Function(g) \$"'{g.Key}' (0X{AscW(g.Key):X})[{String.Join(", ", g.Select(Function(t) t.i))}]").DefaultIfEmpty("All characters are unique.")))        Next    End Sub End Module`
Output:
```'' (Length 0) All characters are unique.
'.' (Length 1) All characters are unique.
'abcABC' (Length 6) All characters are unique.
'XYZ ZYX' (Length 7) 'X' (0X58)[0, 6], 'Y' (0X59)[1, 5], 'Z' (0X5A)[2, 4]
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (Length 36) '0' (0X30)[9, 24]```

## Wren

Translation of: Go
Library: Wren-fmt
`import "/fmt" for Conv, Fmt var analyze = Fn.new { |s|    var chars = s.codePoints.toList    var le = chars.count    System.print("Analyzing %(Fmt.q(s)) which has a length of %(le):")    if (le > 1) {        for (i in 0...le-1) {            for (j in i+1...le) {                if (chars[j] == chars[i]) {                    System.print("  Not all characters in the string are unique.")                    var c = String.fromCodePoint(chars[i])                    var hex = "0x" + Conv.hex(chars[i])                    System.print("  '%(c)' (%(hex)) is duplicated at positions %(i+1) and %(j+1).\n")                    return                }            }        }    }    System.print("  All characters in the string are unique.\n")} var strings = [    "",    ".",    "abcABC",    "XYZ ZYX",    "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",    "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",    "hétérogénéité",    "🎆🎃🎇🎈",    "😍😀🙌💃😍🙌",    "🐠🐟🐡🦈🐬🐳🐋🐡"]for (s in strings) analyze.call(s)`
Output:
```Analyzing "" which has a length of 0:
All characters in the string are unique.

Analyzing "." which has a length of 1:
All characters in the string are unique.

Analyzing "abcABC" which has a length of 6:
All characters in the string are unique.

Analyzing "XYZ ZYX" which has a length of 7:
Not all characters in the string are unique.
'X' (0x58) is duplicated at positions 1 and 7.

Analyzing "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" which has a length of 36:
Not all characters in the string are unique.
'0' (0x30) is duplicated at positions 10 and 25.

Analyzing "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" which has a length of 39:
Not all characters in the string are unique.
'0' (0x30) is duplicated at positions 1 and 11.

Analyzing "hétérogénéité" which has a length of 13:
Not all characters in the string are unique.
'é' (0xe9) is duplicated at positions 2 and 4.

Analyzing "🎆🎃🎇🎈" which has a length of 4:
All characters in the string are unique.

Analyzing "😍😀🙌💃😍🙌" which has a length of 6:
Not all characters in the string are unique.
'😍' (0x1f60d) is duplicated at positions 1 and 5.

Analyzing "🐠🐟🐡🦈🐬🐳🐋🐡" which has a length of 8:
Not all characters in the string are unique.
'🐡' (0x1f421) is duplicated at positions 3 and 8.
```

## XPL0

`include xpllib;                 \contains StrLen function proc    StrUnique(S);           \Show if string has unique charschar    S;int     L, I, J, K;[L:= StrLen(S);IntOut(0, L);  Text(0, ":       ^"");  Text(0, S);  ChOut(0, ^");  CrLf(0);for I:= 0 to L-1 do    for J:= I+1 to L-1 do        [if S(I) = S(J) then                [ChOut(0, \tab\ 9);                for K:= 0 to I do ChOut(0, ^ );                ChOut(0, ^^);                for K:= 0 to J-I-2 do ChOut(0, ^ );                ChOut(0, ^^);                Text(0, " Duplicate character: ");                ChOut(0, S(I));                Text(0, ", hex ");                SetHexDigits(2);                HexOut(0, S(I));                CrLf(0);                return;                ];        ];Text(0, "       Unique, no duplicates");  CrLf(0);]; [Text(0, "Length");  CrLf(0);StrUnique("");StrUnique(".");StrUnique("abcABC");StrUnique("XYZ ZYX");StrUnique("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");StrUnique("thequickbrownfoxjumps");]`
Output:
```Length
0:      ""
Unique, no duplicates
1:      "."
Unique, no duplicates
6:      "abcABC"
Unique, no duplicates
7:      "XYZ ZYX"
^     ^ Duplicate character: X, hex 58
36:     "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
^              ^ Duplicate character: 0, hex 30
21:     "thequickbrownfoxjumps"
^            ^ Duplicate character: u, hex 75
```

## zkl

`fcn stringUniqueness(str){  // Does not handle Unicode   sz,unique,uz,counts := str.len(), str.unique(), unique.len(), str.counts();   println("Length %d: \"%s\"".fmt(sz,str));   if(sz==uz or uz==1) println("\tAll characters are unique");   else  // counts is (char,count, char,count, ...)      println("\tDuplicate: ",         counts.pump(List,Void.Read,fcn(str,c,n){            if(n>1){	       is,z:=List(),-1; do(n){ is.append(z=str.find(c,z+1)) }	       "'%s' (0x%x)[%s]".fmt(c,c.toAsc(),is.concat(","))	    }	    else Void.Skip	 }.fp(str)).concat(", "));}`
`testStrings:=T("", ".", "abcABC", "XYZ ZYX",    "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",   "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X");foreach s in (testStrings){ stringUniqueness(s) }`
Output:
```Length 0: ""
All characters are unique
Length 1: "."
All characters are unique
Length 6: "abcABC"
All characters are unique
Length 7: "XYZ ZYX"
Duplicate: 'X' (0x58)[0,6], 'Y' (0x59)[1,5], 'Z' (0x5a)[2,4]
Length 36: "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
Duplicate: '0' (0x30)[9,24]
Length 39: "01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X"
Duplicate: '0' (0x30)[0,10,25,37], 'X' (0x58)[34,38]
```