Determine if a string has all unique characters: Difference between revisions

m
m (→‎{{header|Haskell}}: Applied hlint, hindent. Specified imports.)
m (→‎{{header|Wren}}: Minor tidy)
 
(102 intermediate revisions by 48 users not shown)
Line 33:
Show all output here on this page.
 
{{Template:Strings}}
 
;Related tasks:
:*   [https://rosettacode.org/wiki/Determine_if_a_string_has_all_the_same_characters determine if a string has all the same characters]
:*   [https://rosettacode.org/wiki/Pangram_checker pangram checker]
:*   [https://rosettacode.org/wiki/Compare_a_list_of_strings compare a list of strings]
:*   [https://rosettacode.org/wiki/Determine_if_a_string_is_collapsible determine if a string is collapsible]
<br><br>
 
=={{header|11l}}==
{{trans|Kotlin}}
 
<syntaxhighlight lang="11l">F processString(input)
[Char = Int] charMap
V dup = Char("\0")
V index = 0
V pos1 = -1
V pos2 = -1
L(key) input
index++
I key C charMap
dup = key
pos1 = charMap[key]
pos2 = index
L.break
charMap[key] = index
V unique = I dup == Char("\0") {‘yes’} E ‘no’
V diff = I dup == Char("\0") {‘’} E ‘'’dup‘'’
V hexs = I dup == Char("\0") {‘’} E hex(dup.code)
V position = I dup == Char("\0") {‘’} E pos1‘ ’pos2
print(‘#<40 #<6 #<10 #<8 #<3 #<5’.format(input, input.len, unique, diff, hexs, position))
 
print(‘#<40 #2 #10 #8 #. #.’.format(‘String’, ‘Length’, ‘All Unique’, ‘1st Diff’, ‘Hex’, ‘Positions’))
print(‘#<40 #2 #10 #8 #. #.’.format(‘------------------------’, ‘------’, ‘----------’, ‘--------’, ‘---’, ‘---------’))
L(s) [‘’, ‘.’, ‘abcABC’, ‘XYZ ZYX’, ‘1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ’]
processString(s)</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">PROC PrintBH(BYTE a)
BYTE ARRAY hex=['0 '1 '2 '3 '4 '5 '6 '7 '8 '9 'A 'B 'C 'D 'E 'F]
 
Put(hex(a RSH 4))
Put(hex(a&$0F))
RETURN
 
PROC Test(CHAR ARRAY s)
BYTE i,j,n,pos1,pos2
 
pos1=0 pos2=0
n=s(0)-1
IF n=255 THEN n=0 FI
FOR i=1 TO n
DO
FOR j=i+1 TO s(0)
DO
IF s(j)=s(i) THEN
pos1=i
pos2=j
EXIT
FI
OD
IF pos1#0 THEN
EXIT
FI
OD
 
PrintF("""%S"" (len=%B) -> ",s,s(0))
IF pos1=0 THEN
PrintE("all characters are unique.")
ELSE
PrintF("""%C"" (hex=$",s(pos1))
PrintBH(s(pos1))
PrintF(") is duplicated at pos. %B and %B.%E",pos1,pos2)
FI
PutE()
RETURN
 
PROC Main()
Test("")
Test(".")
Test("abcABC")
Test("XYZ ZYX")
Test("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Determine_if_a_string_has_all_unique_characters.png Screenshot from Atari 8-bit computer]
<pre>
"" (len=0) -> all characters are unique.
 
"." (len=1) -> all characters are unique.
 
"abcABC" (len=6) -> all characters are unique.
 
"XYZ ZYX" (len=7) -> "X" (hex=$58) is duplicated at pos. 1 and 7.
 
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (len=36) -> "0" (hex=$30) is duplicated at pos. 10 and 25.
</pre>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">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;
</syntaxhighlight>
 
{{out}}
<pre>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#</pre>
 
=={{header|ALGOL 68}}==
<syntaxhighlight lang="algol68">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
OD
END</syntaxhighlight>
{{out}}
<pre>
<<<>>> (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
</pre>
 
=={{header|AppleScript}}==
 
Following AppleScript's convention of one-based indices:
{{Trans|Haskell}}
{{Trans|Python}}
{{Trans|JavaScript}}
<syntaxhighlight lang="applescript">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 a
on 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 a
on 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 list
end keys
 
-- chr :: Int -> Char
on chr(n)
character id n
end chr
 
-- chars :: String -> [Char]
on chars(s)
characters of s
end chars
 
-- compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
on compose(f, g)
script
property mf : mReturn(f)
property mg : mReturn(g)
on |λ|(x)
mf's |λ|(mg's |λ|(x))
end |λ|
end script
end 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 acc
end 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 if
end enumFromTo
 
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on 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 tell
end foldl
 
-- fst :: (a, b) -> a
on fst(tpl)
if class of tpl is record then
|1| of tpl
else
item 1 of tpl
end if
end fst
 
-- fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> String
on 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 -> Dict
on 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 tell
end insertDict
 
-- intercalate :: String -> [String] -> String
on 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
str
end intercalate
 
-- justifyRight :: Int -> Char -> String -> String
on justifyRight(n, cFiller, strText)
if n > length of strText then
text -n thru -1 of ((replicate(n, cFiller) as text) & strText)
else
strText
end if
end justifyRight
 
-- length :: [a] -> Int
on |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 if
end |length|
 
-- lookupDict :: a -> Dict -> Maybe b
on 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 if
end 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 tell
end map
 
-- maximum :: Ord a => [a] -> a
on 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 -> b
on 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 if
end maybe
 
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end 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 if
end mReturn
 
-- quoted :: Char -> String -> String
on quoted(c, s)
-- string flanked on both sides
-- by a specified quote character.
c & s & c
end 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 & dbl
end replicate
 
-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on 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 if
end take
 
-- unlines :: [String] -> String
on 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
str
end 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 tell
end zipWith</syntaxhighlight>
{{Out}}
<pre>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</pre>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">strings: [
"", ".", "abcABC", "XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",
"hétérogénéité",
"🎆🎃🎇🎈", "😍😀🙌💃😍🙌", "🐠🐟🐡🦈🐬🐳🐋🐡"
]
 
loop strings 'str [
chars: split str
prints ["\"" ++ str ++ "\"" ~"(size |size str|):"]
if? chars = unique chars ->
print "has no duplicates."
else [
seen: #[]
done: false
 
i: 0
while [and? i<size chars
not? done][
ch: chars\[i]
if? not? key? seen ch [
seen\[ch]: i
]
else [
print ~"has duplicate char `|ch|` on |get seen ch| and |i|"
done: true
]
i: i+1
]
]
]</syntaxhighlight>
 
{{out}}
 
<pre>"" (size 0): has no duplicates.
"." (size 1): has no duplicates.
"abcABC" (size 6): has no duplicates.
"XYZ ZYX" (size 7): has duplicate char `Z` on 2 and 4
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (size 36): has duplicate char `0` on 9 and 24
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" (size 39): has duplicate char `0` on 0 and 10
"hétérogénéité" (size 13): has duplicate char `é` on 1 and 3
"🎆🎃🎇🎈" (size 4): has no duplicates.
"😍😀🙌💃😍🙌" (size 6): has duplicate char `😍` on 0 and 4
"🐠🐟🐡🦈🐬🐳🐋🐡" (size 8): has duplicate char `🐡` on 2 and 7</pre>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">unique_characters(str){
arr := [], res := ""
for i, v in StrSplit(str)
arr[v] := arr[v] ? arr[v] "," i : i
for i, v in Arr
if InStr(v, ",")
res .= v "|" i " @ " v "`tHex = " format("{1:X}", Asc(i)) "`n"
Sort, res, N
res := RegExReplace(res, "`am)^[\d,]+\|")
res := StrSplit(res, "`n").1
return """" str """`tlength = " StrLen(str) "`n" (res ? "Duplicates Found:`n" res : "Unique Characters")
}</syntaxhighlight>
Examples:<syntaxhighlight lang="autohotkey">test := ["",".","abcABC","XYZ ZYX","1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]
for i, v in test
MsgBox % unique_characters(v)
return</syntaxhighlight>
Outputs:<pre>"" length = 0
Unique Characters
---------------------------
"." length = 1
Unique Characters
---------------------------
"abcABC" length = 6
Duplicates Found:
a @ 1,4 Hex = 61
---------------------------
"XYZ ZYX" length = 7
Duplicates Found:
X @ 1,7 Hex = 58
---------------------------
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" length = 36
Duplicates Found:
0 @ 10,25 Hex = 30
---------------------------</pre>
 
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f DETERMINE_IF_A_STRING_HAS_ALL_UNIQUE_CHARACTERS.AWK
BEGIN {
Line 79 ⟶ 761:
}
function max(x,y) { return((x > y) ? x : y) }
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 92 ⟶ 774:
|----------------------------------------|--------|------------|----------|-----|-----------|
</pre>
 
=={{header|BASIC}}==
==={{header|BASIC256}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vb">subroutine CaracteresUnicos (cad$)
lngt = length(cad$)
print 'Cadena = "'; cad$; '", longitud = '; lngt
for i = 1 to lngt
for j = i + 1 to lngt
if mid(cad$,i,1) = mid(cad$,j,1) then
print " Primer duplicado en las posiciones " & i & " y " & j & ", caracter = '" & mid(cad$,i,1) & "', valor hex = " & tohex(asc(mid(cad$,i,1)))
return
end if
next j
next i
print " Todos los caracteres son unicos." & chr(10)
end subroutine
 
call CaracteresUnicos("")
call CaracteresUnicos(".")
call CaracteresUnicos("abcABC")
call CaracteresUnicos("XYZ ZYX")
call CaracteresUnicos("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")</syntaxhighlight>
{{out}}
<pre>Similar as FreeBASIC entry.</pre>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
{{trans|FreeBASIC}}
<syntaxhighlight lang="qbasic">100 cls
110 sub caracteresunicos(cad$)
120 lngt = len(cad$)
130 print 'Cadena = "';cad$;'" longitud = ';lngt
140 for i = 1 to lngt
150 for j = i+1 to lngt
160 if mid$(cad$,i,1) = mid$(cad$,j,1) then
170 print " Primer duplicado en las posiciones ";i;" y ";j;", caracter = '";mid$(cad$,i,1);"', valor hex = ";hex$(asc(mid$(cad$,i,1)))
180 print
190 exit sub
200 endif
210 next j
220 next i
230 print " Todos los caracteres son unicos.";chr$(10)
240 end sub
250 caracteresunicos("")
260 caracteresunicos(".")
270 caracteresunicos("abcABC")
280 caracteresunicos("XYZ ZYX")
290 caracteresunicos("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")
300 end</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
==={{header|FreeBASIC}}===
<syntaxhighlight lang="freebasic">Sub CaracteresUnicos (cad As String)
Dim As Integer lngt = Len(cad)
Print "Cadena = """; cad; """, longitud = "; lngt
For i As Integer = 1 To lngt
For j As Integer = i + 1 To lngt
If Mid(cad,i,1) = Mid(cad,j,1) Then
Print " Primer duplicado en las posiciones " & i & _
" y " & j & ", caracter = '" & Mid(cad,i,1) & _
"', valor hex = " & Hex(Asc(Mid(cad,i,1)))
Print
Exit Sub
End If
Next j
Next i
Print " Todos los caracteres son unicos." & Chr(10)
End Sub
 
CaracteresUnicos ("")
CaracteresUnicos (".")
CaracteresUnicos ("abcABC")
CaracteresUnicos ("XYZ ZYX")
CaracteresUnicos ("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")
Sleep</syntaxhighlight>
{{out}}
<pre>
Cadena = "", longitud = 0
Todos los caracteres son unicos.
 
Cadena = ".", longitud = 1
Todos los caracteres son unicos.
 
Cadena = "abcABC", longitud = 6
Todos los caracteres son unicos.
 
Cadena = "XYZ ZYX", longitud = 7
Primer duplicado en las posiciones 1 y 7, caracter = 'X', valor hex = 58
 
Cadena = "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ", longitud = 36
Primer duplicado en las posiciones 10 y 25, caracter = '0', valor hex = 30
</pre>
 
==={{header|FutureBasic}}===
<syntaxhighlight lang="futurebsic">void local fn StringHasUniqueCharacters( string as CFStringRef )
long i, j, length = len( string )
if length == 0 then printf @"The string \"\" is empty and thus has no characters to compare.\n" : exit fn
printf @"The string: \"%@\" has %ld characters.", string, length
for i = 0 to length - 1
for j = i + 1 to length - 1
if ( fn StringIsEqual( mid( string, i, 1 ), mid( string, j, 1 ) ) )
CFStringRef duplicate = mid( string, i, 1 )
printf @"The first duplicate character, \"%@\", is found at positions %ld and %ld.", duplicate, i, j
printf @"The hex value of \"%@\" is: 0X%x\n", duplicate, fn StringCharacterAtIndex( duplicate, 0 )
exit fn
end if
next
next
printf @"All characters in string are unique.\n"
end fn
 
fn StringHasUniqueCharacters( @"" )
fn StringHasUniqueCharacters( @"." )
fn StringHasUniqueCharacters( @"abcABC" )
fn StringHasUniqueCharacters( @"XYZ ZYX" )
fn StringHasUniqueCharacters( @"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" )
 
HandleEvents</syntaxhighlight>
{{output}}
<pre>
The string "" is empty and thus has no characters to compare.
 
The string: "." has 1 characters.
All characters in string are unique.
 
The string: "abcABC" has 6 characters.
All characters in string are unique.
 
The string: "XYZ ZYX" has 7 characters.
The first duplicate character, "X", is found at positions 0 and 6.
The hex value of "X" is: 0X58
 
The string: "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" has 36 characters.
The first duplicate character, "0", is found at positions 9 and 24.
The hex value of "0" is: 0X30
</pre>
 
==={{header|PureBasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="purebasic">Procedure CaracteresUnicos(cad.s)
lngt.i = Len(cad)
PrintN("Cadena = '" + cad + "' longitud = " + Str(lngt))
For i.i = 1 To lngt
For j.i = i + 1 To lngt
If Mid(cad, i, 1) = Mid(cad, j, 1)
PrintN(" Primer duplicado en las posiciones " + Str(i) + " y " + Str(j) + ", caracter = '" + Mid(cad, i, 1) + "', valor hex = " + Hex(Asc(Mid(cad, i, 1))))
ProcedureReturn
EndIf
Next
Next
PrintN(" Todos los caracteres son unicos.")
EndProcedure
 
OpenConsole()
CaracteresUnicos("")
CaracteresUnicos(".")
CaracteresUnicos("abcABC")
CaracteresUnicos("XYZ ZYX")
CaracteresUnicos("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")
PrintN(#CRLF$ + "--- Press ENTER to exit ---"): Input()
CloseConsole()</syntaxhighlight>
{{out}}
<pre>Similar as FreeBASIC entry.</pre>
 
==={{header|Visual Basic .NET}}===
{{trans|C#}}
<syntaxhighlight lang="vbnet">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</syntaxhighlight>
{{out}}
<pre>'' (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]</pre>
 
==={{header|Yabasic}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vb">sub caracteresunicos (cad$)
local lngt, i, j
 
lngt = len(cad$)
print "cadena = \"", cad$, "\", longitud = ", lngt
for i = 1 to lngt
for j = i + 1 to lngt
if mid$(cad$,i,1) = mid$(cad$,j,1) then
print " Primer duplicado en las posiciones ", i, " y ", j, ", caracter = \'", mid$(cad$,i,1), "\', valor hex = ", hex$(asc(mid$(cad$,i,1)))
print
return
end if
next j
next i
print " Todos los caracteres son unicos.\n"
end sub
 
caracteresunicos ("")
caracteresunicos (".")
caracteresunicos ("abcABC")
caracteresunicos ("XYZ ZYX")
caracteresunicos ("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
 
=={{header|BQN}}==
O(n^2) method used for finding indices.
 
Hex function and loop similar to [[Determine if a string has all the same characters#BQN|Determine if a string has all the same characters]]
 
<syntaxhighlight lang="bqn">Check←=⌜˜
Hex←⊏⟜(∾"0A"+⟜↕¨10‿26)16{⌽𝕗|⌊∘÷⟜𝕗⍟(↕1+·⌊𝕗⋆⁼1⌈⊢)}
{
𝕊 str:
r←Check str
•Out {
∧´1=+´˘r ? "All characters are unique" ;
i←/⊏(1<+´˘r)/r
ch←(⊑i)⊑str
"'"∾ch∾"' (hex: "∾(Hex ch-@)∾", indices: "∾(•Fmt i)∾") duplicated in string '"∾str∾"'"
}
}¨⟨
""
"."
"abcABC"
"XYZ ZYX"
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
⟩</syntaxhighlight><syntaxhighlight lang="text">All characters are unique
All characters are unique
All characters are unique
'X' (hex: 58, indices: ⟨ 0 7 ⟩) duplicated in string 'XYZ ZYX'
'0' (hex: 30, indices: ⟨ 9 24 ⟩) duplicated in string '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'</syntaxhighlight>
 
=={{header|C}}==
In interactive mode, strings with spaces have to be enclosed in double quotes ("")
<syntaxhighlight lang="c">
<lang C>
#include<stdbool.h>
#include<string.h>
Line 223 ⟶ 1,150:
return 0;
}
</syntaxhighlight>
</lang>
Output, test strings from the task [[Determine_if_a_string_has_all_the_same_characters]] are also included :
<pre>
Line 258 ⟶ 1,185:
"4444 444k" - Length 9 - Contains the following duplicate characters :
'4' (0x34) at positions : 1 2 3 4 6 7 8
</pre>
 
=={{header|C sharp|C#}}==
<syntaxhighlight lang="csharp">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.")
)
);
}
}
}</syntaxhighlight>
{{out}}
<pre>
"" (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]
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#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;
}</syntaxhighlight>
 
{{out}}
<pre>
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.
 
</pre>
 
=={{header|Clojure}}==
<syntaxhighlight lang="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))))))))
</syntaxhighlight>
 
{{out}}
<pre>
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
</pre>
 
=={{header|Common Lisp}}==
<syntaxhighlight lang="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)</syntaxhighlight>
 
{{out}}
<pre>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</pre>
=={{header|D}}==
{{trans|C++}}
<syntaxhighlight lang="d">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");
}</syntaxhighlight>
{{out}}
<pre>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.</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Cpp}}
<syntaxhighlight lang="delphi">
program Determine_if_a_string_has_all_unique_characters;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils;
 
procedure string_has_repeated_character(str: string);
var
len, i, j: Integer;
begin
len := length(str);
Writeln('input: \', str, '\, length: ', len);
for i := 1 to len - 1 do
begin
for j := i + 1 to len do
begin
if str[i] = str[j] then
begin
Writeln('String contains a repeated character.');
Writeln('Character "', str[i], '" (hex ', ord(str[i]).ToHexString,
') occurs at positions ', i + 1, ' and ', j + 1, '.'#10);
Exit;
end;
end;
end;
Writeln('String contains no repeated characters.' + sLineBreak);
end;
 
begin
string_has_repeated_character('');
string_has_repeated_character('.');
string_has_repeated_character('abcABC');
string_has_repeated_character('XYZ ZYX');
string_has_repeated_character('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ');
readln;
end.</syntaxhighlight>
{{out}}
Delphi strings are start index in one.
<pre>
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 0058) occurs at positions 2 and 8.
 
input: \1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ\, length: 36
String contains a repeated character.
Character "0" (hex 0030) occurs at positions 11 and 26.</pre>
 
=={{header|EasyLang}}==
<syntaxhighlight>
func$ hex h .
for d in [ h div 16 h mod 16 ]
if d > 9
d += 7
.
h$ &= strchar (d + 48)
.
return h$
.
proc unichar s$ . .
len d[] 65536
s$[] = strchars s$
for i to len s$[]
h = strcode s$[i]
if d[h] <> 0
write " --> duplicates: '" & s$[i] & "' (" & hex h & "h)"
print "' positions: " & d[h] & ", " & i
return
.
d[h] = i
.
print "ok"
.
repeat
s$ = input
until s$ = "EOF"
print "'" & s$ & "'" & " length " & len s$
unichar s$
print ""
.
input_data
 
.
abcABC
XYZ ZYX
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ
EOF
</syntaxhighlight>
 
=={{header|Erlang|Erlang}}==
<syntaxhighlight lang="erlang">
-module(string_examples).
-export([all_unique/1, all_unique_examples/0]).
 
all_unique(String) ->
CharPosPairs = lists:zip(String, lists:seq(1, length(String))),
Duplicates = [{Char1, Pos1, Pos2} || {Char1, Pos1} <- CharPosPairs,
{Char2, Pos2} <- CharPosPairs,
Char1 =:= Char2,
Pos2 > Pos1],
case Duplicates of
[] ->
all_unique;
[{Char, P1, P2}|_] ->
{not_all_unique, Char, P1, P2}
end.
 
all_unique_examples() ->
lists:foreach(fun (Str) ->
io:format("String \"~ts\" (length ~p): ",
[Str, length(Str)]),
case all_unique(Str) of
all_unique ->
io:format("All characters unique.~n");
{not_all_unique, Char, P1, P2} ->
io:format("First duplicate is '~tc' (0x~.16b)"
" at positions ~p and ~p.~n",
[Char, Char, P1, P2])
end
end,
["", ".", "abcABC", "XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]).
</syntaxhighlight>
{{out}}
<pre>
$ erl
Erlang/OTP 23 [erts-11.1.8] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1]
 
Eshell V11.1.8 (abort with ^G)
1> c(string_examples).
{ok,string_examples}
2> string_examples:all_unique_examples().
String "" (length 0): All characters unique.
String "." (length 1): All characters unique.
String "abcABC" (length 6): All characters unique.
String "XYZ ZYX" (length 7): First duplicate is 'X' (0x58) at positions 1 and 7.
String "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length 36): First duplicate is '0' (0x30) at positions 10 and 25.
ok
 
</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Determine if a string has all unique characters. Nigel Galloway: June 9th., 2020
let 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"
</syntaxhighlight>
{{out}}
<pre>
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)
</pre>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: formatting fry generalizations io kernel math.parser
sequences sets ;
 
Line 279 ⟶ 1,598:
"XYZ ZYX"
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
[ uniqueness-report nl ] 5 napply</langsyntaxhighlight>
{{out}}
<pre>
Line 295 ⟶ 1,614:
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" — length 36 — contains repeated characters:
'0' (0x30) at indices 9 and 24.
</pre>
 
=={{header|Fortran}}==
<syntaxhighlight lang="fortran">
program demo_verify
implicit none
call nodup('')
call nodup('.')
call nodup('abcABC')
call nodup('XYZ ZYX')
call nodup('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ')
contains
 
subroutine nodup(str)
character(len=*),intent(in) :: str
character(len=*),parameter :: g='(*(g0))'
character(len=:),allocatable :: ch
integer :: where
integer :: i
where=0
ch=''
 
do i=1,len(str)-1
ch=str(i:i)
where=index(str(i+1:),ch)
if(where.ne.0)then
where=where+i
exit
endif
enddo
 
if(where.eq.0)then
write(*,g)'STR: "',str,'"',new_line('a'),'LEN: ',len(str),'. No duplicate characters found'
else
write(*,g)'STR: "',str,'"'
write(*,'(a,a,t1,a,a)')repeat(' ',where+5),'^',repeat(' ',i+5),'^'
write(*,g)'LEN: ',len(str), &
& '. Duplicate chars. First duplicate at positions ',i,' and ',where, &
& ' where a ','"'//str(where:where)//'"(hex:',hex(str(where:where)),') was found.'
endif
write(*,*)
 
end subroutine nodup
 
function hex(ch) result(hexstr)
character(len=1),intent(in) :: ch
character(len=:),allocatable :: hexstr
hexstr=repeat(' ',100)
write(hexstr,'(Z0)')ch
hexstr=trim(hexstr)
end function hex
 
end program demo_verify
</syntaxhighlight>
 
{{out}}
<pre>
STR: ""
LEN: 0. No duplicate characters found
 
STR: "."
LEN: 1. No duplicate characters found
 
STR: "abcABC"
LEN: 6. No duplicate characters found
 
STR: "XYZ ZYX"
^ ^
LEN: 7. Duplicate chars. First duplicate at positions 1 and 7 where a "X"(hex:58) was found.
 
STR: "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
^ ^
LEN: 36. Duplicate chars. First duplicate at positions 10 and 25 where a "0"(hex:30) was found.
 
</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 336 ⟶ 1,729:
analyze(s)
}
}</langsyntaxhighlight>
 
{{out}}
Line 376 ⟶ 1,769:
'🐡' (0x1f421) is duplicated at positions 3 and 8.
</pre>
 
=={{header|Groovy}}==
{{trans|Java}}
<syntaxhighlight lang="groovy">class StringUniqueCharacters {
static void main(String[] args) {
printf("%-40s %2s %10s %8s %s %s%n", "String", "Length", "All Unique", "1st Diff", "Hex", "Positions")
printf("%-40s %2s %10s %8s %s %s%n", "------------------------", "------", "----------", "--------", "---", "---------")
for (String s : ["", ".", "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 = (int) dup == 0 ? "yes" : "no"
String diff = (int) dup == 0 ? "" : "'" + dup + "'"
String hex = (int) dup == 0 ? "" : Integer.toHexString((int) dup).toUpperCase()
String position = (int) dup == 0 ? "" : pos1 + " " + pos2
printf("%-40s %-6d %-10s %-8s %-3s %-5s%n", input, input.length(), unique, diff, hex, position)
}
}</syntaxhighlight>
{{out}}
<pre>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</pre>
 
=={{header|Haskell}}==
<langsyntaxhighlight Haskelllang="haskell">import Data.List (groupBy, intersperse, sort, transpose)
import Data.Char (ord, toUpper)
import Data.Function(on)
import Numeric (showHex)
 
 
hexFromChar :: Char -> String
hexFromChar c = map toUpper $ showHex (ord c) ""
 
string :: String -> String
string xs = ('\"' : xs) ++<> "\""
 
char :: Char -> String
char c = ['\'', c, '\'']
 
size :: String -> String
size = show . length
 
positions :: (Int, Int) -> String
positions (a, b) = show a ++<> " " ++<> show b
 
forTable :: String -> [String]
forTable xs = string xs : go (allUnique xs)
Line 402 ⟶ 1,840:
go Nothing = [size xs, "yes", "", "", ""]
go (Just (u, ij)) = [size xs, "no", char u, hexFromChar u, positions ij]
 
showTable :: Bool -> Char -> Char -> Char -> [[String]] -> String
showTable _ _ _ _ [] = []
Line 410 ⟶ 1,848:
(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
Line 432 ⟶ 1,870:
(["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, _)on (y, _) -> x ==) yfst) . 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"]</langsyntaxhighlight>
{{out}}
<pre>
Line 458 ⟶ 1,896:
+--------------------------------------+------+----------+--------+---+---------+</pre>
 
Alternatively, defining a duplicatedCharIndices function in terms of sortOn, groupBy, and filter:
 
<syntaxhighlight lang="haskell">import Data.List (groupBy, intercalate, sortOn)
Or perhaps, as an alternative to grouping and sorting:
<lang haskell>import Data.ListFunction (find, intercalateon)
import Control.Arrow (second)
import Numeric (showHex)
import Data.Char (ord)
 
 
------------- INDICES OF DUPLICATED CHARACTERS -----------
 
duplicatedCharIndices :: String -> Maybe (Char, [Int])
duplicatedCharIndices xs = go $ zip xs [0 ..]s
| null duplicates = Nothing
| otherwise =
Just $
((,) . (snd . head) <*> fmap fst) (head (sortOn (fst . head) duplicates))
where
go []duplicates = Nothing
filter ((1 <) . length) $
go [_] = Nothing
groupBy (on (==) snd) $ sortOn snd $ zip [0 ..] s
go ((c, i):cs) =
 
maybe
(go cs) --
(Just . second ((i :) . return))
(find ((c ==) . fst) cs)
 
--------------------------- TEST--- -------------------------
main :: IO ()
main =
Line 482 ⟶ 1,924:
fTable
"First duplicated character, if any:"
((++)fmap (<$>) show <*> ((" (" ++<>) . (++<> ")") . show . length))
(maybe
"None"
Line 488 ⟶ 1,930:
unwords
[ show c
, "(0x" ++<> showHex (ord c) ") at"
, intercalate ", " (show <$> ixs)
]))
Line 494 ⟶ 1,936:
["", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]
 
 
--------------------------DISPLAY--------------------------
------------------------- DISPLAY ------------------------
 
fTable :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> String
fTable s xShow fxShow f xs =
unlines $
let rjust n c = drop . length <*> (replicate n c ++)
s : fmap (((<>) w. =rjust maximumw (length' ' . xShow) <$*> xs((" -> " <>) . fxShow . f)) xs
where
in unlines $
rjust sn :c fmap= (((++)drop . rjust w ' ' . xShow)length <*> (("replicate ->n " ++) . fxShow . f))c xs</lang>)
w = maximum (length . xShow <$> xs)
</syntaxhighlight>
{{Out}}
<pre>First duplicated character, if any:
Line 508 ⟶ 1,954:
"XYZ ZYX" (7) -> 'X' (0x58) at 0, 6
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (36) -> '0' (0x30) at 9, 24</pre>
 
 
Or, as an alternative to grouping and sorting – folding a string down to a Map of indices:
<syntaxhighlight lang="haskell">import qualified Safe as S
import qualified Data.Map.Strict as M
import Data.List (intercalate, foldl') --'
import Data.Ord (comparing)
import Numeric (showHex)
import Data.Char (ord)
 
 
----------- INDICES OF ANY DUPLICATED CHARACTERS ---------
 
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] -> String
fTable 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)</syntaxhighlight>
{{Out}}
<pre>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</pre>
 
=={{header|J}}==
Quotes surround the literals to make the computed one-at-a-time results present well in the combined table.
<syntaxhighlight lang="j">
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.
)
</syntaxhighlight>
Tests include those of the C example and a pair of MS-DOS line terminations.
<pre>
(;:'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 │
└──────┴──────────────────────────────────────┴─────────────┘
</pre>
 
More uniqueness tests with performance comparison
<syntaxhighlight lang="j">
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 -.@: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.
)
</syntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="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);
}
 
}
</syntaxhighlight>
{{Out}}
<pre>
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
</pre>
 
===Using Java 11===
<syntaxhighlight lang="java">
 
import java.util.HashSet;
import java.util.List;
import java.util.OptionalInt;
import java.util.Set;
 
public final class DetermineUniqueCharacters {
 
public static void main(String[] aArgs) {
List<String> words = List.of( "", ".", "abcABC", "XYZ ZYX", "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" );
for ( String word : words ) {
Set<Integer> seen = new HashSet<Integer>();
OptionalInt first = word.chars().filter( ch -> ! seen.add(ch) ).findFirst();
if ( first.isPresent() ) {
final char ch = (char) first.getAsInt();
final String hex = Integer.toHexString(ch).toUpperCase();
System.out.println("Word: \"" + word + "\" contains a repeated character.");
System.out.println("Character '" + ch + "' (hex " + hex + ") occurs at positions "
+ word.indexOf(ch) + " and " + word.indexOf(ch, word.indexOf(ch) + 1));
} else {
System.out.println("Word: \"" + word + "\" has all unique characters.");
}
System.out.println();
}
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
Word: "" has all unique characters.
 
Word: "." has all unique characters.
 
Word: "abcABC" has all unique characters.
 
Word: "XYZ ZYX" contains a repeated character.
Character 'Z' (hex 5A) occurs at positions 2 and 4
 
Word: "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" contains a repeated character.
Character '0' (hex 30) occurs at positions 9 and 24
</pre>
 
=={{header|JavaScript}}==
 
<langsyntaxhighlight lang="javascript">(() => {
'use strict';
 
Line 517 ⟶ 2,223:
const duplicatedCharIndices = s => {
const
duplicationsduplicates = filter(g => 1 < g.length)(
groupBy(on(eq)(snd))(
sortBy(comparingsortOn(snd))(
zip(enumFrom(0))(chars(s))
)
)
);
return 0 < duplicationsduplicates.length ? Just(() => {
constfanArrow(compose(snd, fst))(map(fst))(
firstCase =sortOn(compose(fst, fst))(
sortBy(comparing(compose(fst, fst)))(duplicates
duplications)[0]
)
) : Nothing();
return Just(Tuple(firstCase[0][1])(
firstCase.map(fst)
));
})() : Nothing()
};
 
Line 541 ⟶ 2,243:
console.log(
fTable('First duplicated character, if any:')(
s => `'${s}' (${s.length})`
)(maybe('None')(tpl => {
const [c, ixs] = Array.from(tpl);
Line 577 ⟶ 2,279:
// 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
Line 602 ⟶ 2,295:
// 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]
Line 652 ⟶ 2,351:
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
Line 672 ⟶ 2,377:
const snd = tpl => tpl[1];
 
// sortBysortOn :: (aOrd -b => (a -> Orderingb) -> [a] -> [a]
const sortBysortOn = f => xs =>
// Equivalent to sortBy(comparing(f)), but with f(x)
xs.slice()
// evaluated only once for each x in xs.
.sort(uncurry(f));
// ('Schwartzian' decorate-sort-undecorate).
xs => xs.map(
x => [f(x), x]
).sort(
(a, b) => a[0] < b[0] ? -1 : (a[0] > b[0] ? 1 : 0)
).map(x => x[1]);
 
// take :: Int -> [a] -> [a]
Line 714 ⟶ 2,425:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>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</pre>
 
 
Or, as an alternative to sorting and grouping – folding a string down to a dictionary of indices:
<langsyntaxhighlight lang="javascript">(() => {
'use strict';
 
// duplicatedCharIndices :: String -> Maybe (Char, [Int])
const duplicatedCharIndices = s => {
const go = xs =>minimumByMay(
1 < xs.length ? comparing(compose(fst, snd)) => {
)(filter(x => 1 < constx[1].length)(
rest = xsObject.sliceentries(1),
[c, i] = Arrays.fromsplit(xs[0]'');.reduce(
return maybe (go(rest)a, c, i) => Object.assign(a, {
compose [c]: (Just,a[c] secondArrow(cons|| []).concat(i)))
)(find(compose(eq(c }), fst))(rest)){}
})() : Nothing( );
return go( )
zip(chars(s))(enumFrom(0));
);
};
 
// ------------------------TEST------------------------
Line 748 ⟶ 2,457:
console.log(
fTable('First duplicated character, if any:')(
s => `'${s}' (${s.length })`
)(maybe('None')(tpl => {
const [c, ixs] = Array.from(tpl);
Line 784 ⟶ 2,493:
// 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);
 
// cons :: a -> [a] -> [a]
const cons = x =>
xs => [x].concat(xs);
 
 
// enumFrom :: Enum a => a -> [a]
Line 803 ⟶ 2,516:
}
 
// eq (==)filter :: Eq (a =-> aBool) -> [a] -> Bool[a]
const eqfilter = af => bxs => a === bxs.filter(f);
 
// findfst :: (a, -> Boolb) -> [a] -> Maybe a
const findfst = ptpl => xs => {tpl[0];
const i = xs.findIndex(p);
return -1 !== i ? (
Just(xs[i])
) : Nothing();
};
 
// fTable :: String -> (a -> String) -> (b -> String)
Line 829 ⟶ 2,537:
).join('\n');
};
 
// fst :: (a, b) -> a
const fst = tpl => tpl[0];
 
// length :: [a] -> Int
Line 846 ⟶ 2,551:
// 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);
 
// secondArrow :: (a -> b) -> ((c, a) -> (c, b))
const secondArrow = f => xy =>
// A function over a simple value lifted
// to a function over a tuple.
// f (a, b) -> (a, f(b))
Tuple(xy[0])(
f(xy[1])
);
 
// showHex :: Int -> String
Line 864 ⟶ 2,567:
 
// snd :: (a, b) -> b
const snd = tpl => tpl[1];
tpl[1];
 
// take :: Int -> [a] -> [a]
// take :: Int -> String -> String
const take = n => xs =>
xs => 'GeneratorFunction' !== xs.constructor.constructor.name ? (
xs.slice(0, n)
) : [].concat.apply([], Array.from({
Line 877 ⟶ 2,581:
return x.done ? [] : [x.value];
}));
 
// zip :: [a] -> [b] -> [(a, b)]
const zip = xs => ys => {
const
lng = Math.min(length(xs), length(xs)),
vs = take(lng)(ys);
return take(lng)(xs)
.map((x, i) => Tuple(x)(vs[i]));
};
 
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Line 899 ⟶ 2,594:
// MAIN ---
return main();
})();</langsyntaxhighlight>
{{Out}}
<pre>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</pre>
 
=={{header|jq}}==
"First Duplicate" is here understood to be the first character found to be a duplicate
when scanning from left to right, so the First Duplicate in XYYX is Y. It would require only a trivial
modification of `firstDuplicate` as defined here to implement the alternative
interpretation as the first character to be duplicated.
<syntaxhighlight lang="jq"># Emit null if there is no duplicate, else [c, [ix1, ix2]]
def firstDuplicate:
label $out
| foreach explode[] as $i ({ix: -1};
.ix += 1
| .ix as $ix
| .iu = ([$i] | implode)
| .[.iu] += [ $ix] ;
if .[.iu]|length == 2 then [.iu, .[.iu]], break $out else empty end )
// null ;</syntaxhighlight>
 
Some helper functions for accomplishing other aspects of the task:
<syntaxhighlight lang="jq"># hex of a number or a single (unicode) character
def hex:
def stream:
recurse(if . >= 16 then ./16|floor else empty end) | . % 16 ;
if type=="string" then explode[0] else . end
| [stream] | reverse
| map(if . < 10 then 48 + . else . + 87 end) | implode ;
 
def lpad($len): tostring | " " * ($len - width) + .;
 
def q: "«\(.)»";
 
def header:
"\("string"|q|lpad(38)) : |s| : C : hex IO=0";
 
def data:
"",
".",
"abcABC",
"XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
"😍😀🙌💃😍🙌" ;</syntaxhighlight>
The main program:<syntaxhighlight lang="jq">header,
(data
| firstDuplicate as [$k, $v]
| "\(q|lpad(38)) : \(length|lpad(4)) : \($k // " ") : \($k |if . then hex else " " end) \($v // [])" )
</syntaxhighlight>
{{out}}
<syntaxhighlight lang="sh">
«string» : |s| : C : hex IO=0
«» : 0 : : []
«.» : 1 : : []
«abcABC» : 6 : : []
«XYZ ZYX» : 7 : Z : 5A [2,4]
«1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ» : 36 : 0 : 30 [9,24]
«😍😀🙌💃😍🙌» : 6 : 😍:1f60d [0,4]</syntaxhighlight>
The last line above was adjusted manually as jq has no built-in function for computing the horizontal "printing" width of unicode strings in general.
 
=={{header|Julia}}==
<langsyntaxhighlight lang="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))
Line 935 ⟶ 2,685:
"🐠🐟🐡🦈🐬🐳🐋🐡",
])
</langsyntaxhighlight>{{out}}
<pre>
String | Length | All Unique | First Duplicate (Hex) | Positions
Line 949 ⟶ 2,699:
🐠🐟🐡🦈🐬🐳🐋🐡 8 no 🐡 (1f421) 3 8
</pre>
 
=={{header|Kotlin}}==
{{trans|Java}}
<syntaxhighlight lang="scala">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)
}</syntaxhighlight>
{{out}}
<pre>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</pre>
 
=={{header|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".
 
<syntaxhighlight lang="lua">local find, format = string.find, string.format
local 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)
end
end
 
local show = report_dup_char
show('coccyx')
show('')
show('.')
show('abcABC')
show('XYZ ZYX')
show('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ')
</syntaxhighlight>
 
{{out}}
<pre>"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</pre>
 
=={{header|Maple}}==
<syntaxhighlight lang="maple">CheckUnique:=proc(s)
local i, index;
printf("input: \"%s\", length: %a\n", s, StringTools:-Length(s));
for i from 1 to StringTools:-Length(s) do
index := StringTools:-SearchAll(s[i], s);
if (numelems([index]) > 1) then
printf("The given string has duplicated characters.\n");
printf("The first duplicated character is %a (0x%x) which appears at index %a.\n\n",
s[i], convert(s[i], 'bytes')[1], {index});
return;
end if;
end do;
# if no repeated found
printf("The given string has all unique characters.\n\n");
end proc:
 
# Test
CheckUnique("");
CheckUnique(".");
CheckUnique("abcABC");
CheckUnique("XYZ ZYX");
CheckUnique("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");</syntaxhighlight>
{{out}}
<pre>
input: "", length: 0
The given string has all unique characters.
 
input: ".", length: 1
The given string has all unique characters.
 
input: "abcABC", length: 6
The given string has all unique characters.
 
input: "XYZ ZYX", length: 7
The given string has duplicated characters.
The first duplicated character is "X" (0x58) which appears at index {1, 7}.
 
input: "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ", length: 36
The given string has duplicated characters.
The first duplicated character is "0" (0x30) which appears at index {10, 25}.
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[UniqueCharacters]
UniqueCharacters[s_String] := Module[{c, len, good = True},
c = Characters[s];
len = Length[c];
Print[s, " with length ", len];
Do[
If[c[[i]] == c[[j]],
Print["Character ", c[[i]], " is repeated at positions ", i,
" and ", j];
good = False
]
,
{i, len - 1},
{j, i + 1, len}
];
If[good,
Print["No repeats"];
True
,
False
]
]
UniqueCharacters[""]
UniqueCharacters["."]
UniqueCharacters["abcABC"]
UniqueCharacters["XYZ ZYX"]
UniqueCharacters["1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]</syntaxhighlight>
{{out}}
<pre> with length 0
No repeats
True
. with length 1
No repeats
True
abcABC with length 6
No repeats
True
XYZ ZYX with length 7
Character X is repeated at positions 1 and 7
Character Y is repeated at positions 2 and 6
Character Z is repeated at positions 3 and 5
False
1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ with length 36
Character 0 is repeated at positions 10 and 25
False</pre>
 
=={{header|Nanoquery}}==
<syntaxhighlight lang="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</syntaxhighlight>
{{out}}
<pre>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</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import unicode, strformat
 
proc checkUniqueChars(s: string) =
 
echo fmt"Checking string ""{s}"":"
let runes = s.toRunes
for i in 0..<runes.high:
let rune = runes[i]
for j in (i+1)..runes.high:
if runes[j] == rune:
echo "The string contains duplicate characters."
echo fmt"Character {rune} ({int(rune):x}) is present at positions {i+1} and {j+1}."
echo ""
return
echo "All characters in the string are unique."
echo ""
 
const Strings = ["",
".",
"abcABC",
"XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
"hétérogénéité",
"🎆🎃🎇🎈",
"😍😀🙌💃😍🙌",
"🐠🐟🐡🦈🐬🐳🐋🐡"]
 
for s in Strings:
s.checkUniqueChars()</syntaxhighlight>
 
{{out}}
<pre>Checking string "":
All characters in the string are unique.
 
Checking string ".":
All characters in the string are unique.
 
Checking string "abcABC":
All characters in the string are unique.
 
Checking string "XYZ ZYX":
The string contains duplicate characters.
Character X (58) is present at positions 1 and 7.
 
Checking string "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ":
The string contains duplicate characters.
Character 0 (30) is present at positions 10 and 25.
 
Checking string "hétérogénéité":
The string contains duplicate characters.
Character é (e9) is present at positions 2 and 4.
 
Checking string "🎆🎃🎇🎈":
All characters in the string are unique.
 
Checking string "😍😀🙌💃😍🙌":
The string contains duplicate characters.
Character 😍 (1f60d) is present at positions 1 and 5.
 
Checking string "🐠🐟🐡🦈🐬🐳🐋🐡":
The string contains duplicate characters.
Character 🐡 (1f421) is present at positions 3 and 8.</pre>
 
=={{header|OCaml}}==
Using a map to store characters we've met (as keys) and their first position (as indexes).
<syntaxhighlight lang="ocaml">module CMap = Map.Make(struct
type t = char
let compare = compare
end)
 
(** Add index as argument to string.fold_left *)
let string_fold_left_i f acc str =
snd (String.fold_left
(fun (index, acc) char -> (index+1, f acc index char))
(0, acc) str)
 
exception Found of int * int * char
 
let has_duplicates str =
try let _ = string_fold_left_i
(fun map index char ->
match CMap.find_opt char map with
| None -> CMap.add char index map
| Some i -> raise (Found (i,index,char)))
CMap.empty str
in Ok ()
with Found (i,j,c) -> Error (i,j,c)
 
let printer str =
Format.printf "%S (len %d) : " str (String.length str);
match has_duplicates str with
| Ok () -> Format.printf "No duplicates.\n"
| Error (i,j,c) -> Format.printf "Duplicate '%c' (%#x) at %d and %d\n" c (int_of_char c) i j
 
let () =
printer "";
printer ".";
printer "abcABC";
printer "XYZ ZYX";
printer "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"</syntaxhighlight>
 
{{out}}
<pre>"" (len 0) : No duplicates.
"." (len 1) : No duplicates.
"abcABC" (len 6) : No duplicates.
"XYZ ZYX" (len 7) : Duplicate 'Z' (0x5a) at 2 and 4
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (len 36) : Duplicate '0' (0x30) at 9 and 24</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 983 ⟶ 3,056:
say "no duplicated characters."
}
}</langsyntaxhighlight>
{{out}}
<pre>"" (length: 0) has no duplicated characters.
Line 1,010 ⟶ 3,083:
'Δ' GREEK CAPITAL LETTER DELTA (0x394) in positions: 1, 4</pre>
 
=={{header|Perl 6Phix}}==
As with [[Determine_if_a_string_has_all_the_same_characters#Phix]], you can use utf8_to_utf32() when needed.
{{works with|Rakudo|2019.07.1}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
Perl 6 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.
<span style="color: #008080;">procedure</span> <span style="color: #000000;">all_uniq</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
 
<span style="color: #004080;">string</span> <span style="color: #000000;">chars</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<lang perl6> -> $str {
<span style="color: #004080;">sequence</span> <span style="color: #000000;">posns</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
my $i = 0;
<span style="color: #000000;">multi</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
print "\n{$str.perl} (length: {$str.chars}), has ";
<span style="color: #004080;">integer</span> <span style="color: #000000;">lm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
my %m;
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
%m{$_}.push: ++$i for $str.comb;
<span style="color: #004080;">integer</span> <span style="color: #000000;">si</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
if any(%m.values) > 1 {
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">si</span><span style="color: #0000FF;">,</span><span style="color: #000000;">chars</span><span style="color: #0000FF;">)</span>
say "duplicated characters:";
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
say "'{.key}' ({.key.uninames}; hex ordinal: {(.key.ords).fmt: "0x%X"})" ~
<span style="color: #000000;">chars</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">si</span>
" in positions: {.value.join: ', '}" for %m.grep( *.value > 1 ).sort( *.value[0] );
<span style="color: #000000;">posns</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">}}</span>
} else {
say "no<span duplicatedstyle="color: characters.#008080;">else</span>
<span style="color: #000000;">posns</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">i</span>
}
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">posns</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">])=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
} for
<span style="color: #000000;">multi</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">k</span>
'',
<span style="color: #000000;">lm</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
'.',
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
'abcABC',
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
'XYZ ZYX',
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ',
<span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"\"%s\" (length %d): "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)}),</span>
'01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X',
<span style="color: #000000;">nod</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">ordinal</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lm</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">),</span>
'🦋🙂👨‍👩‍👧‍👦🙄ΔΔ̂ 🦋Δ👍👨‍👩‍👧‍👦'</lang>
<span style="color: #000000;">ess</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"s"</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">lm</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lm</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"all characters are unique"</span>
<span style="color: #0000FF;">:</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"contains %s duplicate%s:"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">nod</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ess</span><span style="color: #0000FF;">}))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">multi</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">mi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">multi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">ci</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">chars</span><span style="color: #0000FF;">[</span><span style="color: #000000;">mi</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s '%c'(#%02x) at %V\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ci</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ci</span><span style="color: #0000FF;">,</span><span style="color: #000000;">posns</span><span style="color: #0000FF;">[</span><span style="color: #000000;">mi</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"."</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"abcABC"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"XYZ ZYX"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"333"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"55"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tttTTT"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tTTTtt"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"4444 444k"</span><span style="color: #0000FF;">}</span>
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">,</span><span style="color: #000000;">all_uniq</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
<pre>"" (length: 0), has no duplicated characters.
"" (length 0): all characters are unique
 
"." (length: 1),: has no duplicatedall characters. are unique
 
"abcABC" (length: 6),: has no duplicatedall characters. are unique
 
"XYZ ZYX" (length: 7),: hascontains duplicatedthree charactersduplicates:
'Z'(#5A) at {3,5}
'X' (LATIN CAPITAL LETTER X; hex ordinal: 0x58) in positions: 1, 7
'Y'(#59) at {2,6}
'Y' (LATIN CAPITAL LETTER Y; hex ordinal: 0x59) in positions: 2, 6
'X'(#58) at {1,7}
'Z' (LATIN CAPITAL LETTER Z; hex ordinal: 0x5A) in positions: 3, 5
 
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length: 36),: hascontains duplicatedone charactersduplicate:
'0'(#30) at {10,25}
'0' (DIGIT ZERO; hex ordinal: 0x30) in positions: 10, 25
 
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" (length: 39),: hascontains duplicatedtwo charactersduplicates:
'0'(#30) at {1,11,26,38}
'0' (DIGIT ZERO; hex ordinal: 0x30) in positions: 1, 11, 26, 38
'X'(#58) at {35,39}
'X' (LATIN CAPITAL LETTER X; hex ordinal: 0x58) in positions: 35, 39
 
" " (length 3): contains one duplicate:
' '(#20) at {1,2,3}
 
"2" (length 1): all characters are unique
 
"333" (length 3): contains one duplicate:
"🦋🙂👨‍👩‍👧‍👦🙄ΔΔ̂ 🦋Δ👍👨‍👩‍👧‍👦" (length: 11), has duplicated characters:
'3'(#33) at {1,2,3}
'🦋' (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
"55" (length 2): contains one duplicate:
'Δ' (GREEK CAPITAL LETTER DELTA; hex ordinal: 0x394) in positions: 5, 9
'5'(#35) at {1,2}
 
"tttTTT" (length 6): contains two duplicates:
't'(#74) at {1,2,3}
'T'(#54) at {4,5,6}
 
"tTTTtt" (length 6): contains two duplicates:
'T'(#54) at {2,3,4}
't'(#74) at {1,5,6}
 
"4444 444k" (length 9): contains one duplicate:
'4'(#34) at {1,2,3,4,6,7,8}
</pre>
The results are effectively printed in order of posns[2], but that can easily be changed, for example by sorting multi before that final print loop.
 
=={{header|PhixPicoLisp}}==
<syntaxhighlight lang="picolisp">(de burn (Lst)
As with [[Determine_if_a_string_has_all_the_same_characters#Phix]], you can use utf8_to_utf32() when needed.
(let P 0
<lang Phix>procedure all_uniq(sequence s)
(by
string msg = "all characters are unique"
for i=1 to length '(s(A) do
integer si = s[i], (set A (inc 'P))
(put A 'P (char r = find(si,s,i+1A)) -- (or maybe rfind(si,s,i-1))
if r thengroup
Lst ) ) )
msg = sprintf(`first duplicate character "%c"(#%02x) at positions %d and %d`,{si,si,i,r})
(de first (Lst)
exit
end if(mini
end for '((L)
(nand
printf(1,"\"%s\" (length %d): %s\n",{s,length(s),msg})
(cdr L)
end procedure
(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")</syntaxhighlight>
{{out}}
<pre>
(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)
</pre>
 
=={{header|Prolog}}==
constant tests = {"",".","abcABC","XYZ ZYX","1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"}
<syntaxhighlight lang="prolog">report_duplicates(S) :-
for i=1 to length(tests) do all_uniq(tests[i]) end for</lang>
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').</syntaxhighlight>
{{out}}
<pre>
?- forall(test, true).
"" (length 0): all characters are unique
For value "":
"." (length 1): all characters are unique
"abcABC" (length 6): all All characters are unique
 
"XYZ ZYX" (length 7): first duplicate character "X"(#58) at positions 1 and 7
For value ".":
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length 36): first duplicate character "0"(#30) at positions 10 and 25
All characters are unique
</pre>
 
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.
 
?-</pre>
 
=={{header|Python}}==
Line 1,090 ⟶ 3,273:
Defined in terms of itertools.groupby:
 
<langsyntaxhighlight lang="python">'''Determine if a string has all unique characters'''
 
from itertools import groupby
Line 1,098 ⟶ 3,281:
def duplicatedCharIndices(s):
'''Just the first duplicated character, and
the first two indices of its occurrence, or
of Nothing if there are no duplications.
'''
def go(xs):
if 1 < len(xs):
duplicationsduplicates = list(filter(lambda kv: 1 < len(kv[1]), [
(k, list(v)) for k, v in groupby(
sorted(xs, key=lambda ix: (ix[1], ix[0])swap),
key=snd
)
]))
ifreturn duplications:Just(second(fmap(fst))(
dup = sorted(duplications, key=lambda kv: kv[1][0])[0]
return Just((dup[0], [x[0] for x in dup[1]]))duplicates,
else key=lambda kv: kv[1][0]
return Nothing()[0]
)) if duplicates else Nothing()
else:
return Nothing()
Line 1,179 ⟶ 3,363:
'''
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) -> a
def fst(tpl):
'''First member of a pair.'''
return tpl[0]
 
 
# head :: [a] -> a
def head(xs):
'''The first element of a non-empty list.'''
return xs[0] if isinstance(xs, list) else next(xs)
 
 
Line 1,190 ⟶ 3,394:
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[0], f(xy[1]))
 
 
Line 1,196 ⟶ 3,408:
'''Second member of a pair.'''
return tpl[1]
 
 
# swap :: (a, b) -> (b, a)
def swap(tpl):
'''The swapped components of a pair.'''
return (tpl[1], tpl[0])
 
 
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>First duplicated character, if any:
Line 1,210 ⟶ 3,428:
 
 
Or, as an alternative to sorting and grouping, folding a string down to a dictionary with '''reduce''':
 
<langsyntaxhighlight lang="python">'''Determine if a string has all unique characters'''
 
from functools import reduce
Line 1,220 ⟶ 3,438:
def duplicatedCharIndices(s):
'''Just the first duplicated character, and
the first two indices of its occurrence, or
of Nothing if there are no duplications.
'''
def go(xsdct, ic):
ifi, 1c <= len(xs):ic
return dict(i, c), rest = xs[0], xs[1:]
return maybe(go(rest))(dct,
**{c: dct[c] + [i] if c in compose(Just,dct swap,else first(cons([i)))]}
)
)(find(compose(eq(c), snd))(rest))
duplicates = else:[
(k, v) for return Nothing(k, v)
return go(list 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[0] < kxs[1][0]
) else sofar
)(sofar)
) if 1 < len(indices) else sofar
 
return reduce(
earliestDuplication,
reduce(
positionRecord,
enumerate(s),
{}
).items(),
Nothing()
)
 
 
Line 1,251 ⟶ 3,513:
fTable('First duplicated character, if any:')(
showSample
)(maybe('None')(showDuplicate))(duplicatedCharIndicesduplicatedCharIndices_)([
'', '.', 'abcABC', 'XYZ ZYX',
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'
Line 1,307 ⟶ 3,569:
 
 
# conshead :: a -> [a] -> [a]
def conshead(xxs):
'''ConstructionThe first element of a non-empty list from x as head,.'''
return xs[0] if and isinstance(xs, aslist) tail.else next(xs)
'''
return lambda xs: [x] + (
xs if isinstance(xs, list) else [xs]
)
 
 
# eq (==) :: Eq a => a -> a -> Bool
def eq(a):
'''True if a and b are comparable and a equals b.'''
return lambda b: a == b
 
 
# find :: (a -> Bool) -> [a] -> Maybe a
def find(p):
'''Just the first element in the list that matches p,
or Nothing if no elements match.
'''
def go(xs):
for x in xs:
if p(x):
return Just(x)
return Nothing()
return lambda xs: go(xs)
 
 
# first :: (a -> b) -> ((a, c) -> (b, c))
def first(f):
'''A simple function lifted to a function over a tuple,
with f applied only the first of two values.
'''
return lambda xy: (f(xy[0]), xy[1])
 
 
Line 1,359 ⟶ 3,590:
'''Second member of a pair.'''
return tpl[1]
 
 
# swap :: (a, b) -> (b, a)
def swap(tpl):
'''The swapped components of a pair.'''
return (tpl[1], tpl[0])
 
 
# MAIN ---
if __name__ == '__main__':
main()</langsyntaxhighlight>
{{Out}}
<pre>First duplicated character, if any:
Line 1,377 ⟶ 3,602:
'XYZ ZYX' (7) -> 'X' (0x58) at [0, 6]
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ' (36) -> '0' (0x30) at [9, 24]</pre>
 
=== 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.
 
<syntaxhighlight lang="python">import re
 
pattern = '(.)' + '.*?' + r'\1'
 
def find_dup_char(subject):
match = re.search(pattern, subject)
if match:
return match.groups(0)[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_char
show('coccyx')
show('')
show('.')
show('abcABC')
show('XYZ ZYX')
show('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ')
</syntaxhighlight>
 
{{out}}
<pre>"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
</pre>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ over find swap found ] is has ( $ c --> b )
 
[ dip [ 0 0 true ]
dup size 2 < iff
drop done
dup size 1 - times
[ behead 2dup has iff
[ swap find
dip not
2swap 2drop
i^ tuck + 1+ rot
0 conclude ] done
drop ]
drop ] is uniquechars ( $ --> n n b )
 
[ dup say 'String "'
echo$
say '" has length '
dup size echo
say ". "
dup uniquechars iff
[ say "There are no duplicated characters."
drop 2drop ]
else
[ rot over peek
dup say 'The character "'
emit
say '" (hex:'
16 base put
echo
base release
say ") is at positions "
swap echo
say " and "
echo
say "." ]
cr ] is task ( $ --> )
 
$ "" task
$ "." task
$ "abcABC" task
$ "XYZ ZYX" task
$ "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" task</syntaxhighlight>
 
{{out}}
 
<pre>String "" has length 0. There are no duplicated characters.
String "." has length 1. There are no duplicated characters.
String "abcABC" has length 6. There are no duplicated characters.
String "XYZ ZYX" has length 7. The character "X" (hex:58) is at positions 0 and 6.
String "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" has length 36. The character "0" (hex:30) is at positions 9 and 24.
</pre>
 
=={{header|R}}==
Most of this is adapted from [[Determine if a string has all the same characters#R]].
<syntaxhighlight lang="rsplus">isAllUnique <- function(string)
{
strLength <- nchar(string)
if(length(strLength) > 1)
{
#R has a distinction between the length of a string and that of a character vector. It is a common source
#of problems when coming from another language. We will try to avoid the topic here.
#For our purposes, let us only say that there is a good reason why we have made
#isAllUnique(c("foo", "bar") immediately throw an error.
stop("This task is intended for character vectors with lengths of at most 1.")
}
else if(length(strLength) == 0)
{
cat("Examining a character vector of length 0.",
"It is therefore made entirely of unique characters.\n")
TRUE
}
else if(strLength == 0)
{
cat("Examining a character vector of length 1, containing an empty string.",
"It is therefore made entirely of unique characters.\n")
TRUE
}
else if(strLength == 1)
{
cat("Examining the string", paste0(sQuote(string), ","),
"which is of length", paste0(strLength, "."),
"It is therefore made entirely of unique characters.\n")
TRUE
}
else
{
cat("Examining the string", paste0(sQuote(string), ","),
"which is of length", paste0(strLength, ":"), "\n")
#strsplit outputs a list. Its first element is the vector of characters that we desire.
characters <- strsplit(string, "")[[1]]
#Our use of match is using R's vector recycling rules. Element i is being checked
#against every other.
indexesOfDuplicates <- sapply(seq_len(strLength), function(i) match(TRUE, characters[i] == characters[-i], nomatch = -1)) + 1
firstDuplicateElementIndex <- indexesOfDuplicates[indexesOfDuplicates != 0][1]
if(is.na(firstDuplicateElementIndex))
{
cat("It has no duplicates. It is therefore made entirely of unique characters.\n")
TRUE
}
else
{
cat("It has duplicates. ")
firstDuplicatedCharacter <- characters[firstDuplicateElementIndex]
cat(sQuote(firstDuplicatedCharacter), "is the first duplicated character. It has hex value",
sprintf("0x%X", as.integer(charToRaw(firstDuplicatedCharacter))),
"and is at index", paste0(firstDuplicateElementIndex, "."),
"\nThis is a duplicate of the character at index",
paste0(match(firstDuplicateElementIndex, indexesOfDuplicates), "."), "\n")
FALSE
}
}
}
 
#Tests:
cat("Test: A string of length 0 (an empty string):\n")
cat("Test 1 of 2: An empty character vector:\n")
print(isAllUnique(character(0)))
cat("Test 2 of 2: A character vector containing the empty string:\n")
print(isAllUnique(""))
cat("Test: A string of length 1 which contains .:\n")
print(isAllUnique("."))
cat("Test: A string of length 6 which contains abcABC:\n")
print(isAllUnique("abcABC"))
cat("Test: A string of length 7 which contains XYZ ZYX:\n")
print(isAllUnique("XYZ ZYX"))
cat("Test: A string of length 36 doesn't contain the letter 'oh':\n")
print(isAllUnique("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"))</syntaxhighlight>
{{out}}
<pre>Test: A string of length 0 (an empty string):
Test 1 of 2: An empty character vector:
Examining a character vector of length 0. It is therefore made entirely of unique characters.
[1] TRUE
Test 2 of 2: A character vector containing the empty string:
Examining a character vector of length 1, containing an empty string. It is therefore made entirely of unique characters.
[1] TRUE
Test: A string of length 1 which contains .:
Examining the string ‘.’, which is of length 1. It is therefore made entirely of unique characters.
[1] TRUE
Test: A string of length 6 which contains abcABC:
Examining the string ‘abcABC’, which is of length 6:
It has no duplicates. It is therefore made entirely of unique characters.
[1] TRUE
Test: A string of length 7 which contains XYZ ZYX:
Examining the string ‘XYZ ZYX’, which is of length 7:
It has duplicates. ‘X’ is the first duplicated character. It has hex value 0x58 and is at index 7.
This is a duplicate of the character at index 1.
[1] FALSE
Test: A string of length 36 doesn't contain the letter 'oh':
Examining the string ‘1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ’, which is of length 36:
It has duplicates. ‘0’ is the first duplicated character. It has hex value 0x30 and is at index 25.
This is a duplicate of the character at index 10.
[1] FALSE</pre>
 
=={{header|Racket}}==
 
<syntaxhighlight lang="racket">#lang racket
 
(define (first-non-unique-element.index seq)
(let/ec ret
(for/fold ((es (hash))) ((e seq) (i (in-naturals)))
(if (hash-has-key? es e) (ret (list e (hash-ref es e) i)) (hash-set es e i)))
#f))
 
(define (report-if-a-string-has-all-unique-characters str)
(printf "~s (length ~a): ~a~%" str (string-length str)
(match (first-non-unique-element.index str)
[#f "contains all unique characters"]
[(list e i i′) (format "has character '~a' (0x~a) at index ~a (first seen at ~a)"
e (number->string (char->integer e) 16) i′ i)])))
 
(module+ main
(for-each report-if-a-string-has-all-unique-characters
(list "" "." "abcABC" "XYZ ZYX"
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")))
</syntaxhighlight>
 
{{out}}
<pre>"" (length 0): contains all unique characters
"." (length 1): contains all unique characters
"abcABC" (length 6): contains all unique characters
"XYZ ZYX" (length 7): has character 'Z' (0x5a) at index 4 (first seen at 2)
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length 36): has character '0' (0x30) at index 24 (first seen at 9)</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2020.08.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.
 
<syntaxhighlight lang="raku" line=""> -> $str {
my $i = 0;
print "\n{$str.raku} (length: {$str.chars}), has ";
my %m = $str.comb.Bag;
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[0] );
} else {
say "no duplicated characters."
}
} for
'',
'.',
'abcABC',
'XYZ ZYX',
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ',
'01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X',
'🦋🙂👨‍👩‍👧‍👦🙄ΔΔ̂ 🦋Δ👍👨‍👩‍👧‍👦'</syntaxhighlight>
{{out}}
<pre>"" (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
</pre>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="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.*/
Line 1,407 ⟶ 3,908:
if p\==0 then return k /*Find a dup? Return location.*/
end /*k*/
return 0 /*indicate all chars unique. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the internal defaults}}
<pre>
Line 1,432 ⟶ 3,933:
The characters in the string aren't all unique.
The character 0 ('30'x) at position 10 is repeated at position 25
</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
inputStr = ["",".","abcABC","XYZ ZYX","1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]
for Str in inputStr
for x = 1 to len(Str)
for y = x + 1 to len(Str)
if Str[x] = Str[y]
char = Str[x]
? "Input = " + "'" + Str + "'" + ", length = " + len(Str)
? " First duplicate at positions " + x + " and " + y + ", character = " + "'" + char + "'"
loop 3
ok
next
next
? "Input = " + "'" + Str + "'" + ", length = " + len(Str)
? " All characters are unique."
next
</syntaxhighlight>
{{out}}
<pre>
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'
 
Input = '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ', length = 36
First duplicate at positions 10 and 25, character = '0'
</pre>
 
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ → string
≪ "All chars unique" ""
1 string SIZE '''FOR''' j
string j DUP SUB
'''IF''' DUP2 POS
'''THEN''' DUP " duplicated at " +
string ROT POS →STR + " and " + j →STR +
ROT DROP SWAP
string SIZE 'j' STO
'''ELSE''' + '''END NEXT'''
DROP
≫ ≫ ''''UNICH?'''' STO
|
'''UNICH?''' ''( "string" -- "report" )''
initialize stack
scan string
extract jth character
if already seen
generate report
.
.
exit loop
else add the char to already seen list
clean stack
.
|}
{{in}}
<pre>
≪ { "" "." "abcABC" "XYZ ZYX" "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" } → cases
≪ 1 cases SIZE FOR n cases n GET UNICH? NEXT
≫ ≫ ´TASK’ STO
</pre>
{{out}}
<pre>
5: "All chars unique"
4: "All chars unique"
3: "All chars unique"
2: "Z duplicated at 3 and 5"
1: "0 duplicated at 10 and 25"
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">strings = ["",
".",
"abcABC",
Line 1,460 ⟶ 4,043:
puts res
end
</syntaxhighlight>
</lang>
{{out}}
<pre>"" (size 0) has no duplicates.
Line 1,473 ⟶ 4,056:
"🐠🐟🐡🦈🐬🐳🐋🐡" (size 8) has duplicate char 🐡 (0x1f421) on 2 and 7.
</pre>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">fn unique(s: &str) -> Option<(usize, usize, char)> {
s.chars().enumerate().find_map(|(i, c)| {
s.chars()
.enumerate()
.skip(i + 1)
.find(|(_, other)| c == *other)
.map(|(j, _)| (i, j, c))
})
}
 
fn main() {
let strings = [
"",
".",
"abcABC",
"XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",
"hétérogénéité",
"🎆🎃🎇🎈",
"😍😀🙌💃😍🙌",
"🐠🐟🐡🦈🐬🐳🐋🐡",
];
 
for string in &strings {
print!("\"{}\" (length {})", string, string.chars().count());
match unique(string) {
None => println!(" is unique"),
Some((i, j, c)) => println!(
" is not unique\n\tfirst duplicate: \"{}\" (U+{:0>4X}) at indices {} and {}",
c, c as usize, i, j
),
}
}
}
</syntaxhighlight>
{{out}}
<pre>"" (length 0) is unique
"." (length 1) is unique
"abcABC" (length 6) is unique
"XYZ ZYX" (length 7) is not unique
first duplicate: "X" (U+0058) at indices 0 and 6
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ" (length 36) is not unique
first duplicate: "0" (U+0030) at indices 9 and 24
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X" (length 39) is not unique
first duplicate: "0" (U+0030) at indices 0 and 10
"hétérogénéité" (length 13) is not unique
first duplicate: "é" (U+00E9) at indices 1 and 3
"🎆🎃🎇🎈" (length 4) is unique
"😍😀🙌💃😍🙌" (length 6) is not unique
first duplicate: "😍" (U+1F60D) at indices 0 and 4
"🐠🐟🐡🦈🐬🐳🐋🐡" (length 8) is not unique
first duplicate: "🐡" (U+1F421) at indices 2 and 7
</pre>
 
=={{header|Sidef}}==
<syntaxhighlight lang="ruby">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
}</syntaxhighlight>
{{out}}
<pre>
'' (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
</pre>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">package require Tcl 8.6 ; # For binary encode
 
array set yesno {1 Yes 2 No}
Line 1,511 ⟶ 4,217:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,524 ⟶ 4,230:
--> Character 'é' (hex: 0xe9) reappears at indexes: 1 3.
</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">fn analyze(s string) {
chars := s.runes()
le := chars.len
println("Analyzing $s which has a length of $le:")
if le > 1 {
for i := 0; i < le-1; i++ {
for j := i + 1; j < le; j++ {
if chars[j] == chars[i] {
println(" Not all characters in the string are unique.")
println(" '${chars[i]}'' (0x${chars[i]:x}) is duplicated at positions ${i+1} and ${j+1}.\n")
return
}
}
}
}
println(" All characters in the string are unique.\n")
}
fn main() {
strings := [
"",
".",
"abcABC",
"XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",
"hétérogénéité",
"🎆🎃🎇🎈",
"😍😀🙌💃😍🙌",
"🐠🐟🐡🦈🐬🐳🐋🐡",
]
for s in strings {
analyze(s)
}
}</syntaxhighlight>
 
{{out}}
<pre>
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.
</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">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)</syntaxhighlight>
 
{{out}}
<pre>
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.
</pre>
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">include xpllib; \contains StrLen function
 
proc StrUnique(S); \Show if string has unique chars
Line 1,559 ⟶ 4,421:
StrUnique("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");
StrUnique("thequickbrownfoxjumps");
]</langsyntaxhighlight>
 
{{out}}
Line 1,579 ⟶ 4,441:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="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));
Line 1,592 ⟶ 4,454:
else Void.Skip
}.fp(str)).concat(", "));
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">testStrings:=T("", ".", "abcABC", "XYZ ZYX",
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X");
foreach s in (testStrings){ stringUniqueness(s) }</langsyntaxhighlight>
{{out}}
<pre>
9,485

edits