Skip to content
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

Add 4 new Common Lisp exercises #93

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions common-lisp/isbn-verifier/.exercism/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"PaulT89"
],
"files": {
"solution": [
"isbn-verifier.lisp"
],
"test": [
"isbn-verifier-test.lisp"
],
"example": [
".meta/example.lisp"
]
},
"blurb": "Check if a given string is a valid ISBN-10 number.",
"source": "Converting a string into a number and some basic processing utilizing a relatable real world example.",
"source_url": "https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation"
}
1 change: 1 addition & 0 deletions common-lisp/isbn-verifier/.exercism/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"track":"common-lisp","exercise":"isbn-verifier","id":"15547c7317a04ba0ba72f69af94e25d7","url":"https://exercism.org/tracks/common-lisp/exercises/isbn-verifier","handle":"wsgac","is_requester":true,"auto_approve":false}
94 changes: 94 additions & 0 deletions common-lisp/isbn-verifier/HELP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Help

## Running the tests

Start the REPL from the directory that you downloaded the exercise to.

You can run the tests by loading the test file into the REPL with `(load "exercise-test")` (replacing "exercise" with appropriate name). Then evaluate `(exercise-test:run-tests)` to run all the tests.

If you write your code directly in the REPL then simply evaluate `(exercise-test:run-tests)`.

If you write your code in the exercise lisp file then load it with `(load "exercise")` then evaluate `(exercise-test:run-tests)`.

## Submitting your solution

You can submit your solution using the `exercism submit isbn-verifier.lisp` 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 [Common Lisp track's documentation](https://exercism.org/docs/tracks/common-lisp)
- The [Common Lisp track's programming category on the forum](https://forum.exercism.org/c/programming/common-lisp)
- [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.

## Setup

Check out [Installing Common
Lisp][track-install] for
instructions to get started or take a look at the guides available in
the [track's documentation pages][track-docs].

## Where to look for help

Any of the resources listed in the list of [Useful Common Lisp Resources][track-resources] are good places to look for information.

There are also some [Online Communities][awesome-cl-communities] which may be good places to go for help.

## Formatting

While Common Lisp doesn't care about indentation and layout of code,
nor whether you use spaces or tabs, this is an important consideration
for submissions to exercism.
Exercism.org's code widget cannot handle mixing of tab and space characters well so using only spaces is recommended to make
the code more readable to the human reviewers.
Please review your editors settings on how to accomplish this.
Below are instructions for popular editors for Common Lisp.

### VIM

Use the following commands to ensure VIM uses only spaces for
indentation:

```vimscript
:set tabstop=2
:set shiftwidth=2
:set expandtab
```

(or as a oneliner `:set tabstop=2 shiftwidth=2 expandtab`). This can
be added to your `~/.vimrc` file to use it all the time.

### Emacs

Emacs is very well suited for editing Common Lisp and has many
powerful add-on packages available. The only thing that one needs to
do with a stock emacs to make it work well with exercism.org is to
evaluate the following code:

`(setq-default indent-tabs-mode nil)`

This can be placed in your `~/.emacs` (or `~/.emacs.d/init.el`) in
order to have it set whenever Emacs is launched.

One suggested add-on for Emacs and Common Lisp is
[SLIME][slime] which offers tight integration
with the REPL; making iterative coding and testing very easy.

## Submitting Incomplete Solutions
It's possible to submit an incomplete solution so you can ask for mentoring to help you come to the correct solution.

[awesome-cl-communities]: https://github.com/GustavBertram/awesome-common-lisp-learning#online-community
[slime]: https://github.com/slime/slime
[track-docs]: /docs/tracks/common-lisp
[track-install]: /docs/tracks/common-lisp/installation
[track-resources]: /docs/tracks/common-lisp/resources
57 changes: 57 additions & 0 deletions common-lisp/isbn-verifier/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# ISBN Verifier

Welcome to ISBN Verifier on Exercism's Common Lisp Track.
If you need help running the tests or submitting your code, check out `HELP.md`.

## Instructions

The [ISBN-10 verification process][isbn-verification] is used to validate book identification numbers.
These normally contain dashes and look like: `3-598-21508-8`

## ISBN

The ISBN-10 format is 9 digits (0 to 9) plus one check character (either a digit or an X only).
In the case the check character is an X, this represents the value '10'.
These may be communicated with or without hyphens, and can be checked for their validity by the following formula:

```text
(d₁ * 10 + d₂ * 9 + d₃ * 8 + d₄ * 7 + d₅ * 6 + d₆ * 5 + d₇ * 4 + d₈ * 3 + d₉ * 2 + d₁₀ * 1) mod 11 == 0
```

If the result is 0, then it is a valid ISBN-10, otherwise it is invalid.

## Example

Let's take the ISBN-10 `3-598-21508-8`.
We plug it in to the formula, and get:

```text
(3 * 10 + 5 * 9 + 9 * 8 + 8 * 7 + 2 * 6 + 1 * 5 + 5 * 4 + 0 * 3 + 8 * 2 + 8 * 1) mod 11 == 0
```

Since the result is 0, this proves that our ISBN is valid.

## Task

Given a string the program should check if the provided string is a valid ISBN-10.
Putting this into place requires some thinking about preprocessing/parsing of the string prior to calculating the check digit for the ISBN.

The program should be able to verify ISBN-10 both with and without separating dashes.

## Caveats

Converting from strings to numbers can be tricky in certain languages.
Now, it's even trickier since the check digit of an ISBN-10 may be 'X' (representing '10').
For instance `3-598-21507-X` is a valid ISBN-10.

[isbn-verification]: https://en.wikipedia.org/wiki/International_Standard_Book_Number

## Source

### Created by

- @PaulT89

### Based on

Converting a string into a number and some basic processing utilizing a relatable real world example. - https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation
96 changes: 96 additions & 0 deletions common-lisp/isbn-verifier/isbn-verifier-test.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
;; Ensures that isbn-verifier.lisp and the testing library are always loaded
(eval-when (:compile-toplevel :load-toplevel :execute)
(load "isbn-verifier")
(quicklisp-client:quickload :fiveam))

;; Defines the testing package with symbols from isbn-verifier and FiveAM in scope
;; The `run-tests` function is exported for use by both the user and test-runner
(defpackage :isbn-verifier-test
(:use :cl :fiveam)
(:export :run-tests))

;; Enter the testing package
(in-package :isbn-verifier-test)

;; Define and enter a new FiveAM test-suite
(def-suite* isbn-verifier-suite)

(test valid-isbn
(let ((isbn "3-598-21508-8"))
(is-true (isbn-verifier:validp isbn))))

(test invalid-isbn-check-digit
(let ((isbn "3-598-21508-9"))
(is-false (isbn-verifier:validp isbn))))

(test valid-isbn-with-a-check-digit-of-10
(let ((isbn "3-598-21507-X"))
(is-true (isbn-verifier:validp isbn))))

(test check-digit-is-a-character-other-than-x
(let ((isbn "3-598-21507-A"))
(is-false (isbn-verifier:validp isbn))))

(test invalid-check-digit-in-isbn-is-not-treated-as-zero
(let ((isbn "4-598-21507-B"))
(is-false (isbn-verifier:validp isbn))))

(test invalid-character-in-isbn-is-not-treated-as-zero
(let ((isbn "3-598-P1581-X"))
(is-false (isbn-verifier:validp isbn))))

(test x-is-only-valid-as-a-check-digit
(let ((isbn "3-598-2X507-9"))
(is-false (isbn-verifier:validp isbn))))

(test valid-isbn-without-separating-dashes
(let ((isbn "3598215088"))
(is-true (isbn-verifier:validp isbn))))

(test isbn-without-separating-dashes-and-x-as-check-digit
(let ((isbn "359821507X"))
(is-true (isbn-verifier:validp isbn))))

(test isbn-without-check-digit-and-dashes
(let ((isbn "359821507"))
(is-false (isbn-verifier:validp isbn))))

(test too-long-isbn-and-no-dashes
(let ((isbn "3598215078X"))
(is-false (isbn-verifier:validp isbn))))

(test too-short-isbn
(let ((isbn "00"))
(is-false (isbn-verifier:validp isbn))))

(test isbn-without-check-digit
(let ((isbn "3-598-21507"))
(is-false (isbn-verifier:validp isbn))))

(test check-digit-of-x-should-not-be-used-for-0
(let ((isbn "3-598-21515-X"))
(is-false (isbn-verifier:validp isbn))))

(test empty-isbn
(let ((isbn ""))
(is-false (isbn-verifier:validp isbn))))

(test input-is-9-characters
(let ((isbn "134456729"))
(is-false (isbn-verifier:validp isbn))))

(test invalid-characters-are-not-ignored-after-checking-length
(let ((isbn "3132P34035"))
(is-false (isbn-verifier:validp isbn))))

(test invalid-characters-are-not-ignored-before-checking-length
(let ((isbn "3598P215088"))
(is-false (isbn-verifier:validp isbn))))

(test input-is-too-long-but-contains-a-valid-isbn
(let ((isbn "98245726788"))
(is-false (isbn-verifier:validp isbn))))

(defun run-tests (&optional (test-or-suite 'isbn-verifier-suite))
"Provides human readable results of test run. Default to entire suite."
(run! test-or-suite))
32 changes: 32 additions & 0 deletions common-lisp/isbn-verifier/isbn-verifier.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
(defpackage :isbn-verifier
(:use :cl)
(:export :validp))

(in-package :isbn-verifier)

(define-condition invalid-character (error)
())

(defun char-to-number (c i)
(cond
((char<= #\0 c #\9)
(- (char-code c) (char-code #\0)))
((and (char-equal c #\x) (= i 10)) 10)
((char-equal c #\-) nil)
(t (error 'invalid-character))))

(defun validp (isbn)
(handler-case (loop
with i = 1
for c in (coerce isbn 'list)
for cc = (char-to-number c i)
if cc
do (incf i)
and collect cc into digits
finally (return (and (= 10 (length digits))
(zerop (mod (loop
for d in digits
for i from 10 downto 1
sum (* d i)) 11)))))
(invalid-character ()
nil)))
21 changes: 21 additions & 0 deletions common-lisp/matching-brackets/.exercism/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"authors": [
"PaulT89"
],
"contributors": [
"verdammelt"
],
"files": {
"solution": [
"matching-brackets.lisp"
],
"test": [
"matching-brackets-test.lisp"
],
"example": [
".meta/example.lisp"
]
},
"blurb": "Make sure the brackets and braces all match.",
"source": "Ginna Baker"
}
1 change: 1 addition & 0 deletions common-lisp/matching-brackets/.exercism/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"track":"common-lisp","exercise":"matching-brackets","id":"4a62f984a53c42ea8d6e4ab6ed08a8a1","url":"https://exercism.org/tracks/common-lisp/exercises/matching-brackets","handle":"wsgac","is_requester":true,"auto_approve":false}
Loading