Skip to content

Commit e9efda0

Browse files
committed
new exercise: anagram
1 parent 047e2f5 commit e9efda0

14 files changed

+485
-0
lines changed

config.json

+8
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,14 @@
518518
"practices": [],
519519
"prerequisites": [],
520520
"difficulty": 2
521+
},
522+
{
523+
"slug": "anagram",
524+
"name": "Anagram",
525+
"uuid": "93cc0fba-0270-49d9-9ec3-62e721a1f64f",
526+
"practices": [],
527+
"prerequisites": [],
528+
"difficulty": 4
521529
}
522530
]
523531
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Instruction append
2+
3+
## Input/Output format
4+
5+
The function receives a single string of words, each suffixed with a line break.
6+
7+
The first one is the word the remaining ones are supposed to be anagrams of.
8+
9+
Return a string of all valid anagrams, each suffixed by a line break.
10+
11+
12+
## Reserved Addresses
13+
14+
The buffer for the input string uses bytes 64-319 of linear memory.
15+
16+
You may modify this buffer in place if you wish to avoid additional memory allocations.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Instructions
2+
3+
Given a target word and one or more candidate words, your task is to find the candidates that are anagrams of the target.
4+
5+
An anagram is a rearrangement of letters to form a new word: for example `"owns"` is an anagram of `"snow"`.
6+
A word is _not_ its own anagram: for example, `"stop"` is not an anagram of `"stop"`.
7+
8+
The target word and candidate words are made up of one or more ASCII alphabetic characters (`A`-`Z` and `a`-`z`).
9+
Lowercase and uppercase characters are equivalent: for example, `"PoTS"` is an anagram of `"sTOp"`, but `"StoP"` is not an anagram of `"sTOp"`.
10+
The words you need to find should be taken from the candidate words, using the same letter case.
11+
12+
Given the target `"stone"` and the candidate words `"stone"`, `"tones"`, `"banana"`, `"tons"`, `"notes"`, and `"Seton"`, the anagram words you need to find are `"tones"`, `"notes"`, and `"Seton"`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Introduction
2+
3+
At a garage sale, you find a lovely vintage typewriter at a bargain price!
4+
Excitedly, you rush home, insert a sheet of paper, and start typing away.
5+
However, your excitement wanes when you examine the output: all words are garbled!
6+
For example, it prints "stop" instead of "post" and "least" instead of "stale."
7+
Carefully, you try again, but now it prints "spot" and "slate."
8+
After some experimentation, you find there is a random delay before each letter is printed, which messes up the order.
9+
You now understand why they sold it for so little money!
10+
11+
You realize this quirk allows you to generate anagrams, which are words formed by rearranging the letters of another word.
12+
Pleased with your finding, you spend the rest of the day generating hundreds of anagrams.

exercises/practice/anagram/.eslintrc

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"root": true,
3+
"extends": "@exercism/eslint-config-javascript",
4+
"env": {
5+
"jest": true
6+
},
7+
"overrides": [
8+
{
9+
"files": [
10+
"*.spec.js"
11+
],
12+
"excludedFiles": [
13+
"custom.spec.js"
14+
],
15+
"extends": "@exercism/eslint-config-javascript/maintainers"
16+
}
17+
]
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"atk"
4+
],
5+
"files": {
6+
"solution": [
7+
"anagram.wat"
8+
],
9+
"test": [
10+
"anagram.spec.js"
11+
],
12+
"example": [
13+
".meta/proof.ci.wat"
14+
]
15+
},
16+
"blurb": "Given a word and a list of possible anagrams, select the correct sublist.",
17+
"source": "Inspired by the Extreme Startup game",
18+
"source_url": "https://github.com/rchatley/extreme_startup"
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
(module
2+
(memory (export "mem") 1)
3+
4+
(global $lineBreak i32 (i32.const 10))
5+
(global $toLower i32 (i32.const 32))
6+
(global $a i32 (i32.const 97))
7+
(global $z i32 (i32.const 122))
8+
(global $wordLetterCount i32 (i32.const 512))
9+
(global $anagramLetterCount i32 (i32.const 540))
10+
(global $outputOffset i32 (i32.const 1024))
11+
12+
;;
13+
;; Find the anagrams to the first word in the string of subsequent words
14+
;;
15+
;; @param {i32} $inputOffset - offset of the word list in linear memory
16+
;; @param {i32} $inputLength - length of the word list in linear memory
17+
;;
18+
;; @returns {(i32,i32)} - offset and length of the output word list
19+
;;
20+
(func (export "findAnagrams") (param $inputOffset i32) (param $inputLength i32) (result i32 i32)
21+
(local $pos i32)
22+
(local $char i32)
23+
(local $start i32)
24+
(local $length i32)
25+
(local $outputLength i32)
26+
(memory.fill (global.get $wordLetterCount) (i32.const 0) (i32.const 26))
27+
(memory.fill (global.get $anagramLetterCount) (i32.const 0) (i32.const 26))
28+
(loop $chars
29+
(local.set $char (i32.load8_u (i32.add (local.get $inputOffset) (local.get $pos))))
30+
(if (i32.eq (local.get $char) (global.get $lineBreak)) (then
31+
(if (local.get $start) (then
32+
(local.set $length (i32.const -1))
33+
(loop $compare
34+
(local.set $length (i32.add (local.get $length) (i32.const 1)))
35+
(br_if $compare (i32.and (i32.eq
36+
(i32.load8_u (i32.add (global.get $wordLetterCount) (local.get $length)))
37+
(i32.load8_u (i32.add (global.get $anagramLetterCount) (local.get $length))))
38+
(i32.lt_u (local.get $length) (i32.const 26)))))
39+
(if (i32.eq (local.get $length (i32.const 26))) (then
40+
(local.set $length (i32.sub (i32.add (local.get $pos) (i32.const 1)) (local.get $start)))
41+
(if (i32.gt_u (local.get $length) (i32.const 1)) (then
42+
(local.set $char (i32.const 0))
43+
(loop $notEqual
44+
(local.set $char (i32.add (local.get $char) (i32.const 1)))
45+
(br_if $notEqual (i32.and (i32.lt_u (local.get $char) (local.get $length))
46+
(i32.eq (i32.or (i32.load8_u (i32.add (local.get $inputOffset) (local.get $char)))
47+
(global.get $toLower))
48+
(i32.or (i32.load8_u (i32.add (i32.add (local.get $inputOffset) (local.get $start))
49+
(local.get $char))) (global.get $toLower))))))
50+
(if (i32.ne (local.get $char) (local.get $length)) (then
51+
(memory.copy (i32.add (global.get $outputOffset) (local.get $outputLength))
52+
(i32.add (local.get $inputOffset) (local.get $start)) (local.get $length))
53+
(local.set $outputLength (i32.add (local.get $outputLength) (local.get $length)))))))))))
54+
(memory.fill (global.get $anagramLetterCount) (i32.const 0) (i32.const 26))
55+
(local.set $start (i32.add (local.get $pos) (i32.const 1)))
56+
) (else
57+
(local.set $char (i32.or (local.get $char) (global.get $toLower)))
58+
(if (i32.and (i32.ge_u (local.get $char) (global.get $a))
59+
(i32.le_u (local.get $char) (global.get $z))) (then
60+
(local.set $length (i32.add (select (global.get $anagramLetterCount) (global.get $wordLetterCount)
61+
(local.get $start)) (i32.sub (local.get $char) (global.get $a))))
62+
(i32.store8 (local.get $length) (i32.add (i32.load8_u (local.get $length)) (i32.const 1)))
63+
))))
64+
(local.set $pos (i32.add (local.get $pos) (i32.const 1)))
65+
(br_if $chars (i32.lt_u (local.get $pos) (local.get $inputLength))))
66+
(global.get $outputOffset) (local.get $outputLength)
67+
)
68+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[dd40c4d2-3c8b-44e5-992a-f42b393ec373]
13+
description = "no matches"
14+
15+
[b3cca662-f50a-489e-ae10-ab8290a09bdc]
16+
description = "detects two anagrams"
17+
include = false
18+
19+
[03eb9bbe-8906-4ea0-84fa-ffe711b52c8b]
20+
description = "detects two anagrams"
21+
reimplements = "b3cca662-f50a-489e-ae10-ab8290a09bdc"
22+
23+
[a27558ee-9ba0-4552-96b1-ecf665b06556]
24+
description = "does not detect anagram subsets"
25+
26+
[64cd4584-fc15-4781-b633-3d814c4941a4]
27+
description = "detects anagram"
28+
29+
[99c91beb-838f-4ccd-b123-935139917283]
30+
description = "detects three anagrams"
31+
32+
[78487770-e258-4e1f-a646-8ece10950d90]
33+
description = "detects multiple anagrams with different case"
34+
35+
[1d0ab8aa-362f-49b7-9902-3d0c668d557b]
36+
description = "does not detect non-anagrams with identical checksum"
37+
38+
[9e632c0b-c0b1-4804-8cc1-e295dea6d8a8]
39+
description = "detects anagrams case-insensitively"
40+
41+
[b248e49f-0905-48d2-9c8d-bd02d8c3e392]
42+
description = "detects anagrams using case-insensitive subject"
43+
44+
[f367325c-78ec-411c-be76-e79047f4bd54]
45+
description = "detects anagrams using case-insensitive possible matches"
46+
47+
[7cc195ad-e3c7-44ee-9fd2-d3c344806a2c]
48+
description = "does not detect an anagram if the original word is repeated"
49+
include = false
50+
51+
[630abb71-a94e-4715-8395-179ec1df9f91]
52+
description = "does not detect an anagram if the original word is repeated"
53+
reimplements = "7cc195ad-e3c7-44ee-9fd2-d3c344806a2c"
54+
55+
[9878a1c9-d6ea-4235-ae51-3ea2befd6842]
56+
description = "anagrams must use all letters exactly once"
57+
58+
[85757361-4535-45fd-ac0e-3810d40debc1]
59+
description = "words are not anagrams of themselves (case-insensitive)"
60+
include = false
61+
62+
[68934ed0-010b-4ef9-857a-20c9012d1ebf]
63+
description = "words are not anagrams of themselves"
64+
reimplements = "85757361-4535-45fd-ac0e-3810d40debc1"
65+
66+
[589384f3-4c8a-4e7d-9edc-51c3e5f0c90e]
67+
description = "words are not anagrams of themselves even if letter case is partially different"
68+
reimplements = "85757361-4535-45fd-ac0e-3810d40debc1"
69+
70+
[ba53e423-7e02-41ee-9ae2-71f91e6d18e6]
71+
description = "words are not anagrams of themselves even if letter case is completely different"
72+
reimplements = "85757361-4535-45fd-ac0e-3810d40debc1"
73+
74+
[a0705568-628c-4b55-9798-82e4acde51ca]
75+
description = "words other than themselves can be anagrams"
76+
include = false
77+
78+
[33d3f67e-fbb9-49d3-a90e-0beb00861da7]
79+
description = "words other than themselves can be anagrams"
80+
reimplements = "a0705568-628c-4b55-9798-82e4acde51ca"
81+
82+
[a6854f66-eec1-4afd-a137-62ef2870c051]
83+
description = "handles case of greek letters"
84+
85+
[fd3509e5-e3ba-409d-ac3d-a9ac84d13296]
86+
description = "different characters may have the same bytes"

exercises/practice/anagram/.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
audit=false

exercises/practice/anagram/LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Exercism
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)