Hex words: Difference between revisions

From Rosetta Code
Content added Content deleted
(Added Algol 68)
m (omits)
Line 689: Line 689:
13 such words found which contain 4 or more different digits.
13 such words found which contain 4 or more different digits.
</pre>
</pre>

{{omit from|6502 Assembly|unixdict.txt is much larger than the CPU's address space.}}
{{omit from|8080 Assembly|See 6502 Assembly.}}
{{omit from|Z80 Assembly|See 6502 Assembly.}}

Revision as of 03:11, 14 November 2021

Hex words 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.
Definition

For the purposes of this task a hex word means a word which (in lower case form) consists entirely of the letters a, b, c, d, e and f.

Task

Using unixdict.txt, find all hex words with 4 letters or more.

Convert each such word to its decimal equivalent and compute its base 10 digital root.

Display all three in increasing order of digital root and show the total count of such words.

Also filter out all such words which contain at least 4 distinct letters and display the same statistics but in decreasing order of decimal equivalent together with their total count.

ALGOL 68

<lang algol68># find words that contain only hex digits a-f # IF FILE input file;

   STRING file name = "unixdict.txt";
   open( input file, file name, stand in channel ) /= 0

THEN

   # failed to open the file #
   print( ( "Unable to open """ + file name + """", newline ) )

ELSE

   # file opened OK #
   BOOL at eof := FALSE;
   # set the EOF handler for the file #
   on logical file end( input file, ( REF FILE f )BOOL:
                                    BEGIN
                                        # note that we reached EOF on the #
                                        # latest read #
                                        at eof := TRUE;
                                        # return TRUE so processing can continue #
                                        TRUE
                                    END
                      );
   INT count := 0;
   INT max words = 100; # guess at the maximum number of words #
   MODE HEXWORD = STRUCT( STRING word, LONG INT value, INT root, INT len );
   [ 1 : max words ]HEXWORD hw;
   WHILE STRING word;
         get( input file, ( word, newline ) );
         NOT at eof
   DO
       # check the word contains only a-f and compute its decimal value #
       IF  INT word len = ( UPB word + 1 ) - LWB word;
           word len >= 4
       THEN
           # the word is at least 4 characters long #
           BOOL is hex word := word /= "";
           LONG INT  int word    := 0;
           FOR i FROM LWB word TO UPB word
           WHILE is hex word := word[ i ] >= "a" AND word[ i ] <= "f"
           DO
               int word *:= 16;
               int word +:= ( ABS word[ i ] - ABS "a" ) + 10
           OD;
           IF is hex word
           THEN
               # have a hex word #
               count +:= 1;
               # compute the digital root #
               LONG INT r := int word;
               WHILE r > 9 DO
                   LONG INT dr := r MOD 10;
                   WHILE ( r OVERAB 10 ) > 0 DO dr +:= r MOD 10 OD;
                   r := dr
               OD;
               word  OF hw[ count ] := word;
               value OF hw[ count ] := int word;
               root  OF hw[ count ] := SHORTEN r;
               len   OF hw[ count ] := word len
           FI
       FI
   OD;
   close( input file );
   # prints the HEXWORD hw #
   PROC show = ( HEXWORD hw )VOID:
   BEGIN
       STRING pad = IF len OF hw >= 12 THEN "" ELSE ( 12 - len OF hw ) * " " FI;
       print( ( word OF hw, ": ", pad, whole( value OF hw, -10 ), " [ ", whole( root OF hw, 0 ), " ]", newline ) )
   END # show # ;
   # Quicksorts in-place the array of HEXWORDS a, from lb to ub on ascending value #
   PROC quicksort = ( REF[]HEXWORD a, INT lb, ub )VOID:
        IF ub > lb THEN
           # more than one element, so must sort #
           INT left   := lb;
           INT right  := ub;
           # choosing the middle element of the array as the pivot #
           LONG INT pivot  := value OF a[ left + ( ( right + 1 ) - left ) OVER 2 ];
           WHILE
               WHILE IF left  <= ub THEN value OF a[ left  ] < pivot ELSE FALSE FI DO left  +:= 1 OD;
               WHILE IF right >= lb THEN value OF a[ right ] > pivot ELSE FALSE FI DO right -:= 1 OD;
               left <= right
           DO
               HEXWORD t  := a[ left  ];
               a[ left  ] := a[ right ];
               a[ right ] := t;
               left      +:= 1;
               right     -:= 1
           OD;
           quicksort( a, lb,   right );
           quicksort( a, left, ub    )
        FI # quicksort # ;
   # show the hex words in ascending order of digital root #
   FOR r FROM 1 TO 9 DO
       FOR i FROM 1 TO count DO
           IF root OF hw[ i ] = r THEN show( hw[ i ] ) FI
       OD
   OD;
   print( ( "Found ", whole( count, 0 ), " hex words", newline, newline ) );
   # show the words in descending value order excluding those with less than 4 unique letters #
   quicksort( hw, 1, count );
   INT count 4 := 0;
   FOR i FROM count BY -1 TO 1 DO
       # check the word has at least four different digits #
       INT a := 0, b := 0, c := 0, d := 0, e := 0, f := 0;
       FOR c pos FROM LWB word OF hw[ i ] TO UPB word OF hw[ i ] DO
           IF   CHAR ch = ( word OF hw[ i ] )[ c pos ];
                ch = "a"
           THEN a := 1
           ELIF ch = "b"
           THEN b := 1
           ELIF ch = "c"
           THEN c := 1
           ELIF ch = "d"
           THEN d := 1
           ELIF ch = "e"
           THEN e := 1
           ELSE f := 1
           FI
       OD;
       IF a + b + c + d + e + f >= 4
       THEN
           # have a hex word with at least 4 different digits #
           count 4 +:= 1;
           show( hw[ i ] )
       FI
   OD;
   print( ( "Found ", whole( count 4, 0 ), " hex words with 4 or more distinct digits", newline ) )

FI</lang>

Output:
ababa:            703162 [ 1 ]
abbe:              43966 [ 1 ]
dada:              56026 [ 1 ]
deaf:              57007 [ 1 ]
decade:         14600926 [ 1 ]
cede:              52958 [ 2 ]
feed:              65261 [ 2 ]
abed:              44013 [ 3 ]
added:            712173 [ 3 ]
bade:              47838 [ 3 ]
beebe:            782014 [ 4 ]
decca:            912586 [ 4 ]
dade:              56030 [ 5 ]
bead:              48813 [ 6 ]
deface:         14613198 [ 6 ]
babe:              47806 [ 7 ]
fade:              64222 [ 7 ]
dead:              57005 [ 8 ]
efface:         15727310 [ 8 ]
facade:         16435934 [ 8 ]
accede:         11325150 [ 9 ]
beef:              48879 [ 9 ]
cafe:              51966 [ 9 ]
dacca:            896202 [ 9 ]
deed:              57069 [ 9 ]
face:              64206 [ 9 ]
Found 26 hex words

facade:         16435934 [ 8 ]
efface:         15727310 [ 8 ]
deface:         14613198 [ 6 ]
decade:         14600926 [ 1 ]
accede:         11325150 [ 9 ]
decca:            912586 [ 4 ]
fade:              64222 [ 7 ]
face:              64206 [ 9 ]
deaf:              57007 [ 1 ]
cafe:              51966 [ 9 ]
bead:              48813 [ 6 ]
bade:              47838 [ 3 ]
abed:              44013 [ 3 ]
Found 13 hex words with 4 or more distinct digits

Factor

Works with: Factor version 0.99 2021-06-02

<lang factor>USING: formatting io io.encodings.ascii io.files kernel literals math math.parser prettyprint sequences sets sorting ;

CONSTANT: words $[

   "unixdict.txt" ascii file-lines
   [ length 3 > ] filter
   [ "abcdef" subset? ] filter

]

droot ( m -- n ) 1 - 9 mod 1 + ;
info. ( str -- ) dup hex> dup droot "%-8s-> %-10d-> %d\n" printf ;
info-by ( quot ? -- )
   [ sort-with ] [ inv-sort-with ] if [ length ] keep
   [ info. ] each pprint ; inline

words [ hex> droot ] t info-by " hex words with 4 or more letters found." print nl

words [ cardinality 3 > ] filter [ hex> ] f info-by " such words found which contain 4 or more different digits." print</lang>

Output:
ababa   -> 703162    -> 1
abbe    -> 43966     -> 1
dada    -> 56026     -> 1
deaf    -> 57007     -> 1
decade  -> 14600926  -> 1
cede    -> 52958     -> 2
feed    -> 65261     -> 2
abed    -> 44013     -> 3
added   -> 712173    -> 3
bade    -> 47838     -> 3
beebe   -> 782014    -> 4
decca   -> 912586    -> 4
dade    -> 56030     -> 5
bead    -> 48813     -> 6
deface  -> 14613198  -> 6
babe    -> 47806     -> 7
fade    -> 64222     -> 7
dead    -> 57005     -> 8
efface  -> 15727310  -> 8
facade  -> 16435934  -> 8
accede  -> 11325150  -> 9
beef    -> 48879     -> 9
cafe    -> 51966     -> 9
dacca   -> 896202    -> 9
deed    -> 57069     -> 9
face    -> 64206     -> 9
26 hex words with 4 or more letters found.

facade  -> 16435934  -> 8
efface  -> 15727310  -> 8
deface  -> 14613198  -> 6
decade  -> 14600926  -> 1
accede  -> 11325150  -> 9
decca   -> 912586    -> 4
fade    -> 64222     -> 7
face    -> 64206     -> 9
deaf    -> 57007     -> 1
cafe    -> 51966     -> 9
bead    -> 48813     -> 6
bade    -> 47838     -> 3
abed    -> 44013     -> 3
13 such words found which contain 4 or more different digits.

Julia

<lang julia>digroot(n) = (while n > 9 n = sum(digits(n)) end; n)

function hexwords(wordfile = "unixdict.txt")

   words = lowercase.(split(read(wordfile, String), r"\s+"))
   filter!(w -> length(w) >= 4 && all(c -> c in "abcdef", w), words)
   results = [[w, parse(Int, w, base = 16)] for w in words]
   for a in results
       pushfirst!(a, digroot(a[2]))
   end
   println("Hex words in $wordfile:\nRoot  Word      Base 10\n", "-"^30)
   for a in sort!(results)
       println(rpad(a[1], 6), rpad(a[2], 10), a[3])
   end
   println("Total count of these words: $(length(results)).")
   println("\nHex words with > 3 distinct letters:\nRoot  Word      Base 10\n", "-"^30)
   filter!(a -> length(unique(a[2])) > 3, results)
   for a in results
       println(rpad(a[1], 6), rpad(a[2], 10), a[3])
   end
   println("Total count of those words: $(length(results)).")

end

hexwords()

</lang>

Output:
Hex words in unixdict.txt:
Root  Word      Base 10
------------------------------
1     ababa     703162
1     abbe      43966
1     dada      56026
1     deaf      57007
1     decade    14600926
2     cede      52958
2     feed      65261
3     abed      44013
3     added     712173
3     bade      47838
4     beebe     782014
4     decca     912586
5     dade      56030
6     bead      48813
6     deface    14613198
7     babe      47806
7     fade      64222
8     dead      57005
8     efface    15727310
8     facade    16435934
9     accede    11325150
9     beef      48879
9     cafe      51966
9     dacca     896202
9     deed      57069
9     face      64206
Total count of these words: 26.

Hex words with > 3 distinct letters:
Root  Word      Base 10
------------------------------
1     deaf      57007
1     decade    14600926
3     abed      44013
3     bade      47838
4     decca     912586
6     bead      48813
6     deface    14613198
7     fade      64222
8     efface    15727310
8     facade    16435934
9     accede    11325150
9     cafe      51966
9     face      64206
Total count of those words: 13.

Perl

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

use strict; # https://rosettacode.org/wiki/Hex_words use warnings; use List::AllUtils qw( nsort_by uniq );

sub root

 {
 local $_ = shift;
 $_ = eval while s/\B/+/g;
 return $_;
 }

my @bydecimal = grep +(uniq /[a-f]/g)[3],

 my @byroot = map { sprintf "%10s %10d %3d\n", $_, hex $_, root hex $_
 } do { local(@ARGV, $/) = 'unixdict.txt'; <> =~ /^[a-f]{4,}$/gm };

print +(nsort_by { (split ' ')[2] } @byroot),

 "total count = @{[ scalar @byroot ]} and @{[ scalar @bydecimal
 ]} have at least 4 distinct digits\n",
 reverse nsort_by { (split ' ')[1] } @bydecimal;</lang>
Output:
     ababa     703162   1
      abbe      43966   1
      dada      56026   1
      deaf      57007   1
    decade   14600926   1
      cede      52958   2
      feed      65261   2
      abed      44013   3
     added     712173   3
      bade      47838   3
     beebe     782014   4
     decca     912586   4
      dade      56030   5
      bead      48813   6
    deface   14613198   6
      babe      47806   7
      fade      64222   7
      dead      57005   8
    efface   15727310   8
    facade   16435934   8
    accede   11325150   9
      beef      48879   9
      cafe      51966   9
     dacca     896202   9
      deed      57069   9
      face      64206   9
total count = 26 and 13 have at least 4 distinct digits
    facade   16435934   8
    efface   15727310   8
    deface   14613198   6
    decade   14600926   1
    accede   11325150   9
     decca     912586   4
      fade      64222   7
      face      64206   9
      deaf      57007   1
      cafe      51966   9
      bead      48813   6
      bade      47838   3
      abed      44013   3

Phix

with javascript_semantics
function af(string s) return max(s)<='f' and min(s)>='a' end function
function digital_root(integer n)
    assert(n>=0)
    while n>9 do
        integer tot = 0
        while n>0 do
            tot += remainder(n,10)
            n = floor(n/10)
        end while
        n = tot
    end while
    return n
end function
sequence words = filter(unix_dict(4),af),
         decml = apply(true,to_integer,{words,0,16}),
         roots = apply(decml,digital_root),
         tags = custom_sort(roots,tagset(length(roots)))

function caejasp() -- columnize/apply/extract/join/apply/sprint(...)
    sequence s = columnize(apply(true,extract,{{words,decml,roots},{tags}}))
    return join(apply(true,sprintf,{{"%6s -> %8d -> %d\n"},s}))
end function
printf(1," %s\n %d hex words with 4 or more letters found,\n",{caejasp(),length(tags)})
function ge4(integer t) return length(unique(words[t]))>=4 end function
tags = filter(tags,ge4)
tags = extract(tags,reverse(custom_sort(extract(decml,tags),tagset(length(tags)))))
printf(1," %d with 4 or more distinct characters:\n\n %s\n",{length(tags),caejasp()})
Output:
  ababa ->   703162 -> 1
   abbe ->    43966 -> 1
   dada ->    56026 -> 1
   deaf ->    57007 -> 1
 decade -> 14600926 -> 1
   cede ->    52958 -> 2
   feed ->    65261 -> 2
   abed ->    44013 -> 3
  added ->   712173 -> 3
   bade ->    47838 -> 3
  beebe ->   782014 -> 4
  decca ->   912586 -> 4
   dade ->    56030 -> 5
   bead ->    48813 -> 6
 deface -> 14613198 -> 6
   babe ->    47806 -> 7
   fade ->    64222 -> 7
   dead ->    57005 -> 8
 efface -> 15727310 -> 8
 facade -> 16435934 -> 8
 accede -> 11325150 -> 9
   beef ->    48879 -> 9
   cafe ->    51966 -> 9
  dacca ->   896202 -> 9
   deed ->    57069 -> 9
   face ->    64206 -> 9

 26 hex words with 4 or more letters found,
 13 with 4 or more distinct characters:

 facade -> 16435934 -> 8
 efface -> 15727310 -> 8
 deface -> 14613198 -> 6
 decade -> 14600926 -> 1
 accede -> 11325150 -> 9
  decca ->   912586 -> 4
   fade ->    64222 -> 7
   face ->    64206 -> 9
   deaf ->    57007 -> 1
   cafe ->    51966 -> 9
   bead ->    48813 -> 6
   bade ->    47838 -> 3
   abed ->    44013 -> 3

Python

<lang python>def digroot(n):

   while n > 9:
       n = sum([int(d) for d in str(n)])
   return n

with open('unixdict.txt') as f:

   lines = [w.strip() for w in f.readlines()]
   words = [w for w in lines if len(w) >= 4 and all(c in 'abcdef' for c in w)]
   results = [[w, int(w, 16)] for w in words]
   for a in results:
       a.append(digroot(a[1]))
       
   print(f"Hex words in unixdict.txt:\nRoot  Word      Base 10\n", "-"*22)
   for a in sorted(results, key=lambda x:x[2]):
       print(f"{a[2]}     {a[0]:6}{a[1]:10}")
       
   print("Total count of these words:", len(results))
   print("\nHex words with > 3 distinct letters:\nRoot  Word      Base 10\n", "-"*22)
   results = [a for a in results if len(set(str(a[0]))) > 3]
   for a in sorted(results, key=lambda x:x[2]):
       print(f"{a[2]}     {a[0]:6}{a[1]:10}")
       
   print("Total count of those words:", len(results))

</lang>

Output:
Hex words in unixdict.txt:
Root  Word      Base 10
 ----------------------
1     ababa     703162
1     abbe       43966
1     dada       56026
1     deaf       57007
1     decade  14600926
2     cede       52958
2     feed       65261
3     abed       44013
3     added     712173
3     bade       47838
4     beebe     782014
4     decca     912586
5     dade       56030
6     bead       48813
6     deface  14613198
7     babe       47806
7     fade       64222
8     dead       57005
8     efface  15727310
8     facade  16435934
9     accede  11325150
9     beef       48879
9     cafe       51966
9     dacca     896202
9     deed       57069
9     face       64206
Total count of these words: 26

Hex words with > 3 distinct letters:
Root  Word      Base 10
 ----------------------
1     deaf       57007
1     decade  14600926
3     abed       44013
3     bade       47838
4     decca     912586
6     bead       48813
6     deface  14613198
7     fade       64222
8     efface  15727310
8     facade  16435934
9     accede  11325150
9     cafe       51966
9     face       64206
Total count of those words: 13

Raku

Sorted by digital root with a secondary alphabetical sort. <lang perl6>sub dr (Int $_ is copy) { $_ = dr(.comb.sum) while .chars > 1; $_ }

my %hex = './unixdict.txt'.IO.slurp.words.grep( *.chars > 3 )\

 .grep({ not / <-[abcdef]> / }).map: { $_ => dr :16($_).comb.sum }

say "{+%hex} hex words longer than 3 characters found in unixdict.txt:"; printf "%6s ➡ %8d ➡ %d\n", .key, :16(.key), .value for %hex.sort: { .value, .key }

my %many = %hex.grep: +*.key.comb.Set > 3;

say "\nOf which {+%many} contain at least four distinct characters:"; printf "%6s ➡ %8d ➡ %d\n", .key, :16(.key), .value for %many.sort: { -:16(.key) }</lang>

Output:
26 hex words longer than 3 characters found in unixdict.txt:
 ababa ➡   703162 ➡ 1
  abbe ➡    43966 ➡ 1
  dada ➡    56026 ➡ 1
  deaf ➡    57007 ➡ 1
decade ➡ 14600926 ➡ 1
  cede ➡    52958 ➡ 2
  feed ➡    65261 ➡ 2
  abed ➡    44013 ➡ 3
 added ➡   712173 ➡ 3
  bade ➡    47838 ➡ 3
 beebe ➡   782014 ➡ 4
 decca ➡   912586 ➡ 4
  dade ➡    56030 ➡ 5
  bead ➡    48813 ➡ 6
deface ➡ 14613198 ➡ 6
  babe ➡    47806 ➡ 7
  fade ➡    64222 ➡ 7
  dead ➡    57005 ➡ 8
efface ➡ 15727310 ➡ 8
facade ➡ 16435934 ➡ 8
accede ➡ 11325150 ➡ 9
  beef ➡    48879 ➡ 9
  cafe ➡    51966 ➡ 9
 dacca ➡   896202 ➡ 9
  deed ➡    57069 ➡ 9
  face ➡    64206 ➡ 9

Of which 13 contain at least four distinct characters:
facade ➡ 16435934 ➡ 8
efface ➡ 15727310 ➡ 8
deface ➡ 14613198 ➡ 6
decade ➡ 14600926 ➡ 1
accede ➡ 11325150 ➡ 9
 decca ➡   912586 ➡ 4
  fade ➡    64222 ➡ 7
  face ➡    64206 ➡ 9
  deaf ➡    57007 ➡ 1
  cafe ➡    51966 ➡ 9
  bead ➡    48813 ➡ 6
  bade ➡    47838 ➡ 3
  abed ➡    44013 ➡ 3

Wren

Library: Wren-ioutil
Library: Wren-fmt
Library: Wren-math
Library: Wren-seq

<lang ecmascript>import "./ioutil" for FileUtil import "./fmt" for Conv, Fmt import "./math" for Int import "./seq" for Lst

var words = FileUtil.readLines("unixdict.txt").where { |w| w.count > 0 && w[0].bytes[0] < 103 } var hexDigits = "abcdef" var lines = [] for (word in words) {

   if (word.count < 4) continue
   if (word.all { |c| hexDigits.contains(c) }) {
       var num = Conv.atoi(word, 16)
       var dr = Int.digitalRoot(num)[0] 
       lines.add(Fmt.swrite("$-7s -> $-9s -> $d", word, num, dr))
   }

} lines.sort { |a, b| a[-1].bytes[0] < b[-1].bytes[0] } System.print(lines.join("\n")) System.print("\n%(lines.count) hex words with 4 or more letters found.\n") var digits4 = [] for (line in lines) {

   var word = line.split("->")[0].trimEnd()
   if (Lst.distinct(word.toList).count >= 4) digits4.add(line)

} digits4.sort { |a, b| Num.fromString(a.split("->")[1]) > Num.fromString(b.split("->")[1]) } System.print(digits4.join("\n")) System.print("\n%(digits4.count) such words found which contain 4 or more different digits.")</lang>

Output:
decade  -> 14600926  -> 1
ababa   -> 703162    -> 1
abbe    -> 43966     -> 1
dada    -> 56026     -> 1
deaf    -> 57007     -> 1
feed    -> 65261     -> 2
cede    -> 52958     -> 2
added   -> 712173    -> 3
bade    -> 47838     -> 3
abed    -> 44013     -> 3
decca   -> 912586    -> 4
beebe   -> 782014    -> 4
dade    -> 56030     -> 5
deface  -> 14613198  -> 6
bead    -> 48813     -> 6
babe    -> 47806     -> 7
fade    -> 64222     -> 7
dead    -> 57005     -> 8
facade  -> 16435934  -> 8
efface  -> 15727310  -> 8
dacca   -> 896202    -> 9
beef    -> 48879     -> 9
cafe    -> 51966     -> 9
deed    -> 57069     -> 9
face    -> 64206     -> 9
accede  -> 11325150  -> 9

26 hex words with 4 or more letters found.

facade  -> 16435934  -> 8
efface  -> 15727310  -> 8
deface  -> 14613198  -> 6
decade  -> 14600926  -> 1
accede  -> 11325150  -> 9
decca   -> 912586    -> 4
fade    -> 64222     -> 7
face    -> 64206     -> 9
deaf    -> 57007     -> 1
cafe    -> 51966     -> 9
bead    -> 48813     -> 6
bade    -> 47838     -> 3
abed    -> 44013     -> 3

13 such words found which contain 4 or more different digits.