Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Determine_if_a_string_has_all_unique_characters
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
;Task:
|
||||
|
||||
Given a character string (which may be empty, or have a length of zero characters):
|
||||
::* create a function/procedure/routine to:
|
||||
::::* determine if all the characters in the string are unique
|
||||
::::* indicate if or which character is duplicated and where
|
||||
::* display each string and its length (as the strings are being examined)
|
||||
::* a zero─length (empty) string shall be considered as unique
|
||||
::* process the strings from left─to─right
|
||||
::* if unique, display a message saying such
|
||||
::* if not unique, then:
|
||||
::::* display a message saying such
|
||||
::::* display what character is duplicated
|
||||
::::* only the 1<sup>st</sup> non─unique character need be displayed
|
||||
::::* display where "both" duplicated characters are in the string
|
||||
::::* the above messages can be part of a single message
|
||||
::::* display the hexadecimal value of the duplicated character
|
||||
|
||||
|
||||
|
||||
Use (at least) these five test values (strings):
|
||||
:::* a string of length 0 (an empty string)
|
||||
:::* a string of length 1 which is a single period (<big>'''.'''</big>)
|
||||
:::* a string of length 6 which contains: '''abcABC'''
|
||||
:::* a string of length 7 which contains a blank in the middle: '''XYZ ZYX'''
|
||||
:::* a string of length 36 which ''doesn't'' contain the letter "oh":
|
||||
:::::::: '''1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'''
|
||||
|
||||
|
||||
|
||||
Show all output here on this page.
|
||||
|
||||
{{Template:Strings}}
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
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)
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# syntax: GAWK -f DETERMINE_IF_A_STRING_HAS_ALL_UNIQUE_CHARACTERS.AWK
|
||||
BEGIN {
|
||||
for (i=0; i<=255; i++) { ord_arr[sprintf("%c",i)] = i } # build array[character]=ordinal_value
|
||||
n = split(",.,abcABC,XYZ ZYX,1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",arr,",")
|
||||
for (i in arr) {
|
||||
width = max(width,length(arr[i]))
|
||||
}
|
||||
width += 2
|
||||
fmt = "| %-*s | %-6s | %-10s | %-8s | %-3s | %-9s |\n"
|
||||
head1 = head2 = sprintf(fmt,width,"string","length","all unique","1st diff","hex","positions")
|
||||
gsub(/[^|\n]/,"-",head1)
|
||||
printf(head1 head2 head1) # column headings
|
||||
for (i=1; i<=n; i++) {
|
||||
main(arr[i])
|
||||
}
|
||||
printf(head1) # column footing
|
||||
exit(0)
|
||||
}
|
||||
function main(str, c,hex,i,leng,msg,position1,position2,tmp_arr) {
|
||||
msg = "yes"
|
||||
leng = length(str)
|
||||
for (i=1; i<=leng; i++) {
|
||||
c = substr(str,i,1)
|
||||
if (c in tmp_arr) {
|
||||
msg = "no"
|
||||
first_diff = "'" c "'"
|
||||
hex = sprintf("%2X",ord_arr[c])
|
||||
position1 = index(str,c)
|
||||
position2 = i
|
||||
break
|
||||
}
|
||||
tmp_arr[c] = ""
|
||||
}
|
||||
printf(fmt,width,"'" str "'",leng,msg,first_diff,hex,position1 " " position2)
|
||||
}
|
||||
function max(x,y) { return((x > y) ? x : y) }
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
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;
|
||||
|
|
@ -0,0 +1,394 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
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
|
||||
]
|
||||
]
|
||||
]
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
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")
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
test := ["",".","abcABC","XYZ ZYX","1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"]
|
||||
for i, v in test
|
||||
MsgBox % unique_characters(v)
|
||||
return
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
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"
|
||||
⟩
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
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'
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
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.")
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
#include<stdbool.h>
|
||||
#include<string.h>
|
||||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
|
||||
typedef struct positionList{
|
||||
int position;
|
||||
struct positionList *next;
|
||||
}positionList;
|
||||
|
||||
typedef struct letterList{
|
||||
char letter;
|
||||
int repititions;
|
||||
positionList* positions;
|
||||
struct letterList *next;
|
||||
}letterList;
|
||||
|
||||
letterList* letterSet;
|
||||
bool duplicatesFound = false;
|
||||
|
||||
void checkAndUpdateLetterList(char c,int pos){
|
||||
bool letterOccurs = false;
|
||||
letterList *letterIterator,*newLetter;
|
||||
positionList *positionIterator,*newPosition;
|
||||
|
||||
if(letterSet==NULL){
|
||||
letterSet = (letterList*)malloc(sizeof(letterList));
|
||||
letterSet->letter = c;
|
||||
letterSet->repititions = 0;
|
||||
|
||||
letterSet->positions = (positionList*)malloc(sizeof(positionList));
|
||||
letterSet->positions->position = pos;
|
||||
letterSet->positions->next = NULL;
|
||||
|
||||
letterSet->next = NULL;
|
||||
}
|
||||
|
||||
else{
|
||||
letterIterator = letterSet;
|
||||
|
||||
while(letterIterator!=NULL){
|
||||
if(letterIterator->letter==c){
|
||||
letterOccurs = true;
|
||||
duplicatesFound = true;
|
||||
|
||||
letterIterator->repititions++;
|
||||
positionIterator = letterIterator->positions;
|
||||
|
||||
while(positionIterator->next!=NULL)
|
||||
positionIterator = positionIterator->next;
|
||||
|
||||
newPosition = (positionList*)malloc(sizeof(positionList));
|
||||
newPosition->position = pos;
|
||||
newPosition->next = NULL;
|
||||
|
||||
positionIterator->next = newPosition;
|
||||
}
|
||||
if(letterOccurs==false && letterIterator->next==NULL)
|
||||
break;
|
||||
else
|
||||
letterIterator = letterIterator->next;
|
||||
}
|
||||
|
||||
if(letterOccurs==false){
|
||||
newLetter = (letterList*)malloc(sizeof(letterList));
|
||||
newLetter->letter = c;
|
||||
|
||||
newLetter->repititions = 0;
|
||||
|
||||
newLetter->positions = (positionList*)malloc(sizeof(positionList));
|
||||
newLetter->positions->position = pos;
|
||||
newLetter->positions->next = NULL;
|
||||
|
||||
newLetter->next = NULL;
|
||||
|
||||
letterIterator->next = newLetter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printLetterList(){
|
||||
positionList* positionIterator;
|
||||
letterList* letterIterator = letterSet;
|
||||
|
||||
while(letterIterator!=NULL){
|
||||
if(letterIterator->repititions>0){
|
||||
printf("\n'%c' (0x%x) at positions :",letterIterator->letter,letterIterator->letter);
|
||||
|
||||
positionIterator = letterIterator->positions;
|
||||
|
||||
while(positionIterator!=NULL){
|
||||
printf("%3d",positionIterator->position + 1);
|
||||
positionIterator = positionIterator->next;
|
||||
}
|
||||
}
|
||||
|
||||
letterIterator = letterIterator->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc,char** argv)
|
||||
{
|
||||
int i,len;
|
||||
|
||||
if(argc>2){
|
||||
printf("Usage : %s <Test string>\n",argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc==1||strlen(argv[1])==1){
|
||||
printf("\"%s\" - Length %d - Contains only unique characters.\n",argc==1?"":argv[1],argc==1?0:1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = strlen(argv[1]);
|
||||
|
||||
for(i=0;i<len;i++){
|
||||
checkAndUpdateLetterList(argv[1][i],i);
|
||||
}
|
||||
|
||||
printf("\"%s\" - Length %d - %s",argv[1],len,duplicatesFound==false?"Contains only unique characters.\n":"Contains the following duplicate characters :");
|
||||
|
||||
if(duplicatesFound==true)
|
||||
printLetterList();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(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))))))))
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
;; * 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)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
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");
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
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.
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
-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"]).
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// 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"
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
USING: formatting fry generalizations io kernel math.parser
|
||||
sequences sets ;
|
||||
|
||||
: repeated ( elt seq -- )
|
||||
[ dup >hex over ] dip indices first2
|
||||
" '%c' (0x%s) at indices %d and %d.\n" printf ;
|
||||
|
||||
: uniqueness-report ( str -- )
|
||||
dup dup length "%u — length %d — contains " printf
|
||||
[ duplicates ] keep over empty?
|
||||
[ 2drop "all unique characters." print ]
|
||||
[ "repeated characters:" print '[ _ repeated ] each ] if ;
|
||||
|
||||
""
|
||||
"."
|
||||
"abcABC"
|
||||
"XYZ ZYX"
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
|
||||
[ uniqueness-report nl ] 5 napply
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func analyze(s string) {
|
||||
chars := []rune(s)
|
||||
le := len(chars)
|
||||
fmt.Printf("Analyzing %q which has a length of %d:\n", s, le)
|
||||
if le > 1 {
|
||||
for i := 0; i < le-1; i++ {
|
||||
for j := i + 1; j < le; j++ {
|
||||
if chars[j] == chars[i] {
|
||||
fmt.Println(" Not all characters in the string are unique.")
|
||||
fmt.Printf(" %q (%#[1]x) is duplicated at positions %d and %d.\n\n", chars[i], i+1, j+1)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println(" All characters in the string are unique.\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
strings := []string{
|
||||
"",
|
||||
".",
|
||||
"abcABC",
|
||||
"XYZ ZYX",
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
|
||||
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",
|
||||
"hétérogénéité",
|
||||
"🎆🎃🎇🎈",
|
||||
"😍😀🙌💃😍🙌",
|
||||
"🐠🐟🐡🦈🐬🐳🐋🐡",
|
||||
}
|
||||
for _, s := range strings {
|
||||
analyze(s)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
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)
|
||||
where
|
||||
go Nothing = [size xs, "yes", "", "", ""]
|
||||
go (Just (u, ij)) = [size xs, "no", char u, hexFromChar u, positions ij]
|
||||
|
||||
showTable :: Bool -> Char -> Char -> Char -> [[String]] -> String
|
||||
showTable _ _ _ _ [] = []
|
||||
showTable header ver hor sep contents =
|
||||
unlines $
|
||||
hr :
|
||||
(if header
|
||||
then z : hr : zs
|
||||
else intersperse hr zss) <>
|
||||
[hr]
|
||||
where
|
||||
vss = map (map length) contents
|
||||
ms = map maximum (transpose vss) :: [Int]
|
||||
hr = concatMap (\n -> sep : replicate n hor) ms <> [sep]
|
||||
top = replicate (length hr) hor
|
||||
bss = map (map (`replicate` ' ') . zipWith (-) ms) vss
|
||||
zss@(z:zs) =
|
||||
zipWith
|
||||
(\us bs -> concat (zipWith (\x y -> (ver : x) <> y) us bs) <> [ver])
|
||||
contents
|
||||
bss
|
||||
|
||||
table xs =
|
||||
showTable
|
||||
True
|
||||
'|'
|
||||
'-'
|
||||
'+'
|
||||
(["string", "length", "all unique", "1st diff", "hex", "positions"] :
|
||||
map forTable xs)
|
||||
|
||||
allUnique
|
||||
:: (Ord b, Ord a, Num b, Enum b)
|
||||
=> [a] -> Maybe (a, (b, b))
|
||||
allUnique xs = go . groupBy (on (==) fst) . 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"]
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import Data.List (groupBy, intercalate, sortOn)
|
||||
import Data.Function (on)
|
||||
import Numeric (showHex)
|
||||
import Data.Char (ord)
|
||||
|
||||
|
||||
------------- INDICES OF DUPLICATED CHARACTERS -----------
|
||||
|
||||
duplicatedCharIndices :: String -> Maybe (Char, [Int])
|
||||
duplicatedCharIndices s
|
||||
| null duplicates = Nothing
|
||||
| otherwise =
|
||||
Just $
|
||||
((,) . (snd . head) <*> fmap fst) (head (sortOn (fst . head) duplicates))
|
||||
where
|
||||
duplicates =
|
||||
filter ((1 <) . length) $
|
||||
groupBy (on (==) snd) $ sortOn snd $ zip [0 ..] s
|
||||
|
||||
|
||||
--------------------------- TEST -------------------------
|
||||
main :: IO ()
|
||||
main =
|
||||
putStrLn $
|
||||
fTable
|
||||
"First duplicated character, if any:"
|
||||
(fmap (<>) 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)
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
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)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
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.
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
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.
|
||||
)
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// duplicatedCharIndices :: String -> Maybe (Char, [Int])
|
||||
const duplicatedCharIndices = s => {
|
||||
const
|
||||
duplicates = filter(g => 1 < g.length)(
|
||||
groupBy(on(eq)(snd))(
|
||||
sortOn(snd)(
|
||||
zip(enumFrom(0))(chars(s))
|
||||
)
|
||||
)
|
||||
);
|
||||
return 0 < duplicates.length ? Just(
|
||||
fanArrow(compose(snd, fst))(map(fst))(
|
||||
sortOn(compose(fst, fst))(
|
||||
duplicates
|
||||
)[0]
|
||||
)
|
||||
) : Nothing();
|
||||
};
|
||||
|
||||
// ------------------------TEST------------------------
|
||||
const main = () =>
|
||||
console.log(
|
||||
fTable('First duplicated character, if any:')(
|
||||
s => `'${s}' (${s.length})`
|
||||
)(maybe('None')(tpl => {
|
||||
const [c, ixs] = Array.from(tpl);
|
||||
return `'${c}' (0x${showHex(ord(c))}) at ${ixs.join(', ')}`
|
||||
}))(duplicatedCharIndices)([
|
||||
"", ".", "abcABC", "XYZ ZYX",
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
|
||||
])
|
||||
);
|
||||
|
||||
|
||||
// -----------------GENERIC FUNCTIONS------------------
|
||||
|
||||
// Just :: a -> Maybe a
|
||||
const Just = x => ({
|
||||
type: 'Maybe',
|
||||
Nothing: false,
|
||||
Just: x
|
||||
});
|
||||
|
||||
// Nothing :: Maybe a
|
||||
const Nothing = () => ({
|
||||
type: 'Maybe',
|
||||
Nothing: true,
|
||||
});
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = a => b => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
// chars :: String -> [Char]
|
||||
const chars = s => s.split('');
|
||||
|
||||
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
|
||||
const compose = (...fs) =>
|
||||
x => fs.reduceRight((a, f) => f(a), x);
|
||||
|
||||
// enumFrom :: Enum a => a -> [a]
|
||||
function* enumFrom(x) {
|
||||
let v = x;
|
||||
while (true) {
|
||||
yield v;
|
||||
v = 1 + v;
|
||||
}
|
||||
}
|
||||
|
||||
// eq (==) :: Eq a => a -> a -> Bool
|
||||
const eq = a => b => a === b;
|
||||
|
||||
// fanArrow (&&&) :: (a -> b) -> (a -> c) -> (a -> (b, c))
|
||||
const fanArrow = f =>
|
||||
// Compose a function from a simple value to a tuple of
|
||||
// the separate outputs of two different functions.
|
||||
g => x => Tuple(f(x))(g(x));
|
||||
|
||||
// filter :: (a -> Bool) -> [a] -> [a]
|
||||
const filter = f => xs => xs.filter(f);
|
||||
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl => tpl[0];
|
||||
|
||||
// fTable :: String -> (a -> String) -> (b -> String)
|
||||
// -> (a -> b) -> [a] -> String
|
||||
const fTable = s => xShow => fxShow => f => xs => {
|
||||
// Heading -> x display function ->
|
||||
// fx display function ->
|
||||
// f -> values -> tabular string
|
||||
const
|
||||
ys = xs.map(xShow),
|
||||
w = Math.max(...ys.map(length));
|
||||
return s + '\n' + zipWith(
|
||||
a => b => a.padStart(w, ' ') + ' -> ' + b
|
||||
)(ys)(
|
||||
xs.map(x => fxShow(f(x)))
|
||||
).join('\n');
|
||||
};
|
||||
|
||||
// groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
|
||||
const groupBy = fEq =>
|
||||
// Typical usage: groupBy(on(eq)(f), xs)
|
||||
xs => 0 < xs.length ? (() => {
|
||||
const
|
||||
tpl = xs.slice(1).reduce(
|
||||
(gw, x) => {
|
||||
const
|
||||
gps = gw[0],
|
||||
wkg = gw[1];
|
||||
return fEq(wkg[0])(x) ? (
|
||||
Tuple(gps)(wkg.concat([x]))
|
||||
) : Tuple(gps.concat([wkg]))([x]);
|
||||
},
|
||||
Tuple([])([xs[0]])
|
||||
);
|
||||
return tpl[0].concat([tpl[1]])
|
||||
})() : [];
|
||||
|
||||
// length :: [a] -> Int
|
||||
const length = xs =>
|
||||
// Returns Infinity over objects without finite length.
|
||||
// This enables zip and zipWith to choose the shorter
|
||||
// argument when one is non-finite, like cycle, repeat etc
|
||||
(Array.isArray(xs) || 'string' === typeof xs) ? (
|
||||
xs.length
|
||||
) : Infinity;
|
||||
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = f => xs =>
|
||||
(Array.isArray(xs) ? (
|
||||
xs
|
||||
) : xs.split('')).map(f);
|
||||
|
||||
// maybe :: b -> (a -> b) -> Maybe a -> b
|
||||
const maybe = v =>
|
||||
// Default value (v) if m is Nothing, or f(m.Just)
|
||||
f => m => m.Nothing ? v : f(m.Just);
|
||||
|
||||
// on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
|
||||
const on = f =>
|
||||
g => a => b => f(g(a))(g(b));
|
||||
|
||||
// ord :: Char -> Int
|
||||
const ord = c => c.codePointAt(0);
|
||||
|
||||
// showHex :: Int -> String
|
||||
const showHex = n =>
|
||||
n.toString(16);
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => tpl[1];
|
||||
|
||||
// sortOn :: Ord b => (a -> b) -> [a] -> [a]
|
||||
const sortOn = f =>
|
||||
// Equivalent to sortBy(comparing(f)), but with f(x)
|
||||
// evaluated only once for each x in xs.
|
||||
// ('Schwartzian' decorate-sort-undecorate).
|
||||
xs => xs.map(
|
||||
x => [f(x), x]
|
||||
).sort(
|
||||
(a, b) => a[0] < b[0] ? -1 : (a[0] > b[0] ? 1 : 0)
|
||||
).map(x => x[1]);
|
||||
|
||||
// take :: Int -> [a] -> [a]
|
||||
// take :: Int -> String -> String
|
||||
const take = n => xs =>
|
||||
'GeneratorFunction' !== xs.constructor.constructor.name ? (
|
||||
xs.slice(0, n)
|
||||
) : [].concat.apply([], Array.from({
|
||||
length: n
|
||||
}, () => {
|
||||
const x = xs.next();
|
||||
return x.done ? [] : [x.value];
|
||||
}));
|
||||
|
||||
// uncurry :: (a -> b -> c) -> ((a, b) -> c)
|
||||
const uncurry = f =>
|
||||
(x, y) => f(x)(y)
|
||||
|
||||
// zip :: [a] -> [b] -> [(a, b)]
|
||||
const zip = xs => ys => {
|
||||
const
|
||||
lng = Math.min(length(xs), length(ys)),
|
||||
vs = take(lng)(ys);
|
||||
return take(lng)(xs)
|
||||
.map((x, i) => Tuple(x)(vs[i]));
|
||||
};
|
||||
|
||||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
const zipWith = f =>
|
||||
xs => ys => {
|
||||
const
|
||||
lng = Math.min(length(xs), length(ys)),
|
||||
vs = take(lng)(ys);
|
||||
return take(lng)(xs)
|
||||
.map((x, i) => f(x)(vs[i]));
|
||||
};
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
(() => {
|
||||
'use strict';
|
||||
|
||||
// duplicatedCharIndices :: String -> Maybe (Char, [Int])
|
||||
const duplicatedCharIndices = s =>
|
||||
minimumByMay(
|
||||
comparing(compose(fst, snd))
|
||||
)(filter(x => 1 < x[1].length)(
|
||||
Object.entries(
|
||||
s.split('').reduce(
|
||||
(a, c, i) => Object.assign(a, {
|
||||
[c]: (a[c] || []).concat(i)
|
||||
}), {}
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
// ------------------------TEST------------------------
|
||||
const main = () =>
|
||||
console.log(
|
||||
fTable('First duplicated character, if any:')(
|
||||
s => `'${s}' (${s.length })`
|
||||
)(maybe('None')(tpl => {
|
||||
const [c, ixs] = Array.from(tpl);
|
||||
return `'${c}' (0x${showHex(ord(c))}) at ${ixs.join(', ')}`
|
||||
}))(duplicatedCharIndices)([
|
||||
"", ".", "abcABC", "XYZ ZYX",
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ"
|
||||
])
|
||||
);
|
||||
|
||||
|
||||
// -----------------GENERIC FUNCTIONS------------------
|
||||
|
||||
// Just :: a -> Maybe a
|
||||
const Just = x => ({
|
||||
type: 'Maybe',
|
||||
Nothing: false,
|
||||
Just: x
|
||||
});
|
||||
|
||||
// Nothing :: Maybe a
|
||||
const Nothing = () => ({
|
||||
type: 'Maybe',
|
||||
Nothing: true,
|
||||
});
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = a => b => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
// chars :: String -> [Char]
|
||||
const chars = s => s.split('');
|
||||
|
||||
// comparing :: (a -> b) -> (a -> a -> Ordering)
|
||||
const comparing = f =>
|
||||
x => y => {
|
||||
const
|
||||
a = f(x),
|
||||
b = f(y);
|
||||
return a < b ? -1 : (a > b ? 1 : 0);
|
||||
};
|
||||
|
||||
// compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
|
||||
const compose = (...fs) =>
|
||||
x => fs.reduceRight((a, f) => f(a), x);
|
||||
|
||||
// enumFrom :: Enum a => a -> [a]
|
||||
function* enumFrom(x) {
|
||||
let v = x;
|
||||
while (true) {
|
||||
yield v;
|
||||
v = 1 + v;
|
||||
}
|
||||
}
|
||||
|
||||
// filter :: (a -> Bool) -> [a] -> [a]
|
||||
const filter = f => xs => xs.filter(f);
|
||||
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl => tpl[0];
|
||||
|
||||
// fTable :: String -> (a -> String) -> (b -> String)
|
||||
// -> (a -> b) -> [a] -> String
|
||||
const fTable = s => xShow => fxShow => f => xs => {
|
||||
// Heading -> x display function ->
|
||||
// fx display function ->
|
||||
// f -> values -> tabular string
|
||||
const
|
||||
ys = xs.map(xShow),
|
||||
w = Math.max(...ys.map(length));
|
||||
return s + '\n' + zipWith(
|
||||
a => b => a.padStart(w, ' ') + ' -> ' + b
|
||||
)(ys)(
|
||||
xs.map(x => fxShow(f(x)))
|
||||
).join('\n');
|
||||
};
|
||||
|
||||
// length :: [a] -> Int
|
||||
const length = xs =>
|
||||
// Returns Infinity over objects without finite length.
|
||||
// This enables zip and zipWith to choose the shorter
|
||||
// argument when one is non-finite, like cycle, repeat etc
|
||||
(Array.isArray(xs) || 'string' === typeof xs) ? (
|
||||
xs.length
|
||||
) : Infinity;
|
||||
|
||||
// maybe :: b -> (a -> b) -> Maybe a -> b
|
||||
const maybe = v =>
|
||||
// Default value (v) if m is Nothing, or f(m.Just)
|
||||
f => m => m.Nothing ? v : f(m.Just);
|
||||
|
||||
// minimumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a
|
||||
const minimumByMay = f =>
|
||||
xs => xs.reduce((a, x) =>
|
||||
a.Nothing ? Just(x) : (
|
||||
f(x)(a.Just) < 0 ? Just(x) : a
|
||||
), Nothing());
|
||||
|
||||
// ord :: Char -> Int
|
||||
const ord = c => c.codePointAt(0);
|
||||
|
||||
// showHex :: Int -> String
|
||||
const showHex = n =>
|
||||
n.toString(16);
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl =>
|
||||
tpl[1];
|
||||
|
||||
// take :: Int -> [a] -> [a]
|
||||
// take :: Int -> String -> String
|
||||
const take = n =>
|
||||
xs => 'GeneratorFunction' !== xs.constructor.constructor.name ? (
|
||||
xs.slice(0, n)
|
||||
) : [].concat.apply([], Array.from({
|
||||
length: n
|
||||
}, () => {
|
||||
const x = xs.next();
|
||||
return x.done ? [] : [x.value];
|
||||
}));
|
||||
|
||||
// zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
||||
const zipWith = f =>
|
||||
xs => ys => {
|
||||
const
|
||||
lng = Math.min(length(xs), length(ys)),
|
||||
vs = take(lng)(ys);
|
||||
return take(lng)(xs)
|
||||
.map((x, i) => f(x)(vs[i]));
|
||||
};
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# 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 ;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# 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",
|
||||
"😍😀🙌💃😍🙌" ;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
header,
|
||||
(data
|
||||
| firstDuplicate as [$k, $v]
|
||||
| "\(q|lpad(38)) : \(length|lpad(4)) : \($k // " ") : \($k |if . then hex else " " end) \($v // [])" )
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
«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]
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
arr(s) = [c for c in s]
|
||||
alldup(a) = filter(x -> length(x) > 1, [findall(x -> x == a[i], a) for i in 1:length(a)])
|
||||
firstduplicate(s) = (a = arr(s); d = alldup(a); isempty(d) ? nothing : first(d))
|
||||
|
||||
function testfunction(strings)
|
||||
println("String | Length | All Unique | First Duplicate | Positions\n" *
|
||||
"-------------------------------------------------------------------------------------")
|
||||
for s in strings
|
||||
n = firstduplicate(s)
|
||||
a = arr(s)
|
||||
println(rpad(s, 38), rpad(length(s), 11), n == nothing ? "yes" :
|
||||
rpad("no $(a[n[1]])", 26) * rpad(n[1], 4) * "$(n[2])")
|
||||
end
|
||||
end
|
||||
|
||||
testfunction([
|
||||
"",
|
||||
".",
|
||||
"abcABC",
|
||||
"XYZ ZYX",
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
|
||||
"hétérogénéité",
|
||||
"🎆🎃🎇🎈",
|
||||
"😍😀🙌💃😍🙌",
|
||||
"🐠🐟🐡🦈🐬🐳🐋🐡",
|
||||
])
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
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)
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
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')
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
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");
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
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"]
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
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()
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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"
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use utf8;
|
||||
binmode(STDOUT, ':utf8');
|
||||
use List::AllUtils qw(uniq);
|
||||
use Unicode::UCD 'charinfo';
|
||||
|
||||
for my $str (
|
||||
'',
|
||||
'.',
|
||||
'abcABC',
|
||||
'XYZ ZYX',
|
||||
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ',
|
||||
'01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X',
|
||||
'Δ👍👨👍Δ',
|
||||
'ΔδΔ̂ΔΛ',
|
||||
) {
|
||||
my @S;
|
||||
push @S, $1 while $str =~ /(\X)/g;
|
||||
printf qq{\n"$str" (length: %d) has }, scalar @S;
|
||||
if (@S != uniq @S ) {
|
||||
say "duplicated characters:";
|
||||
my %P;
|
||||
push @{ $P{$S[$_]} }, 1+$_ for 0..$#S;
|
||||
for my $k (sort keys %P) {
|
||||
next unless @{$P{$k}} > 1;
|
||||
printf "'%s' %s (0x%x) in positions: %s\n", $k, charinfo(ord $k)->{'name'}, ord($k), join ', ', @{$P{$k}};
|
||||
}
|
||||
} else {
|
||||
say "no duplicated characters."
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
(phixonline)-->
|
||||
<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>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">posns</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
|
||||
<span style="color: #000000;">multi</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">lm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</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;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<span style="color: #000000;">chars</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">si</span>
|
||||
<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>
|
||||
<span style="color: #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>
|
||||
<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>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
(de burn (Lst)
|
||||
(let P 0
|
||||
(by
|
||||
'((A)
|
||||
(set A (inc 'P))
|
||||
(put A 'P (char A)) )
|
||||
group
|
||||
Lst ) ) )
|
||||
(de first (Lst)
|
||||
(mini
|
||||
'((L)
|
||||
(nand
|
||||
(cdr L)
|
||||
(apply min (mapcar val L)) ) )
|
||||
Lst ) )
|
||||
(de uniq? (Str)
|
||||
(let M (first (burn (chop Str)))
|
||||
(ifn M
|
||||
(prinl Str " (length " (length Str) "): all characters are unique")
|
||||
(prin
|
||||
Str " (length " (length Str) "): first duplicate character "
|
||||
(car M)
|
||||
" at positions " )
|
||||
(println (mapcar val M)) ) ) )
|
||||
(uniq?)
|
||||
(uniq? ".")
|
||||
(uniq? "abcABC")
|
||||
(uniq? "XYZ ZYX")
|
||||
(uniq? "1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ")
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
report_duplicates(S) :-
|
||||
duplicates(S, Dups),
|
||||
format('For value "~w":~n', S),
|
||||
report(Dups),
|
||||
nl.
|
||||
|
||||
report(Dups) :-
|
||||
maplist(only_one_position, Dups),
|
||||
format(' All characters are unique~n').
|
||||
|
||||
report(Dups) :-
|
||||
exclude(only_one_position, Dups, [c(Char,Positions)|_]),
|
||||
reverse(Positions, PosInOrder),
|
||||
atomic_list_concat(PosInOrder, ', ', PosAsList),
|
||||
format(' The character ~w is non unique at ~p~n', [Char, PosAsList]).
|
||||
|
||||
only_one_position(c(_,[_])).
|
||||
|
||||
duplicates(S, Count) :-
|
||||
atom_chars(S, Chars),
|
||||
char_count(Chars, 0, [], Count).
|
||||
|
||||
char_count([], _, C, C).
|
||||
char_count([C|T], Index, Counted, Result) :-
|
||||
select(c(C,Positions), Counted, MoreCounted),
|
||||
succ(Index, Index1),
|
||||
char_count(T, Index1, [c(C,[Index|Positions])|MoreCounted], Result).
|
||||
char_count([C|T], Index, Counted, Result) :-
|
||||
\+ member(c(C,_), Counted),
|
||||
succ(Index, Index1),
|
||||
char_count(T, Index1, [c(C,[Index])|Counted], Result).
|
||||
|
||||
test :- report_duplicates('').
|
||||
test :- report_duplicates('.').
|
||||
test :- report_duplicates('abcABC').
|
||||
test :- report_duplicates('XYZ ZYX').
|
||||
test :- report_duplicates('1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ').
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
'''Determine if a string has all unique characters'''
|
||||
|
||||
from itertools import groupby
|
||||
|
||||
|
||||
# duplicatedCharIndices :: String -> Maybe (Char, [Int])
|
||||
def duplicatedCharIndices(s):
|
||||
'''Just the first duplicated character, and
|
||||
the indices of its occurrence, or
|
||||
Nothing if there are no duplications.
|
||||
'''
|
||||
def go(xs):
|
||||
if 1 < len(xs):
|
||||
duplicates = list(filter(lambda kv: 1 < len(kv[1]), [
|
||||
(k, list(v)) for k, v in groupby(
|
||||
sorted(xs, key=swap),
|
||||
key=snd
|
||||
)
|
||||
]))
|
||||
return Just(second(fmap(fst))(
|
||||
sorted(
|
||||
duplicates,
|
||||
key=lambda kv: kv[1][0]
|
||||
)[0]
|
||||
)) if duplicates else Nothing()
|
||||
else:
|
||||
return Nothing()
|
||||
return go(list(enumerate(s)))
|
||||
|
||||
|
||||
# TEST ----------------------------------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Test over various strings.'''
|
||||
|
||||
def showSample(s):
|
||||
return repr(s) + ' (' + str(len(s)) + ')'
|
||||
|
||||
def showDuplicate(cix):
|
||||
c, ix = cix
|
||||
return repr(c) + (
|
||||
' (' + hex(ord(c)) + ') at ' + repr(ix)
|
||||
)
|
||||
|
||||
print(
|
||||
fTable('First duplicated character, if any:')(
|
||||
showSample
|
||||
)(maybe('None')(showDuplicate))(duplicatedCharIndices)([
|
||||
'', '.', 'abcABC', 'XYZ ZYX',
|
||||
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
# FORMATTING ----------------------------------------------
|
||||
|
||||
# fTable :: String -> (a -> String) ->
|
||||
# (b -> String) -> (a -> b) -> [a] -> String
|
||||
def fTable(s):
|
||||
'''Heading -> x display function -> fx display function ->
|
||||
f -> xs -> tabular string.
|
||||
'''
|
||||
def go(xShow, fxShow, f, xs):
|
||||
ys = [xShow(x) for x in xs]
|
||||
w = max(map(len, ys))
|
||||
return s + '\n' + '\n'.join(map(
|
||||
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
|
||||
xs, ys
|
||||
))
|
||||
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
|
||||
xShow, fxShow, f, xs
|
||||
)
|
||||
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
# Just :: a -> Maybe a
|
||||
def Just(x):
|
||||
'''Constructor for an inhabited Maybe (option type) value.
|
||||
Wrapper containing the result of a computation.
|
||||
'''
|
||||
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
|
||||
|
||||
|
||||
# Nothing :: Maybe a
|
||||
def Nothing():
|
||||
'''Constructor for an empty Maybe (option type) value.
|
||||
Empty wrapper returned where a computation is not possible.
|
||||
'''
|
||||
return {'type': 'Maybe', 'Nothing': True}
|
||||
|
||||
|
||||
# fmap :: (a -> b) -> [a] -> [b]
|
||||
def fmap(f):
|
||||
'''fmap over a list.
|
||||
f lifted to a function over a list.
|
||||
'''
|
||||
return lambda xs: [f(x) for x in xs]
|
||||
|
||||
|
||||
# fst :: (a, b) -> 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)
|
||||
|
||||
|
||||
# maybe :: b -> (a -> b) -> Maybe a -> b
|
||||
def maybe(v):
|
||||
'''Either the default value v, if m is Nothing,
|
||||
or the application of f to x,
|
||||
where m is Just(x).
|
||||
'''
|
||||
return lambda f: lambda m: v if (
|
||||
None is m or m.get('Nothing')
|
||||
) else f(m.get('Just'))
|
||||
|
||||
|
||||
# second :: (a -> b) -> ((c, a) -> (c, b))
|
||||
def second(f):
|
||||
'''A simple function lifted to a function over a tuple,
|
||||
with f applied only to the second of two values.
|
||||
'''
|
||||
return lambda xy: (xy[0], f(xy[1]))
|
||||
|
||||
|
||||
# snd :: (a, b) -> b
|
||||
def snd(tpl):
|
||||
'''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()
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
'''Determine if a string has all unique characters'''
|
||||
|
||||
from functools import reduce
|
||||
|
||||
|
||||
# duplicatedCharIndices :: String -> Maybe (Char, [Int])
|
||||
def duplicatedCharIndices(s):
|
||||
'''Just the first duplicated character, and
|
||||
the indices of its occurrence, or
|
||||
Nothing if there are no duplications.
|
||||
'''
|
||||
def go(dct, ic):
|
||||
i, c = ic
|
||||
return dict(
|
||||
dct,
|
||||
**{c: dct[c] + [i] if c in dct else [i]}
|
||||
)
|
||||
duplicates = [
|
||||
(k, v) for (k, v)
|
||||
in reduce(go, enumerate(s), {}).items()
|
||||
if 1 < len(v)
|
||||
]
|
||||
return Just(
|
||||
min(duplicates, key=compose(head, snd))
|
||||
) if duplicates else Nothing()
|
||||
|
||||
|
||||
# And another alternative here would be to fuse the 1 < len(v)
|
||||
# filtering, and the min() search for the earliest duplicate,
|
||||
# down to a single `earliestDuplication` fold:
|
||||
|
||||
# duplicatedCharIndices_ :: String -> Maybe (Char, [Int])
|
||||
def duplicatedCharIndices_(s):
|
||||
'''Just the first duplicated character, and
|
||||
the indices of its occurrence, or
|
||||
Nothing if there are no duplications.
|
||||
'''
|
||||
def positionRecord(dct, ic):
|
||||
i, c = ic
|
||||
return dict(
|
||||
dct,
|
||||
**{c: dct[c] + [i] if c in dct else [i]}
|
||||
)
|
||||
|
||||
def earliestDuplication(sofar, charPosns):
|
||||
c, indices = charPosns
|
||||
return (
|
||||
maybe(Just((c, indices)))(
|
||||
lambda kxs: Just((c, indices)) if (
|
||||
# Earlier duplication ?
|
||||
indices[0] < kxs[1][0]
|
||||
) else sofar
|
||||
)(sofar)
|
||||
) if 1 < len(indices) else sofar
|
||||
|
||||
return reduce(
|
||||
earliestDuplication,
|
||||
reduce(
|
||||
positionRecord,
|
||||
enumerate(s),
|
||||
{}
|
||||
).items(),
|
||||
Nothing()
|
||||
)
|
||||
|
||||
|
||||
# TEST ----------------------------------------------------
|
||||
# main :: IO ()
|
||||
def main():
|
||||
'''Test over various strings.'''
|
||||
|
||||
def showSample(s):
|
||||
return repr(s) + ' (' + str(len(s)) + ')'
|
||||
|
||||
def showDuplicate(cix):
|
||||
c, ix = cix
|
||||
return repr(c) + (
|
||||
' (' + hex(ord(c)) + ') at ' + repr(ix)
|
||||
)
|
||||
|
||||
print(
|
||||
fTable('First duplicated character, if any:')(
|
||||
showSample
|
||||
)(maybe('None')(showDuplicate))(duplicatedCharIndices_)([
|
||||
'', '.', 'abcABC', 'XYZ ZYX',
|
||||
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
# FORMATTING ----------------------------------------------
|
||||
|
||||
# fTable :: String -> (a -> String) ->
|
||||
# (b -> String) -> (a -> b) -> [a] -> String
|
||||
def fTable(s):
|
||||
'''Heading -> x display function -> fx display function ->
|
||||
f -> xs -> tabular string.
|
||||
'''
|
||||
def go(xShow, fxShow, f, xs):
|
||||
ys = [xShow(x) for x in xs]
|
||||
w = max(map(len, ys))
|
||||
return s + '\n' + '\n'.join(map(
|
||||
lambda x, y: y.rjust(w, ' ') + ' -> ' + fxShow(f(x)),
|
||||
xs, ys
|
||||
))
|
||||
return lambda xShow: lambda fxShow: lambda f: lambda xs: go(
|
||||
xShow, fxShow, f, xs
|
||||
)
|
||||
|
||||
|
||||
# GENERIC -------------------------------------------------
|
||||
|
||||
# Just :: a -> Maybe a
|
||||
def Just(x):
|
||||
'''Constructor for an inhabited Maybe (option type) value.
|
||||
Wrapper containing the result of a computation.
|
||||
'''
|
||||
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
|
||||
|
||||
|
||||
# Nothing :: Maybe a
|
||||
def Nothing():
|
||||
'''Constructor for an empty Maybe (option type) value.
|
||||
Empty wrapper returned where a computation is not possible.
|
||||
'''
|
||||
return {'type': 'Maybe', 'Nothing': True}
|
||||
|
||||
|
||||
# compose :: ((a -> a), ...) -> (a -> a)
|
||||
def compose(*fs):
|
||||
'''Composition, from right to left,
|
||||
of a series of functions.
|
||||
'''
|
||||
return lambda x: reduce(
|
||||
lambda a, f: f(a),
|
||||
fs[::-1], x
|
||||
)
|
||||
|
||||
|
||||
# head :: [a] -> a
|
||||
def head(xs):
|
||||
'''The first element of a non-empty list.'''
|
||||
return xs[0] if isinstance(xs, list) else next(xs)
|
||||
|
||||
|
||||
# maybe :: b -> (a -> b) -> Maybe a -> b
|
||||
def maybe(v):
|
||||
'''Either the default value v, if m is Nothing,
|
||||
or the application of f to x,
|
||||
where m is Just(x).
|
||||
'''
|
||||
return lambda f: lambda m: v if (
|
||||
None is m or m.get('Nothing')
|
||||
) else f(m.get('Just'))
|
||||
|
||||
|
||||
# snd :: (a, b) -> b
|
||||
def snd(tpl):
|
||||
'''Second member of a pair.'''
|
||||
return tpl[1]
|
||||
|
||||
|
||||
# MAIN ---
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
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')
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
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"))
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*REXX pgm determines if a string is comprised of all unique characters (no duplicates).*/
|
||||
@.= /*assign a default for the @. array. */
|
||||
parse arg @.1 /*obtain optional argument from the CL.*/
|
||||
if @.1='' then do; @.1= /*Not specified? Then assume defaults.*/
|
||||
@.2= .
|
||||
@.3= 'abcABC'
|
||||
@.4= 'XYZ ZYX'
|
||||
@.5= '1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ'
|
||||
end
|
||||
|
||||
do j=1; if j\==1 & @.j=='' then leave /*String is null & not j=1? We're done*/
|
||||
say copies('─', 79) /*display a separator line (a fence). */
|
||||
say 'Testing for the string (length' length(@.j)"): " @.j
|
||||
say
|
||||
dup= isUnique(@.j)
|
||||
say 'The characters in the string' word("are aren't", 1 + (dup>0) ) 'all unique.'
|
||||
if dup==0 then iterate
|
||||
?= substr(@.j, dup, 1)
|
||||
say 'The character ' ? " ('"c2x(?)"'x) at position " dup ,
|
||||
' is repeated at position ' pos(?, @.j, dup+1)
|
||||
end /*j*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
isUnique: procedure; parse arg x /*obtain the character string.*/
|
||||
do k=1 to length(x) - 1 /*examine all but the last. */
|
||||
p= pos( substr(x, k, 1), x, k + 1) /*see if the Kth char is a dup*/
|
||||
if p\==0 then return k /*Find a dup? Return location.*/
|
||||
end /*k*/
|
||||
return 0 /*indicate all chars unique. */
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#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")))
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
-> $str {
|
||||
my $i = 0;
|
||||
print "\n{$str.raku} (length: {$str.chars}), has ";
|
||||
my %m;
|
||||
%m{$_}.push: ++$i for $str.comb;
|
||||
if any(%m.values) > 1 {
|
||||
say "duplicated characters:";
|
||||
say "'{.key}' ({.key.uninames}; hex ordinal: {(.key.ords).fmt: "0x%X"})" ~
|
||||
" in positions: {.value.join: ', '}" for %m.grep( *.value > 1 ).sort( *.value[0] );
|
||||
} else {
|
||||
say "no duplicated characters."
|
||||
}
|
||||
} for
|
||||
'',
|
||||
'.',
|
||||
'abcABC',
|
||||
'XYZ ZYX',
|
||||
'1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ',
|
||||
'01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X',
|
||||
'🦋🙂👨👩👧👦🙄ΔΔ̂ 🦋Δ👍👨👩👧👦'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
strings = ["",
|
||||
".",
|
||||
"abcABC",
|
||||
"XYZ ZYX",
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
|
||||
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X",
|
||||
"hétérogénéité",
|
||||
"🎆🎃🎇🎈",
|
||||
"😍😀🙌💃😍🙌",
|
||||
"🐠🐟🐡🦈🐬🐳🐋🐡",]
|
||||
|
||||
strings.each do |str|
|
||||
seen = {}
|
||||
print "#{str.inspect} (size #{str.size}) "
|
||||
res = "has no duplicates." #may change
|
||||
str.chars.each_with_index do |c,i|
|
||||
if seen[c].nil?
|
||||
seen[c] = i
|
||||
else
|
||||
res = "has duplicate char #{c} (#{'%#x' % c.ord}) on #{seen[c]} and #{i}."
|
||||
break
|
||||
end
|
||||
end
|
||||
puts res
|
||||
end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package require Tcl 8.6 ; # For binary encode
|
||||
|
||||
array set yesno {1 Yes 2 No}
|
||||
|
||||
set test {
|
||||
{}
|
||||
{.}
|
||||
{abcABC}
|
||||
{XYZ ZYX}
|
||||
{1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ}
|
||||
{hétérogénéité}
|
||||
}
|
||||
|
||||
# Loop through test strings
|
||||
foreach str $test {
|
||||
set chars [dict create] ; # init dictionary
|
||||
set num_chars 1 ; # In case of empty string
|
||||
|
||||
# Loop through characters in string
|
||||
for {set i 0} {$i < [string length $str]} {incr i} {
|
||||
set c [string index $str $i] ; # get char at index
|
||||
dict lappend chars $c $i ; # add index to a running list for key=char
|
||||
set indexes [dict get $chars $c] ; # get the whole running list
|
||||
set num_chars [llength $indexes] ; # count the # of indexes
|
||||
if {$num_chars > 1} {
|
||||
break ; # Found a duplicate, break out of the loop
|
||||
}
|
||||
}
|
||||
|
||||
# Handle Output
|
||||
puts [format "Tested: %38s (len: %2d). All unique? %3s. " \
|
||||
"'$str'" [string length $str] $yesno($num_chars)]
|
||||
if {$num_chars > 1} {
|
||||
puts [format " --> Character '%s' (hex: 0x%s) reappears at indexes: %s." \
|
||||
$c [binary encode hex $c] $indexes]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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)
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
include xpllib; \contains StrLen function
|
||||
|
||||
proc StrUnique(S); \Show if string has unique chars
|
||||
char S;
|
||||
int L, I, J, K;
|
||||
[L:= StrLen(S);
|
||||
IntOut(0, L); Text(0, ": ^""); Text(0, S); ChOut(0, ^"); CrLf(0);
|
||||
for I:= 0 to L-1 do
|
||||
for J:= I+1 to L-1 do
|
||||
[if S(I) = S(J) then
|
||||
[ChOut(0, \tab\ 9);
|
||||
for K:= 0 to I do ChOut(0, ^ );
|
||||
ChOut(0, ^^);
|
||||
for K:= 0 to J-I-2 do ChOut(0, ^ );
|
||||
ChOut(0, ^^);
|
||||
Text(0, " Duplicate character: ");
|
||||
ChOut(0, S(I));
|
||||
Text(0, ", hex ");
|
||||
SetHexDigits(2);
|
||||
HexOut(0, S(I));
|
||||
CrLf(0);
|
||||
return;
|
||||
];
|
||||
];
|
||||
Text(0, " Unique, no duplicates"); CrLf(0);
|
||||
];
|
||||
|
||||
[Text(0, "Length"); CrLf(0);
|
||||
StrUnique("");
|
||||
StrUnique(".");
|
||||
StrUnique("abcABC");
|
||||
StrUnique("XYZ ZYX");
|
||||
StrUnique("1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ");
|
||||
StrUnique("thequickbrownfoxjumps");
|
||||
]
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
sub caracteresunicos (cad$)
|
||||
local lngt
|
||||
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")
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
fcn stringUniqueness(str){ // Does not handle Unicode
|
||||
sz,unique,uz,counts := str.len(), str.unique(), unique.len(), str.counts();
|
||||
println("Length %d: \"%s\"".fmt(sz,str));
|
||||
if(sz==uz or uz==1) println("\tAll characters are unique");
|
||||
else // counts is (char,count, char,count, ...)
|
||||
println("\tDuplicate: ",
|
||||
counts.pump(List,Void.Read,fcn(str,c,n){
|
||||
if(n>1){
|
||||
is,z:=List(),-1; do(n){ is.append(z=str.find(c,z+1)) }
|
||||
"'%s' (0x%x)[%s]".fmt(c,c.toAsc(),is.concat(","))
|
||||
}
|
||||
else Void.Skip
|
||||
}.fp(str)).concat(", "));
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
testStrings:=T("", ".", "abcABC", "XYZ ZYX",
|
||||
"1234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ",
|
||||
"01234567890ABCDEFGHIJKLMN0PQRSTUVWXYZ0X");
|
||||
foreach s in (testStrings){ stringUniqueness(s) }
|
||||
Loading…
Add table
Add a link
Reference in a new issue