8
\$\begingroup\$

Warning: Wouldn't you rather answer a challenge about ponies?1


If you have read The Hostile Hospital, you would know that the Baudelaire orphans, from one of the scraps of paper recovered from the Quagmire's notebooks, they discover a name, "Ana Gram". Later on, they realize that means the word "anagram", not a name. And that information helps them in finding out who Count Olaf disguised Violet Baudelaire as (Laura V. Bleediotie). They have to search through the entire hospital list, but trace the correct person down. However, what if they lived in a time where YOU helped them? Not personally, but with a program?

So your task today is simple. Given a string a and an array, return a smaller array that contains all the possible anagrams of a.

Rules:

  • This is , so shortest answer wins
  • Make sure to lowercase everything in the array and the string
  • Two strings that are the same are not anagrams after normalizing
  • Make sure to watch out for initials! You should also remove them
  • There may be multiple possible anagrams. Output them all

Test cases:

String, Array 
-> Array

"Violet", ["Veilo","Efh", "Telvio","veliot"]
-> ["Telvio","veliot"]

"Krotasmon", ["Krotas Mon","Krota","Monsakrot", "Trokasmont","KROTASMON"]
-> ["Monsakrot"]

"Laura V. Bleediotie", ["Violet Baudelaire", "Violet. Baudelaire", "VIOLeT BAUDELAIRE", "BUADELIAR VIOLETM", "Laura V. Bleediotie"]
-> ["Violet Baudelaire", "Violet. Baudelaire", "VIOLeT BAUDELAIRE"]

1: Inspired by the "all rights reserved" page of LS: The Unauthorized Autobiography

\$\endgroup\$
7
  • \$\begingroup\$ Closely related \$\endgroup\$
    – Arnauld
    Commented Nov 18, 2022 at 7:45
  • \$\begingroup\$ Yes, I knew that and Manage Trash So. \$\endgroup\$ Commented Nov 18, 2022 at 8:25
  • 3
    \$\begingroup\$ Two strings that are the same are not anagrams -> Can you confirm that the comparison should be done after normalization? (same case and non-letter characters removed). For instance, my understanding is that Krotas Mon is not an anagram of Krotasmon. \$\endgroup\$
    – Arnauld
    Commented Nov 18, 2022 at 14:28
  • 1
    \$\begingroup\$ Yes, it has to be done after normalisation. \$\endgroup\$ Commented Nov 18, 2022 at 14:41
  • 6
    \$\begingroup\$ Please also make that clear in the question itself. \$\endgroup\$ Commented Nov 18, 2022 at 18:55

8 Answers 8

5
\$\begingroup\$

Python, 106 bytes

-12 by mousetail, Kevin Cruijssen
-5 by Jitse

lambda w,l,S=sorted:[x for x in l if S(g(x))==S(g(w))!=g(w)!=g(x)]
g=lambda s:s.lower().translate(['']*96)

Attempt This Online!

\$\endgroup\$
8
  • \$\begingroup\$ " |\." can be \W for -2 bytes. \$\endgroup\$ Commented Nov 18, 2022 at 10:00
  • \$\begingroup\$ 119 bytes \$\endgroup\$ Commented Nov 18, 2022 at 10:01
  • 1
    \$\begingroup\$ @mousetail You can remove two more spaces at s.lower()if'`' \$\endgroup\$ Commented Nov 18, 2022 at 10:03
  • \$\begingroup\$ Also you are allowed to not count the f= for -2 bytes, if you move that line to the top \$\endgroup\$ Commented Nov 18, 2022 at 10:04
  • 2
    \$\begingroup\$ 106 \$\endgroup\$
    – Jitse
    Commented Nov 18, 2022 at 13:09
2
\$\begingroup\$

05AB1E, 14 bytes

šl€áD€{ćQsćÊ*Ï

Inputs in the order String, Array.

Try it online or verify all test cases.

Explanation:

š         # Prepend the first (implicit) input to the second (implicit) input-list
 l        # Convert everything in the list to lowercase
  ۇ      # Only keep the letters of each string in the list
    D     # Duplicate this list
     €{   # Sort the characters of each string in the list
       ć  # Extract head; push the modified list and modified first input separated to
          # the stack
        Q # Check which modified strings in the list are equal to this modified input
    s     # Swap so the duplicated list is at the top again
     ć    # Extract its head as well
      Ê   # Check which partially-modified strings in the list are NOT equal to this
          # partially-modified input
    *     # Combine the checks at the same positions (vectorized multiply that acts as a
          # vectorized logical AND)
     Ï    # Only keep the strings from the second (implicit) input-list at the truthy
          # positions
          # (after which the filtered list is output implicitly as result) 
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Not yet updated in the question, but Commented that e.g. Krotas Mon is not an anagram of Krotasmon (the equality check is post-filtering and lowering). \$\endgroup\$ Commented Nov 18, 2022 at 20:26
  • \$\begingroup\$ @JonathanAllan Thanks for the heads up. Should be fixed (at the cost of no bytes). \$\endgroup\$ Commented Nov 18, 2022 at 23:14
1
\$\begingroup\$

Jelly, 18 bytes

ŒlfØa,Ṣ$
Ç⁼"Ç}</ðƇ

A dyadic Link that accepts the list of potentials on the left and the identity on the right and yields the filtered list.

Try it online!

How?

ŒlfØa,Ṣ$ - Helper Link: list of characters, Name
Œl       - lower case (Name)
   Øa    - "a-z"
  f      - (lowered Name) filter keep ("a-z")
       $ - last two links as a monad - f(X=that):
      Ṣ  -   sort (X)
     ,   -   (X) pair with (that)

Ç⁼"Ç}</ðƇ - Main Link: Potentials; Identity
        Ƈ - keep Potentials, P, for which:
       ð  -   dyadic chain - f(P, Identity):
Ç         -     call Helper with Name=P
   Ç}     -     call Helper with Name=Identity
  "       -     zip with:
 ⁼        -       equal?
      /   -     reduce by:
     <    -       less than?
                i.e. alphas(lowered(P)) == alphas(lowered(Identity))
                     less than?
                     sorted(alphas(lowered(P))) == sorted(alphas(lowered(Identity)))
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 37 bytes

≔Φ↧S№βιθWS«≔Φ↧ι№βκη¿‹⁼ηθ⬤⁺ηθ⁼№ηκ№θκ⟦ι

Try it online! Link is to verbose version of code. Takes the array as a list of newline-terminated strings. Explanation:

≔Φ↧S№βιθ

Lower case the target anagram and only keep letters.

WS«

Loop through the array.

≔Φ↧ι№βκη

Lower case the current element and only keep letters.

¿‹⁼ηθ⬤⁺ηθ⁼№ηκ№θκ

If the strings do not equal and both strings contain equal counts of all the letters in both strings:

⟦ι

Output the current element on its own line.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Not yet updated in the question, but Commented that e.g. Krotas Mon is not an anagram of Krotasmon (the equality check is post-filtering and lowering). \$\endgroup\$ Commented Nov 18, 2022 at 20:27
  • \$\begingroup\$ @JonathanAllan Thanks, updated. \$\endgroup\$
    – Neil
    Commented Nov 18, 2022 at 21:00
1
\$\begingroup\$

C (clang), 163 155 151 134 218 193 186 169 bytes

-3 bytes thanks to ceilingcat!!

+84 bytes thanks to c--

-24 bytes thanks to c--

u[256];v[256];*w;q(*h,*j){bzero(h,512);for(w=h+128;*j;j++)*j>64&&h[*w++=32|*j]++;}f(**o,i){for(q(u,i);*o;o++)q(v,*o),bcmp(u,v,w-v<<2)*!bcmp(u,v,512)&&printf("%ls,",*o);}

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +1 for "+84 bytes thanks to c--", it's probably not a good approach though \$\endgroup\$
    – c--
    Commented Nov 20, 2022 at 18:22
0
\$\begingroup\$

Nibbles, 12 bytes (24 nibbles)

|@~`^+%;~$.|$\$a`($$_@;$
|                           # filter
 @                          # the second argment (=array of possible anagrams)
  ~                         # returning elements that are falsy for:
       ;~$                  #   apply and save the following function to each element:
           |$               #     filter each element
             \$a            #       to keep only alphabetic characters
          .                 #     and then map over each character
                `($         #       converting to lowercase
                   $_       #   apply the saved function to the first argument
      %                     #   split each normalized element
                            #     by the normalized first argment 
     +                      #     and flatten
                            #     (this removes normalized identities)
   `^                       #   and then get the element-wise xor
                     @;$    #     with the normalized first argument
                            #     (so anagrams give empty list, 
                            #     identities/non-anagrams give lists of all/different characters)           

enter image description here See the other test cases here

\$\endgroup\$
0
\$\begingroup\$

Ruby, 80 bytes

->s,a{g=->s{s.upcase.gsub(/[^A-Z]/,"").chars.sort}
a.select{s!=_1&&g[s]==g[_1]}}

Attempt This Online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Not yet updated in the question, but Commented that e.g. Krotas Mon is not an anagram of Krotasmon (the equality check is post-filtering and lowering). \$\endgroup\$ Commented Nov 18, 2022 at 20:27
0
\$\begingroup\$

JavaScript (ES10*), 105 bytes

* Not a strict requirement, but starting with ECMAScript 2019 (aka ES10), the .sort() method is guaranteed to be stable. This used to be left to the implementation.

Expects (string)(array).

s=>a=>a.filter(w=>(g=c=>(h=s=>[...s.toLowerCase().replace(/[^a-z]/g,'')].sort(c)+0)(w)==h(s))()&!g(_=>1))

Try it online!

Commented

For each test, the helper function g is called twice: once to check that the normalized strings are equal when the letters are sorted, and once to check that they're different when no sort is applied.

s =>                    // s   = reference string
a =>                    // a[] = array of strings
a.filter(w =>           // for each string w in a[]:
  ( g = c =>            //   g is a helper function taking a callback c
    ( h = s =>          //     h is a helper function taking a string s
      [...              //       split into an array of characters:
        s.toLowerCase() //         convert s to lower case
        .replace(       //         remove ...
          /[^a-z]/g, '' //         ... all non-letter characters
        )               //
      ].sort(c)         //       sort the resulting array using the callback c
      + 0               //       add a final 0 to coerce to a string
    )(w) == h(s)        //     is the normalization of w equal to that of s?
  )()                   //   we first call g() with an undefined callback
  &                     //   so that the default lexicographical sort is used
  !g(_ => 1)            //   we then call g() with a callback that leaves the
                        //   arrays unchanged
)                       // end of filter()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.