Jump to content

English cardinal anagrams

From Rosetta Code
English cardinal anagrams 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.

Certain numbers, when spelled out in their English cardinal representation, are anagrams of other numbers.

Some are very obvious: sixty-seven <=> seventy-six

Others are a little more subtle: one hundred twelve <=> two hundred eleven


Task
  • Find and display the first thirty numbers that are a member of English cardinal anagrams, starting from zero.
  • Find and display the count of English cardinal anagrams from zero to one thousand.
  • Find and display the largest group(s) of English cardinal anagrams from zero to one thousand.


Stretch
  • Find and display the count of English cardinal anagrams from zero to ten thousand, restricted to numbers within those bounds. (Ignore anagrams of numbers outside those bounds. E.G. 1010 <=> 10001)
  • Find and display the largest group(s) of English cardinal anagrams from zero to ten thousand.


See also


ALGOL 68

Using slightly modified code from the Four is magic task.

Library: ALGOL 68-sort

Note, the source of the RC ALGOL 68 sort library (sort.incl.a68) is on a separate page of Rosetta Code, see the above link.

BEGIN # construct number names from a number                                  #
    PR read "sort.incl.a68" PR                       # include sort utilities #
    MODE NUMBER = LONG INT;        # adjust to suit, must be at least 64 bits #
    OP TOINT = ( NUMBER n )INT: SHORTEN n;                   # adjust to suit #
    []STRING units
           = ( "one", "two",  "three", "four", "five", "six", "seven", "eight", "nine" );
    []STRING teens
           = ( "ten",     "eleven",  "twelve",    "thirteen", "fourteen"
             , "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
             );
    []STRING tens
           = ( "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" );
    []STRING power suffix
           = ( "thousand", "million", "billion", "trillion", "quadrillion", "quintillion" );
    # returns c encoded as a = 1, b = 2, etc. c must be in "a".."z"           #
    OP LETTER = ( CHAR c )INT: ( ABS c - ABS "a" ) + 1;
    # returns n converted to a number name, n must be in range 1-99           #
    PROC two digits = ( INT n )STRING:
         IF   n < 10
         THEN units[ n ]
         ELIF n < 20
         THEN teens[ n - 9 ]
         ELIF INT last1 = n MOD 10;
              last1 = 0
         THEN tens[ ( n OVER 10 ) - 1 ]
         ELSE tens[ ( n OVER 10 ) - 1 ] + " " + units[ last1 ]
         FI # two digits # ;
    # returns n converted to a number name, n must be in range 1-999          #
    PROC three digits = ( INT n )STRING:
         IF   n < 100
         THEN two digits( n )
         ELIF STRING hundreds = units[ n OVER 100 ] + " hundred";
              INT    last2 = n MOD 100;
              last2 = 0
         THEN hundreds
         ELSE hundreds + " and " + two digits( last2 )
         FI # three digits # ;
    # returns the "name" of n                                                 #
    OP NAME = ( NUMBER n )STRING:
       IF   n < 0 THEN "negative " + NAME - n
       ELIF n = 0 THEN "zero"
       ELSE # have a positive number to name                                  #
            NUMBER   v         := n;
            STRING   result    := "";
            INT      power pos := 0;
            WHILE v /= 0 DO
                IF   INT v999 = TOINT ( v MOD 1000 );
                     v999 /= 0
                THEN STRING component := three digits( v999 );
                     IF power pos > 0 THEN
                         component +:= " " + power suffix[ power pos ]
                     FI;
                     IF result /= "" THEN component +:= " " FI;
                     component +=: result
                FI;
                power pos +:= 1;
                v OVERAB 1000
            OD;
            result
       FI # NAME # ;
    # returns the number name of n, only needed of NUMBER is not INT          #
    OP NAME   = ( INT n )STRING: NAME NUMBER( n );

    # returns a "hash" of s - s with the letters in order, spaces are ignored #
    OP HASHOF = ( STRING s )STRING:
       BEGIN
           [ 1 : 26 ]INT counts; FOR i TO UPB counts DO counts[ i ] := 0 OD;
           FOR i FROM LWB s TO UPB s DO
               CHAR c = s[ i ];
               IF c /= " " THEN counts[ LETTER c ] +:= 1 FI
           OD;
           STRING result := "";
           FOR i FROM LETTER "a" TO LETTER "z" DO
               IF counts[ i ] > 0 THEN result +:= counts[ i ] * REPR ( ABS "a" + i - 1 ) FI
           OD;
           result
       END # HASHOF # ;

    # mode to hold details of a possible cardinal name anagram                #
    MODE CARDINALANA = STRUCT( STRING h                  # "hash" of the name #
                             , INT    n                          # the number #
                             , INT    count # count of numbers with this hash #
                             );
    # exchanges the values of swap a and with b                               #
    OP   =:= = ( REF CARDINALANA swap a, with b )VOID:
         BEGIN CARDINALANA t = with b; with b := swap a; swap a := t END;
    # in-place quick sort a[ lb : ub ] using qs lt for the comparisons        #
    PROC quicksort anagrams = ( REF[]CARDINALANA qs a
                              , INT              lb, ub
                              , PROC(CARDINALANA,CARDINALANA)BOOL qs lt
                              ) VOID:
         IF ub <= lb
         THEN SKIP                      # at most 1 element - no need to sort #
         ELSE                           # more than one element, so must sort #
            INT qs left  := lb;
            INT qs right := ub;
            # choosing the middle element of the array as the pivot           #
            CARDINALANA pivot := qs a[ qs left + ( ( qs right + 1 ) - qs left ) OVER 2 ];
            WHILE
                WHILE IF qs left  <= ub THEN qs lt( qs a[ qs left  ], pivot ) ELSE FALSE FI
                DO
                    qs left  +:= 1
                OD;
                WHILE IF qs right >= lb THEN qs lt( pivot, qs a[ qs right ] ) ELSE FALSE FI
                DO
                    qs right -:= 1
                OD;
                qs left <= qs right
            DO
                qs a[ qs left  ] =:= qs a[ qs right ];
                qs left          +:= 1;
                qs right         -:= 1
            OD;
            quicksort anagrams( qs a, lb,      qs right, qs lt );
            quicksort anagrams( qs a, qs left, ub,       qs lt )
         FI # quicksort anagrams # ;

    BEGIN
        []INT tests = ( 1 000, 10 000 );
        FOR max pos FROM LWB tests TO UPB tests DO
            INT max number = tests[ max pos ]; # largest number for this test #
            # construct a table of the possible anagrams                      #
            [ 0 : max number + 1 ]CARDINALANA anagram;
            FOR n FROM 0 TO max number DO
               h OF anagram[ n ]     := HASHOF NAME n;
               n OF anagram[ n ]     := n;
               count OF anagram[ n ] := 0
            OD;
            # add a final dummy element to simplify counting the anagrams     #
            h OF anagram[ max number + 1 ]     := "z" * 26;
            n OF anagram[ max number + 1 ]     := -1;
            count OF anagram[ max number + 1 ] := 0;
            # sort the possible anagrams into "hash" and number order         #
            quicksort anagrams( anagram, 0, max number
                              , ( CARDINALANA a, b )BOOL: h OF a < h OF b
                                                     OR ( h OF a = h OF b AND n OF a < n OF b )
                              );
            # add counts of each anagram to the table                         #
            STRING max value  := "";
            INT    prev start := LWB anagram;
            STRING prev value := max value;
            INT  max count  := 0, this count := 0;
            FOR i FROM LWB anagram TO UPB anagram DO
                STRING value := h OF anagram[ i ];
                IF value = prev value THEN
                    this count +:= 1
                ELSE
                    IF this count > max count THEN
                        max count := this count
                    FI;
                    FOR p FROM prev start TO i DO count OF anagram[ p ] := this count OD;
                    prev value := value;
                    prev start := i;
                    this count := 1
                FI
            OD;
            PROC show group = ( []INT group )VOID:
                 BEGIN
                    INT pos := -1;
                    print( ( "        [" ) );
                    FOR i FROM LWB group TO UPB group DO
                        IF ( pos +:= 1 ) = 10 THEN print( ( newline, "         " ) ); pos := 0 FI;
                        print( ( " ", whole( group[ i ], IF group[ i ] < 100 THEN -3 ELSE 0 FI ) ) )
                    OD;
                    print( ( " ]", newline ) )
                 END # show group # ;
            # show some features of the anagrams                              #
            # count the anagrams                                              #
            INT anagram count := 0;
            FOR i FROM LWB anagram + 1 TO UPB anagram DO
                IF count OF anagram[ i ] > 1 AND h OF anagram[ i ] /= h OF anagram[ i - 1 ] THEN
                    anagram count +:= 1
                FI
            OD;
            IF max pos = 1 THEN
                # first test - show the first 30 anagrams                     #
                [ 1 : max number ]INT first;
                FOR i TO max number DO
                    first[ i ] := IF count OF anagram[ i ] > 1 THEN n OF anagram[ i ] ELSE max int FI
                OD;
                print( ( "    the first 30 anagrams:", newline ) );
                show group( ( QUICKSORT first )[ 1 : 30 ] )
            FI;
            print( ( "Up to ", whole( max number, 0 ) ) );
            print( ( " there are ", whole( anagram count, 0 ), " anagrams", newline ) );
            # show the largest group(s) of anagrams                           #
            print( ( "    the largest group(s) of anagrams:", newline ) );
            [ 1 : max count ]INT a group;
            INT a pos  := 0;
            prev value := "";
            FOR i FROM LWB anagram TO UPB anagram DO
                IF count OF anagram[ i ] = max count THEN
                    IF prev value = "" OR h OF anagram[ i ] /= prev value THEN
                        IF prev value /= "" THEN
                            show group( a group )
                        FI;
                        prev value := h OF anagram[ i ];
                        a pos := 0
                    FI;
                    a group[ a pos +:= 1 ] := n OF anagram[ i ]
                FI
            OD;
            show group( a group )
        OD
    END
END
Output:
    the first 30 anagrams:
        [  67  69  76  79  96  97 102 103 104 105
          106 107 108 109 112 122 123 124 125 126
          127 128 129 132 133 134 135 136 137 138 ]
Up to 1000 there are 317 anagrams
    the largest group(s) of anagrams:
        [ 679 697 769 796 967 976 ]
Up to 10000 there are 2534 anagrams
    the largest group(s) of anagrams:
        [ 3679 3697 3769 3796 3967 3976 6379 6397 6793 6973
          7369 7396 7693 7963 9367 9376 9673 9763 ]
        [ 5679 5697 5769 5796 5967 5976 6579 6597 6795 6975
          7569 7596 7695 7965 9567 9576 9675 9765 ]
        [ 6798 6879 6897 6978 7698 7869 7896 7968 8679 8697
          8769 8796 8967 8976 9678 9768 9867 9876 ]
        [ 1679 1697 1769 1796 1967 1976 6179 6197 6791 6971
          7169 7196 7691 7961 9167 9176 9671 9761 ]
        [ 4679 4697 4769 4796 4967 4976 6479 6497 6794 6974
          7469 7496 7694 7964 9467 9476 9674 9764 ]
        [ 2679 2697 2769 2796 2967 2976 6279 6297 6792 6972
          7269 7296 7692 7962 9267 9276 9672 9762 ]

Note the anagram groups are not sorted into starting number order, so the groups up to 10 000 are not in the same order as other samples.

C++

#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
#include <vector>

const std::vector<std::string> units = { "Zero", "One", "Two", "Three", "Four", "Five", "Six",
	"Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
	"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" };

const std::vector<std::string> tens =
	{ "", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };

std::string convert(const uint32_t& n) { // Valid for positive integers ≤ 999_999_999
	if ( n < 20 ) {
		return units[n];
	}
	if ( n < 100 ) {
		return tens[n / 10] + ( ( n % 10 > 0 ) ? " " + convert(n % 10) : "" );
	}
	if ( n < 1'000 ) {
		return units[n / 100] + " Hundred" + ( ( n % 100 > 0 ) ? " and " + convert(n % 100) : "" );
	}
	if ( n < 1'000'000 ) {
		return convert(n / 1'000) + " Thousand" + ( ( n % 1'000 > 0 ) ? " " + convert(n % 1'000) : "" );
	}
	return convert(n / 1'000'000) + " Million"
		+ ( ( n % 1'000'000 > 0 ) ? " " + convert(n % 1'000'000) : "" );
}

std::string to_lower_case(const std::string& text) {
	std::string result = text;
	std::transform(result.begin(), result.end(), result.begin(), [](char ch) { return std::tolower(ch); });
	return result;
}

void print_vector(std::vector<uint32_t> list) {
    std::cout << "[";
    for ( uint64_t i = 0; i < list.size() - 1; ++i ) {
		std::cout << list[i] << ", ";
    }
    std::cout << list.back() << "]" << std::endl;
}

int main() {
	for ( uint32_t limit : { 1'000, 10'000 } ) {
	    std::map<std::vector<char>, std::vector<uint32_t>> anagrams = { };
	    for ( uint32_t i = 0; i < limit; ++i ) {
	    	std::string name = to_lower_case(convert(i));
	        std::vector<char> chars(name.begin(), name.end());
	        std::sort(chars.begin(), chars.end());
	        anagrams[chars].emplace_back(i);
	    }

	    if ( limit == 1'000 ) {
			std::vector<uint32_t> allAnagrams = { };
			for ( const auto& [key, value] : anagrams ) {
				if ( value.size() > 1 ) {
					allAnagrams.insert(allAnagrams.end(), value.begin(), value.end());
			    }
			}
			std::sort(allAnagrams.begin(), allAnagrams.end());
			std::cout << "First 30 English cardinal anagrams:" << std::endl;
			for ( uint32_t i = 0; i < 30; ++i ) {
				std::cout << std::setw(3) << allAnagrams[i] << ( ( i % 10 == 9 ) ? "\n" : " " );
			}
			std::cout << std::endl;
		}

	    const uint32_t count = std::count_if(anagrams.begin(), anagrams.end(),
	        [](const auto& pair) { return pair.second.size() > 1; });
		std::cout << "Count of English cardinal anagrams up to 1000: " << count << std::endl << std::endl;

		uint32_t max = 0;
		std::vector<std::vector<uint32_t>> largest = { };
		for ( const auto& [key, value] : anagrams ) {
			if ( value.size() > max ) {
				max = value.size();
				largest = { value };
			} else if ( value.size() == max ) {
				largest.emplace_back(value);
			}
		}
		std::cout << "Largest group(s) of English cardinal anagrams up to " << limit << ": " << std::endl;
		std::sort(largest.begin(), largest.end(),
			[](const std::vector<uint32_t>& a, const std::vector<uint32_t>& b) { return a[0] < b[0]; });
		std::for_each(largest.begin(), largest.end(), print_vector);
		std::cout << std::endl;
	}

}
Output:
First 30 English cardinal anagrams:
 67  69  76  79  96  97 102 103 104 105
106 107 108 109 112 122 123 124 125 126
127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1000: 317

Largest group(s) of English cardinal anagrams up to 1000: 
[679, 697, 769, 796, 967, 976]

Count of English cardinal anagrams up to 1000: 2534

Largest group(s) of English cardinal anagrams up to 10000: 
[1679, 1697, 1769, 1796, 1967, 1976, 6179, 6197, 6791, 6971, 7169, 7196, 7691, 7961, 9167, 9176, 9671, 9761]
[2679, 2697, 2769, 2796, 2967, 2976, 6279, 6297, 6792, 6972, 7269, 7296, 7692, 7962, 9267, 9276, 9672, 9762]
[3679, 3697, 3769, 3796, 3967, 3976, 6379, 6397, 6793, 6973, 7369, 7396, 7693, 7963, 9367, 9376, 9673, 9763]
[4679, 4697, 4769, 4796, 4967, 4976, 6479, 6497, 6794, 6974, 7469, 7496, 7694, 7964, 9467, 9476, 9674, 9764]
[5679, 5697, 5769, 5796, 5967, 5976, 6579, 6597, 6795, 6975, 7569, 7596, 7695, 7965, 9567, 9576, 9675, 9765]
[6798, 6879, 6897, 6978, 7698, 7869, 7896, 7968, 8679, 8697, 8769, 8796, 8967, 8976, 9678, 9768, 9867, 9876]

FreeBASIC

Translation of: Wren
#define floor(x) ((x*2.0-0.5) Shr 1)
#define MIN(a, b) iif((a) < (b), (a), (b))

Sub SortInt(array() As Integer)
    Static As Integer i, j, mn
    Dim As Integer lb = Lbound(array), ub = Ubound(array)
    For i = lb To ub - 1
        mn = i
        For j = i + 1 To ub
            If array(j) < array(mn) Then mn = j
        Next j
        Swap array(mn), array(i)
    Next i
End Sub

Sub SortStr(array() As String)
    Dim As Integer i, j
	Dim As Integer lb = Lbound(array), ub = Ubound(array)
    For i = lb To ub - 1
        For j = i + 1 To ub
            If array(i) > array(j) Then Swap array(i), array(j)
        Next j
    Next i
End Sub

Function say(n As Integer) As String
    Dim As String small(0 To 19) = { _
    "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", _
    "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", _
    "sixteen", "seventeen", "eighteen", "nineteen"}
    
    Dim As String tens(0 To 9) = { _
    "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}
    
    Dim As String illions(0 To 5) = { _
    "", " thousand", " million", " billion", " trillion", " quadrillion"}
    
    Dim As Integer s, p, i
    Dim As String t = "", sx, ix
    
    If (n < 0) Then
        t = "negative "
        n = -n
    End If
    If (n < 20) Then
        t &= small(n)
    Elseif (n < 100) Then
        t &= tens(floor(n / 10))
        s = n Mod 10
        If (s > 0) Then t &= "-" & small(s)
    Elseif (n < 1000) Then
        t &= small(floor(n / 100)) & " hundred"
        s = n Mod 100
        If (s > 0) Then t &= " " & say(s)
    Else 
        sx = ""
        i = 0
        While (n > 0)
            p = n Mod 1000
            n = floor(n / 1000)
            If (p > 0) Then
                ix = say(p) & illions(i)
                If (sx <> "") Then ix &= " " & sx
                sx = ix
            End If
            i += 1
        Wend
        t &= sx
    End If
    Return t
End Function

Function CleanString(s As String) As String    ' REPLACE
    Dim As String result = ""
    For i As Integer = 1 To Len(s)
        If Mid(s, i, 1) <> " " And Mid(s, i, 1) <> "-" Then
            result &= Mid(s, i, 1)
        End If
    Next
    Return result
End Function

Sub ParseValues(s As String, values() As Integer)
    ' Divide una cadena en valores enteros sin usar SPLIT
    Dim As Integer cnt = 0, start = 1, commaPos
    Do
        commaPos = Instr(start, s, ",")
        If commaPos = 0 Then commaPos = Len(s) + 1
        Redim Preserve values(cnt)
        values(cnt) = Val(Mid(s, start, commaPos - start))
        cnt += 1
        start = commaPos + 1
    Loop While commaPos <= Len(s)
End Sub

Dim As Integer limit, i, j, k, max
Dim As Integer largest(),all(), values()
Dim As String ana(), anaMap(), keyArray()

For limit = 1000 To 10000 Step 9000
    Redim ana(0)
    Redim anaMap(0)
    For i = 0 To limit
        Dim As String key = CleanString(say(i))
        Redim keyArray(Len(key) - 1)
        For j = 0 To Len(key) - 1
            keyArray(j) = Mid(key, j + 1, 1)
        Next j
        
        SortStr(keyArray())
        key = ""
        For j = Lbound(keyArray) To Ubound(keyArray)
            key &= keyArray(j)
        Next j
        Dim As Integer found = -1
        For k = 0 To Ubound(ana)
            If ana(k) = key Then
                found = k
                Exit For
            End If
        Next k
        If found = -1 Then
            Redim Preserve ana(Ubound(ana) + 1)
            ana(Ubound(ana)) = key
            Redim Preserve anaMap(Ubound(anaMap) + 1)
            anaMap(Ubound(anaMap)) = Str(i)
        Else
            anaMap(found) &= "," & Str(i)
        End If
    Next i
    If (limit = 1000) Then
        Redim all(0)
        For i As Integer = 0 To Ubound(anaMap)
            Dim values() As Integer
            ParseValues(anaMap(i), values())
            If Ubound(values) > 0 Then
                For w As Integer = 0 To Ubound(values)
                    Redim Preserve all(Ubound(all) + 1)
                    all(Ubound(all)) = values(w)
                Next w
            End If
        Next i
        
        SortInt(all())
        Print "First 30 English cardinal anagrams:"
        For j = 1 To MIN(30, Ubound(all))
            Print Using "####"; all(j);
            If j Mod 10 = 0 Then Print
        Next j
    End If
    Dim As Integer cnt = 0
    For i = 0 To Ubound(anaMap)
        ParseValues(anaMap(i), values())
        If Ubound(values) > 0 Then cnt += 1
    Next i
    
    Print Using !"\nCount of English cardinal anagrams up to ##,###: #,###"; limit; cnt
    max = 0
    Redim largest(0)
    For i = 0 To Ubound(anaMap)
        ParseValues(anaMap(i), values())
        If Ubound(values) > max Then
            max = Ubound(values)
            Redim largest(Ubound(values))
            For j = 0 To Ubound(values)
                largest(j) = values(j)
            Next j
        Elseif Ubound(values) = max Then
            Dim As Integer oldSize = Ubound(largest)
            Redim Preserve largest(oldSize + Ubound(values) + 1)
            For j = 0 To Ubound(values)
                largest(oldSize + j + 1) = values(j)
            Next j
        End If
    Next i
    
    Print !"\nLargest group(s) of English cardinal anagrams up to"; limit; ":"
    For k As Integer = 0 To Ubound(largest)
        Print largest(k);
        If k < Ubound(largest) Then Print " ";
        If (k+1) Mod 18 = 0 Then Print
    Next k
    
    If (limit = 1000) Then Print
Next limit

Sleep
Output:
First 30 English cardinal anagrams:
  67  69  76  79  96  97 102 103 104 105
 106 107 108 109 112 122 123 124 125 126
 127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to  1,000:   317

Largest group(s) of English cardinal anagrams up to 1000:
 679  697  769  796  967  976

Count of English cardinal anagrams up to 10,000: 2,534

Largest group(s) of English cardinal anagrams up to 10000:
 1679  1697  1769  1796  1967  1976  6179  6197  6791  6971  7169  7196  7691  7961  9167  9176  9671  9761
 2679  2697  2769  2796  2967  2976  6279  6297  6792  6972  7269  7296  7692  7962  9267  9276  9672  9762
 3679  3697  3769  3796  3967  3976  6379  6397  6793  6973  7369  7396  7693  7963  9367  9376  9673  9763
 4679  4697  4769  4796  4967  4976  6479  6497  6794  6974  7469  7496  7694  7964  9467  9476  9674  9764
 5679  5697  5769  5796  5967  5976  6579  6597  6795  6975  7569  7596  7695  7965  9567  9576  9675  9765
 6798  6879  6897  6978  7698  7869  7896  7968  8679  8697  8769  8796  8967  8976  9678  9768  9867  9876

J

Using the definitions at Number_names#J and

ukgram=: /:~@uk&.> 

sample=: I.(e. ~. #~ 1<#/.~)ukgram i. 1e6
sam1e3=: I.(e. ~. #~ 1<#/.~)ukgram i. 1e3
sam1e4=: I.(e. ~. #~ 1<#/.~)ukgram i. 1e4

largegroups=: {{
   tokens=. /:~@uk&.> y
   utokens=. ~. tokens
   ucounts=. #/.~ tokens
   uids=. utokens #~ (=>./) ucounts
   >}.y </.~ uids i. tokens
}}

We get:

   3 10$ sample
 67  69  76  79  96  97 102 103 104 105
106 107 108 109 112 122 123 124 125 126
127 128 129 132 133 134 135 136 137 138
   +/1000>:sample  NB. count of values in OEIS::A169936 less than 1000
680
   #~.ukgram (#~ 1000>:])sample NB. count of distinct anagrams for those values
317
   largegroups (#~ 1000&>:) sample
679 697 769 796 967 976

Stretch:

If we consider all values in values in OEIS:A169936 which are less than 1e4

   +/10000>:sample  NB. distinct members in subsequence
9662
   #~.ukgram (#~ 10000>:])sample   NB. distinct anagrams in subsequence
2968
   largegroups (#~ 10000&>:) sample   NB. anagram groups with most members in subsequence
1679 1697 1769 1796 1967 1976 6179 6197 6791 6971 7169 7196 7691 7961 9167 9176 9671 9761
2679 2697 2769 2796 2967 2976 6279 6297 6792 6972 7269 7296 7692 7962 9267 9276 9672 9762
3679 3697 3769 3796 3967 3976 6379 6397 6793 6973 7369 7396 7693 7963 9367 9376 9673 9763
4679 4697 4769 4796 4967 4976 6479 6497 6794 6974 7469 7496 7694 7964 9467 9476 9674 9764
5679 5697 5769 5796 5967 5976 6579 6597 6795 6975 7569 7596 7695 7965 9567 9576 9675 9765
6798 6879 6897 6978 7698 7869 7896 7968 8679 8697 8769 8796 8967 8976 9678 9768 9867 9876

If we explicitly exclude anagrams whose only partner is greater than 1e4, we get a slightly smaller subsequence:

   #sam1e4
9228
   #~.ukgram sam1e4
2534

Note however that for values less than 1000, every member of the OEIS:A169936 sequence had a partner which was also less than 1000:

   #sam1e3
680
   +/1000>:sample
680

Java

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public final class EnglishCardinalAnagrams {

	public static void main(String[] args) {
		for ( int limit : List.of( 1_000, 10_000 ) ) {
		    Map<List<Character>, List<Integer>> anagrams = new HashMap<List<Character>, List<Integer>>();
		    for ( int i = 0; i < limit; i++ ) {
		    	String name = NumberToWordsConverter.convert(i).toLowerCase();
		    	List<Character> chars = name.chars().mapToObj( ch -> (char) ch ).sorted().toList();
		    	anagrams.computeIfAbsent(chars, k -> new ArrayList<Integer>() ).add(i);
		    }
		    
		    if ( limit == 1_000 ) {
		    	List<Integer> allAnagrams = anagrams.values().stream().filter( list -> list.size() > 1 )
		    		.flatMap(Collection::stream).sorted().toList();		    	
		    	System.out.println("First 30 English cardinal anagrams:");
		    	for ( int i = 0; i < 30; i++ ) {
		    		System.out.print(String.format("%3d%s", allAnagrams.get(i),
		    			( i % 10 == 9 ) ? "\n" : " " ));
		    	}
		        System.out.println();
		    }		
		
		    final long count = anagrams.values().stream().filter( list -> list.size() > 1  ).count();
		    System.out.println("Count of English cardinal anagrams up to 1000: " + count);
		    System.out.println();
		    
		    int max = 0;
    	    List<List<Integer>> largest = new ArrayList<List<Integer>>();
    	    for ( List<Integer> list : anagrams.values() ) {
    	        if ( list.size() > max ) {
    	            max = list.size();
    	            largest = Stream.of( list ).limit(1).collect(Collectors.toList());
    	        } else if ( list.size() == max ) {
    	            largest.addLast(list);
    	        }
    	    }
    	    System.out.println("Largest group(s) of English cardinal anagrams up to " + limit + ": ");    	    
    	    largest.sort( (list1, list2) -> list1.getFirst().compareTo(list2.getFirst()));
    	    largest.forEach(System.out::println);
    	    System.out.println();
		}
	}
	
	private static final class NumberToWordsConverter { // Valid for positive integers ≤ 999_999_999	

		public static String convert(int n) {
			if ( n < 20 ) {
				return units[n];
			}
			if ( n < 100 ) {
				return tens[n / 10] + ( ( n % 10 > 0 ) ? " " + convert(n % 10) : "" );
			}
			if ( n < 1_000 ) {
				return units[n / 100] + " Hundred" + ( ( n % 100 > 0 ) ? " and " + convert(n % 100) : "" );
			}
			if ( n < 1_000_000 ) {
				return convert(n / 1_000) + " Thousand"
                    + ( ( n % 1_000 > 0 ) ? " " + convert(n % 1_000) : "" );
			}
			return convert(n / 1_000_000) + " Million"
				+ ( ( n % 1_000_000 > 0 ) ? " " + convert(n % 1_000_000) : "" );		
		}
		
		private static final String[] units = { "Zero", "One", "Two", "Three", "Four", "Five", "Six",
			"Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
			"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" };
		
		private static final String[] tens =
			{ "", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };
		
	}
	
}
Output:
First 30 English cardinal anagrams:
 67  69  76  79  96  97 102 103 104 105
106 107 108 109 112 122 123 124 125 126
127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1000: 317

Largest group(s) of English cardinal anagrams up to 1000: 
[679, 697, 769, 796, 967, 976]

Count of English cardinal anagrams up to 1000: 2534

Largest group(s) of English cardinal anagrams up to 10000: 
[1679, 1697, 1769, 1796, 1967, 1976, 6179, 6197, 6791, 6971, 7169, 7196, 7691, 7961, 9167, 9176, 9671, 9761]
[2679, 2697, 2769, 2796, 2967, 2976, 6279, 6297, 6792, 6972, 7269, 7296, 7692, 7962, 9267, 9276, 9672, 9762]
[3679, 3697, 3769, 3796, 3967, 3976, 6379, 6397, 6793, 6973, 7369, 7396, 7693, 7963, 9367, 9376, 9673, 9763]
[4679, 4697, 4769, 4796, 4967, 4976, 6479, 6497, 6794, 6974, 7469, 7496, 7694, 7964, 9467, 9476, 9674, 9764]
[5679, 5697, 5769, 5796, 5967, 5976, 6579, 6597, 6795, 6975, 7569, 7596, 7695, 7965, 9567, 9576, 9675, 9765]
[6798, 6879, 6897, 6978, 7698, 7869, 7896, 7968, 8679, 8697, 8769, 8796, 8967, 8976, 9678, 9768, 9867, 9876]

Julia

import SpelledOut: spelled_out
import Counters: counter

languages = Dict("English" => :en, "Spanish" => :es, "Portuguese" => :pt_BR)

""" remove diacritical marks, as anagrams use only standard alphabet """
undiacritical(s) = replace(replace(replace(s, r"[éêé]" => "e"), "ã" => "a"), r"[óõ]" => "o")

""" get the letter frequencies as an anagram representation of string str """
function anarep(str)
    s = undiacritical(lowercase(str))
    return [count(c, s) for c in 'a':'z'] # ignores spaces, hyphens, capitalization
end

""" task at rosettacode.org/wiki/English_cardinal_anagrams """
function process_task(maxrange, showfirst30, lang = "English")
    numstrings = map(n -> spelled_out(n, lang=languages[lang]), 0:maxrange)
    numreps = map(anarep, numstrings)
    anadict = counter(numreps)
    counts = [anadict[numreps[i]] for i in 1:maxrange]
    if showfirst30
        println("First 30 $lang cardinal anagrams:")
        i, printed = 1, 0
        while i < maxrange && printed < 30
            if counts[i] > 1
                printed += 1
                print(rpad(i, 4), printed % 10 == 0 ? "\n" : "")
            end
            i += 1
        end
    end
    print("\nCount of $lang cardinal anagrams up to $maxrange: ")
    println(count(values(anadict) .> 1))
    println("\nLargest group(s) of $lang cardinal anagrams up to $maxrange:")
    maxcount = maximum(counts)
    for r in unique([numreps[i] for i in 1:maxrange if counts[i] == maxcount])
        println(findall(==(r), numreps))
    end
end

process_task(1000, true)
process_task(10000, false)
process_task(10000, false, "Spanish")
process_task(10000, false, "Portuguese")
Output:
First 30 English cardinal anagrams:
67  69  76  79  96  97  102 103 104 105        
106 107 108 109 112 122 123 124 125 126        
127 128 129 132 133 134 135 136 137 138        

Count of English cardinal anagrams up to 1000: 317

Largest group(s) of English cardinal anagrams up to 1000:
[679, 697, 769, 796, 967, 976]

Count of English cardinal anagrams up to 10000: 2534

Largest group(s) of English cardinal anagrams up to 10000:
[1679, 1697, 1769, 1796, 1967, 1976, 6179, 6197, 6791, 6971, 7169, 7196, 7691, 7961, 9167, 9176, 9671, 9761]     
[2679, 2697, 2769, 2796, 2967, 2976, 6279, 6297, 6792, 6972, 7269, 7296, 7692, 7962, 9267, 9276, 9672, 9762]
[3679, 3697, 3769, 3796, 3967, 3976, 6379, 6397, 6793, 6973, 7369, 7396, 7693, 7963, 9367, 9376, 9673, 9763]     
[4679, 4697, 4769, 4796, 4967, 4976, 6479, 6497, 6794, 6974, 7469, 7496, 7694, 7964, 9467, 9476, 9674, 9764]     
[5679, 5697, 5769, 5796, 5967, 5976, 6579, 6597, 6795, 6975, 7569, 7596, 7695, 7965, 9567, 9576, 9675, 9765]     
[6798, 6879, 6897, 6978, 7698, 7869, 7896, 7968, 8679, 8697, 8769, 8796, 8967, 8976, 9678, 9768, 9867, 9876]

Count of Spanish cardinal anagrams up to 10000: 2635

Largest group(s) of Spanish cardinal anagrams up to 10000:
[2304, 2403, 3204, 3402, 4203, 4302]
[2306, 2603, 3206, 3602, 6203, 6302]
[2308, 2803, 3208, 3802, 8203, 8302]
[2324, 2423, 3224, 3422, 4223, 4322]
[2326, 2623, 3226, 3622, 6223, 6322]
[2328, 2823, 3228, 3822, 8223, 8322]
[2334, 2433, 3234, 3432, 4233, 4332]
[2336, 2633, 3236, 3632, 6233, 6332]
[2338, 2833, 3238, 3832, 8233, 8332]
[2344, 2443, 3244, 3442, 4243, 4342]
[2346, 2643, 3246, 3642, 6243, 6342]
[2348, 2843, 3248, 3842, 8243, 8342]
[2354, 2453, 3254, 3452, 4253, 4352]
[2356, 2653, 3256, 3652, 6253, 6352]
[2358, 2853, 3258, 3852, 8253, 8352]
[2364, 2463, 3264, 3462, 4263, 4362]
[2366, 2663, 3266, 3662, 6263, 6362]
[2368, 2863, 3268, 3862, 8263, 8362]
[2374, 2473, 3274, 3472, 4273, 4372]
[2376, 2673, 3276, 3672, 6273, 6372]
[2378, 2873, 3278, 3872, 8273, 8372]
[2384, 2483, 3284, 3482, 4283, 4382]
[2386, 2683, 3286, 3682, 6283, 6382]
[2388, 2883, 3288, 3882, 8283, 8382]
[2394, 2493, 3294, 3492, 4293, 4392]
[2396, 2693, 3296, 3692, 6293, 6392]
[2398, 2893, 3298, 3892, 8293, 8392]
[2406, 2604, 4206, 4602, 6204, 6402]
[2408, 2804, 4208, 4802, 8204, 8402]
[2426, 2624, 4226, 4622, 6224, 6422]
[2428, 2824, 4228, 4822, 8224, 8422]
[2436, 2634, 4236, 4632, 6234, 6432]
[2438, 2834, 4238, 4832, 8234, 8432]
[2446, 2644, 4246, 4642, 6244, 6442]
[2448, 2844, 4248, 4842, 8244, 8442]
[2456, 2654, 4256, 4652, 6254, 6452]
[2458, 2854, 4258, 4852, 8254, 8452]
[2466, 2664, 4266, 4662, 6264, 6462]
[2468, 2864, 4268, 4862, 8264, 8462]
[2476, 2674, 4276, 4672, 6274, 6472]
[2478, 2874, 4278, 4872, 8274, 8472]
[2486, 2684, 4286, 4682, 6284, 6482]
[2488, 2884, 4288, 4882, 8284, 8482]
[2496, 2694, 4296, 4692, 6294, 6492]
[2498, 2894, 4298, 4892, 8294, 8492]
[2608, 2806, 6208, 6802, 8206, 8602]
[2628, 2826, 6228, 6822, 8226, 8622]
[2638, 2836, 6238, 6832, 8236, 8632]
[2648, 2846, 6248, 6842, 8246, 8642]
[2658, 2856, 6258, 6852, 8256, 8652]
[2668, 2866, 6268, 6862, 8266, 8662]
[2678, 2876, 6278, 6872, 8276, 8672]
[2688, 2886, 6288, 6882, 8286, 8682]
[2698, 2896, 6298, 6892, 8296, 8692]
[3406, 3604, 4306, 4603, 6304, 6403]
[3408, 3804, 4308, 4803, 8304, 8403]
[3426, 3624, 4326, 4623, 6324, 6423]
[3428, 3824, 4328, 4823, 8324, 8423]
[3436, 3634, 4336, 4633, 6334, 6433]
[3438, 3834, 4338, 4833, 8334, 8433]
[3446, 3644, 4346, 4643, 6344, 6443]
[3448, 3844, 4348, 4843, 8344, 8443]
[3456, 3654, 4356, 4653, 6354, 6453]
[3458, 3854, 4358, 4853, 8354, 8453]
[3466, 3664, 4366, 4663, 6364, 6463]
[3468, 3864, 4368, 4863, 8364, 8463]
[3476, 3674, 4376, 4673, 6374, 6473]
[3478, 3874, 4378, 4873, 8374, 8473]
[3486, 3684, 4386, 4683, 6384, 6483]
[3488, 3884, 4388, 4883, 8384, 8483]
[3496, 3694, 4396, 4693, 6394, 6493]
[3498, 3894, 4398, 4893, 8394, 8493]
[3608, 3806, 6308, 6803, 8306, 8603]
[3628, 3826, 6328, 6823, 8326, 8623]
[3638, 3836, 6338, 6833, 8336, 8633]
[3648, 3846, 6348, 6843, 8346, 8643]
[3658, 3856, 6358, 6853, 8356, 8653]
[3668, 3866, 6368, 6863, 8366, 8663]
[3678, 3876, 6378, 6873, 8376, 8673]
[3688, 3886, 6388, 6883, 8386, 8683]
[3698, 3896, 6398, 6893, 8396, 8693]
[4608, 4806, 6408, 6804, 8406, 8604]
[4628, 4826, 6428, 6824, 8426, 8624]
[4638, 4836, 6438, 6834, 8436, 8634]
[4648, 4846, 6448, 6844, 8446, 8644]
[4658, 4856, 6458, 6854, 8456, 8654]
[4668, 4866, 6468, 6864, 8466, 8664]
[4678, 4876, 6478, 6874, 8476, 8674]
[4688, 4886, 6488, 6884, 8486, 8684]
[4698, 4896, 6498, 6894, 8496, 8694]

Count of Portuguese cardinal anagrams up to 10000: 2505

Largest group(s) of Portuguese cardinal anagrams up to 10000:
[4679, 4697, 4796, 4976, 6479, 6497, 6794, 6974, 7496, 7694, 9476, 9674]
[4798, 4879, 4897, 4978, 7498, 7894, 8479, 8497, 8794, 8974, 9478, 9874]
[6798, 6879, 6897, 6978, 7698, 7896, 8679, 8697, 8796, 8976, 9678, 9876]

Perl

use strict; use warnings;
use feature <say postderef>;
use List::AllUtils 'max_by';
use Lingua::EN::Numbers 'num2en';

for my $limit (1e3, 1e4) {
    my(%E,@E);
    push $E{ join '', sort split '', num2en($_) }->@*, $_ for 0..$limit;
    for (keys %E) { delete $E{$_} if $E{$_}->@* < 2 }
    @E = sort { $a <=> $b } map { @$_ } values %E;

    say 'First 30 English cardinal anagrams:' . join ' ', @E[0..29] if $limit == 1e3;
    say "\nCount of English cardinal anagrams up to $limit: " . keys %E;
    say "\nLargest group(s) of English cardinal anagrams up to $limit";
    say join ' ', $E{$_}->@* for max_by {f $E{$_}->@* } keys %E;
}
Output:
First 30 English cardinal anagrams:
67 69 76 79 96 97 102 103 104 105 106 107 108 109 112 122 123 124 125 126 127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1000: 317

Largest group(s) of English cardinal anagrams up to 1000
679 697 769 796 967 976

Count of English cardinal anagrams up to 10000: 2534

Largest group(s) of English cardinal anagrams up to 10000
5679 5697 5769 5796 5967 5976 6579 6597 6795 6975 7569 7596 7695 7965 9567 9576 9675 9765
4679 4697 4769 4796 4967 4976 6479 6497 6794 6974 7469 7496 7694 7964 9467 9476 9674 9764
3679 3697 3769 3796 3967 3976 6379 6397 6793 6973 7369 7396 7693 7963 9367 9376 9673 9763
1679 1697 1769 1796 1967 1976 6179 6197 6791 6971 7169 7196 7691 7961 9167 9176 9671 9761
2679 2697 2769 2796 2967 2976 6279 6297 6792 6972 7269 7296 7692 7962 9267 9276 9672 9762
6798 6879 6897 6978 7698 7869 7896 7968 8679 8697 8769 8796 8967 8976 9678 9768 9867 9876

Phix

with javascript_semantics
for limit in {1000, 10000} do
    sequence ana = {}, ani = {}
    for i=0 to limit do
        string key = trim(sort(ordinal(i,true)))
        integer k = find(key,ana)
        if k then
            ani[k] &= i
        else
            ana = append(ana,key)
            ani = append(ani,{i})
        end if
    end for
    sequence lengths = apply(ani,length)
    if limit==1000 then
        sequence all = {}
        for i,l in lengths do
            if l>1 then
                all = append(all,ani[i])
                if length(all)>=30 then exit end if
            end if
        end for
        all = sort(flatten(all))[1..30]
        printf(1,"First 30 English cardinal anagrams:\n%s\n",
                 join_by(all,1,10," ",fmt:="%3d"))
    end if
    printf(1,"Count of English cardinal anagrams up to %,d: %,d\n\n",
             {limit, length(filter(lengths,">",1))})
    integer maxlen = max(lengths)
    sequence biggest = {}
    for i,l in lengths do
        if l=maxlen then
            biggest = append(biggest,"["&join(ani[i]," ",fmt:="%d")&"]")
        end if
    end for
    printf(1,"Largest group%s of English cardinal anagrams up to %,d:\n %s\n\n",
              {iff(length(biggest)=1?"":"s"),limit,join(biggest,"\n ")})
end for
Output:
First 30 English cardinal anagrams:
 67  69  76  79  96  97 102 103 104 105
106 107 108 109 112 122 123 124 125 126
127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1,000: 317

Largest group of English cardinal anagrams up to 1,000:
 [679 697 769 796 967 976]

Count of English cardinal anagrams up to 10,000: 2,534

Largest groups of English cardinal anagrams up to 10,000:
 [1679 1697 1769 1796 1967 1976 6179 6197 6791 6971 7169 7196 7691 7961 9167 9176 9671 9761]
 [2679 2697 2769 2796 2967 2976 6279 6297 6792 6972 7269 7296 7692 7962 9267 9276 9672 9762]
 [3679 3697 3769 3796 3967 3976 6379 6397 6793 6973 7369 7396 7693 7963 9367 9376 9673 9763]
 [4679 4697 4769 4796 4967 4976 6479 6497 6794 6974 7469 7496 7694 7964 9467 9476 9674 9764]
 [5679 5697 5769 5796 5967 5976 6579 6597 6795 6975 7569 7596 7695 7965 9567 9576 9675 9765]
 [6798 6879 6897 6978 7698 7869 7896 7968 8679 8697 8769 8796 8967 8976 9678 9768 9867 9876]

Python

""" rosettacode.org/wiki/English_cardinal_anagrams  """
from collections import Counter
from num2words import num2words


def anagrammed(astring):
    """ Get the letter counts of astring for use as an anagram representation.
            Ignores spaces, hyphens, capitalization """
    lstr = astring.lower()
    charcounts = [sum(c == letter for c in lstr)
                  for letter in 'abcdefghijklmnopqrstuvwxyz']
    return ''.join([f'{j:0>2d}' for j in charcounts])


def process_task(maxrange, showfirst30=True):
    """ task at rosettacode.org/wiki/English_cardinal_anagrams """
    numwords = [num2words(n) for n in range(maxrange+1)]
    anastrings = [anagrammed(astr) for astr in numwords]
    rep_to_count = Counter(anastrings)
    counts = [rep_to_count[anastrings[i]] for i in range(maxrange+1)]
    if showfirst30:
        print("First 30 English cardinal anagrams:")
        i, printed = 1, 0
        while i < maxrange and printed < 30:
            if counts[i] > 1:
                printed += 1
                print(f'{i:4}', end='\n' if printed % 10 == 0 else '')
            i += 1

    print(f'\nCount of English cardinal anagrams up to {maxrange}: ', end='')
    print(sum(n > 1 for n in rep_to_count.values()))
    print(f'\nLargest group(s) of English cardinal anagrams up to {maxrange}:')
    maxcount = max(counts)
    for rep in set(anastrings[i] for i in range(maxrange+1) if counts[i] == maxcount):
        print([i for i in range(maxrange+1) if anastrings[i] == rep])


process_task(1000)
process_task(10000, False)
Output:
First 30 English cardinal anagrams:
  67  69  76  79  96  97 102 103 104 105
 106 107 108 109 112 122 123 124 125 126
 127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1000: 317

Largest group(s) of English cardinal anagrams up to 1000:
[679, 697, 769, 796, 967, 976]

Count of English cardinal anagrams up to 10000: 2534

Largest group(s) of English cardinal anagrams up to 10000:
[4679, 4697, 4769, 4796, 4967, 4976, 6479, 6497, 6794, 6974, 7469, 7496, 7694, 7964, 9467, 9476, 9674, 9764]
[3679, 3697, 3769, 3796, 3967, 3976, 6379, 6397, 6793, 6973, 7369, 7396, 7693, 7963, 9367, 9376, 9673, 9763]
[5679, 5697, 5769, 5796, 5967, 5976, 6579, 6597, 6795, 6975, 7569, 7596, 7695, 7965, 9567, 9576, 9675, 9765]
[1679, 1697, 1769, 1796, 1967, 1976, 6179, 6197, 6791, 6971, 7169, 7196, 7691, 7961, 9167, 9176, 9671, 9761]
[6798, 6879, 6897, 6978, 7698, 7869, 7896, 7968, 8679, 8697, 8769, 8796, 8967, 8976, 9678, 9768, 9867, 9876]
[2679, 2697, 2769, 2796, 2967, 2976, 6279, 6297, 6792, 6972, 7269, 7296, 7692, 7962, 9267, 9276, 9672, 9762]

Quackery

name$ is defined at Number names#Quackery.

  [ stack ]                             is bunches      (   --> s )
  [ stack ]                             is sames        (   --> s )

  [ [] swap witheach
      [ dup space = iff drop done
        dup char , = iff drop done
        join ] ]                        is strip        ( $ --> $ )

  [ [] swap times
      [ i^ name$ strip sort
        nested i^ join
        nested join ]
    sortwith
      [ 0 peek swap 0 peek $< ]
   [] bunches put
   [] sames put
   behead swap witheach
     [ over 0 peek
       over 0 peek = iff
         [ 1 peek sames gather ]
         done
       sames take nested bunches gather
       dup 1 peek nested sames put
       nip ]
    drop
    sames take nested bunches gather
    bunches take
    [] swap
     witheach [ dup size 2 < iff
       drop else [ nested join ] ] ]    is cardinagrams ( n --> [ )

1000 cardinagrams
say "First thirty 30 cardinal anagrams:" cr
[] over witheach join
sort 30 split drop sort echo cr cr
dup
say "Number of cardinal anagrams up to 1000: "
size echo cr cr
0 over witheach [ size max ]
say "Largest group(s) therein :" cr
swap witheach
  [ 2dup size != iff drop done
    echo cr ]
drop
cr
10000 cardinagrams
say "Number of cardinal anagrams up to 10000: "
dup size echo cr cr
0 over witheach [ size max ]
say "Largest group(s) therein:" cr
swap witheach
  [ 2dup size != iff drop done
    echo cr ]
drop
Output:
First thirty 30 cardinal anagrams:
[ 67 69 76 79 96 97 102 103 104 105 106 107 108 109 112 122 123 124 125 126 127 128 129 132 133 134 135 136 137 138 ]

Number of cardinal anagrams up to 1000: 317

Largest group(s) therein :
[ 679 697 769 796 967 976 ]

Number of cardinal anagrams up to 10000: 2534

Largest group(s) therein:
[ 3679 3697 3769 3796 3967 3976 6379 6397 6793 6973 7369 7396 7693 7963 9367 9376 9673 9763 ]
[ 5679 5697 5769 5796 5967 5976 6579 6597 6795 6975 7569 7596 7695 7965 9567 9576 9675 9765 ]
[ 6798 6879 6897 6978 7698 7869 7896 7968 8679 8697 8769 8796 8967 8976 9678 9768 9867 9876 ]
[ 1679 1697 1769 1796 1967 1976 6179 6197 6791 6971 7169 7196 7691 7961 9167 9176 9671 9761 ]
[ 4679 4697 4769 4796 4967 4976 6479 6497 6794 6974 7469 7496 7694 7964 9467 9476 9674 9764 ]
[ 2679 2697 2769 2796 2967 2976 6279 6297 6792 6972 7269 7296 7692 7962 9267 9276 9672 9762 ]

Raku

use Lingua::EN::Numbers;
use List::Allmax;

for 1_000, 10_000 {
    my %eca; # English cardinal anagrams
    (^$_).map: { %eca{.&cardinal.comb.sort.join}.push: $_ }

    once say "\nFirst 30 English cardinal anagrams:\n " ~
    (sort flat %eca.grep(+*.value > 1)».value.map: *.flat)[^30]\
    .batch(10)».fmt("%3d").join: "\n ";

    say "\nCount of English cardinal anagrams up to {.&comma}: " ~
        +%eca.grep(+*.value > 1)».value.map: *.flat;

    say "\nLargest group(s) of English cardinal anagrams up to {.&comma}:\n [" ~
        %eca.&all-max( :by(+*.value) )».value.sort.join("]\n [") ~ ']'
}
Output:
First 30 English cardinal anagrams:
  67  69  76  79  96  97 102 103 104 105
 106 107 108 109 112 122 123 124 125 126
 127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1,000: 317

Largest group(s) of English cardinal anagrams up to 1,000:
 [679 697 769 796 967 976]

Count of English cardinal anagrams up to 10,000: 2534

Largest group(s) of English cardinal anagrams up to 10,000:
 [1679 1697 1769 1796 1967 1976 6179 6197 6791 6971 7169 7196 7691 7961 9167 9176 9671 9761]
 [2679 2697 2769 2796 2967 2976 6279 6297 6792 6972 7269 7296 7692 7962 9267 9276 9672 9762]
 [3679 3697 3769 3796 3967 3976 6379 6397 6793 6973 7369 7396 7693 7963 9367 9376 9673 9763]
 [4679 4697 4769 4796 4967 4976 6479 6497 6794 6974 7469 7496 7694 7964 9467 9476 9674 9764]
 [5679 5697 5769 5796 5967 5976 6579 6597 6795 6975 7569 7596 7695 7965 9567 9576 9675 9765]
 [6798 6879 6897 6978 7698 7869 7896 7968 8679 8697 8769 8796 8967 8976 9678 9768 9867 9876]

Wren

Library: Wren-sort
Library: Wren-fmt
import "./sort" for Sort
import "./fmt" for Fmt, Name

for (limit in [1000, 10000]) {
    var ana = {}
    for (i in 0..limit) {
        var key = Sort.quick(Name.fromNum(i).toList).join("")
        if (ana.containsKey(key)) {
            ana[key].add(i)
        } else {
            ana[key] = [i]
        }
    }
    if (limit == 1000) {
        var all = []
        for (v in ana.values) {
            if (v.count > 1) all.addAll(v)
        }
        System.print("First 30 English cardinal anagrams:")
        Fmt.tprint("$3d", all.sort().take(30), 10)
        System.print()
    }
    var count = ana.count { |me| me.value.count > 1 }
    Fmt.print("Count of English cardinal anagrams up to $,d: $,d", limit, count)
    var max = 0
    var largest
    for (v in ana.values) {
        if (v.count > max) {
            max = v.count
            largest = [v]
        } else if (v.count == max) {
            largest.add(v)
        }
    }
    Fmt.print("\nLargest group(s) of English cardinal anagrams up to $,d:", limit)
    largest.sort { |l1, l2| l1[0] < l2[0] }
    System.print(largest.map { |l| "[" + l.join(" ") + "]" }.join("\n"))
    if (limit == 1000) System.print()
}
Output:
First 30 English cardinal anagrams:
 67  69  76  79  96  97 102 103 104 105
106 107 108 109 112 122 123 124 125 126
127 128 129 132 133 134 135 136 137 138

Count of English cardinal anagrams up to 1,000: 317

Largest group(s) of English cardinal anagrams up to 1,000:
[679 697 769 796 967 976]

Count of English cardinal anagrams up to 10,000: 2,534

Largest group(s) of English cardinal anagrams up to 10,000:
[1679 1697 1769 1796 1967 1976 6179 6197 6791 6971 7169 7196 7691 7961 9167 9176 9671 9761]
[2679 2697 2769 2796 2967 2976 6279 6297 6792 6972 7269 7296 7692 7962 9267 9276 9672 9762]
[3679 3697 3769 3796 3967 3976 6379 6397 6793 6973 7369 7396 7693 7963 9367 9376 9673 9763]
[4679 4697 4769 4796 4967 4976 6479 6497 6794 6974 7469 7496 7694 7964 9467 9476 9674 9764]
[5679 5697 5769 5796 5967 5976 6579 6597 6795 6975 7569 7596 7695 7965 9567 9576 9675 9765]
[6798 6879 6897 6978 7698 7869 7896 7968 8679 8697 8769 8796 8967 8976 9678 9768 9867 9876]
Cookies help us deliver our services. By using our services, you agree to our use of cookies.