Skip to content

Commit

Permalink
Add bottle-song WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
BNAndras committed Jan 7, 2024
1 parent cc01ad2 commit 3ac17f8
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ bin/configlet.exe
bin/generate-exercise
*~
.mailmap
.vscode/
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,14 @@
"prerequisites": ["arrays", "conditionals"],
"status": "beta"
},
{
"slug": "bottle-song",
"name": "Bottle Song",
"uuid": "c2070351-2096-431d-be6f-caaaa9347de6",
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "collatz-conjecture",
"name": "Collatz Conjecture",
Expand Down
57 changes: 57 additions & 0 deletions exercises/practice/bottle-song/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Instructions

Recite the lyrics to that popular children's repetitive song: Ten Green Bottles.

Note that not all verses are identical.

```text
Ten green bottles hanging on the wall,
Ten green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be nine green bottles hanging on the wall.
Nine green bottles hanging on the wall,
Nine green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be eight green bottles hanging on the wall.
Eight green bottles hanging on the wall,
Eight green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be seven green bottles hanging on the wall.
Seven green bottles hanging on the wall,
Seven green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be six green bottles hanging on the wall.
Six green bottles hanging on the wall,
Six green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be five green bottles hanging on the wall.
Five green bottles hanging on the wall,
Five green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be four green bottles hanging on the wall.
Four green bottles hanging on the wall,
Four green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be three green bottles hanging on the wall.
Three green bottles hanging on the wall,
Three green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be two green bottles hanging on the wall.
Two green bottles hanging on the wall,
Two green bottles hanging on the wall,
And if one green bottle should accidentally fall,
There'll be one green bottle hanging on the wall.
One green bottle hanging on the wall,
One green bottle hanging on the wall,
And if one green bottle should accidentally fall,
There'll be no green bottles hanging on the wall.
```
19 changes: 19 additions & 0 deletions exercises/practice/bottle-song/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"BNAndras"
],
"files": {
"solution": [
"bottle-song.lisp"
],
"test": [
"bottle-song-test.lisp"
],
"example": [
".meta/example.lisp"
]
},
"blurb": "Produce the lyrics to the popular children's repetitive song: Ten Green Bottles.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Ten_Green_Bottles"
}
45 changes: 45 additions & 0 deletions exercises/practice/bottle-song/.meta/example.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
(defpackage :bottle-song
(:use :cl)
(:export :recite))

(in-package :bottle-song)

(defparameter +quantities+
'((10 . "ten")
(9 . "nine")
(8 . "eight")
(7 . "seven")
(6 . "six")
(5 . "five")
(4 . "four")
(3 . "three")
(2 . "two")
(1 . "one")
(0 . "no")))


(defun pluralize (quantity)
(if (eq quantity 1) "bottle" "bottles"))

(defun line (index)
(let ((count (string-capitalize (cdr (assoc index +quantities+))))
(word (pluralize index)))
(format nil "~a green ~a hanging on the wall," count word)))

(defun verse (index)
(let ((word (pluralize (- index 1)))
(count (cdr (assoc (- index 1) +quantities+))))
(list (line index)
(line index)
"And if one green bottle should accidentally fall,"
(format nil "There'll be ~a green ~a hanging on the wall." count word))))

(defun recite (start-bottles take-down)
(reduce (lambda (acc line)
(if (zerop (length acc))
line
(concatenate 'string acc "\n\n" line)))
(map 'list
#'verse
(loop for n from 0 below take-down collect (- start-bottles n)))
:initial-value ""))
24 changes: 24 additions & 0 deletions exercises/practice/bottle-song/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This is an auto-generated file. Regular comments will be removed when this
# file is regenerated. Regenerating will not touch any manually added keys,
# so comments can be added in a "comment" key.

[d4ccf8fc-01dc-48c0-a201-4fbeb30f2d03]
description = "first generic verse"

[0f0aded3-472a-4c64-b842-18d4f1f5f030]
description = "last generic verse"

[f61f3c97-131f-459e-b40a-7428f3ed99d9]
description = "verse with 2 bottles"

[05eadba9-5dbd-401e-a7e8-d17cc9baa8e0]
description = "verse with 1 bottle"

[a4a28170-83d6-4dc1-bd8b-319b6abb6a80]
description = "first two verses"

[3185d438-c5ac-4ce6-bcd3-02c9ff1ed8db]
description = "last three verses"

[28c1584a-0e51-4b65-9ae2-fbc0bf4bbb28]
description = "all verses"
62 changes: 62 additions & 0 deletions exercises/practice/bottle-song/bottle-song-test.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
;; Ensures that bottle-song.lisp and the testing library are always loaded
(eval-when (:compile-toplevel :load-toplevel :execute)
(load "bottle-song")
(quicklisp-client:quickload :fiveam))

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

;; Enter the testing package
(in-package :bottle-song-test)

;; Define and enter a new FiveAM test-suite
(def-suite* bottle-song-suite)

(test first-generic-verse
(let ((start-bottles 10)
(take-down 1)
(result '("Ten green bottles hanging on the wall," "Ten green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be nine green bottles hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

(test last-generic-verse
(let ((start-bottles 3)
(take-down 1)
(result '("Three green bottles hanging on the wall," "Three green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be two green bottles hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

(test verse-with-2-bottles
(let ((start-bottles 2)
(take-down 1)
(result '("Two green bottles hanging on the wall," "Two green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be one green bottle hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

(test verse-with-1-bottle
(let ((start-bottles 1)
(take-down 1)
(result '("One green bottle hanging on the wall," "One green bottle hanging on the wall," "And if one green bottle should accidentally fall," "There'll be no green bottles hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

(test first-two-verses
(let ((start-bottles 10)
(take-down 2)
(result '("Ten green bottles hanging on the wall," "Ten green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be nine green bottles hanging on the wall." "" "Nine green bottles hanging on the wall," "Nine green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be eight green bottles hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

(test last-three-verses
(let ((start-bottles 3)
(take-down 3)
(result '("Three green bottles hanging on the wall," "Three green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be two green bottles hanging on the wall." "" "Two green bottles hanging on the wall," "Two green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be one green bottle hanging on the wall." "" "One green bottle hanging on the wall," "One green bottle hanging on the wall," "And if one green bottle should accidentally fall," "There'll be no green bottles hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

(test all-verses
(let ((start-bottles 10)
(take-down 10)
(result '("Ten green bottles hanging on the wall," "Ten green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be nine green bottles hanging on the wall." "" "Nine green bottles hanging on the wall," "Nine green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be eight green bottles hanging on the wall." "" "Eight green bottles hanging on the wall," "Eight green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be seven green bottles hanging on the wall." "" "Seven green bottles hanging on the wall," "Seven green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be six green bottles hanging on the wall." "" "Six green bottles hanging on the wall," "Six green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be five green bottles hanging on the wall." "" "Five green bottles hanging on the wall," "Five green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be four green bottles hanging on the wall." "" "Four green bottles hanging on the wall," "Four green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be three green bottles hanging on the wall." "" "Three green bottles hanging on the wall," "Three green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be two green bottles hanging on the wall." "" "Two green bottles hanging on the wall," "Two green bottles hanging on the wall," "And if one green bottle should accidentally fall," "There'll be one green bottle hanging on the wall." "" "One green bottle hanging on the wall," "One green bottle hanging on the wall," "And if one green bottle should accidentally fall," "There'll be no green bottles hanging on the wall.")))
(is (equal result (bottle-song:recite start-bottles take-down)))))

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

(in-package :bottle-song)

(defun recite (start-bottles take-down))

0 comments on commit 3ac17f8

Please sign in to comment.