Unique characters: Difference between revisions

Add two StandardML versions
(Add two StandardML versions)
 
(61 intermediate revisions by 24 users not shown)
Line 13:
{{Template:Strings}}
<br><br>
 
=={{header|11l}}==
<syntaxhighlight lang="11l">DefaultDict[Char, Int] d
L(s) [‘133252abcdeeffd’, ‘a6789798st’, ‘yxcdfgxcyz’]
L(c) s
d[c]++
 
L(k) sorted(d.keys())
I d[k] == 1
print(k, end' ‘’)</syntaxhighlight>
 
{{out}}
<pre>
156bgstz
</pre>
 
=={{header|8080 Assembly}}==
<syntaxhighlight lang="8080asm">puts: equ 9 ; CP/M print syscall
TERM: equ '$' ; CP/M string terminator
org 100h
jmp demo
;;; Given a list of strings, find characters appearing only
;;; in one string and once only.
;;; Input: DE = list of strings, BC = start of output
unique: xra a ; Zero out the workspace
mvi h,upage
mov l,a
uzbuf: mov m,a
inr l
jnz uzbuf
push d
ustr: pop h
mov e,m ; Load next string pointer
inx h
mov d,m
inx h
mov a,d ; End of list?
ora e
jz uclat ; Then go find the uniques
push h ; Otherwise, keep list pointer
mvi h,upage
uchar: ldax d ; Get character
cpi TERM ; Done?
jz ustr ; Then do next string
mov l,a ; Otherwise, count the character
inr m
inx d ; Next character
jmp uchar
uclat: lxi h,upage*256 ; Start of page
utst: dcr m ; Is this character included?
jnz uskip
mov a,l ; If so add it to the output
stax b
inx b
uskip: inr l ; Try next character
jnz utst
mvi a,TERM ; CP/M string terminator
stax b
ret
;;; Demo code
demo: lxi b,outbuf ; Set BC to location of output buffe
lxi d,list ; Set DE to the list of strings
call unique ; Call the code
mvi c,puts ; Print the result
lxi d,outbuf
jmp 5
;;; List of strings
list: dw str1, str2, str3, 0
str1: db '133252abcdeeffd', TERM
str2: db 'a6789798st', TERM
str3: db 'yxcdfgxcyz', TERM
;;; Memory
upage: equ ($/256)+1 ; Workspace for 'unique'
outbuf: equ (upage+1)*256 ; Output </syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|8086 Assembly}}==
<syntaxhighlight lang="asm"> cpu 8086
org 100h
puts: equ 9 ; MS-DOS syscall to print a string
TERM: equ '$' ; String terminator
section .text
jmp demo
;;; Given a list of strings, find characters appearing
;;; only in one string and once only.
;;; Input: BX = list of strings, DX = start of output
;;; Assuming DS = ES
unique: mov cx,128 ; Zero out array
mov di,uniqws
xor ax,ax
rep stosw
.str: mov si,[bx] ; Get next string
inc bx
inc bx
test si,si ; Done?
jz .fltr ; Then start writing to output
.char: lodsb ; Read character
cmp al,TERM ; Done?
je .str ; Then get next string
mov di,ax ; Otherwise, count the character
inc byte [di+uniqws]
jmp .char
.fltr: mov di,dx
xor bx,bx
.fchr: dec byte [bx+uniqws]
jnz .skip ; Character occurs once?
mov al,bl ; If so, write it
stosb
.skip: inc bl ; Any more?
jnz .fchr
mov [di],byte TERM ; Terminate string
ret
;;; Demo code
demo: mov bx,list ; Find unique characters
mov dx,outbuf
call unique
mov ah,puts ; Print result
mov dx,outbuf
int 21h
ret
section .data
list: dw .s1, .s2, .s3, 0
.s1: db '133252abcdeeffd', TERM
.s2: db 'a6789798st', TERM
.s3: db 'yxcdfgxcyz', TERM
section .bss
uniqws: resb 256
outbuf: resb 256</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE MAX="128"
CHAR ARRAY counts(MAX)
 
BYTE FUNC GetCount(CHAR ARRAY s CHAR c)
BYTE count,i
 
count=0
FOR i=1 TO s(0)
DO
IF s(i)=c THEN
count==+1
FI
OD
RETURN (count)
 
PROC UpdateCounts(CHAR ARRAY s)
BYTE i,c
 
FOR i=1 TO s(0)
DO
c=s(i)
counts(c)==+GetCount(s,c)
OD
RETURN
 
PROC Main()
DEFINE PTR="CARD"
DEFINE CNT="3"
PTR ARRAY l(CNT)
INT i
 
l(0)="133252abcdeeffd"
l(1)="a6789798st"
l(2)="yxcdfgxcyz"
 
SetBlock(counts,MAX,0)
FOR i=0 TO CNT-1
DO
UpdateCounts(l(i))
OD
FOR i=0 TO MAX-1
DO
IF counts(i)=1 THEN
Put(i) Put(32)
FI
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Unique_characters.png Screenshot from Atari 8-bit computer]
<pre>
1 5 6 b g s t z
</pre>
 
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Text_Io;
 
procedure Unique_Characters is
 
List : array (Character) of Natural := (others => 0);
 
procedure Count (Item : String) is
begin
for C of Item loop
List (C) := List (C) + 1;
end loop;
end Count;
 
procedure Put_Only_Once is
use Ada.Text_Io;
begin
for C in List'Range loop
if List (C) = 1 then
Put (C);
Put (' ');
end if;
end loop;
New_Line;
end Put_Only_Once;
 
begin
Count ("133252abcdeeffd");
Count ("a6789798st");
Count ("yxcdfgxcyz");
Put_Only_Once;
end Unique_Characters;</syntaxhighlight>
{{out}}
<pre>1 5 6 b g s t z</pre>
 
=={{header|ALGOL 68}}==
Case sensitive. This assumes a small character set (e.g. ASCII where max abs char is 255). Would probably need some work if CHAR is Unicode.
<syntaxhighlight lang="algol68">BEGIN # find the characters that occur once only in a list of stings #
# returns the characters that occur only once in the elements of s #
OP UNIQUE = ( []STRING s )STRING:
BEGIN
[ 0 : max abs char ]INT counts; # counts of used characters #
FOR i FROM LWB counts TO UPB counts DO counts[ i ] := 0 OD;
# count the occurances of the characters in the elements of s #
FOR i FROM LWB s TO UPB s DO
FOR j FROM LWB s[ i ] TO UPB s[ i ] DO
counts[ ABS s[ i ][ j ] ] +:= 1
OD
OD;
# construct a string of the characters that occur only once #
STRING result := "";
FOR i FROM LWB counts TO UPB counts DO
IF counts[ i ] = 1 THEN result +:= REPR i FI
OD;
result
END; # UNIQUE #
# task test case #
print( ( UNIQUE []STRING( "133252abcdeeffd", "a6789798st", "yxcdfgxcyz" ), newline ) )
END</syntaxhighlight>
{{out}}
<pre>
156bgstz
</pre>
 
=={{header|AppleScript}}==
Line 18 ⟶ 267:
The filtering here is case sensitive, the sorting dependent on locale.
 
<langsyntaxhighlight lang="applescript">on uniqueCharacters(listOfStrings)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
Line 30 ⟶ 279:
return (mutableSet's sortedArrayUsingDescriptors:({sortDescriptor})) as list
end uniqueCharacters</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">{"1", "5", "6", "b", "g", "s", "t", "z"}</langsyntaxhighlight>
 
===Core language only===
This isn't quite as fast as the ASObjC solution above, but it can be case-insensitive if required. (Simply leave out the 'considering case' statement round the call to the handler). The requirement for AppleScript 2.3.1 is just for the 'use' command which loads the "Heap Sort" script. If "Heap Sort"'s loaded differently or compiled directly into the code, this script will work on systems at least as far back as Mac OS X 10.5 (Leopard) and possibly earlier. Same output as above.
 
<langsyntaxhighlight lang="applescript">use AppleScript version "2.3.1" -- OS X 10.9 (Mavericks) or later
use sorter : script "Heap Sort" -- <https://www.rosettacode.org/wiki/Sorting_algorithms/Heapsort#AppleScript>
 
Line 72 ⟶ 321:
considering case
return uniqueCharacters({"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"})
end considering</langsyntaxhighlight>
 
 
===Functional===
 
Composing a solution from existing generic primitives, for speed of drafting and refactoring, and for high levels of code reuse.
 
<syntaxhighlight lang="applescript">use framework "Foundation"
 
 
-------------------- UNIQUE CHARACTERS -------------------
 
-- uniques :: [String] -> String
on uniques(xs)
script single
on |λ|(x)
if 1 = length of x then
item 1 of x
else
{}
end if
end |λ|
end script
concatMap(single, ¬
group(sort(concatMap(my chars, xs))))
end uniques
 
 
 
--------------------------- TEST -------------------------
on run
uniques({"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"})
--> {"1", "5", "6", "b", "g", "s", "t", "z"}
end run
 
 
------------------------- GENERIC ------------------------
 
-- chars :: String -> [Char]
on chars(s)
characters of s
end chars
 
 
-- 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
if {text, string} contains class of xs then
acc as text
else
acc
end if
end concatMap
 
 
-- eq (==) :: Eq a => a -> a -> Bool
on eq(a, b)
a = b
end eq
 
 
-- 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
 
 
-- group :: Eq a => [a] -> [[a]]
on group(xs)
script eq
on |λ|(a, b)
a = b
end |λ|
end script
groupBy(eq, xs)
end group
 
 
-- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
on groupBy(f, xs)
-- Typical usage: groupBy(on(eq, f), xs)
set mf to mReturn(f)
script enGroup
on |λ|(a, x)
if length of (active of a) > 0 then
set h to item 1 of active of a
else
set h to missing value
end if
if h is not missing value and mf's |λ|(h, x) then
{active:(active of a) & {x}, sofar:sofar of a}
else
{active:{x}, sofar:(sofar of a) & {active of a}}
end if
end |λ|
end script
if length of xs > 0 then
set dct to foldl(enGroup, {active:{item 1 of xs}, sofar:{}}, rest of xs)
if length of (active of dct) > 0 then
sofar of dct & {active of dct}
else
sofar of dct
end if
else
{}
end if
end groupBy
 
 
-- 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
 
 
-- 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
 
 
-- sort :: Ord a => [a] -> [a]
on sort(xs)
((current application's NSArray's arrayWithArray:xs)'s ¬
sortedArrayUsingSelector:"compare:") as list
end sort</syntaxhighlight>
{{Out}}
<pre>{"1", "5", "6", "b", "g", "s", "t", "z"}</pre>
 
=={{header|APL}}==
<syntaxhighlight lang="apl">uniques ← (⊂∘⍋⌷⊣)∘(∪(/⍨)(1=(≢⊢))⌸)∘∊</syntaxhighlight>
{{out}}
<pre> uniques '133252abcdeeffd' 'a6789798st' 'yxcdfgxcyz'
156bgstz</pre>
 
=={{header|Arturo}}==
 
<langsyntaxhighlight lang="rebol">arr: ["133252abcdeeffd" "a6789798st" "yxcdfgxcyz"]
str: join arr
 
print sort select split str 'ch -> 1 = size match str ch</langsyntaxhighlight>
 
{{out}}
Line 86 ⟶ 503:
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f UNIQUE_CHARACTERS.AWK
#
Line 112 ⟶ 529:
exit(0)
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 120 ⟶ 537:
3 strings, 35 characters, 20 different, 8 unique: 156bgstz
</pre>
 
=={{header|BASIC}}==
<syntaxhighlight lang="basic">10 DEFINT A-Z
20 DIM C(255)
30 READ A$: IF A$="" GOTO 90
40 FOR I=1 TO LEN(A$)
50 A=ASC(MID$(A$,I,1))
60 C(A)=C(A)+1
70 NEXT I
80 GOTO 30
90 FOR I=1 TO 255
100 IF C(I)=1 THEN A$=A$+CHR$(I)
110 NEXT I
120 PRINT A$
130 DATA "133252abcdeeffd"
140 DATA "a6789798st"
150 DATA "yxcdfgxcyz"
160 DATA ""</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
 
let uniques(strings, out) be
$( let counts = vec 255
for i=0 to 255 do counts!i := 0
until !strings = 0
$( let string = !strings
strings := strings + 1
for i=1 to string%0 do
counts!(string%i) := counts!(string%i) + 1
$)
out%0 := 0
for i=0 to 255 if counts!i = 1
$( out%0 := out%0 + 1
out%(out%0) := i
$)
$)
 
let start() be
$( let strings = vec 3 and out = vec 1+255/BYTESPERWORD
 
strings!0 := "133252abcdeeffd"
strings!1 := "a6789798st"
strings!2 := "yxcdfgxcyz"
strings!3 := 0
uniques(strings, out)
writef("%S*N", out)
$)</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|BQN}}==
<syntaxhighlight lang="bqn">Uniq ← (⍷/˜1=/⁼∘⊐)∧∘∾</syntaxhighlight>
 
{{out}}
<pre>
Uniq "133252abcdeeffd"‿"a6789798st"‿"yxcdfgxcyz"
"156bgstz"
</pre>
 
=={{header|C}}==
<syntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
 
char *uniques(char *str[], char *buf) {
static unsigned counts[256];
unsigned i;
char *s, *o = buf;
memset(counts, 0, 256 * sizeof(unsigned));
for (; *str; str++)
for (s = *str; *s; s++)
counts[(unsigned) *s]++;
for (i=0; i<256; i++)
if (counts[i] == 1)
*o++ = (char) i;
*o = '\0';
return buf;
}
 
int main() {
char buf[256];
char *strings[] = {
"133252abcdeeffd",
"a6789798st",
"yxcdfgxcyz",
NULL
};
printf("%s\n", uniques(strings, buf));
return 0;
}</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <map>
 
Line 137 ⟶ 653:
}
std::cout << '\n';
}</langsyntaxhighlight>
 
{{out}}
Line 143 ⟶ 659:
156bgstz
</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
 
 
<syntaxhighlight lang="Delphi">
 
var SA: array [0..2] of string = ('133252abcdeeffd', 'a6789798st', 'yxcdfgxcyz');
 
function CharsAppearingOnce(S: string): string;
{Return all character that only occur once}
var SL: TStringList;
var I,Inx: integer;
begin
SL:=TStringList.Create;
try
{Store each character and store a count}
{of the number of occurances in the object}
for I:=1 to Length(S) do
begin
{Check to see if letter is already in list}
Inx:=SL.IndexOf(S[I]);
{Increment the count if it is, otherwise store it}
if Inx>=0 then SL.Objects[Inx]:=Pointer(Integer(SL.Objects[Inx])+1)
else SL.AddObject(S[I],Pointer(1));
end;
{Sort the list}
SL.Sort;
{Now return letters with a count of one}
Result:='';
for I:=0 to SL.Count-1 do
if integer(SL.Objects[I])<2 then Result:=Result+SL[I];
finally SL.Free; end;
end;
 
procedure ShowUniqueChars(Memo: TMemo);
var I: integer;
var S: string;
begin
{Concatonate all strings}
S:='';
for I:=0 to High(SA) do S:=S+SA[I];
{Get all characters that appear once}
S:=CharsAppearingOnce(S);
Memo.Lines.Add(S);
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
156bgstz
 
Elapsed Time: 0.959 ms.
 
</pre>
 
 
=={{header|Factor}}==
{{works with|Factor|0.99 build 2074}}
<langsyntaxhighlight lang="factor">USING: io sequences sets.extras sorting ;
 
{ "133252abcdeeffd" "a6789798st" "yxcdfgxcyz" }
concat non-repeating natural-sort print</langsyntaxhighlight>
{{out}}
<pre>
156bgstz
</pre>
 
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">Dim As Integer c(255), i, a
Dim As String s
Do
Read s
For i = 1 To Len(s)
a = Asc(Mid(s,i,1))
c(a) += 1
Next i
Loop Until s = ""
 
For i = 1 To 255
If c(i) = 1 Then s &= Chr(i)
Next i
Print s
 
Data "133252abcdeeffd", "a6789798st", "yxcdfgxcyz", ""
Sleep</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">window 1, @"Unique characters"
 
void local fn DoIt
CountedSetRef set = fn CountedSetWithCapacity(0)
CFArrayRef array = @[@"133252abcdeeffd",@"a6789798st",@"yxcdfgxcyz"]
CFStringRef string, chr
long index
CFMutableArrayRef mutArray = fn MutableArrayWithCapacity(0)
for string in array
for index = 0 to len(string) - 1
CountedSetAddObject( set, mid(string,index,1) )
next
next
for chr in set
if ( fn CountedSetCountForObject( set, chr ) == 1 )
MutableArrayAddObject( mutArray, chr )
end if
next
MutableArraySortUsingSelector( mutArray, @"compare:" )
print fn ArrayComponentsJoinedByString( mutArray, @"" )
end fn
 
fn DoIt
 
HandleEvents</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 179 ⟶ 808:
sort.Slice(chars, func(i, j int) bool { return chars[i] < chars[j] })
fmt.Println(string(chars))
}</langsyntaxhighlight>
 
{{out}}
Line 185 ⟶ 814:
156bgstz
</pre>
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">import Data.List (group, sort)
 
uniques :: [String] -> String
uniques ks =
[c | (c : cs) <- (group . sort . concat) ks, null cs]
 
main :: IO ()
main =
putStrLn $
uniques
[ "133252abcdeeffd",
"a6789798st",
"yxcdfgxcyz"
]</syntaxhighlight>
{{Out}}
<pre>156bgstz</pre>
 
 
Or folding the strings down to a hash of character frequencies:
<syntaxhighlight lang="haskell">import qualified Data.Map.Strict as M
 
--------- UNIQUE CHARACTERS FROM A LIST OF STRINGS -------
 
uniqueChars :: [String] -> String
uniqueChars =
M.keys . M.filter (1 ==)
. foldr (M.unionWith (+) . charCounts) M.empty
 
charCounts :: String -> M.Map Char Int
charCounts =
foldr
(flip (M.insertWith (+)) 1)
M.empty
 
--------------------------- TEST -------------------------
main :: IO ()
main =
putStrLn $
uniqueChars
[ "133252abcdeeffd",
"a6789798st",
"yxcdfgxcyz"
]</syntaxhighlight>
{{Out}}
<pre>156bgstz</pre>
 
=={{header|JavaScript}}==
<syntaxhighlight lang="javascript">(() => {
"use strict";
 
// ---------------- UNIQUE CHARACTERS ----------------
 
// uniques :: [String] -> [Char]
const uniques = xs =>
group(
xs.flatMap(x => [...x])
.sort()
)
.flatMap(
x => 1 === x.length ? (
x
) : []
);
 
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () =>
uniques([
"133252abcdeeffd",
"a6789798st",
"yxcdfgxcyz"
]);
 
 
// --------------------- GENERIC ---------------------
 
// group :: Eq a => [a] -> [[a]]
const group = xs => {
// A list of lists, each containing only equal elements,
// such that the concatenation of these lists is xs.
const go = ys =>
0 < ys.length ? (() => {
const
h = ys[0],
i = ys.findIndex(y => h !== y);
 
return i !== -1 ? (
[ys.slice(0, i)].concat(go(ys.slice(i)))
) : [ys];
})() : [];
 
return go(xs);
};
 
 
// MAIN ---
return JSON.stringify(main());
})();</syntaxhighlight>
{{Out}}
<pre>["1","5","6","b","g","s","t","z"]</pre>
 
 
Or, folding the strings (with Array.reduce) down to a hash of character frequencies:
 
<syntaxhighlight lang="javascript">(() => {
"use strict";
 
// uniqueChars :: [String] -> [Char]
const uniqueChars = ws =>
Object.entries(
ws.reduce(
(dict, w) => [...w].reduce(
(a, c) => Object.assign({}, a, {
[c]: 1 + (a[c] || 0)
}),
dict
), {}
)
)
.flatMap(
([k, v]) => 1 === v ? (
[k]
) : []
);
 
// ---------------------- TEST -----------------------
const main = () =>
uniqueChars([
"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"
]);
 
 
return JSON.stringify(main());
})();</syntaxhighlight>
{{Out}}
<pre>["1","5","6","b","s","t","g","z"]</pre>
 
=={{header|J}}==
The simple approach here is to merge the argument strings and find characters which occur exactly once in that intermediate result:
<syntaxhighlight lang="j">uniques=: ~.#~1=#/.~</syntaxhighlight>
In other words, <code>~.</code> finds the distinct characters, <code>#/.~</code> finds the corresponding counts of those characters, so <code>1=#/.~</code> is true for the characters which occur exactly once, and <code>#~</code> filters the distinct characters based on those truth values.
{{out}}
<pre> uniques;'133252abcdeeffd';'a6789798st';'yxcdfgxcyz'
156bgstz</pre>
 
Here, <code>;</code> as a separator between quoted strings builds a list of the strings, and <code>;</code> as a prefix of that list merges the contents of the strings of that list into a single string. We could just as easily have formed a single string, but that's not what the task asked for. (Since <code>uniques</code> is a verb (aka a "function"), it's not a list element in this context.)
 
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
<lang jq>
The following "bag-of-words" solution is quite efficient as it takes advantage of the fact that jq implements JSON objects as a hash.<syntaxhighlight lang="jq">
# bag of words
def bow(stream):
Line 198 ⟶ 976:
def in_one_just_once:
bow( .[] | explode[] | [.] | implode) | with_entries(select(.value==1)) | keys;
</syntaxhighlight>
</lang>
'''The task'''
<langsyntaxhighlight lang="jq">["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
| in_one_just_once</langsyntaxhighlight>
{{out}}
<pre>
Line 208 ⟶ 986:
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">list = ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
 
function is_once_per_all_strings_in(a::Vector{String})
Line 217 ⟶ 995:
 
println(is_once_per_all_strings_in(list))
</langsyntaxhighlight>{{out}}<pre>
['1', '5', '6', 'b', 'g', 's', 't', 'z']
</pre>
One might think that the method above suffers from too many passes through the text with one pass per count, but with a small text length the dictionary lookup takes more time. Compare times for a single pass version:
 
<langsyntaxhighlight lang="julia">function uniquein(a)
counts = Dict{Char, Int}()
for c in prod(list)
Line 235 ⟶ 1,013:
@btime is_once_per_all_strings_in(list)
@btime uniquein(list)
</langsyntaxhighlight>{{out}}<pre>
['1', '5', '6', 'b', 'g', 's', 't', 'z']
1.740 μs (28 allocations: 3.08 KiB)
Line 242 ⟶ 1,020:
 
This can be rectified (see Phix entry) if we don't save the counts as we go but just exclude entries with duplicates:
<langsyntaxhighlight lang="julia">function uniquein2(a)
s = sort(collect(prod(list)))
l = length(s)
Line 251 ⟶ 1,029:
 
@btime uniquein2(list)
</langsyntaxhighlight>{{out}}<pre>
['1', '5', '6', 'b', 'g', 's', 't', 'z']
1.010 μs (14 allocations: 1.05 KiB)
</pre>
 
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">local strings = {"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}
unpack = unpack or table.unpack -- compatibility for all Lua versions
 
local map = {}
for i, str in ipairs (strings) do
for i=1, string.len(str) do
local char = string.sub(str,i,i)
if map[char] == nil then
map[char] = true
else
map[char] = false
end
end
end
 
local list = {}
for char, bool in pairs (map) do
if bool then
table.insert (list, char)
end
end
table.sort (list)
print (unpack (list))</syntaxhighlight>
{{out}}<pre>1 5 6 b g s t z</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">Select[Tally[Sort[Characters[StringJoin[{"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}]]]], Last /* EqualTo[1]][[All, 1]]</syntaxhighlight>
{{out}}
<pre>{"1", "5", "6", "b", "g", "s", "t", "z"}</pre>
 
=={{header|Nim}}==
One solution, but others are possible, for instance concatenating the strings and building the count table from it rather than merging several count tables. And to build the last sequence, we could have used something like <code>sorted(toSeq(charCount.pairs).filterIt(it[1] == 1).mapIt(it[0]))</code>, which is a one liner but less readable and less efficient than our solution using “collect”.
 
<langsyntaxhighlight Nimlang="nim">import algorithm, sugar, tables
 
var charCount: CountTable[char]
Line 270 ⟶ 1,082:
if count == 1: ch
 
echo sorted(uniqueChars)</langsyntaxhighlight>
 
{{out}}
<pre>@['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre>
 
=={{header|Pascal}}==
{{works with|Extended Pascal}}
<syntaxhighlight lang="pascal">program uniqueCharacters(output);
 
type
{ `integer…` prefix to facilitate sorting in documentation tools }
integerNonNegative = 0..maxInt;
{ all variables of this data type will be initialized to `1` }
integerPositive = 1..maxInt value 1;
charFrequency = array[char] of integerNonNegative;
{ This “discriminates” the `string` _schema_ data type. }
line = string(80);
{ A schema data type definition looks sort of like a function: }
lines(length: integerPositive) = array[1..length] of line;
 
{ `protected` in Extended Pascal means, you can’t modify this parameter. }
function createStatistics(protected sample: lines): charFrequency;
var
i, n: integerPositive;
{ The `value …` clause will initialize this variable to the given value. }
statistics: charFrequency value [chr(0)..maxChar: 0];
begin
{ You can inspect the discriminant of schema data type just like this: }
for n := 1 to sample.length do
begin
{ The length of a `string(…)` though needs to be queried: }
for i := 1 to length(sample[n]) do
begin
statistics[sample[n, i]] := statistics[sample[n, i]] + 1
end
end;
{ There needs to be exactly one assignment to the result variable: }
createStatistics := statistics
end;
 
{ === MAIN ============================================================= }
var
c: char;
sample: lines(3) value [1: '133252abcdeeffd';
2: 'a6789798st'; 3: 'yxcdfgxcyz'];
statistics: charFrequency;
begin
statistics := createStatistics(sample);
for c := chr(0) to maxChar do
begin
{
The colon (`:`) specifies the display width of the parameter.
While for `integer` and `real` values it means the _minimum_ width,
for `string` and `char` values it is the _exact_ width.
}
write(c:ord(statistics[c] = 1))
end;
writeLn
end.</syntaxhighlight>
{{out}}
<pre>156bgstz</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl"># 20210506 Perl programming solution
 
use strict;
Line 289 ⟶ 1,163:
"133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "AАΑSäaoö٥🤔👨‍👩‍👧‍👧";
my $uca = Unicode::Collate->new();
print $uca->sort ( grep { $seen{$_} == 1 } keys %seen )</langsyntaxhighlight>
{{out}}
<pre>
Line 296 ⟶ 1,170:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">once</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</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>
Line 306 ⟶ 1,180:
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)),</span><span style="color: #000000;">once</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;">"found %d unique characters: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 313 ⟶ 1,187:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de uni (Lst
(let R NIL
(mapc
Line 331 ⟶ 1,205:
"133252abcdeeffd"
"a6789798st"
"yxcdfgxcyz" ) ) )</langsyntaxhighlight>
{{out}}
<pre>
("1" "5" "6" "b" "g" "s" "t" "z")
</pre>
 
=={{header|PL/M}}==
<syntaxhighlight lang="pli">100H:
BDOS: PROCEDURE (FN, ARG); DECLARE FN BYTE, ARG ADDRESS; GO TO 5; END BDOS;
EXIT: PROCEDURE; CALL BDOS(0,0); END EXIT;
PRINT: PROCEDURE (S); DECLARE S ADDRESS; CALL BDOS(9,S); END PRINT;
 
/* FIND SORTED UNIQUE CHARACTERS IN ARRAY OF STRINGS */
UNIQUES: PROCEDURE (STRINGS, OUT);
DECLARE (STRINGS, OUT) ADDRESS;
DECLARE STRING BASED STRINGS ADDRESS;
DECLARE IPTR ADDRESS;
DECLARE ICHAR BASED IPTR BYTE;
DECLARE OCHAR BASED OUT BYTE;
DECLARE COUNT (256) BYTE;
DECLARE I ADDRESS;
DO I=0 TO 255; COUNT(I)=0; END;
I = 0;
DO WHILE STRING(I) <> 0;
IPTR = STRING(I);
DO WHILE ICHAR <> '$';
COUNT(ICHAR) = COUNT(ICHAR) + 1;
IPTR = IPTR + 1;
END;
I = I + 1;
END;
DO I=0 TO 255;
IF COUNT(I) = 1 THEN DO;
OCHAR = I;
OUT = OUT + 1;
END;
END;
OCHAR = '$';
END UNIQUES;
 
/* INPUT ARRAY */
/* USING UPPERCASE LETTERS BECAUSE PLM-80 DOES NOT SUPPORT LOWERCASE */
DECLARE STRINGS (4) ADDRESS;
STRINGS(0) = .'133252ABCDEEFFD$';
STRINGS(1) = .'A6789798ST$';
STRINGS(2) = .'YXCDFGXCYZ$';
STRINGS(3) = 0;
 
DECLARE BUFFER (255) BYTE;
CALL UNIQUES(.STRINGS, .BUFFER);
CALL PRINT(.BUFFER);
CALL EXIT;
EOF</syntaxhighlight>
{{out}}
<pre>156BGSTZ</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">'''Unique characters'''
 
from itertools import chain, groupby
 
 
# uniques :: [String] -> [Char]
def uniques(xs):
'''Characters which occur only once
across the given list of strings.
'''
return [
h for h, (_, *tail) in
groupby(sorted(chain(*xs)))
if not tail
]
 
 
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''Characters occurring only once
across a list of 3 given strings.
'''
print(
uniques([
"133252abcdeeffd",
"a6789798st",
"yxcdfgxcyz"
])
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre>
 
Or reducing the given strings down to a hash of character frequencies:
<syntaxhighlight lang="python">'''Unique characters'''
 
from functools import reduce
 
 
# uniqueChars :: [String] -> [Char]
def uniqueChars(ws):
'''Characters which occur only once
across the given list of strings.
'''
def addedWord(dct, w):
return reduce(updatedCharCount, w, dct)
 
def updatedCharCount(a, c):
return dict(
a, **{
c: 1 + a[c] if c in a else 1
}
)
 
return sorted([
k for k, v in reduce(addedWord, ws, {}).items()
if 1 == v
])
 
 
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''Test'''
print(
uniqueChars([
"133252abcdeeffd",
"a6789798st",
"yxcdfgxcyz"
])
)
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ [] swap
witheach join
[] 0 128 of
rot witheach
[ 2dup peek
1+ unrot poke ]
witheach
[ 1 = if
[ i^ join ] ] ] is task ( [ --> $ )
 
[]
$ "133252abcdeeffd" nested join
$ "a6789798st" nested join
$ "yxcdfgxcyz" nested join
 
task echo$</syntaxhighlight>
 
{{out}}
 
<pre>156bgstz</pre>
 
=={{header|Raku}}==
One has to wonder where the digits 0 through 9 come in the alphabet... 🤔 For that matter, What alphabet should they be in order of? Most of these entries seem to presuppose ASCII order but that isn't specified anywhere. What to do with characters outside of ASCII (or Latin-1)? Unicode ordinal order? Or maybe DUCET Unicode collation order? It's all very vague.
 
<syntaxhighlight lang="raku" perl6line>my @list = <133252abcdeeffd a6789798st yxcdfgxcyz>;
 
for @list, (@list, 'AАΑSäaoö٥🤔👨‍👩‍👧‍👧') {
Line 347 ⟶ 1,382:
"\n (DUCET) Unicode collation order: ",
.map( *.comb ).Bag.grep( *.value == 1 )».key.collate.join, "\n";
}</langsyntaxhighlight>
{{out}}
<pre>133252abcdeeffd a6789798st yxcdfgxcyz
Line 367 ⟶ 1,402:
 
On an &nbsp;'''EBCDIC'''&nbsp; machine, &nbsp; the lowercase letters and the uppercase letters &nbsp; aren't &nbsp; contiguous.
<langsyntaxhighlight lang="rexx">/*REXX pgm finds and shows characters that are unique to only one string and once only.*/
parse arg $ /*obtain optional arguments from the CL*/
if $='' | $="," then $= '133252abcdeeffd' "a6789798st" 'yxcdfgxcyz' /*use defaults.*/
Line 385 ⟶ 1,420:
say 'unique characters are: ' @ /*display the unique characters found. */
say
say 'Found ' L " unique characters." /*display the # of unique chars found. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 394 ⟶ 1,429:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
see "working..." + nl
see "Unique characters are:" + nl
Line 427 ⟶ 1,462:
end
return sum
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 435 ⟶ 1,470:
Found 8 unique characters
done...
</pre>
 
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
≪ DUP SIZE → string length
≪ 1 length '''FOR''' n
string n DUP SUB
'''NEXT'''
length 1 '''FOR''' n
1 n 1 - START
'''IF''' DUP2 ≥ '''THEN''' SWAP '''END'''
n ROLLD
'''NEXT'''
n ROLLD
-1 '''STEP'''
2 length '''START''' + '''NEXT'''
≫ ≫
‘SORTS’ STO
≪ DUP 1 DUP SUB → str char1
≪ str SIZE
'''IF''' DUP 1 >
'''THEN'''
DROP 1
'''WHILE''' str OVER 1 + DUP SUB char1 == '''REPEAT''' 1 + '''END'''
'''END'''
char1
≫ ≫
‘OCHST’ STO
≪ "" 1 3 PICK SIZE '''FOR''' j
OVER j GET +
'''NEXT'''
SWAP DROP
SORTS "" SWAP 1
'''WHILE''' OVER SIZE OVER ≥ '''REPEAT'''
DUP2 OVER SIZE SUB OCHST
'''IF''' OVER 1 ==
'''THEN''' 5 ROLL SWAP + 4 ROLLD
'''ELSE''' DROP
'''END'''
+
'''END'''
DROP2
‘UNCHR’ STO
===Shorter code but increased memory requirements===
≪ → strings
≪ { 255 } 0 CON 1 strings SIZE '''FOR''' j
strings j GET 1 OVER SIZE '''FOR''' k
DUP k DUP SUB NUM ROT SWAP DUP2 GET 1 + PUT SWAP
'''NEXT'''
DROP
'''NEXT'''
"" 1 255 '''FOR''' j
'''IF''' OVER j GET 1 == '''THEN''' j CHR + '''END'''
'''NEXT'''
SWAP DROP
‘UNCHR’ STO
 
{"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"} UNCHR
{{out}}
<pre>
1: "156bgstz"
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">words = ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
 
counter = words.inject({}){|h, word| word.chars.tally(h)}
puts counter.filter_map{|char, count| char if count == 1}.sort.join
</syntaxhighlight>
{{out}}
<pre>
156bgstz
</pre>
=={{header|Transd}}==
<syntaxhighlight lang="Scheme">#lang transd
 
MainModule: {
v: ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"],
 
_start: (λ
(for p in (group-by (split (join v "") "")) do
(if (== (size (snd p)) 1) (textout (fst p))))
)
}</syntaxhighlight>
{{out}}
<pre>
156bgstz
</pre>
 
=={{header|Standard ML}}==
Using an Array:
<syntaxhighlight lang="sml">
fun uniqueChars xs =
let
val arr = Array.array(256, 0)
val inc = (fn c => Array.update(arr, ord c, Array.sub(arr, ord c)+1))
val _ = List.app inc (List.concat (List.map String.explode xs))
val ex1 = (fn (i,n,a) => if n=1 then (chr i)::a else a)
in
String.implode (Array.foldri ex1 [] arr)
end
</syntaxhighlight>
{{out}}
<pre>
- uniqueChars ["133252abcdeeffd","a6789798st","yxcdfgxcyz"];
val it = "156bgstz" : string
</pre>
 
A different approach:
<syntaxhighlight lang="sml">
(*
group [1,1,2,4,4,4,2,2,2,1,1,1,3]
=> [[1,1], [2], [4,4,4], [2,2,2], [1,1,1], [3]]
*)
fun group xs =
let
fun collectGroups(a,[]) = [[a]]
| collectGroups(a,b::bs) = if a = (hd b) then (a::b)::bs else [a]::b::bs
in
List.foldr collectGroups [] xs
end
 
fun uniqueChars2 xs =
let
(* turn the strings into one big list of characters *)
val cs = List.concat (List.map String.explode xs)
(* sort the big list of characters *)
val scs = ListMergeSort.sort Char.> cs
(* collect the groups *)
val gs = group scs
(* filter out groups with more than one member *)
val os = List.filter (fn a => null (tl a)) gs
in
String.implode (List.concat os)
end
</syntaxhighlight>
 
=={{header|V (Vlang)}}==
<syntaxhighlight lang="v (vlang)">
fn main() {
strings := ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
mut m := map[rune]int{}
for s in strings {
for c in s {
m[c]++
}
}
mut chars := []rune{}
for k, v in m {
if v == 1 {chars << k}
}
chars.sort_with_compare(fn(i &rune, j &rune) int {
if *i < *j {return -1}
if *i > *j {return 1}
return 0
})
println(chars.string())
}
</syntaxhighlight>
 
{{out}}
<pre>
156bgstz
</pre>
 
Line 440 ⟶ 1,643:
{{libheader|Wren-seq}}
{{libheader|Wren-sort}}
<langsyntaxhighlight ecmascriptlang="wren">import "./seq" for Lst
import "./sort" for Sort
 
var strings = ["133252abcdeeffd", "a6789798st","yxcdfgxcyz"]
Line 448 ⟶ 1,651:
Sort.insertion(uniqueChars)
System.print("Found %(uniqueChars.count) unique character(s), namely:")
System.print(uniqueChars.join(" "))</langsyntaxhighlight>
 
{{out}}
Line 455 ⟶ 1,658:
1 5 6 b g s t z
</pre>
 
=={{header|Yabasic}}==
{{trans|FreeBASIC}}
<syntaxhighlight lang="yabasic">dim c(255)
data "133252abcdeeffd", "a6789798st", "yxcdfgxcyz", ""
repeat
read s$
for i = 1 to len(s$)
a = asc(mid$(s$,i,1))
c(a) = c(a) + 1
next i
until s$ = ""
 
for i = 1 to 255
if c(i) = 1 then s$ = s$ + chr$(i) : fi
next i
print s$
end</syntaxhighlight>
{{out}}
<pre>
Igual que la entrada de FreeBASIC.
</pre>
 
 
=={{header|XPL0}}==
<langsyntaxhighlight XPL0lang="xpl0">int List, I, N, C;
char Tbl(128), Str;
string 0;
Line 473 ⟶ 1,699:
for I:= 0 to 127 do
if Tbl(I) = 1 then ChOut(0, I);
]</langsyntaxhighlight>
 
{{out}}
23

edits