diff --git a/config.json b/config.json index 850b677699..3f4ad36bfb 100644 --- a/config.json +++ b/config.json @@ -528,6 +528,20 @@ "time" ] }, + { + "slug": "line-up", + "name": "Line Up", + "uuid": "034b31ef-331a-419d-bb62-465c05b533d8", + "practices": [ + "numbers", + "strings" + ], + "prerequisites": [ + "numbers", + "strings" + ], + "difficulty": 1 + }, { "slug": "rna-transcription", "name": "RNA Transcription", diff --git a/exercises/practice/line-up/.docs/instructions.md b/exercises/practice/line-up/.docs/instructions.md new file mode 100644 index 0000000000..9e686ecbff --- /dev/null +++ b/exercises/practice/line-up/.docs/instructions.md @@ -0,0 +1,19 @@ +# Instructions + +Given a name and a number, your task is to produce a sentence using that name and that number as an [ordinal numeral][ordinal-numeral]. +Yaʻqūb expects to use numbers from 1 up to 999. + +Rules: + +- Numbers ending in 1 (unless ending in 11) → `"st"` +- Numbers ending in 2 (unless ending in 12) → `"nd"` +- Numbers ending in 3 (unless ending in 13) → `"rd"` +- All other numbers → `"th"` + +Examples: + +- `"Mary", 1` → `"Mary, you are the 1st customer we serve today. Thank you!"` +- `"John", 12` → `"John, you are the 12th customer we serve today. Thank you!"` +- `"Dahir", 162` → `"Dahir, you are the 162nd customer we serve today. Thank you!"` + +[ordinal-numeral]: https://en.wikipedia.org/wiki/Ordinal_numeral diff --git a/exercises/practice/line-up/.docs/introduction.md b/exercises/practice/line-up/.docs/introduction.md new file mode 100644 index 0000000000..ea07268ae3 --- /dev/null +++ b/exercises/practice/line-up/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +Your friend Yaʻqūb works the counter at a deli in town, slicing, weighing, and wrapping orders for a line of hungry customers that gets longer every day. +Waiting customers are starting to lose track of who is next, so he wants numbered tickets they can use to track the order in which they arrive. + +To make the customers feel special, he does not want the ticket to have only a number on it. +They shall get a proper English sentence with their name and number on it. diff --git a/exercises/practice/line-up/.gitignore b/exercises/practice/line-up/.gitignore new file mode 100644 index 0000000000..0c88ff6ec3 --- /dev/null +++ b/exercises/practice/line-up/.gitignore @@ -0,0 +1,5 @@ +/node_modules +/bin/configlet +/bin/configlet.exe +/package-lock.json +/yarn.lock diff --git a/exercises/practice/line-up/.meta/config.json b/exercises/practice/line-up/.meta/config.json new file mode 100644 index 0000000000..b555adb6e6 --- /dev/null +++ b/exercises/practice/line-up/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "line-up.js" + ], + "test": [ + "line-up.spec.js" + ], + "example": [ + ".meta/proof.ci.js" + ] + }, + "blurb": "Help lining up customers at Yaʻqūb's Deli.", + "source": "mk-mxp, based on previous work from Exercism contributors codedge and neenjaw", + "source_url": "https://forum.exercism.org/t/new-exercise-ordinal-numbers/19147" +} diff --git a/exercises/practice/line-up/.meta/proof.ci.js b/exercises/practice/line-up/.meta/proof.ci.js new file mode 100644 index 0000000000..64ba5c1919 --- /dev/null +++ b/exercises/practice/line-up/.meta/proof.ci.js @@ -0,0 +1,25 @@ +const getSuffix = (number) => { + const lastTwoDigits = number % 100; + const lastDigit = number % 10; + + if (lastTwoDigits >= 11 && lastTwoDigits <= 13) { + return 'th'; + } + + if (lastDigit === 1) { + return 'st'; + } + + if (lastDigit === 2) { + return 'nd'; + } + + if (lastDigit === 3) { + return 'rd'; + } + + return 'th'; +}; + +export const format = (name, number) => + `${name}, you are the ${number}${getSuffix(number)} customer we serve today. Thank you!`; diff --git a/exercises/practice/line-up/.meta/tests.toml b/exercises/practice/line-up/.meta/tests.toml new file mode 100644 index 0000000000..36fdf1d0cd --- /dev/null +++ b/exercises/practice/line-up/.meta/tests.toml @@ -0,0 +1,67 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[7760d1b8-4864-4db4-953b-0fa7c047dbc0] +description = "format smallest non-exceptional ordinal numeral 4" + +[e8b7c715-6baa-4f7b-8fb3-2fa48044ab7a] +description = "format greatest single digit non-exceptional ordinal numeral 9" + +[f370aae9-7ae7-4247-90ce-e8ff8c6934df] +description = "format non-exceptional ordinal numeral 5" + +[37f10dea-42a2-49de-bb92-0b690b677908] +description = "format non-exceptional ordinal numeral 6" + +[d8dfb9a2-3a1f-4fee-9dae-01af3600054e] +description = "format non-exceptional ordinal numeral 7" + +[505ec372-1803-42b1-9377-6934890fd055] +description = "format non-exceptional ordinal numeral 8" + +[8267072d-be1f-4f70-b34a-76b7557a47b9] +description = "format exceptional ordinal numeral 1" + +[4d8753cb-0364-4b29-84b8-4374a4fa2e3f] +description = "format exceptional ordinal numeral 2" + +[8d44c223-3a7e-4f48-a0ca-78e67bf98aa7] +description = "format exceptional ordinal numeral 3" + +[6c4f6c88-b306-4f40-bc78-97cdd583c21a] +description = "format smallest two digit non-exceptional ordinal numeral 10" + +[e257a43f-d2b1-457a-97df-25f0923fc62a] +description = "format non-exceptional ordinal numeral 11" + +[bb1db695-4d64-457f-81b8-4f5a2107e3f4] +description = "format non-exceptional ordinal numeral 12" + +[60a3187c-9403-4835-97de-4f10ebfd63e2] +description = "format non-exceptional ordinal numeral 13" + +[2bdcebc5-c029-4874-b6cc-e9bec80d603a] +description = "format exceptional ordinal numeral 21" + +[74ee2317-0295-49d2-baf0-d56bcefa14e3] +description = "format exceptional ordinal numeral 62" + +[b37c332d-7f68-40e3-8503-e43cbd67a0c4] +description = "format exceptional ordinal numeral 100" + +[0375f250-ce92-4195-9555-00e28ccc4d99] +description = "format exceptional ordinal numeral 101" + +[0d8a4974-9a8a-45a4-aca7-a9fb473c9836] +description = "format non-exceptional ordinal numeral 112" + +[06b62efe-199e-4ce7-970d-4bf73945713f] +description = "format exceptional ordinal numeral 123" diff --git a/exercises/practice/line-up/.npmrc b/exercises/practice/line-up/.npmrc new file mode 100644 index 0000000000..d26df800bb --- /dev/null +++ b/exercises/practice/line-up/.npmrc @@ -0,0 +1 @@ +audit=false diff --git a/exercises/practice/line-up/LICENSE b/exercises/practice/line-up/LICENSE new file mode 100644 index 0000000000..90e73be03b --- /dev/null +++ b/exercises/practice/line-up/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Exercism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/exercises/practice/line-up/babel.config.js b/exercises/practice/line-up/babel.config.js new file mode 100644 index 0000000000..a638497df1 --- /dev/null +++ b/exercises/practice/line-up/babel.config.js @@ -0,0 +1,4 @@ +module.exports = { + presets: [['@exercism/babel-preset-javascript', { corejs: '3.40' }]], + plugins: [], +}; diff --git a/exercises/practice/line-up/eslint.config.mjs b/exercises/practice/line-up/eslint.config.mjs new file mode 100644 index 0000000000..ca517111ed --- /dev/null +++ b/exercises/practice/line-up/eslint.config.mjs @@ -0,0 +1,45 @@ +// @ts-check + +import config from '@exercism/eslint-config-javascript'; +import maintainersConfig from '@exercism/eslint-config-javascript/maintainers.mjs'; + +import globals from 'globals'; + +export default [ + ...config, + ...maintainersConfig, + { + files: maintainersConfig[1].files, + rules: { + 'jest/expect-expect': ['warn', { assertFunctionNames: ['expect*'] }], + }, + }, + { + files: ['scripts/**/*.mjs'], + languageOptions: { + globals: { + ...globals.node, + }, + }, + }, + // <> + { + ignores: [ + // # Protected or generated + '/.appends/**/*', + '/.github/**/*', + '/.vscode/**/*', + + // # Binaries + '/bin/*', + + // # Configuration + '/config', + '/babel.config.js', + + // # Typings + '/exercises/**/global.d.ts', + '/exercises/**/env.d.ts', + ], + }, +]; diff --git a/exercises/practice/line-up/jest.config.js b/exercises/practice/line-up/jest.config.js new file mode 100644 index 0000000000..ec8e908127 --- /dev/null +++ b/exercises/practice/line-up/jest.config.js @@ -0,0 +1,22 @@ +module.exports = { + verbose: true, + projects: [''], + testMatch: [ + '**/__tests__/**/*.[jt]s?(x)', + '**/test/**/*.[jt]s?(x)', + '**/?(*.)+(spec|test).[jt]s?(x)', + ], + testPathIgnorePatterns: [ + '/(?:production_)?node_modules/', + '.d.ts$', + '/test/fixtures', + '/test/helpers', + '__mocks__', + ], + transform: { + '^.+\\.[jt]sx?$': 'babel-jest', + }, + moduleNameMapper: { + '^(\\.\\/.+)\\.js$': '$1', + }, +}; diff --git a/exercises/practice/line-up/line-up.js b/exercises/practice/line-up/line-up.js new file mode 100644 index 0000000000..d052cd5eb9 --- /dev/null +++ b/exercises/practice/line-up/line-up.js @@ -0,0 +1,8 @@ +// +// This is only a SKELETON file for the 'Line Up' exercise. It's been provided as a +// convenience to get you started writing code faster. +// + +export const format = () => { + throw new Error('Remove this line and implement the function'); +}; diff --git a/exercises/practice/line-up/line-up.spec.js b/exercises/practice/line-up/line-up.spec.js new file mode 100644 index 0000000000..62877284de --- /dev/null +++ b/exercises/practice/line-up/line-up.spec.js @@ -0,0 +1,118 @@ +import { describe, expect, test, xtest } from '@jest/globals'; +import { format } from './line-up'; + +describe('Line Up', () => { + test('format smallest non-exceptional ordinal numeral 4', () => { + expect(format('Gianna', 4)).toBe( + 'Gianna, you are the 4th customer we serve today. Thank you!', + ); + }); + + xtest('format greatest single digit non-exceptional ordinal numeral 9', () => { + expect(format('Maarten', 9)).toBe( + 'Maarten, you are the 9th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 5', () => { + expect(format('Petronila', 5)).toBe( + 'Petronila, you are the 5th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 6', () => { + expect(format('Attakullakulla', 6)).toBe( + 'Attakullakulla, you are the 6th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 7', () => { + expect(format('Kate', 7)).toBe( + 'Kate, you are the 7th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 8', () => { + expect(format('Maximiliano', 8)).toBe( + 'Maximiliano, you are the 8th customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 1', () => { + expect(format('Mary', 1)).toBe( + 'Mary, you are the 1st customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 2', () => { + expect(format('Haruto', 2)).toBe( + 'Haruto, you are the 2nd customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 3', () => { + expect(format('Henriette', 3)).toBe( + 'Henriette, you are the 3rd customer we serve today. Thank you!', + ); + }); + + xtest('format smallest two digit non-exceptional ordinal numeral 10', () => { + expect(format('Alvarez', 10)).toBe( + 'Alvarez, you are the 10th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 11', () => { + expect(format('Jacqueline', 11)).toBe( + 'Jacqueline, you are the 11th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 12', () => { + expect(format('Juan', 12)).toBe( + 'Juan, you are the 12th customer we serve today. Thank you!', + ); + }); + + xtest('format non-exceptional ordinal numeral 13', () => { + expect(format('Patricia', 13)).toBe( + 'Patricia, you are the 13th customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 21', () => { + expect(format('Washi', 21)).toBe( + 'Washi, you are the 21st customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 62', () => { + expect(format('Nayra', 62)).toBe( + 'Nayra, you are the 62nd customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 100', () => { + expect(format('John', 100)).toBe( + 'John, you are the 100th customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 101', () => { + expect(format('Zeinab', 101)).toBe( + 'Zeinab, you are the 101st customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 112', () => { + expect(format('Knud', 112)).toBe( + 'Knud, you are the 112th customer we serve today. Thank you!', + ); + }); + + xtest('format exceptional ordinal numeral 123', () => { + expect(format('Yma', 123)).toBe( + 'Yma, you are the 123rd customer we serve today. Thank you!', + ); + }); +}); diff --git a/exercises/practice/line-up/package.json b/exercises/practice/line-up/package.json new file mode 100644 index 0000000000..2d55c3710b --- /dev/null +++ b/exercises/practice/line-up/package.json @@ -0,0 +1,34 @@ +{ + "name": "@exercism/javascript-line-up", + "description": "Exercism exercises in Javascript.", + "author": "Katrina Owen", + "private": true, + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/exercism/javascript", + "directory": "exercises/practice/line-up" + }, + "devDependencies": { + "@exercism/babel-preset-javascript": "^0.5.1", + "@exercism/eslint-config-javascript": "^0.8.1", + "@jest/globals": "^29.7.0", + "@types/node": "^24.3.0", + "@types/shelljs": "^0.8.17", + "babel-jest": "^29.7.0", + "core-js": "~3.42.0", + "diff": "^8.0.2", + "eslint": "^9.28.0", + "expect": "^29.7.0", + "globals": "^16.3.0", + "jest": "^29.7.0" + }, + "dependencies": {}, + "scripts": { + "lint": "corepack pnpm eslint .", + "test": "corepack pnpm jest", + "watch": "corepack pnpm jest --watch", + "format": "corepack pnpm prettier -w ." + }, + "packageManager": "pnpm@9.15.2" +}