Skip to content

Commit 2c69c9d

Browse files
authored
Add save-the-cow, deprecating hangman (#1384)
* add `save-the-cow`, deprecating `hangman` * Pin exercise difficulty to old difficulty
1 parent 8389e3a commit 2c69c9d

11 files changed

Lines changed: 326 additions & 19 deletions

File tree

config.json

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,30 @@
19281928
],
19291929
"difficulty": 6
19301930
},
1931+
{
1932+
"slug": "save-the-cow",
1933+
"name": "Save the Cow",
1934+
"uuid": "b98a31d9-9c75-44c7-9eee-ed7be29bd52a",
1935+
"practices": [
1936+
"immutability",
1937+
"inheritance",
1938+
"members",
1939+
"sets"
1940+
],
1941+
"prerequisites": [
1942+
"chars",
1943+
"constructors",
1944+
"immutability",
1945+
"inheritance",
1946+
"members",
1947+
"numbers",
1948+
"observables",
1949+
"options",
1950+
"records",
1951+
"sets"
1952+
],
1953+
"difficulty": 8
1954+
},
19311955
{
19321956
"slug": "sublist",
19331957
"name": "Sublist",
@@ -1951,25 +1975,10 @@
19511975
"slug": "hangman",
19521976
"name": "Hangman",
19531977
"uuid": "ab0f1b66-011f-4aa3-89c5-c89427121279",
1954-
"practices": [
1955-
"immutability",
1956-
"inheritance",
1957-
"members",
1958-
"sets"
1959-
],
1960-
"prerequisites": [
1961-
"chars",
1962-
"constructors",
1963-
"immutability",
1964-
"inheritance",
1965-
"members",
1966-
"numbers",
1967-
"observables",
1968-
"options",
1969-
"records",
1970-
"sets"
1971-
],
1972-
"difficulty": 8
1978+
"practices": [],
1979+
"prerequisites": [],
1980+
"difficulty": 8,
1981+
"status": "deprecated"
19731982
},
19741983
{
19751984
"slug": "lens-person",

exercises/Exercises.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
<Project Path="practice/run-length-encoding/RunLengthEncoding.fsproj" />
125125
<Project Path="practice/saddle-points/SaddlePoints.fsproj" />
126126
<Project Path="practice/satellite/Satellite.fsproj" />
127+
<Project Path="practice/save-the-cow/SaveTheCow.fsproj" />
127128
<Project Path="practice/say/Say.fsproj" />
128129
<Project Path="practice/scale-generator/ScaleGenerator.fsproj" />
129130
<Project Path="practice/scrabble-score/ScrabbleScore.fsproj" />
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"fantomas": {
6+
"version": "6.3.15",
7+
"commands": [
8+
"fantomas"
9+
]
10+
}
11+
}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Instructions
2+
3+
Implement the logic for a word-guessing game.
4+
5+
A player tries to solve a secret word by guessing individual letters.
6+
They win if they reveal all the letters in the secret word.
7+
They lose if they make ten incorrect guesses before revealing the word.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Introduction
2+
3+
Bessie the cow has wandered onto an alien spaceship.
4+
Guess the secret door code to bring her home before the ship blasts off.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module SaveTheCow
2+
3+
open System
4+
5+
let allowedFailures = 9
6+
7+
type Progress =
8+
| Win
9+
| Lose
10+
| Busy of int
11+
12+
type State = { progress: Progress; maskedWord: string; guesses: Set<char> }
13+
14+
let updateProgress word guess (state: State) =
15+
match state.progress with
16+
| Win -> { state with progress = Win }
17+
| Lose -> { state with progress = Lose }
18+
| Busy x ->
19+
if state.maskedWord = word then
20+
{ state with progress = Win }
21+
elif x <= 0 then
22+
{ state with progress = Lose }
23+
elif not <| word.Contains(string guess) || Set.contains guess state.guesses then
24+
{ state with progress = Busy (x - 1) }
25+
else
26+
state
27+
28+
let updateMaskedWord word guess (state: State) =
29+
let updatedGuesses = Set.add guess state.guesses
30+
let updatedMaskedWord =
31+
word
32+
|> Seq.map (fun x -> if Set.contains x updatedGuesses then x else '_')
33+
|> Seq.toArray
34+
|> System.String
35+
36+
{ state with maskedWord = updatedMaskedWord }
37+
38+
let updateGuesses guess (state: State) = { state with guesses = Set.add guess state.guesses }
39+
40+
let updateState word guess (state: State) =
41+
state
42+
|> updateMaskedWord word guess
43+
|> updateProgress word guess
44+
|> updateGuesses guess
45+
46+
let mkStartState (word: string) = { progress = Busy allowedFailures; maskedWord = String('_', word.Length); guesses = Set.empty }
47+
48+
type Game(word) =
49+
let initialState = new Event<State>()
50+
let guesses = new Event<char>()
51+
let startState = mkStartState word
52+
53+
member this.States = Observable.merge initialState.Publish (Observable.scan (fun state guess -> updateState word guess state) startState guesses.Publish)
54+
member this.Start() = initialState.Trigger(startState)
55+
member this.MakeGuess(guess) = guesses.Trigger(guess)
56+
57+
let createGame word = new Game(word)
58+
let startGame (game: Game) = game.Start()
59+
let makeGuess guess (game: Game) = game.MakeGuess(guess)
60+
let statesObservable (game: Game) = game.States
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"authors": [
3+
"ErikSchierboom"
4+
],
5+
"contributors": [
6+
"BNAndras",
7+
"jrr",
8+
"lestephane",
9+
"robkeim",
10+
"valentin-p",
11+
"wolf99"
12+
],
13+
"files": {
14+
"solution": [
15+
"SaveTheCow.fs"
16+
],
17+
"test": [
18+
"SaveTheCowTests.fs"
19+
],
20+
"example": [
21+
".meta/Example.fs"
22+
],
23+
"invalidator": [
24+
"SaveTheCow.fsproj"
25+
]
26+
},
27+
"blurb": "Implement a word-guessing game."
28+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[71d340f9-fc29-4826-872e-ad7d0b83dd98]
13+
description = "Initially 9 failures are allowed and no letters are guessed"
14+
15+
[76759c24-8f1a-4fc8-9ffd-d6a1ff0cf03b]
16+
description = "After 10 failures the game is over"
17+
18+
[d6f2e202-7857-46fb-b709-43a7f3f3b2de]
19+
description = "Losing with several correct guesses"
20+
21+
[71bc0cda-2032-4637-80c8-fc8771124c08]
22+
description = "Feeding a correct letter removes underscores"
23+
24+
[5b568a1c-867d-418f-97a8-7b6f8a7ca0a2]
25+
description = "Feeding a correct letter twice counts as a failure"
26+
27+
[3d40f15b-0271-4c5d-b1a4-3e1f66ff221f]
28+
description = "Guessing a repeated letter reveals all instances"
29+
30+
[11a86435-e401-4250-a26e-3b0d8c4049ad]
31+
description = "Getting all the letters right makes for a win"
32+
33+
[b3d81876-84ee-45bb-b531-baa1b05b4709]
34+
description = "Winning on the last guess is still a win"
35+
36+
[cf204398-5e9f-402f-8bff-42cb7cbbbda9]
37+
description = "Guessing after a lose is error"
38+
39+
[c2ec5b3d-4923-4a0e-a485-6aa6e78c7ece]
40+
description = "Guessing after a win is error"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module SaveTheCow
2+
3+
// TODO: implement this module
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<RootNamespace>Exercism</RootNamespace>
6+
7+
<IsPackable>false</IsPackable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<Compile Include="SaveTheCow.fs" />
12+
<Compile Include="SaveTheCowTests.fs" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
17+
<PackageReference Include="xunit.v3" Version="3.2.2" />
18+
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" />
19+
<PackageReference Include="FsUnit.xUnit" Version="7.1.1" />
20+
</ItemGroup>
21+
22+
</Project>

0 commit comments

Comments
 (0)