Skip to content

Commit

Permalink
Adds Beers to String Concept Exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
pwadsworth committed Sep 22, 2023
1 parent 3be859e commit 7e98912
Show file tree
Hide file tree
Showing 10 changed files with 552 additions and 0 deletions.
14 changes: 14 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,20 @@
"maybe"
],
"status": "beta"
},
{
"slug": "beers",
"name": "Beers",
"uuid": "dd8967c6-4be9-44e8-8710-435cb0997c49",
"concepts": [
"strings"
],
"prerequisites": [
"lists",
"maybe",
"booleans"
],
"status": "beta"
}
],
"practice": [
Expand Down
23 changes: 23 additions & 0 deletions exercises/concept/beers/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Hints

## General

- String functions and operators are described in the [Elm documentation of the String module][string].

[string]: https://package.elm-lang.org/packages/elm/core/latest/String

## 1. Put Multiple Strings Together.

You can use a function or an operator from the `String` module to concatenate strings. Either one will get the job done.

## 2. Replace Strings

You can use functions from the `String` module to replace a string, or part of a string, with another.

## 3. Add Line-Breaks

The Unicode character for new-line is `\n`.

## 4. Recurse!

If you are having trouble making many similar verses followed by different ones, consider calling your own function again in such a way as to keep your original number of beers in scope.
46 changes: 46 additions & 0 deletions exercises/concept/beers/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Instructions

You are the new bosun of a small pirate crew that just killed their previous bosun for fowling their merriment with a bad song. As pirates would have it, your crew likes to pass the time getting loaded to the gunwales while crossing the briny deep and you are in charge of rationing the beer. The Cap'n has tasked you to minimize the number of resupply trips to make the best possible time between hauls. To achieve these conflicting requirements, and keep your crew from blowing you down when you are also loaded to the gunwales, you decide to stick to the tried-and-true 99 Bottles of Beer song using a program to help you keep the song straight and remind you to make a beer run when the ship is running low.

## 1. Return the last stanza when there are 0 beers.

Implement a `beerSongFrom` function that returns the last two verses of the beer song, in separate lines, when given the value `0`.

> No more bottles of beer on the wall, no more bottles of beer.</br>
> Go to shore to get some more, 99 bottles of beer on the wall!</br>
## 2. Return the last two stanzas when starting with 1 beer.

Refactor your `beerSongFrom` function to return the second to last stanza of the beer song when given the value `1`, followed by the rest of the song. Make sure your stanzas are properly separated by one empty line!

> 1 bottle of beer on the wall, 1 bottle of beer.</br>
> Take it down and pass it around, no more bottles of beer on the wall.<br><br>...
## 3. Return the last three stanzas when starting with 2 beers.

Refactor your `beerSongFrom` function once again to return the third to last stanza when given the value `2`, followed by the rest of the song.
> 2 bottles of beer on the wall, 2 bottles of beer.</br>
> Take one down and pass it around, 1 bottle of beer on the wall.<br><br>...
## 4. Return any number of verses with the correct ending.

Your crew is never satisfied with less than 30 beers, and you realize your poor writing skills are likely to make you foul the song if you try to write every stanza by hand. So, you decide to refactor the function one last time to make it work for any number of beers. You also want the last stanza to change to show the crew's satisfaction when they had at least 30 beers, or remind you it is time to get more beer to keep them happy if you started from less than 30.
> ... <br><br>
> 1 bottle of beer on the wall, 1 bottle of beer.</br>
> Take it down and pass it around, no more bottles of beer on the wall.
Should be followed by either

> No more bottles of beer on the wall, no more bottles of beer.</br>
> Go to the shore to get some more, 99 bottles of beer on the wall!
if they started with less than 30 beers, or

> No more bottles of beer on the wall, no more bottles of beer.</br>
> We've taken them down and passed them around; now we're all drunk and passed out!
if they had 30 beers or more.

## Present your song to the crew!

Now you feel almost ready to present your song to the crew without too much risk of being made to dance the hempen jig. But, as they are a picky bunch, make sure you remove as much duplication as possible, optimize for readability, and try to replace conditionals with `case` statements; then publish your solution. Good luck matey!
3 changes: 3 additions & 0 deletions exercises/concept/beers/.docs/introduction.md.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Introduction

%{concept: strings}
39 changes: 39 additions & 0 deletions exercises/concept/beers/.meta/Exemplar.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module Beers exposing (beerSongFrom)


beerSongFrom : Int -> String
beerSongFrom n =
let
songFrom nBeer =
case nBeer of
0 ->
if n > 30 then
"No more bottles of beer on the wall, no more bottles of beer.\n"
++ "We've taken them down and passed them around; "
++ "now we're all drunk and passed out!"

else
"No more bottles of beer on the wall, no more bottles of beer.\n"
++ "Go to shore to get some more, 99 bottles of beer on the wall!"

1 ->
"1 bottle of beer on the wall, 1 bottle of beer.\n"
++ "Take it down and pass it around, no more bottles of beer on the wall.\n"
|> next nBeer

2 ->
"2 bottles of beer on the wall, 2 bottles of beer.\n"
++ "Take one down and pass it around, 1 bottle of beer on the wall.\n"
|> next nBeer

_ ->
"{X} bottles of beer on the wall, {X} bottles of beer.\n"
++ "Take one down and pass it around, {X-1} bottles of beer on the wall.\n"
|> String.replace "{X}" (String.fromInt nBeer)
|> String.replace "{X-1}" (String.fromInt (nBeer - 1))
|> next nBeer

next nBeer songSoFar =
songSoFar ++ "\n" ++ songFrom (nBeer - 1)
in
songFrom n
18 changes: 18 additions & 0 deletions exercises/concept/beers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"authors": [
"pwadsworth"
],
"files": {
"solution": [
"src/Beers.elm"
],
"test": [
"tests/Tests.elm"
],
"exemplar": [
".meta/Exemplar.elm"
]
},

"blurb": "Learn to use Strings while merrily singing with your fellow pirates."
}
32 changes: 32 additions & 0 deletions exercises/concept/beers/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Design

## Goal

The goal of this exercise is to teach students basic string manipulation in Elm.

## Learning objectives


- Insert unicode characters in strings
- Use basic string functions
- Split and join strings
- Cut up strings
- Convert from other types


## Out of scope

- Verify Char properties
- Check for substrings
- Format a string (toUpper, toLower, trim, etc)
- Use some higher order functions

## Concepts

- `strings`

## Prerequisites

- `booleans`
- `maybe`
- `lists`
19 changes: 19 additions & 0 deletions exercises/concept/beers/elm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"elm/core": "1.0.5"
},
"indirect": {}
},
"test-dependencies": {
"direct": {
"elm-explorations/test": "2.1.0"
},
"indirect":{}
}
}
6 changes: 6 additions & 0 deletions exercises/concept/beers/src/Beers.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Beers exposing (beerSongFrom)


beerSongFrom : Int -> String
beerSongFrom n =
Debug.todo "Implement beerSongFrom"
Loading

0 comments on commit 7e98912

Please sign in to comment.