Anagrams, Again
October 18, 2019
We first check the two strings are the same length. Then we count characters in 256 buckets, adding 1 for each character in the first string and adding -1 for each character in the second string. Finally, we scan the 256 buckets and report an anagram if and only if all buckets have a 0 value:
(define (anagram? str1 str2) (if (not (= (string-length str1) (string-length str2))) #f (let ((buckets (make-vector 256 0))) (do ((cs (string->list str1) (cdr cs))) ((null? cs)) (let ((i (char->integer (car cs)))) (vector-set! buckets i (+ (vector-ref buckets i) 1)))) (do ((cs (string->list str2) (cdr cs))) ((null? cs)) (let ((i (char->integer (car cs)))) (vector-set! buckets i (- (vector-ref buckets i) 1)))) (let loop ((i 0)) (if (= i 256) #t (if (not (zero? (vector-ref buckets i))) #f (loop (+ i 1))))))))
Here’s an example:
> (anagram? "time" "emit") #t
You can run the program at https://ideone.com/qTqySy.
In Python. These functions work for ascii and for unicode.
Here is my take on this, using Julia 1.1.1, without any dependencies: https://pastebin.com/9LgUHJr8
Have a nice weekend!
Here’s a solution in C.
Example:
Here’s a sorting-based solution in C.
Example:
@Paul: you need to be a bit careful with this approach with Unicode. Here’s an attempt to deal with combining characters, equivalences & casing:
I’m a bit disappointed that Chrome on my Android phone can’t cope with the combining characters in that last post at all, FF on Linux seems to manage though.
Just trying something: “Ångström”, “Ἀχιλλεύς”, “H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ”
OK, Chrome on Android just seems to have problems when displaying with its code font.