Scrabble score

This commit is contained in:
2025-04-18 21:14:09 +02:00
parent 1757bdbd76
commit 96bd169f8b
24 changed files with 25942 additions and 0 deletions
@@ -0,0 +1,31 @@
{
"authors": [
"zgavin1"
],
"contributors": [
"masters3d",
"SleeplessByte"
],
"files": {
"solution": [
"scrabble-score.ts"
],
"test": [
"scrabble-score.test.ts"
],
"example": [
".meta/proof.ci.ts"
]
},
"blurb": "Given a word, compute the Scrabble score for that word.",
"custom": {
"version.tests.compatibility": "jest-29",
"flag.tests.task-per-describe": false,
"flag.tests.may-run-long": false,
"flag.tests.includes-optional": false,
"flag.tests.jest": true,
"flag.tests.tstyche": false
},
"source": "Inspired by the Extreme Startup game",
"source_url": "https://github.com/rchatley/extreme_startup"
}
@@ -0,0 +1 @@
{"track":"typescript","exercise":"scrabble-score","id":"10e559da61f34d0ab38b5bd6baacdfba","url":"https://exercism.org/tracks/typescript/exercises/scrabble-score","handle":"briemens","is_requester":true,"auto_approve":false}
+16691
View File
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
{
"recommendations": [
"arcanis.vscode-zipfs",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
+7
View File
@@ -0,0 +1,7 @@
{
"cSpell.words": ["exercism"],
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
}
}
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
compressionLevel: mixed
enableGlobalCache: true
+50
View File
@@ -0,0 +1,50 @@
# Help
## Running the tests
Before trying to execute the tests, ensure the assignment folder is set-up correctly by following the installation steps, namely `corepack yarn install` and the Editor SDK setup.
Execute the tests with:
```bash
$ corepack yarn test
```
## Skipped tests
In the test suites all tests but the first have been skipped.
Once you get a test passing, you can enable the next one by changing `xit` to `it`.
Additionally tests may be grouped using `xdescribe`.
Enable the group by changing that to `describe`.
Finally, some exercises may have optional tests `it.skip`.
Remove `.skip` to execute the optional test.
## Submitting your solution
You can submit your solution using the `exercism submit scrabble-score.ts` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [TypeScript track's documentation](https://exercism.org/docs/tracks/typescript)
- The [TypeScript track's programming category on the forum](https://forum.exercism.org/c/programming/typescript)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [TypeScript QuickStart](https://www.typescriptlang.org/docs/handbook/release-notes/overview.html)
- [ECMAScript 2015 Language Specification](https://www.ecma-international.org/wp-content/uploads/ECMA-262_6th_edition_june_2015.pdf) (pdf)
- [Mozilla JavaScript Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference)
- [/r/typescript](https://www.reddit.com/r/typescript) is the TypeScript subreddit.
- [StackOverflow](https://stackoverflow.com/questions/tagged/typescript) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
+53
View File
@@ -0,0 +1,53 @@
# Scrabble Score
Welcome to Scrabble Score on Exercism's TypeScript Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Introduction
[Scrabble][wikipedia] is a word game where players place letter tiles on a board to form words.
Each letter has a value.
A word's score is the sum of its letters' values.
[wikipedia]: https://en.wikipedia.org/wiki/Scrabble
## Instructions
Your task is to compute a word's Scrabble score by summing the values of its letters.
The letters are valued as follows:
| Letter | Value |
| ---------------------------- | ----- |
| A, E, I, O, U, L, N, R, S, T | 1 |
| D, G | 2 |
| B, C, M, P | 3 |
| F, H, V, W, Y | 4 |
| K | 5 |
| J, X | 8 |
| Q, Z | 10 |
For example, the word "cabbage" is worth 14 points:
- 3 points for C
- 1 point for A
- 3 points for B
- 3 points for B
- 1 point for A
- 2 points for G
- 1 point for E
## Source
### Created by
- @zgavin1
### Contributed to by
- @masters3d
- @SleeplessByte
### Based on
Inspired by the Extreme Startup game - https://github.com/rchatley/extreme_startup
@@ -0,0 +1,5 @@
module.exports = {
// eslint-disable-next-line @typescript-eslint/no-require-imports
presets: [[require('@exercism/babel-preset-typescript'), { corejs: '3.38' }]],
plugins: [],
}
@@ -0,0 +1,26 @@
// @ts-check
import tsEslint from 'typescript-eslint'
import config from '@exercism/eslint-config-typescript'
import maintainersConfig from '@exercism/eslint-config-typescript/maintainers.mjs'
export default [
...tsEslint.config(...config, {
files: ['.meta/proof.ci.ts', '.meta/exemplar.ts', '*.test.ts'],
extends: maintainersConfig,
}),
{
ignores: [
// # Protected or generated
'.git/**/*',
'.vscode/**/*',
//# When using npm
'node_modules/**/*',
// # Configuration files
'babel.config.cjs',
'jest.config.cjs',
],
},
]
+22
View File
@@ -0,0 +1,22 @@
module.exports = {
verbose: true,
projects: ['<rootDir>'],
testMatch: [
'**/__tests__/**/*.[jt]s?(x)',
'**/test/**/*.[jt]s?(x)',
'**/?(*.)+(spec|test).[jt]s?(x)',
],
testPathIgnorePatterns: [
'/(?:production_)?node_modules/',
'.d.ts$',
'<rootDir>/test/fixtures',
'<rootDir>/test/helpers',
'__mocks__',
],
transform: {
'^.+\\.[jt]sx?$': 'babel-jest',
},
moduleNameMapper: {
'^(\\.\\/.+)\\.js$': '$1',
},
}
+38
View File
@@ -0,0 +1,38 @@
{
"name": "@exercism/typescript-scrabble-score",
"version": "1.0.0",
"description": "Exercism exercises in Typescript.",
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/exercism/typescript"
},
"type": "module",
"engines": {
"node": "^18.16.0 || >=20.0.0"
},
"devDependencies": {
"@exercism/babel-preset-typescript": "^0.6.0",
"@exercism/eslint-config-typescript": "^0.8.0",
"@jest/globals": "^29.7.0",
"@types/node": "~22.7.6",
"babel-jest": "^29.7.0",
"core-js": "~3.38.1",
"eslint": "^9.12.0",
"expect": "^29.7.0",
"jest": "^29.7.0",
"prettier": "^3.3.3",
"tstyche": "^2.1.1",
"typescript": "~5.6.3",
"typescript-eslint": "^8.10.0"
},
"scripts": {
"test": "corepack yarn node test-runner.mjs",
"test:types": "corepack yarn tstyche",
"test:implementation": "corepack yarn jest --no-cache --passWithNoTests",
"lint": "corepack yarn lint:types && corepack yarn lint:ci",
"lint:types": "corepack yarn tsc --noEmit -p .",
"lint:ci": "corepack yarn eslint . --ext .tsx,.ts"
},
"packageManager": "yarn@4.5.1"
}
@@ -0,0 +1,19 @@
import { describe, it, expect } from '@jest/globals'
import { score } from './scrabble-score.ts'
describe('Scrabble', () => {
it('scores an empty word as zero', () => expect(score('')).toEqual(0))
it('scores a null as zero', () => expect(score(undefined)).toEqual(0))
it('scores a very short word', () => expect(score('a')).toEqual(1))
it('scores the word by the number of letters', () =>
expect(score('street')).toEqual(6))
it('scores more complicated words with more', () =>
expect(score('quirky')).toEqual(22))
it('scores case insensitive words', () =>
expect(score('OXYPHENBUTAZONE')).toEqual(41))
})
@@ -0,0 +1,11 @@
const letters = ['A', 'E', 'I', 'O', 'U', 'L', 'N', 'R', 'S', 'T', 'D', 'G', 'B', 'C', 'M', 'P', 'F', 'H', 'V', 'W', 'Y', 'K', 'J', 'X', 'Q', 'Z']
const values = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 8, 8, 10, 10]
export function score(word: string | undefined): number {
return (word || '')
.toUpperCase()
.split('')
.map(c => letters.indexOf(c))
.map(i => values[i])
.reduce((s, t) => s + t, 0)
}
+111
View File
@@ -0,0 +1,111 @@
#!/usr/bin/env node
/**
* 👋🏽 Hello there reader,
*
* It looks like you are working on this solution using the Exercism CLI and
* not the online editor. That's great! The file you are looking at executes
* the various steps the online test-runner also takes.
*
* @see https://github.com/exercism/typescript-test-runner
*
* TypeScript track exercises generally consist of at least two out of three
* types of tests to run.
*
* 1. tsc, the TypeScript compiler. This tests if the TypeScript code is valid
* 2. tstyche, static analysis tests to see if the types used are expected
* 3. jest, runtime implementation tests to see if the solution is correct
*
* If one of these three fails, this script terminates with -1, -2, or -3
* respectively. If it succeeds, it terminates with exit code 0.
*
* @note you need corepack (bundled with node LTS) enabled in order for this
* test runner to work as expected. Follow the installation and test
* instructions if you see errors about corepack or pnp.
*/
import { execSync } from 'node:child_process'
import { existsSync, readFileSync } from 'node:fs'
import { exit } from 'node:process'
import { URL } from 'node:url'
/**
* Before executing any tests, the test runner attempts to find the
* exercise config.json file which has metadata about which types of tests
* to run for this solution.
*/
const metaDirectory = new URL('./.meta/', import.meta.url)
const exercismDirectory = new URL('./.exercism/', import.meta.url)
const configDirectory = existsSync(metaDirectory)
? metaDirectory
: existsSync(exercismDirectory)
? exercismDirectory
: null
if (configDirectory === null) {
throw new Error(
'Expected .meta or .exercism directory to exist, but I cannot find it.'
)
}
const configFile = new URL('./config.json', configDirectory)
if (!existsSync(configFile)) {
throw new Error('Expected config.json to exist at ' + configFile.toString())
}
// Experimental: import config from './config.json' with { type: 'json' }
/** @type {import('./config.json') } */
const config = JSON.parse(readFileSync(configFile))
const jest = !config.custom || config.custom['flag.tests.jest']
const tstyche = config.custom?.['flag.tests.tstyche']
console.log(
`[tests] tsc: ✅, tstyche: ${tstyche ? '✅' : '❌'}, jest: ${jest ? '✅' : '❌'}, `
)
/**
* 1. tsc: the typescript compiler
*/
try {
console.log('[tests] tsc (compile)')
execSync('corepack yarn lint:types', {
stdio: 'inherit',
cwd: process.cwd(),
})
} catch {
exit(-1)
}
/**
* 2. tstyche: type tests
*/
if (tstyche) {
try {
console.log('[tests] tstyche (type tests)')
execSync('corepack yarn test:types', {
stdio: 'inherit',
cwd: process.cwd(),
})
} catch {
exit(-2)
}
}
/**
* 3. jest: implementation tests
*/
if (jest) {
try {
console.log('[tests] tstyche (implementation tests)')
execSync('corepack yarn test:implementation', {
stdio: 'inherit',
cwd: process.cwd(),
})
} catch {
exit(-3)
}
}
/**
* Done! 🥳
*/
+38
View File
@@ -0,0 +1,38 @@
{
"display": "Configuration for Exercism TypeScript Exercises",
"compilerOptions": {
// Allows you to use the newest syntax, and have access to console.log
// https://www.typescriptlang.org/tsconfig#lib
"lib": ["ES2020", "dom"],
// Make sure typescript is configured to output ESM
// https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#how-can-i-make-my-typescript-project-output-esm
"module": "Node16",
// Since this project is using babel, TypeScript may target something very
// high, and babel will make sure it runs on your local Node version.
// https://babeljs.io/docs/en/
"target": "ES2020", // ESLint doesn't support this yet: "es2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// Because jest-resolve isn't like node resolve, the absolute path must be .ts
"allowImportingTsExtensions": true,
"noEmit": true,
// Because we'll be using babel: ensure that Babel can safely transpile
// files in the TypeScript project.
//
// https://babeljs.io/docs/en/babel-plugin-transform-typescript/#caveats
"isolatedModules": true
},
"include": [
"*.ts",
"*.tsx",
".meta/*.ts",
".meta/*.tsx",
"__typetests__/*.tst.ts"
],
"exclude": ["node_modules"]
}
File diff suppressed because it is too large Load Diff