Is it a near-anagram?
Two words are anagrams of each other if the letters of one can be reordered to spell the other; e.g. ADOBE and ABODE are anagrams. An alternate way of describing it is that both words contain the same count of each letter. If you were to make a table:
ADOBE ABODE
----- -----
A: 1 A: 1
B: 1 B: 1
D: 1 D: 1
E: 1 E: 1
O: 1 O: 1
We can define a "near-anagram" as a pair of words that are almost anagrams, in the sense that they differ by only one letter. For example, TULIP and TUPLE are near-anagrams. TUPLE can be rearranged to spell TULEP, which differs from TULIP by only one letter. As a table:
TUPLE TULIP
----- -----
E: 1 I: 1
L: 1 L: 1
P: 1 P: 1
T: 1 T: 1
U: 1 U: 1
Challenge
The challenge is to take two strings as input and determine if they are near-anagrams.
- The strings can be taken in any convenient format for your language (strings, sequences of characters, etc.)
- The output can be any two distinct values, as long as they are always consistent; e.g. 0 and 1 for false and true.
- The strings will only contain alphabet characters in a single case. You can assume either upper or lower, whichever is convenient; examples are in upper. Input will contain no whitespace. (It is acceptable to take the input as a single string containing the words separated by whitespace, if it is convenient.)
- You can assume the strings will not be the same. A decision problem to handle equal strings is not very interesting. They may be proper anagrams, however.
- You can assume the input is not empty.
- The two words might not be the same length; they may differ by one letter at most (see test cases.)
Winning criteria is code-golf. Shortest answer in each language wins.
Test Cases
ADOBE ABODE -> false (proper anagram)
TUPLE TULIP -> true (near-anagram)
ABCDE DADBC -> true (two Ds)
BAR BARN -> true (one extra letter)
BARN BARREN -> false (too different)
[APL (Dyalog Extended)], 18 by …
4y ago
[JavaScript (Node.js)], 131 by …
4y ago
Stax, 12 bytes ä╫◙=♥:≡ƒélΣ …
4y ago
[Brachylog], 8 bytes pᵐ …
4y ago
[JavaScript (Node.js)], 150 71 …
4y ago
5 answers
JavaScript (Node.js), 150 71 bytes
f=(a,b)=>a[b.length]?f(b,a):b.filter(x=>a[y=a.indexOf(x)]=!~y).length-1
APL (Dyalog Extended), 18 bytes
Anonymous tacit prefix function taking a list of two strings as argument.
2=1⊥(≠⌿∊≢⍤⊢⌸⍤,⍤1↑)
(
…)
apply the following tacit function to the argument:
↑
mix the list of strings into a 2-row character matrix (padding any short string with spaces as necessary)
∊
…⍤1
with the enlisted (flattened into a single string) argument as left argument, apply the following function to each row of the matrix:
⍤,
concatenate the enlisted string to the row string, then:
≢⍤⊢⌸
count the number of occurrences of each unique element, in their order of appearance
≠⌿
Boolean mask indicating where the rows differ
1⊥
sum (lit. evaluate as unary; i.e. count differences)
2=
is 2 equal to that?
0 comment threads
JavaScript (Node.js), 131 bytes
Returns true and false
g=(s,t,c=[...t])=>([...s].forEach(v=>(y=c.indexOf(v),c.splice(y,y>=0))),c)
f=(s,t)=>(x=g(s,t).length)<2&&(y=g(t,s).length)<2&&x+y
Explanation
g
computes a sort of set (Array?) difference between t
and s
, running through the characters of s
and removing any matches in t
, then returning the remaining characters in t
.
f
calls g
to compute both s-t
and t-s
and checks that both are less than 2 (i.e. have only one letter difference either way). Then it checks the sum of the difference is non-zero to check that there is a difference, which I needed to add in to make perfect anagrams false.[1]
-
Without the restriction on perfect anagrams being falsey, I could have removed all of the x and y logic to get a 116 char solution ↩︎
0 comment threads
Brachylog, 8 bytes
pᵐ≠{b|}ᵛ
Since it takes $5!*5! = 14400$ tries to determine that the first test case gives false, I've added some shorter ones...
pᵐ Permute each element of the input.
≠ The permuted elements are not equal,
{ }ᵛ but yield the same result if
| maybe
b their first elements are removed.
1 comment thread