From 93d8ddcac840692063334ba892f0f4d60e2cf667 Mon Sep 17 00:00:00 2001 From: "Khoa A. Tran" Date: Wed, 10 Jan 2018 08:23:14 +0700 Subject: [PATCH 1/6] Implement exercise hangman --- exercises/hangman/README.md | 0 exercises/hangman/example.py | 42 ++++++++++++++++ exercises/hangman/hangman.py | 14 ++++++ exercises/hangman/hangman_test.py | 80 +++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 exercises/hangman/README.md create mode 100644 exercises/hangman/example.py create mode 100644 exercises/hangman/hangman.py create mode 100644 exercises/hangman/hangman_test.py diff --git a/exercises/hangman/README.md b/exercises/hangman/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/exercises/hangman/example.py b/exercises/hangman/example.py new file mode 100644 index 00000000000..4ccaed450dc --- /dev/null +++ b/exercises/hangman/example.py @@ -0,0 +1,42 @@ +class Hangman: + def __init__(self, word): + self.remainingGuesses = 9 + self.status = 'busy' + self.word = word + self.masked_word = '' + self.guesses = [] + for i in self.word: + self.masked_word += '_' + + def guess(self ,char): + self.update_remaining_guesses(char) + self.update_masked_word() + self.update_status() + + def update_masked_word(self): + self.masked_word = '' + for i in self.word: + if i not in self.guesses: + self.masked_word += '_' + else: + self.masked_word += i + + def update_remaining_guesses(self, char): + if char not in self.word or char in self.guesses: + self.remainingGuesses -= 1 + else: + self.guesses.append(char) + + def update_status(self): + if self.masked_word == self.word: + self.status = 'win' + elif self.remainingGuesses < 0: + self.status = 'lose' + else: + self.status = 'busy' + + def get_masked_word(self): + return self.masked_word + + def get_status(self): + return self.status \ No newline at end of file diff --git a/exercises/hangman/hangman.py b/exercises/hangman/hangman.py new file mode 100644 index 00000000000..03f12eb5082 --- /dev/null +++ b/exercises/hangman/hangman.py @@ -0,0 +1,14 @@ +class Hangman(object): + def __init__(self, word): + self.remainingGuesses = 9 + self.status = 'busy' + + def guess(self, char): + pass + + def get_masked_word(self): + pass + + def get_status(self): + pass + diff --git a/exercises/hangman/hangman_test.py b/exercises/hangman/hangman_test.py new file mode 100644 index 00000000000..46f2eaeb644 --- /dev/null +++ b/exercises/hangman/hangman_test.py @@ -0,0 +1,80 @@ +import unittest + +from example import Hangman + +class HangmanTests(unittest.TestCase): + def test_initially_9_failures_are_allowed(self): + game = Hangman('foo') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + + def test_initially_no_letters_are_guessed(self): + game = Hangman('foo') + + self.assertEqual(game.get_masked_word(), '___') + + def test_after_10_failures_the_game_is_over(self): + game = Hangman('foo') + + for i in range(10): + game.guess('x') + + self.assertEqual(game.get_status(), 'lose') + + def test_feeding_a_correct_letter_removes_underscores(self): + game = Hangman('foobar') + + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + self.assertEqual(game.get_masked_word(),'___b__') + + game.guess('o') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + self.assertEqual(game.get_masked_word(),'_oob__') + + def test_feeding_a_correct_letter_twice_counts_as_a_failure(self): + game = Hangman('foobar') + + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + self.assertEqual(game.get_masked_word(),'___b__') + + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(),'___b__') + + def test_getting_all_the_letters_right_makes_for_a_win(self): + game = Hangman('hello') + + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(),'_____') + + game.guess('e') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(),'_e___') + + game.guess('l') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(),'_ell_') + + game.guess('o') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(),'_ello') + + game.guess('h') + self.assertEqual(game.get_status(), 'win') + self.assertEqual(game.get_masked_word(), 'hello') + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file From fd14531acd49978b8010445097672c6ec51d66b1 Mon Sep 17 00:00:00 2001 From: "Khoa A. Tran" Date: Wed, 10 Jan 2018 08:43:11 +0700 Subject: [PATCH 2/6] Update all files to follow PEP8 standard --- exercises/hangman/README.md | 8 +++ exercises/hangman/example.py | 70 +++++++++---------- exercises/hangman/hangman.py | 19 +++-- exercises/hangman/hangman_test.py | 112 +++++++++++++++--------------- 4 files changed, 109 insertions(+), 100 deletions(-) diff --git a/exercises/hangman/README.md b/exercises/hangman/README.md index e69de29bb2d..a69e3adbf12 100644 --- a/exercises/hangman/README.md +++ b/exercises/hangman/README.md @@ -0,0 +1,8 @@ +# Need edit +Implement the logic of the hangman game using functional reactive programming. + +Hangman is a simple word guessing game. + +Functional Reactive Programming is a way to write interactive programs. It differs from the usual perspective in that instead of saying "when the button is pressed increment the counter", you write "the value of the counter is the sum of the number of times the button is pressed." + +Implement the basic logic behind hangman using functional reactive programming. You'll need to install an FRP library for this, this will be described in the language/track specific files of the exercise. \ No newline at end of file diff --git a/exercises/hangman/example.py b/exercises/hangman/example.py index 4ccaed450dc..326d0400959 100644 --- a/exercises/hangman/example.py +++ b/exercises/hangman/example.py @@ -1,42 +1,42 @@ class Hangman: - def __init__(self, word): - self.remainingGuesses = 9 - self.status = 'busy' - self.word = word - self.masked_word = '' - self.guesses = [] - for i in self.word: - self.masked_word += '_' + def __init__(self, word): + self.remainingGuesses = 9 + self.status = 'busy' + self.word = word + self.masked_word = '' + self.guesses = [] + for i in self.word: + self.masked_word += '_' - def guess(self ,char): - self.update_remaining_guesses(char) - self.update_masked_word() - self.update_status() + def guess(self, char): + self.update_remaining_guesses(char) + self.update_masked_word() + self.update_status() - def update_masked_word(self): - self.masked_word = '' - for i in self.word: - if i not in self.guesses: - self.masked_word += '_' - else: - self.masked_word += i + def update_masked_word(self): + self.masked_word = '' + for i in self.word: + if i not in self.guesses: + self.masked_word += '_' + else: + self.masked_word += i - def update_remaining_guesses(self, char): - if char not in self.word or char in self.guesses: - self.remainingGuesses -= 1 - else: - self.guesses.append(char) + def update_remaining_guesses(self, char): + if char not in self.word or char in self.guesses: + self.remainingGuesses -= 1 + else: + self.guesses.append(char) - def update_status(self): - if self.masked_word == self.word: - self.status = 'win' - elif self.remainingGuesses < 0: - self.status = 'lose' - else: - self.status = 'busy' + def update_status(self): + if self.masked_word == self.word: + self.status = 'win' + elif self.remainingGuesses < 0: + self.status = 'lose' + else: + self.status = 'busy' - def get_masked_word(self): - return self.masked_word + def get_masked_word(self): + return self.masked_word - def get_status(self): - return self.status \ No newline at end of file + def get_status(self): + return self.status diff --git a/exercises/hangman/hangman.py b/exercises/hangman/hangman.py index 03f12eb5082..4c316f0b701 100644 --- a/exercises/hangman/hangman.py +++ b/exercises/hangman/hangman.py @@ -1,14 +1,13 @@ class Hangman(object): - def __init__(self, word): - self.remainingGuesses = 9 - self.status = 'busy' - - def guess(self, char): - pass + def __init__(self, word): + self.remainingGuesses = 9 + self.status = 'busy' - def get_masked_word(self): - pass + def guess(self, char): + pass - def get_status(self): - pass + def get_masked_word(self): + pass + def get_status(self): + pass diff --git a/exercises/hangman/hangman_test.py b/exercises/hangman/hangman_test.py index 46f2eaeb644..4394ff1725f 100644 --- a/exercises/hangman/hangman_test.py +++ b/exercises/hangman/hangman_test.py @@ -2,79 +2,81 @@ from example import Hangman + +# Adapt from c-sharp track class HangmanTests(unittest.TestCase): - def test_initially_9_failures_are_allowed(self): - game = Hangman('foo') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 9) + def test_initially_9_failures_are_allowed(self): + game = Hangman('foo') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) - def test_initially_no_letters_are_guessed(self): - game = Hangman('foo') + def test_initially_no_letters_are_guessed(self): + game = Hangman('foo') - self.assertEqual(game.get_masked_word(), '___') + self.assertEqual(game.get_masked_word(), '___') - def test_after_10_failures_the_game_is_over(self): - game = Hangman('foo') + def test_after_10_failures_the_game_is_over(self): + game = Hangman('foo') - for i in range(10): - game.guess('x') + for i in range(10): + game.guess('x') - self.assertEqual(game.get_status(), 'lose') + self.assertEqual(game.get_status(), 'lose') - def test_feeding_a_correct_letter_removes_underscores(self): - game = Hangman('foobar') + def test_feeding_a_correct_letter_removes_underscores(self): + game = Hangman('foobar') - game.guess('b') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 9) - self.assertEqual(game.get_masked_word(),'___b__') + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + self.assertEqual(game.get_masked_word(), '___b__') - game.guess('o') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 9) - self.assertEqual(game.get_masked_word(),'_oob__') + game.guess('o') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + self.assertEqual(game.get_masked_word(), '_oob__') - def test_feeding_a_correct_letter_twice_counts_as_a_failure(self): - game = Hangman('foobar') + def test_feeding_a_correct_letter_twice_counts_as_a_failure(self): + game = Hangman('foobar') - game.guess('b') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 9) - self.assertEqual(game.get_masked_word(),'___b__') + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 9) + self.assertEqual(game.get_masked_word(), '___b__') - game.guess('b') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 8) - self.assertEqual(game.get_masked_word(),'___b__') + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(), '___b__') - def test_getting_all_the_letters_right_makes_for_a_win(self): - game = Hangman('hello') + def test_getting_all_the_letters_right_makes_for_a_win(self): + game = Hangman('hello') - game.guess('b') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 8) - self.assertEqual(game.get_masked_word(),'_____') + game.guess('b') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(), '_____') - game.guess('e') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 8) - self.assertEqual(game.get_masked_word(),'_e___') + game.guess('e') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(), '_e___') - game.guess('l') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 8) - self.assertEqual(game.get_masked_word(),'_ell_') + game.guess('l') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(), '_ell_') - game.guess('o') - self.assertEqual(game.get_status(), 'busy') - self.assertEqual(game.remainingGuesses, 8) - self.assertEqual(game.get_masked_word(),'_ello') + game.guess('o') + self.assertEqual(game.get_status(), 'busy') + self.assertEqual(game.remainingGuesses, 8) + self.assertEqual(game.get_masked_word(), '_ello') - game.guess('h') - self.assertEqual(game.get_status(), 'win') - self.assertEqual(game.get_masked_word(), 'hello') + game.guess('h') + self.assertEqual(game.get_status(), 'win') + self.assertEqual(game.get_masked_word(), 'hello') if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() From 8fd9f15f0d94df03e054baa4a13445884e9aa45e Mon Sep 17 00:00:00 2001 From: "Khoa A. Tran" Date: Thu, 11 Jan 2018 17:31:15 +0700 Subject: [PATCH 3/6] update README.md - Add the text about exception and submition to README --- exercises/hangman/README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/exercises/hangman/README.md b/exercises/hangman/README.md index a69e3adbf12..088c92a4a73 100644 --- a/exercises/hangman/README.md +++ b/exercises/hangman/README.md @@ -5,4 +5,28 @@ Hangman is a simple word guessing game. Functional Reactive Programming is a way to write interactive programs. It differs from the usual perspective in that instead of saying "when the button is pressed increment the counter", you write "the value of the counter is the sum of the number of times the button is pressed." -Implement the basic logic behind hangman using functional reactive programming. You'll need to install an FRP library for this, this will be described in the language/track specific files of the exercise. \ No newline at end of file +Implement the basic logic behind hangman using functional reactive programming. You'll need to install an FRP library for this, this will be described in the language/track specific files of the exercise. + +## Exception messages + +Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to +indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not +every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include +a message. + +To raise a message with an exception, just write it as an argument to the exception type. For example, instead of +`raise Exception`, you shold write: + +```python +raise Exception("Meaningful message indicating the source of the error") +``` + + +## Submitting Exercises + +Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/` directory. + +For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit /python/bob/bob.py`. + +For more detailed information about running tests, code style and linting, +please see the [help page](http://exercism.io/languages/python). From 8639d32cf9eb0d7185014908279103e248daf1c4 Mon Sep 17 00:00:00 2001 From: "Khoa A. Tran" Date: Sun, 21 Jan 2018 16:03:45 -0600 Subject: [PATCH 4/6] Edit config for exercise Hangman and fix small bugs --- config.json | 11 +++++++++++ exercises/hangman/README.md | 3 ++- exercises/hangman/hangman_test.py | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index f2be5794644..b33d2c60ee6 100644 --- a/config.json +++ b/config.json @@ -1244,6 +1244,17 @@ "object_oriented_programming" ] }, + { + "uuid": "adad6be5-855d-4d61-b14a-22e468ba5b44", + "slug": "hangman", + "core": false, + "unlocked_by": null, + "difficulty": 5, + "topics":[ + "events", + "reactive_programming" + ] + }, { "uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd", "slug": "accumulate", diff --git a/exercises/hangman/README.md b/exercises/hangman/README.md index a69e3adbf12..6cd2f2bd7a9 100644 --- a/exercises/hangman/README.md +++ b/exercises/hangman/README.md @@ -1,4 +1,5 @@ -# Need edit +Hangman + Implement the logic of the hangman game using functional reactive programming. Hangman is a simple word guessing game. diff --git a/exercises/hangman/hangman_test.py b/exercises/hangman/hangman_test.py index 4394ff1725f..0c5f17ce424 100644 --- a/exercises/hangman/hangman_test.py +++ b/exercises/hangman/hangman_test.py @@ -1,6 +1,6 @@ import unittest -from example import Hangman +from hangman import Hangman # Adapt from c-sharp track From 09000e97d17508ef665f7e73a6e33acd04e64527 Mon Sep 17 00:00:00 2001 From: "Khoa A. Tran" Date: Tue, 23 Jan 2018 09:23:28 -0600 Subject: [PATCH 5/6] Add topic strings for hangman config --- config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index a73c5bf365c..8241df8aaa4 100644 --- a/config.json +++ b/config.json @@ -1266,7 +1266,8 @@ "difficulty": 5, "topics":[ "events", - "reactive_programming" + "reactive_programming", + "strings" ] }, { From 346237075669274dd4652b9df8b085227be213f6 Mon Sep 17 00:00:00 2001 From: "Khoa A. Tran" Date: Tue, 23 Jan 2018 09:39:39 -0600 Subject: [PATCH 6/6] Update adapt comment in test file --- exercises/hangman/hangman_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/hangman/hangman_test.py b/exercises/hangman/hangman_test.py index 0c5f17ce424..102e829fa7c 100644 --- a/exercises/hangman/hangman_test.py +++ b/exercises/hangman/hangman_test.py @@ -3,7 +3,7 @@ from hangman import Hangman -# Adapt from c-sharp track +# Tests adapted from csharp//hangman/HangmanTest.cs class HangmanTests(unittest.TestCase): def test_initially_9_failures_are_allowed(self): game = Hangman('foo')