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


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]

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.