Unique characters: Difference between revisions
m (→{{header|J}}) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 15: | Line 15: | ||
=={{header|11l}}== |
=={{header|11l}}== |
||
< |
<syntaxhighlight lang="11l">DefaultDict[Char, Int] d |
||
L(s) [‘133252abcdeeffd’, ‘a6789798st’, ‘yxcdfgxcyz’] |
L(s) [‘133252abcdeeffd’, ‘a6789798st’, ‘yxcdfgxcyz’] |
||
L(c) s |
L(c) s |
||
Line 22: | Line 22: | ||
L(k) sorted(d.keys()) |
L(k) sorted(d.keys()) |
||
I d[k] == 1 |
I d[k] == 1 |
||
print(k, end' ‘’)</ |
print(k, end' ‘’)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 30: | Line 30: | ||
=={{header|8080 Assembly}}== |
=={{header|8080 Assembly}}== |
||
< |
<syntaxhighlight lang="8080asm">puts: equ 9 ; CP/M print syscall |
||
TERM: equ '$' ; CP/M string terminator |
TERM: equ '$' ; CP/M string terminator |
||
org 100h |
org 100h |
||
Line 86: | Line 86: | ||
;;; Memory |
;;; Memory |
||
upage: equ ($/256)+1 ; Workspace for 'unique' |
upage: equ ($/256)+1 ; Workspace for 'unique' |
||
outbuf: equ (upage+1)*256 ; Output </ |
outbuf: equ (upage+1)*256 ; Output </syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
=={{header|8086 Assembly}}== |
=={{header|8086 Assembly}}== |
||
< |
<syntaxhighlight lang="asm"> cpu 8086 |
||
org 100h |
org 100h |
||
puts: equ 9 ; MS-DOS syscall to print a string |
puts: equ 9 ; MS-DOS syscall to print a string |
||
Line 141: | Line 141: | ||
section .bss |
section .bss |
||
uniqws: resb 256 |
uniqws: resb 256 |
||
outbuf: resb 256</ |
outbuf: resb 256</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
=={{header|Action!}}== |
=={{header|Action!}}== |
||
< |
<syntaxhighlight lang="action!">DEFINE MAX="128" |
||
CHAR ARRAY counts(MAX) |
CHAR ARRAY counts(MAX) |
||
Line 192: | Line 192: | ||
FI |
FI |
||
OD |
OD |
||
RETURN</ |
RETURN</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Unique_characters.png Screenshot from Atari 8-bit computer] |
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Unique_characters.png Screenshot from Atari 8-bit computer] |
||
Line 200: | Line 200: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_Io; |
||
procedure Unique_Characters is |
procedure Unique_Characters is |
||
Line 230: | Line 230: | ||
Count ("yxcdfgxcyz"); |
Count ("yxcdfgxcyz"); |
||
Put_Only_Once; |
Put_Only_Once; |
||
end Unique_Characters;</ |
end Unique_Characters;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>1 5 6 b g s t z</pre> |
<pre>1 5 6 b g s t z</pre> |
||
Line 236: | Line 236: | ||
=={{header|ALGOL 68}}== |
=={{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. |
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 # |
# returns the characters that occur only once in the elements of s # |
||
OP UNIQUE = ( []STRING s )STRING: |
OP UNIQUE = ( []STRING s )STRING: |
||
Line 257: | Line 257: | ||
# task test case # |
# task test case # |
||
print( ( UNIQUE []STRING( "133252abcdeeffd", "a6789798st", "yxcdfgxcyz" ), newline ) ) |
print( ( UNIQUE []STRING( "133252abcdeeffd", "a6789798st", "yxcdfgxcyz" ), newline ) ) |
||
END</ |
END</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 267: | Line 267: | ||
The filtering here is case sensitive, the sorting dependent on locale. |
The filtering here is case sensitive, the sorting dependent on locale. |
||
< |
<syntaxhighlight lang="applescript">on uniqueCharacters(listOfStrings) |
||
set astid to AppleScript's text item delimiters |
set astid to AppleScript's text item delimiters |
||
set AppleScript's text item delimiters to "" |
set AppleScript's text item delimiters to "" |
||
Line 279: | Line 279: | ||
return (mutableSet's sortedArrayUsingDescriptors:({sortDescriptor})) as list |
return (mutableSet's sortedArrayUsingDescriptors:({sortDescriptor})) as list |
||
end uniqueCharacters</ |
end uniqueCharacters</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
< |
<syntaxhighlight lang="applescript">{"1", "5", "6", "b", "g", "s", "t", "z"}</syntaxhighlight> |
||
===Core language only=== |
===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. |
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. |
||
< |
<syntaxhighlight 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> |
use sorter : script "Heap Sort" -- <https://www.rosettacode.org/wiki/Sorting_algorithms/Heapsort#AppleScript> |
||
Line 321: | Line 321: | ||
considering case |
considering case |
||
return uniqueCharacters({"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}) |
return uniqueCharacters({"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}) |
||
end considering</ |
end considering</syntaxhighlight> |
||
Line 328: | Line 328: | ||
Composing a solution from existing generic primitives, for speed of drafting and refactoring, and for high levels of code reuse. |
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" |
||
Line 481: | Line 481: | ||
((current application's NSArray's arrayWithArray:xs)'s ¬ |
((current application's NSArray's arrayWithArray:xs)'s ¬ |
||
sortedArrayUsingSelector:"compare:") as list |
sortedArrayUsingSelector:"compare:") as list |
||
end sort</ |
end sort</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>{"1", "5", "6", "b", "g", "s", "t", "z"}</pre> |
<pre>{"1", "5", "6", "b", "g", "s", "t", "z"}</pre> |
||
=={{header|APL}}== |
=={{header|APL}}== |
||
< |
<syntaxhighlight lang="apl">uniques ← (⊂∘⍋⌷⊣)∘(∪(/⍨)(1=(≢⊢))⌸)∘∊</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> uniques '133252abcdeeffd' 'a6789798st' 'yxcdfgxcyz' |
<pre> uniques '133252abcdeeffd' 'a6789798st' 'yxcdfgxcyz' |
||
Line 493: | Line 493: | ||
=={{header|Arturo}}== |
=={{header|Arturo}}== |
||
< |
<syntaxhighlight lang="rebol">arr: ["133252abcdeeffd" "a6789798st" "yxcdfgxcyz"] |
||
str: join arr |
str: join arr |
||
print sort select split str 'ch -> 1 = size match str ch</ |
print sort select split str 'ch -> 1 = size match str ch</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 503: | Line 503: | ||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<syntaxhighlight lang="awk"> |
|||
<lang AWK> |
|||
# syntax: GAWK -f UNIQUE_CHARACTERS.AWK |
# syntax: GAWK -f UNIQUE_CHARACTERS.AWK |
||
# |
# |
||
Line 529: | Line 529: | ||
exit(0) |
exit(0) |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 539: | Line 539: | ||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
< |
<syntaxhighlight lang="basic">10 DEFINT A-Z |
||
20 DIM C(255) |
20 DIM C(255) |
||
30 READ A$: IF A$="" GOTO 90 |
30 READ A$: IF A$="" GOTO 90 |
||
Line 554: | Line 554: | ||
140 DATA "a6789798st" |
140 DATA "a6789798st" |
||
150 DATA "yxcdfgxcyz" |
150 DATA "yxcdfgxcyz" |
||
160 DATA ""</ |
160 DATA ""</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
=={{header|BCPL}}== |
=={{header|BCPL}}== |
||
< |
<syntaxhighlight lang="bcpl">get "libhdr" |
||
let uniques(strings, out) be |
let uniques(strings, out) be |
||
Line 587: | Line 587: | ||
uniques(strings, out) |
uniques(strings, out) |
||
writef("%S*N", out) |
writef("%S*N", out) |
||
$)</ |
$)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
=={{header|BQN}}== |
=={{header|BQN}}== |
||
< |
<syntaxhighlight lang="bqn">Uniq ← (⍷/˜1=/⁼∘⊐)∧∘∾</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 601: | Line 601: | ||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 633: | Line 633: | ||
printf("%s\n", uniques(strings, buf)); |
printf("%s\n", uniques(strings, buf)); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
#include <map> |
#include <map> |
||
Line 653: | Line 653: | ||
} |
} |
||
std::cout << '\n'; |
std::cout << '\n'; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 662: | Line 662: | ||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
{{works with|Factor|0.99 build 2074}} |
{{works with|Factor|0.99 build 2074}} |
||
< |
<syntaxhighlight lang="factor">USING: io sequences sets.extras sorting ; |
||
{ "133252abcdeeffd" "a6789798st" "yxcdfgxcyz" } |
{ "133252abcdeeffd" "a6789798st" "yxcdfgxcyz" } |
||
concat non-repeating natural-sort print</ |
concat non-repeating natural-sort print</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 673: | Line 673: | ||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
< |
<syntaxhighlight lang="freebasic">Dim As Integer c(255), i, a |
||
Dim As String s |
Dim As String s |
||
Do |
Do |
||
Line 689: | Line 689: | ||
Data "133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "" |
Data "133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "" |
||
Sleep</ |
Sleep</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
Line 695: | Line 695: | ||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 718: | Line 718: | ||
sort.Slice(chars, func(i, j int) bool { return chars[i] < chars[j] }) |
sort.Slice(chars, func(i, j int) bool { return chars[i] < chars[j] }) |
||
fmt.Println(string(chars)) |
fmt.Println(string(chars)) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 726: | Line 726: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">import Data.List (group, sort) |
||
uniques :: [String] -> String |
uniques :: [String] -> String |
||
Line 739: | Line 739: | ||
"a6789798st", |
"a6789798st", |
||
"yxcdfgxcyz" |
"yxcdfgxcyz" |
||
]</ |
]</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
Line 745: | Line 745: | ||
Or folding the strings down to a hash of character frequencies: |
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 ------- |
--------- UNIQUE CHARACTERS FROM A LIST OF STRINGS ------- |
||
Line 768: | Line 768: | ||
"a6789798st", |
"a6789798st", |
||
"yxcdfgxcyz" |
"yxcdfgxcyz" |
||
]</ |
]</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
< |
<syntaxhighlight lang="javascript">(() => { |
||
"use strict"; |
"use strict"; |
||
Line 823: | Line 823: | ||
// MAIN --- |
// MAIN --- |
||
return JSON.stringify(main()); |
return JSON.stringify(main()); |
||
})();</ |
})();</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>["1","5","6","b","g","s","t","z"]</pre> |
<pre>["1","5","6","b","g","s","t","z"]</pre> |
||
Line 830: | Line 830: | ||
Or, folding the strings (with Array.reduce) down to a hash of character frequencies: |
Or, folding the strings (with Array.reduce) down to a hash of character frequencies: |
||
< |
<syntaxhighlight lang="javascript">(() => { |
||
"use strict"; |
"use strict"; |
||
Line 859: | Line 859: | ||
return JSON.stringify(main()); |
return JSON.stringify(main()); |
||
})();</ |
})();</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>["1","5","6","b","s","t","g","z"]</pre> |
<pre>["1","5","6","b","s","t","g","z"]</pre> |
||
Line 865: | Line 865: | ||
=={{header|J}}== |
=={{header|J}}== |
||
The simple approach here is to merge the argument strings and find characters which occur exactly once in that intermediate result: |
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. |
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}} |
{{out}} |
||
Line 877: | Line 877: | ||
'''Works with gojq, the Go implementation of jq''' |
'''Works with gojq, the Go implementation of 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.< |
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 |
# bag of words |
||
def bow(stream): |
def bow(stream): |
||
Line 886: | Line 886: | ||
def in_one_just_once: |
def in_one_just_once: |
||
bow( .[] | explode[] | [.] | implode) | with_entries(select(.value==1)) | keys; |
bow( .[] | explode[] | [.] | implode) | with_entries(select(.value==1)) | keys; |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''The task''' |
'''The task''' |
||
< |
<syntaxhighlight lang="jq">["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"] |
||
| in_one_just_once</ |
| in_one_just_once</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 896: | Line 896: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">list = ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"] |
||
function is_once_per_all_strings_in(a::Vector{String}) |
function is_once_per_all_strings_in(a::Vector{String}) |
||
Line 905: | Line 905: | ||
println(is_once_per_all_strings_in(list)) |
println(is_once_per_all_strings_in(list)) |
||
</ |
</syntaxhighlight>{{out}}<pre> |
||
['1', '5', '6', 'b', 'g', 's', 't', 'z'] |
['1', '5', '6', 'b', 'g', 's', 't', 'z'] |
||
</pre> |
</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: |
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: |
||
< |
<syntaxhighlight lang="julia">function uniquein(a) |
||
counts = Dict{Char, Int}() |
counts = Dict{Char, Int}() |
||
for c in prod(list) |
for c in prod(list) |
||
Line 923: | Line 923: | ||
@btime is_once_per_all_strings_in(list) |
@btime is_once_per_all_strings_in(list) |
||
@btime uniquein(list) |
@btime uniquein(list) |
||
</ |
</syntaxhighlight>{{out}}<pre> |
||
['1', '5', '6', 'b', 'g', 's', 't', 'z'] |
['1', '5', '6', 'b', 'g', 's', 't', 'z'] |
||
1.740 μs (28 allocations: 3.08 KiB) |
1.740 μs (28 allocations: 3.08 KiB) |
||
Line 930: | Line 930: | ||
This can be rectified (see Phix entry) if we don't save the counts as we go but just exclude entries with duplicates: |
This can be rectified (see Phix entry) if we don't save the counts as we go but just exclude entries with duplicates: |
||
< |
<syntaxhighlight lang="julia">function uniquein2(a) |
||
s = sort(collect(prod(list))) |
s = sort(collect(prod(list))) |
||
l = length(s) |
l = length(s) |
||
Line 939: | Line 939: | ||
@btime uniquein2(list) |
@btime uniquein2(list) |
||
</ |
</syntaxhighlight>{{out}}<pre> |
||
['1', '5', '6', 'b', 'g', 's', 't', 'z'] |
['1', '5', '6', 'b', 'g', 's', 't', 'z'] |
||
1.010 μs (14 allocations: 1.05 KiB) |
1.010 μs (14 allocations: 1.05 KiB) |
||
Line 946: | Line 946: | ||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
< |
<syntaxhighlight lang="lua">local strings = {"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"} |
||
unpack = unpack or table.unpack -- compatibility for all Lua versions |
unpack = unpack or table.unpack -- compatibility for all Lua versions |
||
Line 970: | Line 970: | ||
end |
end |
||
table.sort (list) |
table.sort (list) |
||
print (unpack (list))</ |
print (unpack (list))</syntaxhighlight> |
||
{{out}}<pre>1 5 6 b g s t z</pre> |
{{out}}<pre>1 5 6 b g s t z</pre> |
||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">Select[Tally[Sort[Characters[StringJoin[{"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}]]]], Last /* EqualTo[1]][[All, 1]]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>{"1", "5", "6", "b", "g", "s", "t", "z"}</pre> |
<pre>{"1", "5", "6", "b", "g", "s", "t", "z"}</pre> |
||
Line 981: | Line 981: | ||
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”. |
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”. |
||
< |
<syntaxhighlight lang="nim">import algorithm, sugar, tables |
||
var charCount: CountTable[char] |
var charCount: CountTable[char] |
||
Line 992: | Line 992: | ||
if count == 1: ch |
if count == 1: ch |
||
echo sorted(uniqueChars)</ |
echo sorted(uniqueChars)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 999: | Line 999: | ||
=={{header|Pascal}}== |
=={{header|Pascal}}== |
||
{{works with|Extended Pascal}} |
{{works with|Extended Pascal}} |
||
< |
<syntaxhighlight lang="pascal">program uniqueCharacters(output); |
||
type |
type |
||
Line 1,055: | Line 1,055: | ||
writeLn |
writeLn |
||
end.</ |
end.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156bgstz</pre> |
<pre>156bgstz</pre> |
||
Line 1,061: | Line 1,061: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{trans|Raku}} |
{{trans|Raku}} |
||
< |
<syntaxhighlight lang="perl"># 20210506 Perl programming solution |
||
use strict; |
use strict; |
||
Line 1,073: | Line 1,073: | ||
"133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "AАΑSäaoö٥🤔👨👩👧👧"; |
"133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "AАΑSäaoö٥🤔👨👩👧👧"; |
||
my $uca = Unicode::Collate->new(); |
my $uca = Unicode::Collate->new(); |
||
print $uca->sort ( grep { $seen{$_} == 1 } keys %seen )</ |
print $uca->sort ( grep { $seen{$_} == 1 } keys %seen )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,080: | Line 1,080: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
<!--< |
<!--<syntaxhighlight lang="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: #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> |
<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 1,090: | Line 1,090: | ||
<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: #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> |
<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> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,097: | Line 1,097: | ||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(de uni (Lst |
||
(let R NIL |
(let R NIL |
||
(mapc |
(mapc |
||
Line 1,115: | Line 1,115: | ||
"133252abcdeeffd" |
"133252abcdeeffd" |
||
"a6789798st" |
"a6789798st" |
||
"yxcdfgxcyz" ) ) )</ |
"yxcdfgxcyz" ) ) )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,122: | Line 1,122: | ||
=={{header|PL/M}}== |
=={{header|PL/M}}== |
||
< |
<syntaxhighlight lang="pli">100H: |
||
BDOS: PROCEDURE (FN, ARG); DECLARE FN BYTE, ARG ADDRESS; GO TO 5; END BDOS; |
BDOS: PROCEDURE (FN, ARG); DECLARE FN BYTE, ARG ADDRESS; GO TO 5; END BDOS; |
||
EXIT: PROCEDURE; CALL BDOS(0,0); END EXIT; |
EXIT: PROCEDURE; CALL BDOS(0,0); END EXIT; |
||
Line 1,170: | Line 1,170: | ||
CALL PRINT(.BUFFER); |
CALL PRINT(.BUFFER); |
||
CALL EXIT; |
CALL EXIT; |
||
EOF</ |
EOF</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>156BGSTZ</pre> |
<pre>156BGSTZ</pre> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">'''Unique characters''' |
||
from itertools import chain, groupby |
from itertools import chain, groupby |
||
Line 1,209: | Line 1,209: | ||
# MAIN --- |
# MAIN --- |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
main()</ |
main()</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre> |
<pre>['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre> |
||
Or reducing the given strings down to a hash of character frequencies: |
Or reducing the given strings down to a hash of character frequencies: |
||
< |
<syntaxhighlight lang="python">'''Unique characters''' |
||
from functools import reduce |
from functools import reduce |
||
Line 1,255: | Line 1,255: | ||
# MAIN --- |
# MAIN --- |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
main()</ |
main()</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre> |
<pre>['1', '5', '6', 'b', 'g', 's', 't', 'z']</pre> |
||
Line 1,262: | Line 1,262: | ||
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. |
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. |
||
<lang |
<syntaxhighlight lang="raku" line>my @list = <133252abcdeeffd a6789798st yxcdfgxcyz>; |
||
for @list, (@list, 'AАΑSäaoö٥🤔👨👩👧👧') { |
for @list, (@list, 'AАΑSäaoö٥🤔👨👩👧👧') { |
||
Line 1,269: | Line 1,269: | ||
"\n (DUCET) Unicode collation order: ", |
"\n (DUCET) Unicode collation order: ", |
||
.map( *.comb ).Bag.grep( *.value == 1 )».key.collate.join, "\n"; |
.map( *.comb ).Bag.grep( *.value == 1 )».key.collate.join, "\n"; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>133252abcdeeffd a6789798st yxcdfgxcyz |
<pre>133252abcdeeffd a6789798st yxcdfgxcyz |
||
Line 1,289: | Line 1,289: | ||
On an '''EBCDIC''' machine, the lowercase letters and the uppercase letters aren't contiguous. |
On an '''EBCDIC''' machine, the lowercase letters and the uppercase letters aren't contiguous. |
||
< |
<syntaxhighlight 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*/ |
parse arg $ /*obtain optional arguments from the CL*/ |
||
if $='' | $="," then $= '133252abcdeeffd' "a6789798st" 'yxcdfgxcyz' /*use defaults.*/ |
if $='' | $="," then $= '133252abcdeeffd' "a6789798st" 'yxcdfgxcyz' /*use defaults.*/ |
||
Line 1,307: | Line 1,307: | ||
say 'unique characters are: ' @ /*display the unique characters found. */ |
say 'unique characters are: ' @ /*display the unique characters found. */ |
||
say |
say |
||
say 'Found ' L " unique characters." /*display the # of unique chars found. */</ |
say 'Found ' L " unique characters." /*display the # of unique chars found. */</syntaxhighlight> |
||
{{out|output|text= when using the default inputs:}} |
{{out|output|text= when using the default inputs:}} |
||
<pre> |
<pre> |
||
Line 1,316: | Line 1,316: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
see "working..." + nl |
see "working..." + nl |
||
see "Unique characters are:" + nl |
see "Unique characters are:" + nl |
||
Line 1,349: | Line 1,349: | ||
end |
end |
||
return sum |
return sum |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,360: | Line 1,360: | ||
=={{header|Vlang}}== |
=={{header|Vlang}}== |
||
< |
<syntaxhighlight lang="vlang">fn main() { |
||
strings := ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"] |
strings := ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"] |
||
mut m := map[rune]int{} |
mut m := map[rune]int{} |
||
Line 1,384: | Line 1,384: | ||
}) |
}) |
||
println(chars.string()) |
println(chars.string()) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,394: | Line 1,394: | ||
{{libheader|Wren-seq}} |
{{libheader|Wren-seq}} |
||
{{libheader|Wren-sort}} |
{{libheader|Wren-sort}} |
||
< |
<syntaxhighlight lang="ecmascript">import "/seq" for Lst |
||
import "/sort" for Sort |
import "/sort" for Sort |
||
Line 1,402: | Line 1,402: | ||
Sort.insertion(uniqueChars) |
Sort.insertion(uniqueChars) |
||
System.print("Found %(uniqueChars.count) unique character(s), namely:") |
System.print("Found %(uniqueChars.count) unique character(s), namely:") |
||
System.print(uniqueChars.join(" "))</ |
System.print(uniqueChars.join(" "))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,413: | Line 1,413: | ||
=={{header|Yabasic}}== |
=={{header|Yabasic}}== |
||
{{trans|FreeBASIC}} |
{{trans|FreeBASIC}} |
||
< |
<syntaxhighlight lang="yabasic">dim c(255) |
||
data "133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "" |
data "133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "" |
||
repeat |
repeat |
||
Line 1,427: | Line 1,427: | ||
next i |
next i |
||
print s$ |
print s$ |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,435: | Line 1,435: | ||
=={{header|XPL0}}== |
=={{header|XPL0}}== |
||
< |
<syntaxhighlight lang="xpl0">int List, I, N, C; |
||
char Tbl(128), Str; |
char Tbl(128), Str; |
||
string 0; |
string 0; |
||
Line 1,451: | Line 1,451: | ||
for I:= 0 to 127 do |
for I:= 0 to 127 do |
||
if Tbl(I) = 1 then ChOut(0, I); |
if Tbl(I) = 1 then ChOut(0, I); |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
Revision as of 19:34, 28 August 2022
- Task
Given a list of strings, find characters appearing only in one string and once only.
The result should be given in alphabetical order.
Use the following list for this task:
["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
- Metrics
- Counting
- Word frequency
- Letter frequency
- Jewels and stones
- I before E except after C
- Bioinformatics/base count
- Count occurrences of a substring
- Count how many vowels and consonants occur in a string
- Remove/replace
- XXXX redacted
- Conjugate a Latin verb
- Remove vowels from a string
- String interpolation (included)
- Strip block comments
- Strip comments from a string
- Strip a set of characters from a string
- Strip whitespace from a string -- top and tail
- Strip control codes and extended characters from a string
- Anagrams/Derangements/shuffling
- Word wheel
- ABC problem
- Sattolo cycle
- Knuth shuffle
- Ordered words
- Superpermutation minimisation
- Textonyms (using a phone text pad)
- Anagrams
- Anagrams/Deranged anagrams
- Permutations/Derangements
- Find/Search/Determine
- ABC words
- Odd words
- Word ladder
- Semordnilap
- Word search
- Wordiff (game)
- String matching
- Tea cup rim text
- Alternade words
- Changeable words
- State name puzzle
- String comparison
- Unique characters
- Unique characters in each string
- Extract file extension
- Levenshtein distance
- Palindrome detection
- Common list elements
- Longest common suffix
- Longest common prefix
- Compare a list of strings
- Longest common substring
- Find common directory path
- Words from neighbour ones
- Change e letters to i in words
- Non-continuous subsequences
- Longest common subsequence
- Longest palindromic substrings
- Longest increasing subsequence
- Words containing "the" substring
- Sum of the digits of n is substring of n
- Determine if a string is numeric
- Determine if a string is collapsible
- Determine if a string is squeezable
- Determine if a string has all unique characters
- Determine if a string has all the same characters
- Longest substrings without repeating characters
- Find words which contains all the vowels
- Find words which contains most consonants
- Find words which contains more than 3 vowels
- Find words which first and last three letters are equals
- Find words which odd letters are consonants and even letters are vowels or vice_versa
- Formatting
- Substring
- Rep-string
- Word wrap
- String case
- Align columns
- Literals/String
- Repeat a string
- Brace expansion
- Brace expansion using ranges
- Reverse a string
- Phrase reversals
- Comma quibbling
- Special characters
- String concatenation
- Substring/Top and tail
- Commatizing numbers
- Reverse words in a string
- Suffixation of decimal numbers
- Long literals, with continuations
- Numerical and alphabetical suffixes
- Abbreviations, easy
- Abbreviations, simple
- Abbreviations, automatic
- Song lyrics/poems/Mad Libs/phrases
- Mad Libs
- Magic 8-ball
- 99 Bottles of Beer
- The Name Game (a song)
- The Old lady swallowed a fly
- The Twelve Days of Christmas
- Tokenize
- Text between
- Tokenize a string
- Word break problem
- Tokenize a string with escaping
- Split a character string based on change of character
- Sequences
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' ‘’)
- Output:
156bgstz
8080 Assembly
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
- Output:
156bgstz
8086 Assembly
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
- Output:
156bgstz
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
- Output:
Screenshot from Atari 8-bit computer
1 5 6 b g s t z
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;
- Output:
1 5 6 b g s t z
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.
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
- Output:
156bgstz
AppleScript
AppleScriptObjC
The filtering here is case sensitive, the sorting dependent on locale.
on uniqueCharacters(listOfStrings)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set countedSet to current application's class "NSCountedSet"'s setWithArray:((listOfStrings as text)'s characters)
set AppleScript's text item delimiters to astid
set mutableSet to current application's class "NSMutableSet"'s setWithSet:(countedSet)
tell countedSet to minusSet:(mutableSet)
tell mutableSet to minusSet:(countedSet)
set sortDescriptor to current application's class "NSSortDescriptor"'s sortDescriptorWithKey:("self") ¬
ascending:(true) selector:("localizedStandardCompare:")
return (mutableSet's sortedArrayUsingDescriptors:({sortDescriptor})) as list
end uniqueCharacters
- Output:
{"1", "5", "6", "b", "g", "s", "t", "z"}
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.
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>
on uniqueCharacters(listOfStrings)
script o
property allCharacters : {}
property uniques : {}
end script
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set o's allCharacters to text items of (listOfStrings as text)
set AppleScript's text item delimiters to astid
set characterCount to (count o's allCharacters)
tell sorter to sort(o's allCharacters, 1, characterCount)
set i to 1
set currentCharacter to beginning of o's allCharacters
repeat with j from 2 to characterCount
set thisCharacter to item j of o's allCharacters
if (thisCharacter is not currentCharacter) then
if (j - i = 1) then set end of o's uniques to currentCharacter
set i to j
set currentCharacter to thisCharacter
end if
end repeat
if (i = j) then set end of o's uniques to currentCharacter
return o's uniques
end uniqueCharacters
considering case
return uniqueCharacters({"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"})
end considering
Functional
Composing a solution from existing generic primitives, for speed of drafting and refactoring, and for high levels of code reuse.
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
- Output:
{"1", "5", "6", "b", "g", "s", "t", "z"}
APL
uniques ← (⊂∘⍋⌷⊣)∘(∪(/⍨)(1=(≢⊢))⌸)∘∊
- Output:
uniques '133252abcdeeffd' 'a6789798st' 'yxcdfgxcyz' 156bgstz
Arturo
arr: ["133252abcdeeffd" "a6789798st" "yxcdfgxcyz"]
str: join arr
print sort select split str 'ch -> 1 = size match str ch
- Output:
1 5 6 b g s t z
AWK
# syntax: GAWK -f UNIQUE_CHARACTERS.AWK
#
# sorting:
# PROCINFO["sorted_in"] is used by GAWK
# SORTTYPE is used by Thompson Automation's TAWK
#
BEGIN {
PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
n = split("133252abcdeeffd,a6789798st,yxcdfgxcyz",arr1,",")
for (i=1; i<=n; i++) {
str = arr1[i]
printf("%s\n",str)
total_c += leng = length(str)
for (j=1; j<=leng; j++) {
arr2[substr(str,j,1)]++
}
}
for (c in arr2) {
if (arr2[c] == 1) {
rec = sprintf("%s%s",rec,c)
}
}
printf("%d strings, %d characters, %d different, %d unique: %s\n",n,total_c,length(arr2),length(rec),rec)
exit(0)
}
- Output:
133252abcdeeffd a6789798st yxcdfgxcyz 3 strings, 35 characters, 20 different, 8 unique: 156bgstz
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 ""
- Output:
156bgstz
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)
$)
- Output:
156bgstz
BQN
Uniq ← (⍷/˜1=/⁼∘⊐)∧∘∾
- Output:
Uniq "133252abcdeeffd"‿"a6789798st"‿"yxcdfgxcyz" "156bgstz"
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;
}
- Output:
156bgstz
C++
#include <iostream>
#include <map>
int main() {
const char* strings[] = {"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"};
std::map<char, int> count;
for (const char* str : strings) {
for (; *str; ++str)
++count[*str];
}
for (const auto& p : count) {
if (p.second == 1)
std::cout << p.first;
}
std::cout << '\n';
}
- Output:
156bgstz
Factor
USING: io sequences sets.extras sorting ;
{ "133252abcdeeffd" "a6789798st" "yxcdfgxcyz" }
concat non-repeating natural-sort print
- Output:
156bgstz
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
- Output:
156bgstz
Go
package main
import (
"fmt"
"sort"
)
func main() {
strings := []string{"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}
m := make(map[rune]int)
for _, s := range strings {
for _, c := range s {
m[c]++
}
}
var chars []rune
for k, v := range m {
if v == 1 {
chars = append(chars, k)
}
}
sort.Slice(chars, func(i, j int) bool { return chars[i] < chars[j] })
fmt.Println(string(chars))
}
- Output:
156bgstz
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"
]
- Output:
156bgstz
Or folding the strings down to a hash of character frequencies:
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"
]
- Output:
156bgstz
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());
})();
- Output:
["1","5","6","b","g","s","t","z"]
Or, folding the strings (with Array.reduce) down to a hash of character frequencies:
(() => {
"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());
})();
- Output:
["1","5","6","b","s","t","g","z"]
J
The simple approach here is to merge the argument strings and find characters which occur exactly once in that intermediate result:
uniques=: ~.#~1=#/.~
In other words, ~.
finds the distinct characters, #/.~
finds the corresponding counts of those characters, so 1=#/.~
is true for the characters which occur exactly once, and #~
filters the distinct characters based on those truth values.
- Output:
uniques;'133252abcdeeffd';'a6789798st';'yxcdfgxcyz' 156bgstz
Here, ;
as a separator between quoted strings builds a list of the strings, and ;
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 uniques
is a verb (aka a "function"), it's not a list element in this context.)
jq
Works with gojq, the Go implementation of 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.
# bag of words
def bow(stream):
reduce stream as $word ({}; .[($word|tostring)] += 1);
# Input: an array of strings
# Output: an array of the characters that appear just once
def in_one_just_once:
bow( .[] | explode[] | [.] | implode) | with_entries(select(.value==1)) | keys;
The task
["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
| in_one_just_once
- Output:
["1","5","6","b","g","s","t","z"]
Julia
list = ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]
function is_once_per_all_strings_in(a::Vector{String})
charlist = collect(prod(a))
counts = Dict(c => count(x -> c == x, charlist) for c in unique(charlist))
return sort([p[1] for p in counts if p[2] == 1])
end
println(is_once_per_all_strings_in(list))
- Output:
['1', '5', '6', 'b', 'g', 's', 't', 'z']
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:
function uniquein(a)
counts = Dict{Char, Int}()
for c in prod(list)
counts[c] = get!(counts, c, 0) + 1
end
return sort([c for (c, n) in counts if n == 1])
end
println(uniquein(list))
using BenchmarkTools
@btime is_once_per_all_strings_in(list)
@btime uniquein(list)
- Output:
['1', '5', '6', 'b', 'g', 's', 't', 'z']
1.740 μs (28 allocations: 3.08 KiB) 3.763 μs (50 allocations: 3.25 KiB)
This can be rectified (see Phix entry) if we don't save the counts as we go but just exclude entries with duplicates:
function uniquein2(a)
s = sort(collect(prod(list)))
l = length(s)
return [p[2] for p in enumerate(s) if (p[1] == 1 || p[2] != s[p[1] - 1]) && (p[1] == l || p[2] != s[p[1] + 1])]
end
println(uniquein2(list))
@btime uniquein2(list)
- Output:
['1', '5', '6', 'b', 'g', 's', 't', 'z']
1.010 μs (14 allocations: 1.05 KiB)
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))
- Output:
1 5 6 b g s t z
Mathematica/Wolfram Language
Select[Tally[Sort[Characters[StringJoin[{"133252abcdeeffd", "a6789798st", "yxcdfgxcyz"}]]]], Last /* EqualTo[1]][[All, 1]]
- Output:
{"1", "5", "6", "b", "g", "s", "t", "z"}
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 sorted(toSeq(charCount.pairs).filterIt(it[1] == 1).mapIt(it[0]))
, which is a one liner but less readable and less efficient than our solution using “collect”.
import algorithm, sugar, tables
var charCount: CountTable[char]
for str in ["133252abcdeeffd", "a6789798st", "yxcdfgxcyz"]:
charCount.merge str.toCountTable
let uniqueChars = collect(newSeq):
for ch, count in charCount.pairs:
if count == 1: ch
echo sorted(uniqueChars)
- Output:
@['1', '5', '6', 'b', 'g', 's', 't', 'z']
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.
- Output:
156bgstz
Perl
# 20210506 Perl programming solution
use strict;
use warnings;
use utf8;
use Unicode::Collate 'sort';
my %seen;
binmode(STDOUT, ':encoding(utf8)');
map { s/(\X)/$seen{$1}++/egr }
"133252abcdeeffd", "a6789798st", "yxcdfgxcyz", "AАΑSäaoö٥🤔👨👩👧👧";
my $uca = Unicode::Collate->new();
print $uca->sort ( grep { $seen{$_} == 1 } keys %seen )
- Output:
👨👩👧👧🤔15٥6AäbgoösStzΑА
Phix
function once(integer ch, i, string s) integer l = length(s) return (i=1 or ch!=s[i-1]) and (i=l or ch!=s[i+1]) end function sequence set = {"133252abcdeeffd","a6789798st","yxcdfgxcyz"}, res = filter(sort(join(set,"")),once) printf(1,"found %d unique characters: %s\n",{length(res),res})
- Output:
found 8 unique characters: 156bgstz
PicoLisp
(de uni (Lst
(let R NIL
(mapc
'((L)
(mapc
'((L) (accu 'R L 1)) L ) )
(mapcar chop Lst) )
(mapcar
car
(by
car
sort
(filter '((L) (=1 (cdr L))) R) ) ) ) )
(println
(uni
(quote
"133252abcdeeffd"
"a6789798st"
"yxcdfgxcyz" ) ) )
- Output:
("1" "5" "6" "b" "g" "s" "t" "z")
PL/M
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
- Output:
156BGSTZ
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()
- Output:
['1', '5', '6', 'b', 'g', 's', 't', 'z']
Or reducing the given strings down to a hash of character frequencies:
'''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()
- Output:
['1', '5', '6', 'b', 'g', 's', 't', 'z']
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.
my @list = <133252abcdeeffd a6789798st yxcdfgxcyz>;
for @list, (@list, 'AАΑSäaoö٥🤔👨👩👧👧') {
say "$_\nSemi-bogus \"Unicode natural sort\" order: ",
.map( *.comb ).Bag.grep( *.value == 1 )».key.sort( { .unival, .NFKD[0], .fc } ).join,
"\n (DUCET) Unicode collation order: ",
.map( *.comb ).Bag.grep( *.value == 1 )».key.collate.join, "\n";
}
- Output:
133252abcdeeffd a6789798st yxcdfgxcyz Semi-bogus "Unicode natural sort" order: 156bgstz (DUCET) Unicode collation order: 156bgstz 133252abcdeeffd a6789798st yxcdfgxcyz AАΑSäaoö٥🤔👨👩👧👧 Semi-bogus "Unicode natural sort" order: 15٥6ASäbgoöstzΑА👨👩👧👧🤔 (DUCET) Unicode collation order: 👨👩👧👧🤔ä15٥6AbögosStzΑА
REXX
This REXX program doesn't assume ASCII (or any other) order. This example was run on an ASCII machine.
If this REXX program is run on an ASCII machine, it will use the ASCII order of characters, in this case,
decimal digits, uppercase Latin letters, and then lowercase Latin letters, with other characters interspersed.
On an EBCDIC machine, the order would be lowercase Latin letters, uppercase Latin letters, and then the
decimal digits, with other characters interspersed.
On an EBCDIC machine, the lowercase letters and the uppercase letters aren't contiguous.
/*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.*/
if $='' then do; say "***error*** no lists were specified."; exit 13; end
@= /*will be a list of all unique chars. */
do j=0 for 256; x= d2c(j) /*process all the possible characters. */
if x==' ' then iterate /*ignore blanks which are a delimiter. */
_= pos(x, $); if _==0 then iterate /*character not found, then skip it. */
_= pos(x, $, _+1); if _ >0 then iterate /*Character is a duplicate? Skip it. */
@= @ x
end /*j*/ /*stick a fork in it, we're all done. */
@@= space(@, 0); L= length(@@) /*elided superfluous blanks; get length*/
if @@=='' then @= " (none)" /*if none were found, pretty up message*/
if L==0 then L= "no" /*do the same thing for the # of chars.*/
say 'unique characters are: ' @ /*display the unique characters found. */
say
say 'Found ' L " unique characters." /*display the # of unique chars found. */
- output when using the default inputs:
unique characters are: 1 5 6 b g s t z Found 8 unique characters.
Ring
see "working..." + nl
see "Unique characters are:" + nl
row = 0
str = ""
cList = []
uniqueChars = ["133252abcdeeffd", "a6789798st","yxcdfgxcyz"]
for n = 1 to len(uniqueChars)
str = str + uniqueChars[n]
next
for n = 1 to len(str)
ind = count(str,str[n])
if ind = 1
row = row + 1
add(cList,str[n])
ok
next
cList = sort(cList)
for n = 1 to len(cList)
see "" + cList[n] + " "
next
see nl
see "Found " + row + " unique characters" + nl
see "done..." + nl
func count(cString,dString)
sum = 0
while substr(cString,dString) > 0
sum++
cString = substr(cString,substr(cString,dString)+len(string(sum)))
end
return sum
- Output:
working... Unique characters are: 1 5 6 b g s t z Found 8 unique characters done...
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())
}
- Output:
156bgstz
Wren
import "/seq" for Lst
import "/sort" for Sort
var strings = ["133252abcdeeffd", "a6789798st","yxcdfgxcyz"]
var totalChars = strings.reduce { |acc, str| acc + str }.toList
var uniqueChars = Lst.individuals(totalChars).where { |l| l[1] == 1 }.map { |l| l[0] }.toList
Sort.insertion(uniqueChars)
System.print("Found %(uniqueChars.count) unique character(s), namely:")
System.print(uniqueChars.join(" "))
- Output:
Found 8 unique character(s), namely: 1 5 6 b g s t z
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
- Output:
Igual que la entrada de FreeBASIC.
XPL0
int List, I, N, C;
char Tbl(128), Str;
string 0;
[List:= ["133252abcdeeffd", "a6789798st","yxcdfgxcyz"];
for I:= 0 to 127 do Tbl(I):= 0;
for N:= 0 to 2 do
[Str:= List(N);
I:= 0;
loop [C:= Str(I);
if C = 0 then quit;
I:= I+1;
Tbl(C):= Tbl(C)+1;
];
];
for I:= 0 to 127 do
if Tbl(I) = 1 then ChOut(0, I);
]
- Output:
156bgstz