🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉 # pastafari's solution

## to Anagram in the Clojure Track

Published at Jul 13 2018 · 7 comments
Instructions
Test suite
Solution

Given a word and a list of possible anagrams, select the correct sublist.

Given `"listen"` and a list of candidates like `"enlists" "google" "inlets" "banana"` the program should return a list containing `"inlets"`.

## Source

Inspired by the Extreme Startup game https://github.com/rchatley/extreme_startup

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### anagram_test.clj

``````(ns anagram-test
(:require [clojure.test :refer [deftest is]]
anagram))

(deftest no-matches
(is (= []
(anagram/anagrams-for "diaper" ["hello" "world" "zombies" "pants"]))))

(deftest detect-simple-anagram
(is (= ["tan"] (anagram/anagrams-for "ant" ["tan" "stand" "at"]))))

(deftest does-not-confuse-different-duplicates
(is (= [] (anagram/anagrams-for "galea" ["eagle"]))))

(deftest eliminate-anagram-subsets
(is (= [] (anagram/anagrams-for "good" ["dog" "goody"]))))

(deftest detect-anagram
(is (= ["inlets"]
(let [coll ["enlists" "google" "inlets" "banana"]]
(anagram/anagrams-for "listen" coll)))))

(deftest multiple-anagrams
(is (= ["gallery" "regally" "largely"]
(let [coll ["gallery" "ballerina" "regally"
(anagram/anagrams-for "allergy" coll)))))

(deftest case-insensitive-anagrams
(is (= ["Carthorse"]
(anagram/anagrams-for "Orchestra" coll)))))

(deftest word-is-not-own-anagram
(is (= [] (anagram/anagrams-for "banana" ["banana"]))))

(deftest capital-word-is-not-own-anagram
(is (= [] (anagram/anagrams-for "BANANA" ["banana"]))))``````
``````(ns anagram
(:require [clojure.string :as str]))

(defn- alphagram
[word]
(frequencies (str/lower-case word)))

(defn anagram?
[a b]
(and
(not= a b)
(= (alphagram a)
(alphagram b))))

(defn anagrams-for
[word other-words]
(filter #(anagram? word %) other-words))`````` pastafari
Solution Author

Extracted alphagram into a named function Moved equality check to anagram? Looks nice and clean. Can you avoid the alphagram of the original word being calculated again for each of the other-words?

Also, I'm not sure how appropriate it is to use the name "alphagram" for your frequency map, as the word has a specific meaning related to the sorted letters. pastafari
Solution Author

@rsslldnphy oops, i've actually introduced a bug here. the alphagram method is not really an alphagram, its a frequency map :)) will fix in next iteration.

and point taken about pre-creating the alphagram for word. Nice. pastafari
Solution Author
commented over 6 years ago

Thanks @mdub for the comments. Will refactor this. Regarding performance, memoize should do the trick, no? Because I like the overall solution structure as is... According to your code "BAnaNA" and "banana" are anagrams. It still passes all the tests; but what if after a bug report someone decided that you need a new test for that:

(is (= [] (anagram/anagrams-for "BAnaNA" ["banana"]))))

How would you refactor this code to get this to work, while keeping the code elegant (readable and concise)? I'm curious what solution you will come up with :) (Just add this test in your test suite if you want to try)

I think your code is very readable, nice! Apart from too many newlines for me: anagram? doesn't need to be 6 lines long. One line per idea is enough: (defn anagram? [a b] "Same unordered characters, but not the same word" (and (not= a b) (= (alphagram a) (alphagram b))))

### What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

• What compromises have been made?