Unique characters in each string: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 460: Line 460:
wordCount = ws.length;
wordCount = ws.length;


return sort([
return [
...ws.slice(1).reduceRight(
...ws.slice(1).reduceRight(
(a, x) => intersect(x)(
(a, x) => intersect(x)(
Line 469: Line 469:
]
]
.filter(c => wordCount === charFreqs[c])
.filter(c => wordCount === charFreqs[c])
).join("");
.slice()
.sort()
.join("");
})() : "";
})() : "";


Line 500: Line 502:
// The intersection of two sets.
// The intersection of two sets.
b => new Set([...a].filter(i => b.has(i)));
b => new Set([...a].filter(i => b.has(i)));


// sort :: Ord a => [a] -> [a]
const sort = xs =>
// An A-Z sorted copy of xs.
[...xs].slice().sort(
(a, b) => a < b ? -1 : (a > b ? 1 : 0)
);





Revision as of 21:07, 3 August 2022

Unique characters in each string is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Given a list of strings, find the characters appearing exactly once in each string.

The result should be in alphabetical order.

Use the following list for this task:

        ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]

For this list, the result would be: 1 2 3 a b c

Other tasks related to string operations:
Metrics
Counting
Remove/replace
Anagrams/Derangements/shuffling
Find/Search/Determine
Formatting
Song lyrics/poems/Mad Libs/phrases
Tokenize
Sequences



11l

Translation of: Python

<lang 11l>V LIST = [‘1a3c52debeffd’, ‘2b6178c97a938stf’, ‘3ycxdb1fgxa2yz’]

print(sorted(Set(Array(LIST.join(‘’))).filter(ch -> all(:LIST.map(w -> w.count(@ch) == 1)))))</lang>

Output:
[1, 2, 3, a, b, c]

Action!

<lang Action!>DEFINE MAX="128" CHAR ARRAY uniq(MAX)

BYTE FUNC IsUnique(CHAR ARRAY s CHAR c)

 BYTE count,i
 count=0
 FOR i=1 TO s(0)
 DO
   IF s(i)=c THEN
     count==+1
     IF count>1 THEN
       RETURN (0)
     FI
   FI
 OD
 IF count=0 THEN
   RETURN (0)
 FI

RETURN (1)

PROC SetUnique(CHAR ARRAY s)

 BYTE i,c
 SetBlock(uniq,MAX,0)
 FOR i=1 TO s(0)
 DO
   c=s(i)
   IF IsUnique(s,c) THEN
     uniq(c)=1
   FI
 OD

RETURN

PROC CheckUnique(CHAR ARRAY s)

 BYTE i
 FOR i=0 TO MAX-1
 DO
   IF uniq(i)=1 AND IsUnique(s,i)=0 THEN
     uniq(i)=0
   FI
 OD

RETURN

PROC Main()

 DEFINE PTR="CARD"
 DEFINE CNT="3"
 PTR ARRAY l(CNT)
 INT i
 l(0)="1a3c52debeffd"
 l(1)="2b6178c97a938stf"
 l(2)="3ycxdb1fgxa2yz"
 SetUnique(l(0))
 FOR i=1 TO CNT-1
 DO
   CheckUnique(l(i))
 OD
 FOR i=0 TO MAX-1
 DO
   IF uniq(i) THEN
     Put(i) Put(32)
   FI
 OD

RETURN</lang>

Output:

Screenshot from Atari 8-bit computer

1 2 3 a b c

Ada

<lang Ada>with Ada.Text_Io;

procedure Unique_Characters is

  type Occurence_Count is array (Character) of Natural;
  type Occurence_List  is array (Positive range <>) of Occurence_Count;
  function Occurences (Item : String) return Occurence_Count is
     Count : Occurence_Count := (others => 0);
  begin
     for C of Item loop
        Count (C) := Count (C) + 1;
     end loop;
     return Count;
  end Occurences;
  procedure Put_Unique (List : Occurence_List) is
     use Ada.Text_Io;
  begin
     for C in List (List'First)'Range loop
        if (for all I in List'Range => List (I) (C) = 1) then
           Put (C);
           Put (' ');
        end if;
     end loop;
  end Put_Unique;

begin

  Put_Unique ((1 => Occurences ("1a3c52debeffd"),
               2 => Occurences ("2b6178c97a938stf"),
               3 => Occurences ("3ycxdb1fgxa2yz")));

end Unique_Characters;</lang>

Output:
1 2 3 a b c

ALGOL 68

<lang algol68>BEGIN # find the characters that occur once only in each element of a list #

     # of stings                                                           #
   OP UNIQUEINEACH = ( []STRING s )STRING:
      IF INT required count = ( UPB s + 1 ) - LWB s;
         required count < 1
      THEN "" # the list is empty #
      ELSE    # non-empty list #
           [ 0 : max abs char ]INT counts; # counts of used characters     #
           [ 0 : max abs char ]INT all;
           FOR i FROM LWB all TO UPB all DO all[ i ] := 0 OD;
           # count the occurances of the characters in the elements of s   #
           FOR i FROM LWB s TO UPB s DO
               FOR i FROM LWB counts TO UPB counts DO counts[ i ] := 0 OD;
               FOR j FROM LWB s[ i ] TO UPB s[ i ] DO
                   counts[ ABS s[ i ][ j ] ] +:= 1
               OD;
               FOR j FROM LWB counts TO UPB counts DO
                   # the character is unique in this string                #
                   IF counts[ j ] = 1 THEN all[ j ] +:= 1 FI
               OD
           OD;
           # construct a string of the characters that occur only once     #
           # in each string                                                #
           STRING result := "";
           FOR i FROM LWB all TO UPB all DO
               IF all[ i ] = required count THEN result +:= REPR i FI
           OD;
           result
      FI; # UNIQUEINEACH #
   # task test case                                                        #
   STRING unique = UNIQUEINEACH []STRING( "1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz" );
   FOR c FROM LWB unique TO UPB unique DO print( ( " ", unique[ c ] ) ) OD

END</lang>

Output:
 1 2 3 a b c

AppleScript

AppleScriptObjC

The filtering here is case sensitive, the sorting dependent on locale.

<lang applescript>use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later use framework "Foundation"

on uniqueCharactersInEachString(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:(characters of (listOfstrings as text))
   set AppleScript's text item delimiters to astid
   set mutableSet to current application's class "NSMutableSet"'s setWithSet:(countedSet)
   repeat with thisString in listOfstrings
       tell mutableSet to intersectSet:(current application's class "NSSet"'s setWithArray:(thisString's characters))
       tell countedSet to minusSet:(mutableSet)
   end repeat
   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 uniqueCharactersInEachString

uniqueCharactersInEachString({"1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"})</lang>

Output:

<lang applescript>{"1", "2", "3", "a", "b", "c"}</lang>

Core language only

This can be case-insensitive if required. (Just leave out the 'considering case' statement round the call to the handler). The requirement for AppleScript 2.3.1 is only for the 'use' command which loads the "Heap Sort" script. If "Heap Sort"'s instead loaded with the older 'load script' command or copied into the code, this will work on systems as far back as Mac OS X 10.5 (Leopard) and possibly earlier. Same output as above.

<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>

on uniqueCharactersInEachString(listOfStrings)

   script o
       property allCharacters : {}
       property uniques : {}
       
       on isInAllStrings(thisCharacter)
           repeat with thisString in listOfStrings
               if (thisCharacter is not in thisString) then return false
           end repeat
           
           return true
       end isInAllStrings
   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 stringCount to (count listOfStrings)
   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 = stringCount) and (o's isInAllStrings(currentCharacter))) then ¬
               set end of o's uniques to currentCharacter
           set i to j
           set currentCharacter to thisCharacter
       end if
   end repeat
   if ((j + 1 - i = stringCount) and (o's isInAllStrings(currentCharacter))) then ¬
       set end of o's uniques to currentCharacter
   
   return o's uniques

end uniqueCharactersInEachString

considering case

   uniqueCharactersInEachString({"1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"})

end considering</lang>

Arturo

<lang rebol>arr: ["1a3c52debeffd" "2b6178c97a938stf" "3ycxdb1fgxa2yz"] uniques: split first arr

loop arr 'str [

   uniques: intersection uniques 
       select split str 'x -> 
           1 = size match str x 

]

print sort uniques</lang>

Output:
1 2 3 a b c

AWK

<lang AWK>

  1. syntax: GAWK -f UNIQUE_CHARACTERS_IN_EACH_STRING.AWK
  2. sorting:
  3. PROCINFO["sorted_in"] is used by GAWK
  4. SORTTYPE is used by Thompson Automation's TAWK

BEGIN {

   PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
   n = split("1a3c52debeffd,2b6178c97a938stf,3ycxdb1fgxa2yz",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)][i]++
     }
   }
   for (c in arr2) {
     flag = 0
     for (i=1; i<=n; i++) {
       if (arr2[c][i] != 1) {
         flag = 1
       }
     }
     if (flag == 0) {
       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)

} </lang>

Output:
1a3c52debeffd
2b6178c97a938stf
3ycxdb1fgxa2yz
3 strings, 43 characters, 20 different, 6 unique: 123abc

F#

<lang fsharp> // Unique characters in each string: Nigel Galloway. May 12th., 2021 let fN g=g|>Seq.countBy id|>Seq.filter(fun(_,n)->n=1) let fUc g=g|>List.map fN|>Seq.concat|>Seq.countBy id|>Seq.filter(fun(_,n)->n=List.length g)|>Seq.map(fun((n,_),_)->n)|>Seq.sort printfn "%s" (fUc ["1a3c52debeffd";"2b6178c97a938stf";"3ycxdb1fgxa2yz"]|>Array.ofSeq|>System.String) </lang>

Output:
123abc

Factor

Works with: Factor version 0.99 2021-02-05

<lang factor>USING: io kernel sequences.interleaved sets sorting ;

{ "1a3c52debeffd" "2b6178c97a938sf" "3ycxdb1fgxa2yz" } [ intersect-all ] [ [ duplicates ] gather without ] bi natural-sort CHAR: space <interleaved> print

! How it works: ! intersect-all obtain elements present in every string -> "1a3c2bf" ! [ duplicates ] gather obtain elements that repeat within a single string -> "efd798xy" ! without from the first string, remove elements that are in the second -> "1a3c2b"</lang>

Output:
1 2 3 a b c

FreeBASIC

<lang freebasic>function count_char( s as string, c as string ) as uinteger

   'count occurrences of character c in string s
   dim as integer i, r = 0
   for i = 1 to len(s)
       if mid(s,i,1) = c then r += 1
   next i
   return r

end function

dim as string*20 dat(1 to 3) = {"1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"} dim as string c, uniq dim as integer i,j

for i = 1 to len(dat(1)) 'go through the first string

   c = mid(dat(1),i,1)
   for j = 1 to 3
       if count_char(dat(j), c)<>1 then goto nexti                      'contrary to popular belief, gotos are not evil
   next j
   for j = 1 to len(uniq)-1                                             'if it occurs once in every string
       if mid(uniq,j+1,1)>c then exit for                               'find where we need to put it in alphabetical order
   next j
   uniq = left(uniq,j)+c+right(uniq,len(uniq)-j)                        'and insert it into its correct place
   nexti:

next i

print uniq</lang>

Output:
123abc

Go

<lang go>package main

import (

   "fmt"
   "sort"

)

func main() {

   strings := []string{"1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"}
   u := make(map[rune]int)
   for _, s := range strings {
       m := make(map[rune]int)
       for _, c := range s {
           m[c]++
       }
       for k, v := range m {
           if v == 1 {
               u[k]++
           }
       }
   }
   var chars []rune
   for k, v := range u {
       if v == 3 {
           chars = append(chars, k)
       }
   }
   sort.Slice(chars, func(i, j int) bool { return chars[i] < chars[j] })
   fmt.Println(string(chars))

}</lang>

Output:
123abc

Haskell

<lang haskell>import qualified Data.Map.Strict as M import Data.Maybe (fromJust) import qualified Data.Set as S

onceInEach :: [String] -> String onceInEach [] = [] onceInEach ws@(x : xs) =

 S.elems $
   S.filter
     ((wordCount ==) . fromJust . flip M.lookup freq)
     ( foldr
         (S.intersection . S.fromList)
         (S.fromList x)
         xs
     )
 where
   wordCount = length ws
   freq =
     foldr
       (flip (M.insertWith (+)) 1)
       M.empty
       (concat ws)

TEST -------------------------

main :: IO () main =

 (putStrLn . onceInEach)
   [ "1a3c52debeffd",
     "2b6178c97a938stf",
     "3ycxdb1fgxa2yz"
   ]</lang>
Output:
123abc

JavaScript

<lang javascript>(() => {

   "use strict";
   // --- CHARACTERS SEEN EXACTLY ONCE IN EACH STRING ---
   // onceInEach :: [String] -> String
   const onceInEach = ws =>
       // Characters which occur exactly once
       // in each word in a given list.
       0 < ws.length ? (() => {
           const
               charFreqs = charCounts(ws.join("")),
               charSet = s => new Set([...s]),
               wordCount = ws.length;
           return [
               ...ws.slice(1).reduceRight(
                   (a, x) => intersect(x)(
                       charSet(a)
                   ),
                   charSet(ws[0])
               )
           ]
           .filter(c => wordCount === charFreqs[c])
           .slice()
           .sort()
           .join("");
       })() : "";


   // ---------------------- TEST -----------------------
   const main = () =>
       onceInEach([
           "1a3c52debeffd",
           "2b6178c97a938stf",
           "3ycxdb1fgxa2yz"
       ]);
   // --------------------- GENERIC ---------------------
   // charCounts :: String -> Dict Char Int
   const charCounts = cs =>
       // Dictionary of chars, with the
       // frequency of each in cs.
       [...cs].reduce(
           (a, c) => Object.assign(
               a, {
                   [c]: 1 + (a[c] || 0)
               }
           ), {}
       );


   // intersect :: Set -> Set -> Set
   const intersect = a =>
       // The intersection of two sets.
       b => new Set([...a].filter(i => b.has(i)));


   // MAIN ---
   return main();

})();</lang>

Output:
123abc

jq

Works with: jq

Works with gojq, the Go implementation of jq

Helper functions <lang jq># bag of words def bow(stream):

 reduce stream as $word ({}; .[($word|tostring)] += 1);
  1. input: an array of arrays that represent sets
  2. output: a stream of the items in all the input arrays

def intersections:

 # intersection of (two) sets
 # If a and b are sorted lists, and if all the elements respectively of a and b are distinct,
 # then [a,b] | ios will emit the stream of elements in the set-intersection of a and b.
 def ios:
   .[0] as $a | .[1] as $b
   | if 0 == ($a|length) or 0 == ($b|length) then empty
     elif $a[0] == $b[0] then $a[0], ([$a[1:], $b[1:]] | ios)
     elif $a[0]  < $b[0] then [$a[1:], $b] | ios
     else [$a, $b[1:]] | ios
     end;
  if length == 0 then empty
  elif length == 1 then .[0][]
  elif length == 2 then ios
  elif (.[0]|length) == 0 then empty
  else [.[0], [ .[1:] | intersections]] | ios
  end;</lang>

The task <lang jq>def once_in_each_string:

 # convert each string to an array of the constituent characters
   map((explode | map([.]|implode)))
 # identify the singleton characters in each string; `keys` sorts the keys
   | map( bow(.[]) | with_entries(select(.value==1)) | keys)
   | intersections ;
 

["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"] | [once_in_each_string] </lang>

Output:
["1","2","3","a","b","c"]

Julia

<lang julia>list = ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]

onceineachstring(list) = filter(c -> all(w -> count(x -> x == c, w) == 1, list), (sort ∘ unique ∘ prod)(list))

println(onceineachstring(list))

</lang>

Output:

['1', '2', '3', 'a', 'b', 'c']

Mathematica/Wolfram Language

<lang Mathematica>sets = Characters /@ {"1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"}; uniques = Sort[Select[Tally[#], Last/*EqualTo[1]]All, 1] & /@ sets; Intersection @@ uniques</lang>

Output:
{"1", "2", "3", "a", "b", "c"}

Nim

<lang Nim>import strutils, tables

var result = AllChars for str in ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]:

 let charCount = str.toCountTable      # Mapping char -> count.
 var uniqueChars: set[char]            # Set of unique chars.
 for ch, count in charCount.pairs:
   if count == 1: uniqueChars.incl ch
 result = result * uniqueChars         # Intersection.

echo result</lang>

Output:
{'1', '2', '3', 'a', 'b', 'c'}

Pascal

Works with: Extended Pascal

<lang pascal>program uniqueCharactersInEachString(output);

type { This “discriminates” the Extended Pascal (ISO 10206) schema } { data type `string` to hold a sequence of up to `16` characters. } message = string(16); characters = set of char;

{ \brief determine set of `char` values appear in a `string` once only \param sample the `string` to inspect \return a `set of char` appearing once in \param sample } { In Extended Pascal `protected` denotes an immutable parameter. } function uniqueCharacters(protected sample: message): characters; var { Here, `sample.capacity` refers to `16`. } i: 1..sample.capacity; { EP extension: `… value []` initializes variables to empty set value. } firstOccurence, nonFirstOccurence: characters value []; begin for i := 1 to length(sample) do begin { With sets, `+` denotes the union, `*` denotes the intersection. } nonFirstOccurence := nonFirstOccurence + firstOccurence * [sample[i]]; firstOccurence := firstOccurence + [sample[i]] end;

uniqueCharacters := firstOccurence - nonFirstOccurence end;

{ \brief calls `uniqueCharacters` for several strings \param sample the `array` of strings \return characters appearing once in every \param sample member } function allUniqueCharacters( { This is a “conformant array parameter” as defined by } { ISO standard 7185 (level 1), and ISO standard 10206. } protected sample: array[sampleMinimum..sampleMaximum: integer] of message ): characters; var { `type of` is an Extended Pascal extension. } i: type of sampleMinimum; uniqueInEverySample: characters value [chr(0)..maxChar]; begin for i := sampleMinimum to sampleMaximum do begin uniqueInEverySample := uniqueInEverySample * uniqueCharacters(sample[i]) end;

allUniqueCharacters := uniqueInEverySample end;


{ === MAIN ============================================================= } var c: char; sample: array[1..3] of message; lonelyLetters: characters; begin sample[1] := '1a3c52debeffd'; sample[2] := '2b6178c97a938stf'; sample[3] := '3ycxdb1fgxa2yz';

lonelyLetters := allUniqueCharacters(sample);

{ If the compiler defines ascending evaluation order, in Extended Pascal } { it is also possible to write `for c in allUniqueCharacters(sample)`. } { However, the evaluation order (ascending/descending) is not defined by } { the ISO standard, but the compiler vendor. And note, while it’s } { guaranteed that `'A' < 'B'`, it is not guaranteed that `'a' < 'B'`. } { The following might (and actually on modern systems will) still produce } { a non-alphabetical listing. } for c := chr(0) to maxChar do begin if c in lonelyLetters then begin { The `:2` is a format specifier defining the width of the output. } write(c:2) end end; writeLn end.</lang>

Output:
 1 2 3 a b c

Perl

<lang perl>#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Unique_characters_in_each_string use warnings;

my @strings = ("1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"); my $chars = join "\n", @strings; print "@{[ sort grep

 $chars !~ /$_.*$_/ &&           # the 'only once in each string' test
 @strings == $chars =~ s/$_//g,  # the 'in every string' test
 $chars =~ /./g ]}\n";</lang>
Output:
1 2 3 a b c

Phix

include builtins\sets.e

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 = {"1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"},
         res = intersection(apply(true,filter,{apply(set,sort),once}))
printf(1,"found %d unique common characters: %s\n",{length(res),res})
Output:
found 6 unique common characters: 123abc

Picat

<lang Picat>import ordset.

main =>

 L = ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"],
 U = [new_ordset([C : C = 1 in counts(S)]) : S in L],
 println(fold(intersection,U.first,U.tail)).

% Return a map of occurrences of each element in the list L counts(L) = Map =>

 Map = new_map(),
 foreach(E in L)
   Map.put(E,Map.get(E,0)+1)
 end.</lang>
Output:
123abc

PicoLisp

<lang PicoLisp>(de acc (V K N)

  (if (assoc K (val V))
     (inc (nth (cadr @) N))
     (push V (list K (list 1 0 0))) ) )

(de un (Lst)

  (let (Len (length Lst)  D)
     (for (I . Lst) (mapcar chop Lst)
        (for L Lst
           (acc 'D L I) ) )
     (mapcar
        car
        (by
           car
           sort
           (filter '((L) (fully =1 (cadr L))) D) ) ) ) )

(println

  (un
     (quote
        "1a3c52debeffd"
        "2b6178c97a938stf"
        "3ycxdb1fgxa2yz" ) ) )</lang>
Output:
("1" "2" "3" "a" "b" "c")

Python

<lang python>LIST = ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]

print(sorted([ch for ch in set([c for c in .join(LIST)]) if all(w.count(ch) == 1 for w in LIST)]))

</lang>

Output:
['1', '2', '3', 'a', 'b', 'c']

Raku

<lang perl6>my $strings = <1a3c52debeffd 2b6178c97a938stf 3ycxdb1fgxa2yz>;

put sort keys [∩] $strings.map: *.comb.Bag.grep: *.value == 1</lang>

Output:
1 2 3 a b c

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. <lang rexx>/*REXX pgm finds and shows characters that are unique in each string and once only. */ parse arg $ /*obtain optional arguments from the CL*/ if $= | $="," then $= '1a3c52debeffd' "2b6178c97a938stf" '3ycxdb1fgxa2yz' if $= then do; say "***error*** no lists were specified."; exit 13; end

  1. = words($); $$= /*#: # words in $; $$: $ with no blanks*/
             do i=1  for #;    !.i= word($, i)  /*for speed, build a list of words in $*/
             $$= $$  ||  !.i                    /*build a list of all the strings.     */
             end   /*i*/

@= /*will be a list of all unique chars. */

  do j=0  for 256;        x= d2c(j)             /*process all the possible characters. */
  if pos(x, $$)==0               then iterate   /*Char not found in any string in  $ ? */
          do k=1  for #;  _= pos(x, !.k)        /*examine each string in the  $  list. */
          if _==0                then iterate j /*Character not found?   Then skip it. */
          if pos(x, !.k, _+1)>0  then iterate j /*    "     is a dup?      "    "   "  */
          end   /*k*/
  @= @ x                                        /*append a character, append it to list*/
  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. */</lang>

output   when using the default input:
unique characters are:   1 2 3 a b c

Found  6  unique characters.

Ring

<lang ring> see "working..." + nl see "Unique characters in each string are:" + nl row = 0 str = "" cList = [] uniqueChars = ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"] lenChars = len(uniqueChars)

for n = 1 to lenChars

   str = str + uniqueChars[n]

next

for n = 1 to len(str)

   flag = 1
   for m = 1 to lenChars
       cnt = count(uniqueChars[m],str[n])
       if cnt != 1
          flag = 0
          exit
       ok
   next
   if flag = 1
      ind = find(cList,str[n])
      if ind = 0
         add(cList,str[n])
      ok
   ok

next cList = sort(cList) for n = 1 to len(cList)

   row = row + 1
   see "" + cList[n] + " "

next see nl

see "Found " + row + " unique characters in each string" + 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

</lang>

Output:
working...
Unique characters in each string are:
1 2 3 a b c 
Found 6 unique characters in each string
done...

Ruby

<lang ruby>arr = ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]

uniqs_in_str = arr.map{|str| str.chars.tally.filter_map{|char, count| char if count == 1} } puts uniqs_in_str.inject(&:intersection).sort.join(" ") </lang>

Output:
1 2 3 a b c

Wren

Library: Wren-seq
Library: Wren-sort

<lang ecmascript>import "/seq" for Lst import "/sort" for Sort

var strings = ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"] var uniqueChars = [] for (s in strings) {

   var u = Lst.individuals(s.toList).where { |l| l[1] == 1 }.map { |l| l[0] }
   uniqueChars.addAll(u)

} var n = strings.count uniqueChars = Lst.individuals(uniqueChars).where { |l| l[1] == n }.map { |l| l[0] }.toList Sort.insertion(uniqueChars) System.print("Found %(uniqueChars.count) unique character(s) common to each string, namely:") System.print(uniqueChars.join(" "))</lang>

Output:
Found 6 unique character(s) common to each string, namely:
1 2 3 a b c

Vlang

Translation of: go

<lang vlang>fn main() {

   strings := ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]!
   mut u := map[rune]int{}
   for s in strings {
       mut m := map[rune]int{}
       for c in s {
           m[c]++
       }
       for k, v in m {
           if v == 1 {
               u[k]++
           }
       }
   }
   mut chars := []rune{}
   for k, v in u {
       if v == 3 {
           chars << k
       }
   }
   chars.sort()
   println(chars.string())

}</lang>

Output:
123abc

XPL0

<lang XPL0>char List, Counter(128), Unique(3, 128); int Char, I, J; string 0; \use null-terminated string convention [List:= ["1a3c52debeffd", "2b6178c97a938stf", "3ycxdb1fgxa2yz"]; for I:= 0 to 2 do \each string in List

   [for J:= 0 to 127 do Counter(J):= 0;
   J:= 0;              \count each character in string
   repeat  Char:= List(I, J);
           J:= J+1;
           Counter(Char):= Counter(Char)+1;
   until   Char = 0;   \terminator
   for J:= 0 to 127 do
       Unique(I, J):= Counter(J) = 1;
   ];

for Char:= 1 to 127 do \skip 0 terminator

   if Unique(0, Char) & Unique(1, Char) & Unique(2, Char) then
       [ChOut(0, Char);  ChOut(0, ^ )];

]</lang>

Output:
1 2 3 a b c 

Yabasic

Translation of: FreeBASIC

<lang yabasic>sub count_char(s$, c$)

   local i, r
   r = 0
   for i = 1 to len(s$)
       if mid$(s$,i,1) = c$ then r = r + 1 : fi
   next i
   return r

end sub

dim dat$(2) dat$(0) = "1a3c52debeffd" dat$(1) = "2b6178c97a938stf" dat$(2) = "3ycxdb1fgxa2yz"

for i = 1 to len(dat$(1))

   c$ = mid$(dat$(1), i, 1)
   for j = 0 to 2
       if count_char(dat$(j), c$) <> 1 then goto nexti : fi
   next j
   for j = 0 to len(uniq$)-1
       if mid$(uniq$, j+1, 1) > c$ then break : fi
   next j
   uniq$ = left$(uniq$, j) + c$ + right$(uniq$, len(uniq$)-j)
   label nexti

next i

print uniq$ end</lang>

Output:
123abc