Skip to content

Commit ce8df5a

Browse files
Add anagram exercise (#266)
1 parent 3505d29 commit ce8df5a

File tree

10 files changed

+553
-0
lines changed

10 files changed

+553
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,14 @@
481481
"prerequisites": [],
482482
"difficulty": 4
483483
},
484+
{
485+
"slug": "anagram",
486+
"name": "Anagram",
487+
"uuid": "4172a5bb-0c8e-4a66-9551-8b46acdfc57a",
488+
"practices": [],
489+
"prerequisites": [],
490+
"difficulty": 5
491+
},
484492
{
485493
"slug": "diamond",
486494
"name": "Diamond",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Hints
2+
3+
## General
4+
5+
- The `$t0-9` registers can be used to temporarily store values
6+
- The instructions specify which registers are used as input and output
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Instructions append
2+
3+
## Input/Output format
4+
5+
Each set of words is represented as a null-terminated string, with a newline character at the end of each word.
6+
7+
An example would be `"tones\nnotes\nSeton\n"`
8+
9+
## Registers
10+
11+
| Register | Usage | Type | Description |
12+
| -------- | ------------ | ------- | -------------------------------------------------------------- |
13+
| `$a0` | input | address | null-terminated target string, without newline |
14+
| `$a1` | input | address | null-terminated candidates string with newline after each word |
15+
| `$a2` | input/output | address | null-terminated output string with newline after each word |
16+
| `$t0-9` | temporary | any | for temporary storage |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Instructions
2+
3+
Your task is to, given a target word and a set of candidate words, to find the subset of 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 and candidates are words 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 anagram set is the subset of the candidate set that are anagrams of the target (in any order).
11+
Words in the anagram set should have the same letter case as in the candidate set.
12+
13+
Given the target `"stone"` and candidates `"stone"`, `"tones"`, `"banana"`, `"tons"`, `"notes"`, `"Seton"`, the anagram set is `"tones"`, `"notes"`, `"Seton"`.
Lines changed: 12 additions & 0 deletions
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.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"impl.mips"
8+
],
9+
"test": [
10+
"runner.mips"
11+
],
12+
"example": [
13+
".meta/example.mips"
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+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# | Register | Usage | Type | Description |
2+
# | -------- | ------------ | ------- | -------------------------------------------------------------- |
3+
# | `$a0` | input | address | null-terminated target string, without newline |
4+
# | `$a1` | input | address | null-terminated candidates string with newline after each word |
5+
# | `$a2` | input/output | address | null-terminated output string with newline after each word |
6+
# | `$sp` | stack | address | stack pointer, points to target letter count table |
7+
# | `$a3` | temporary | address | points to candidate letter count table |
8+
# | `$v0` | temporary | address | points to newline or null at end of word |
9+
10+
11+
.macro count_letters (%word, %table)
12+
# %word is address of input word
13+
# %table is address of letter count table to populate
14+
# $v0 is set to adddress of word terminator (\n or \0)
15+
move $v0, %word
16+
addiu $t1, %table, 104
17+
18+
clear:
19+
subiu $t1, $t1, 4
20+
sw $zero, 0($t1)
21+
bne $t1, %table, clear
22+
23+
b read
24+
25+
26+
count:
27+
addiu $v0, $v0, 1 # address of next letter in input word
28+
or $t0, $t0, 32 # force to lower case
29+
subiu $t0, $t0, 'a'
30+
sltiu $t1, $t0, 26 # $t1 is set to 1 if $t0 is alphabetic, otherwise 0
31+
beqz $t1, read # jump to next character if not alphabetic
32+
33+
sll $t0, $t0, 2
34+
add $t1, %table, $t0 # address for letter count
35+
lw $t2, 0($t1)
36+
addi $t2, $t2, 1 # increment letter count
37+
sw $t2, 0($t1)
38+
39+
read:
40+
lb $t0, 0($v0)
41+
bge $t0, 32, count # repeat until end of word
42+
.end_macro
43+
44+
45+
.globl find_anagrams
46+
47+
find_anagrams:
48+
subiu $sp, $sp, 208 # Allocate stack space for letter count tables
49+
addiu $a3, $sp, 104 # Address of candidate letter count table
50+
count_letters ($a0, $sp) # Populate target letter count table
51+
j consider_candidate
52+
53+
54+
copy_next_letter:
55+
addiu $a1, $a1, 1
56+
57+
copy_word:
58+
# Copy word $a1..$v0 inclusive to $a2
59+
lb $t0, 0($a1)
60+
sb $t0, 0($a2)
61+
addiu $a2, $a2, 1
62+
bne $a1, $v0, copy_next_letter
63+
64+
next_candidate:
65+
addiu $a1, $v0, 1
66+
lb $t0, 0($a1)
67+
bnez $t0, consider_candidate
68+
69+
sb $zero, 0($a2) # Write null terminator
70+
addiu $sp, $sp, 208 # Restore original stack pointer
71+
jr $ra
72+
73+
consider_candidate:
74+
count_letters ($a1, $a3)
75+
move $t5, $sp # Pointer into target letter count table
76+
move $t6, $a3 # Pointer into candidate letter count table
77+
78+
compare_count:
79+
lw $t7, 0($t5)
80+
lw $t8, 0($t6)
81+
addiu $t5, $t5, 4 # Increment pointers
82+
addiu $t6, $t6, 4
83+
bne $t7, $t8, next_candidate # Reject candidate if count does not match
84+
bne $t5, $a3, compare_count # Repeat until all 26 counts have been compared
85+
86+
# The letter counts match.
87+
# We now perform a case-insentitive string comparison
88+
89+
move $t5, $a0 # Pointer into target string
90+
move $t6, $a1 # Pointer into candidate string
91+
92+
compare_character:
93+
lb $t7, 0($t5)
94+
lb $t8, 0($t6)
95+
addiu $t5, $t5, 1 # Increment pointers
96+
addiu $t6, $t6, 1
97+
98+
# Force each letter to lowercase
99+
100+
blt $t7, 'A', target_letter_ready
101+
bgt $t7, 'Z', target_letter_ready
102+
addi $t7, $t7, 32
103+
104+
target_letter_ready:
105+
blt $t8, 'A', candidate_letter_ready
106+
bgt $t8, 'Z', candidate_letter_ready
107+
addi $t8, $t8, 32
108+
109+
candidate_letter_ready:
110+
bne $t7, $t8, copy_word # Candidate word is not the same as target word
111+
bne $t6, $v0, compare_character # Repeat until the whole word has been compared
112+
b next_candidate # Skip candidate word, because it is the target word
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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+
include = false
85+
86+
[fd3509e5-e3ba-409d-ac3d-a9ac84d13296]
87+
description = "different characters may have the same bytes"
88+
include = false

exercises/practice/anagram/impl.mips

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# | Register | Usage | Type | Description |
2+
# | -------- | ------------ | ------- | -------------------------------------------------------------- |
3+
# | `$a0` | input | address | null-terminated target string, without newline |
4+
# | `$a1` | input | address | null-terminated candidates string with newline after each word |
5+
# | `$a2` | input/output | address | null-terminated output string with newline after each word |
6+
# | `$t0-9` | temporary | any | for temporary storage |
7+
8+
.globl find_anagrams
9+
10+
find_anagrams:
11+
jr $ra

0 commit comments

Comments
 (0)