-
-
Notifications
You must be signed in to change notification settings - Fork 25
Add alphametics exercise (#312) #443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
glennj
merged 14 commits into
exercism:main
from
kirtisrivastava22:exercise/alphametics
Aug 14, 2026
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
c93925d
Add alphametics exercise (#312)
kirtisrivastava22 537d52a
Register alphametics in track config
kirtisrivastava22 196450e
in sorted order
kirtisrivastava22 2c29bd9
Update exercises/practice/alphametics/.meta/template.j2
kirtisrivastava22 41ba911
Update exercises/practice/alphametics/.meta/example.awk
kirtisrivastava22 a1a2e3c
Update exercises/practice/alphametics/.meta/example.awk
kirtisrivastava22 3979ac3
Address review: simplify parsing, template list comprehension, bump d…
kirtisrivastava22 dbafafd
Merge branch 'exercise/alphametics' of https://github.com/kirtisrivas…
kirtisrivastava22 03f42ac
difficulty set to 8
kirtisrivastava22 1b75d6b
Update exercises/practice/alphametics/.meta/template.j2
kirtisrivastava22 b01a207
Update exercises/practice/alphametics/.meta/template.j2
kirtisrivastava22 eccd8cb
Fix template syntax, drop empty-line output, resync generated tests
kirtisrivastava22 ebaabeb
Fix template loop var and empty-output branch; regenerate tests via g…
kirtisrivastava22 2bb3764
test-alphametics.bats
kirtisrivastava22 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Instructions | ||
|
|
||
| Given an alphametics puzzle, find the correct solution. | ||
|
|
||
| [Alphametics][alphametics] is a puzzle where letters in words are replaced with numbers. | ||
|
|
||
| For example `SEND + MORE = MONEY`: | ||
|
|
||
| ```text | ||
| S E N D | ||
| M O R E + | ||
| ----------- | ||
| M O N E Y | ||
| ``` | ||
|
|
||
| Replacing these with valid numbers gives: | ||
|
|
||
| ```text | ||
| 9 5 6 7 | ||
| 1 0 8 5 + | ||
| ----------- | ||
| 1 0 6 5 2 | ||
| ``` | ||
|
|
||
| This is correct because every letter is replaced by a different number and the | ||
| words, translated into numbers, then make a valid sum. | ||
|
|
||
| Each letter must represent a different digit, and the leading digit of a | ||
| multi-digit number must not be zero. | ||
|
|
||
| ## Input | ||
|
|
||
| Your script will receive the alphametic puzzle as a single string via | ||
| standard input (stdin). The puzzle string follows the format | ||
| `WORD1 + WORD2 + ... == RESULT`. | ||
|
|
||
| For example: | ||
|
|
||
| ```text | ||
| SEND + MORE == MONEY | ||
| ``` | ||
|
|
||
| ## Output | ||
|
|
||
| If the puzzle has a solution, print a single line consisting of | ||
| space-separated `LETTER=DIGIT` pairs, sorted alphabetically by letter. | ||
|
|
||
| For the example above, the output should be: | ||
|
|
||
| ```text | ||
| D=7 E=5 M=1 N=6 O=0 R=8 S=9 Y=2 | ||
| ``` | ||
|
|
||
| If the puzzle has multiple valid solutions, printing any one of them is | ||
| acceptable. | ||
|
|
||
| If the puzzle has no solution, print nothing (an empty line). | ||
|
|
||
| [alphametics]: https://en.wikipedia.org/wiki/Alphametics |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "blurb": "Given an alphametics puzzle, find the correct solution.", | ||
| "authors": [ | ||
| "kirtisrivastava22" | ||
| ], | ||
| "contributors": [], | ||
| "files": { | ||
| "solution": [ | ||
| "alphametics.awk" | ||
| ], | ||
| "test": [ | ||
| "test-alphametics.bats" | ||
| ], | ||
| "example": [ | ||
| ".meta/example.awk" | ||
| ] | ||
| }, | ||
| "icon": "crossword", | ||
| "source": "Wikipedia", | ||
| "source_url": "https://en.wikipedia.org/wiki/Alphametics" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| #!/usr/bin/awk -f | ||
| # | ||
| # Alphametics solver. | ||
| # | ||
| # Reads a puzzle from stdin in the form: | ||
| # WORD1 + WORD2 + ... == RESULT | ||
| # (a single "=" is also accepted) | ||
| # | ||
| # Prints one line of space-separated LETTER=DIGIT pairs, sorted | ||
| # alphabetically by letter, for a valid solution. Prints nothing | ||
| # if no solution exists. | ||
| # | ||
| # Approach: process the puzzle column by column, from the rightmost | ||
| # (units) digit to the leftmost, tracking the carry. Within each | ||
| # column, only the letters that appear for the first time are | ||
| # assigned digits (via backtracking), then the column's arithmetic | ||
| # is checked immediately. This prunes the search far more | ||
| # aggressively than trying full permutations of every letter. | ||
| function colchar(word, col, L) { | ||
| L = length(word) | ||
| if (col < L) return substr(word, L - col, 1) | ||
| return "" | ||
| } | ||
| # Try every valid digit for newl[idx..m], then verify/recurse. | ||
| function assign(idx, m, colletters, ncol, hasres, rch, newl, col, carr, | ||
| d, letter, i, colsum, total, digit_needed, newcarry, required) { | ||
| if (idx > m) { | ||
| colsum = 0 | ||
| for (i = 1; i <= ncol; i++) colsum += assigned[colletters[i]] | ||
| total = colsum + carr | ||
| digit_needed = total % 10 | ||
| newcarry = int(total / 10) | ||
| required = hasres ? assigned[rch] : 0 | ||
| if (digit_needed != required) return 0 | ||
| return solve(col + 1, newcarry) | ||
| } | ||
| letter = newl[idx] | ||
| for (d = 0; d <= 9; d++) { | ||
| if (used[d]) continue | ||
| if (leading[letter] && d == 0) continue | ||
| assigned[letter] = d | ||
| used[d] = 1 | ||
| if (assign(idx + 1, m, colletters, ncol, hasres, rch, newl, col, carr)) return 1 | ||
| delete assigned[letter] | ||
| used[d] = 0 | ||
| } | ||
| return 0 | ||
| } | ||
| function solve(col, carry, | ||
| colletters, ncol, i, ch, hasres, rch, newl, m, j, exists) { | ||
| if (col == maxlen) return (carry == 0) | ||
| ncol = 0 | ||
| for (i = 1; i <= nwords; i++) { | ||
| ch = colchar(addends[i], col) | ||
| if (ch != "") colletters[++ncol] = ch | ||
| } | ||
| hasres = (col < length(result)) | ||
| rch = hasres ? colchar(result, col) : "" | ||
| m = 0 | ||
| for (i = 1; i <= ncol; i++) { | ||
| ch = colletters[i] | ||
| if (!(ch in assigned)) { | ||
| exists = 0 | ||
| for (j = 1; j <= m; j++) if (newl[j] == ch) { exists = 1; break } | ||
| if (!exists) newl[++m] = ch | ||
| } | ||
| } | ||
| if (hasres && !(rch in assigned)) { | ||
| exists = 0 | ||
| for (j = 1; j <= m; j++) if (newl[j] == rch) { exists = 1; break } | ||
| if (!exists) newl[++m] = rch | ||
| } | ||
| return assign(1, m, colletters, ncol, hasres, rch, newl, col, carry) | ||
| } | ||
| { | ||
| line = $0 | ||
| split(line, parts, /\s*==\s*/) | ||
| lhs = parts[1] | ||
| result = parts[2] | ||
| nwords = split(lhs, addends, /\s*\+\s*/) | ||
| maxlen = length(result) | ||
| if (length(result) > 1) leading[substr(result, 1, 1)] = 1 | ||
| for (i = 1; i <= nwords; i++) { | ||
| L = length(addends[i]) | ||
| if (L > maxlen) maxlen = L | ||
| if (L > 1) leading[substr(addends[i], 1, 1)] = 1 | ||
| } | ||
| if (solve(0, 0)) { | ||
| n = 0 | ||
| for (l in assigned) letters[++n] = l | ||
| for (i = 1; i <= n; i++) | ||
| for (j = i + 1; j <= n; j++) | ||
| if (letters[j] < letters[i]) { | ||
| t = letters[i]; letters[i] = letters[j]; letters[j] = t | ||
| } | ||
| out = "" | ||
| for (i = 1; i <= n; i++) { | ||
| if (i > 1) out = out " " | ||
| out = out letters[i] "=" assigned[letters[i]] | ||
| } | ||
| print out | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| {{ header }} | ||
| {% for idx, case in cases %} | ||
| @test "{{ case.description }}" { | ||
| {% if idx == 0 %}# {% endif %}[[ $BATS_RUN_SKIPPED == "true" ]] || skip | ||
| run awk -f alphametics.awk <<< "{{ case.input.puzzle }}" | ||
|
kirtisrivastava22 marked this conversation as resolved.
|
||
| assert_success | ||
| {% if case.expected %} | ||
| assert_output "{% for letter, digit in case.expected | dictsort %}{{ letter }}={{ digit }}{% if not loop.last %} {% endif %}{% endfor %}" | ||
| {% else %} | ||
| refute_output | ||
| {% endif %} | ||
| } | ||
| {% endfor %} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # This is an auto-generated file. | ||
| # | ||
| # This file is synced by a bot with exercism/problem-specifications data. | ||
| # Anything added to this file will be overwritten unless the settings | ||
| # indicate otherwise. All added comments will be preserved. | ||
| # | ||
| # See https://github.com/exercism/docs/blob/main/building/tracks/tests.md | ||
|
|
||
| [e0c08b07-9028-4d5f-91e1-d178fead8e1a] | ||
| description = "puzzle with three letters" | ||
|
|
||
| [a504ee41-cb92-4ec2-9f11-c37e95ab3f25] | ||
| description = "solution must have unique value for each letter" | ||
|
|
||
| [4e3b81d2-be7b-4c5c-9a80-cd72bc6d465a] | ||
| description = "leading zero solution is invalid" | ||
|
|
||
| [8a3e3168-d1ee-4df7-94c7-b9c54845ac3a] | ||
| description = "puzzle with two digits final carry" | ||
|
|
||
| [a9630645-15bd-48b6-a61e-d85c4021cc09] | ||
| description = "puzzle with four letters" | ||
|
|
||
| [3d905a86-5a52-4e4e-bf80-8951535791bd] | ||
| description = "puzzle with six letters" | ||
|
|
||
| [4febca56-e7b7-4789-97b9-530d09ba95f0] | ||
| description = "puzzle with seven letters" | ||
|
|
||
| [12125a75-7284-4f9a-a5fa-191471e0d44f] | ||
| description = "puzzle with eight letters" | ||
|
|
||
| [fb05955f-38dc-477a-a0b6-5ef78969fffa] | ||
| description = "puzzle with ten letters" | ||
|
|
||
| [9a101e81-9216-472b-b458-b513a7adacf7] | ||
| description = "puzzle with ten letters and 199 addends" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #!/usr/bin/awk -f | ||
| # | ||
| # Read an alphametics puzzle from stdin, e.g.: | ||
| # SEND + MORE == MONEY | ||
| # | ||
| # Print a single line of space-separated LETTER=DIGIT pairs, sorted | ||
| # alphabetically by letter, for a valid solution (e.g. "D=7 E=5 M=1 N=6 | ||
| # O=0 R=8 S=9 Y=2"). Print nothing if no solution exists. | ||
|
|
||
| { | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.