From b001abc0553a3aacc773974a854cbbf17acf4900 Mon Sep 17 00:00:00 2001 From: Konstantin Manna Date: Wed, 1 Mar 2017 22:42:02 +0100 Subject: [PATCH] refactor exercise word-search * rewrite tests so that users have more freedom of implementation * update example-implementation to fit test-interface * reduce skeleton to minimal as discussed in #272 --- exercises/word-search/example.py | 79 ++++++------------- exercises/word-search/word_search.py | 29 +------ exercises/word-search/word_search_test.py | 94 ++++++++--------------- 3 files changed, 56 insertions(+), 146 deletions(-) diff --git a/exercises/word-search/example.py b/exercises/word-search/example.py index 405aa1f3b7..85de3ff433 100644 --- a/exercises/word-search/example.py +++ b/exercises/word-search/example.py @@ -1,57 +1,22 @@ -import copy - - -class Point(object): - def __init__(self, x, y): - self.x = x - self.y = y - - def __repr__(self): - return 'Point({}:{})'.format(self.x, self.y) - - def __add__(self, other): - return Point(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - return Point(self.x - other.x, self.y - other.y) - - def __eq__(self, other): - return self.x == other.x and self.y == other.y - - def __ne__(self, other): - return not(self == other) - - -DIRECTIONS = (Point(1, 0), Point(1, -1), Point(1, 1), Point(-1, -1), - Point(0, -1), Point(0, 1), Point(-1, 1), Point(-1, 0)) - - -class WordSearch(object): - def __init__(self, puzzle): - self.rows = puzzle.split() - self.width = len(self.rows[0]) - self.height = len(self.rows) - - def find_char(self, coordinate): - if coordinate.x < 0 or coordinate.x >= self.width: - return - if coordinate.y < 0 or coordinate.y >= self.height: - return - return self.rows[coordinate.y][coordinate.x] - - def find(self, word, position, direction): - current = copy.copy(position) - for letter in word: - if self.find_char(current) != letter: - return - current += direction - return position, current - direction - - def search(self, word): - positions = (Point(x, y) for x in range(self.width) for y in range(self.height)) - for pos in positions: - for d in DIRECTIONS: - result = self.find(word, pos, d) - if result: - return result - return None +def find_stop(row, column, word, puzzle): + directions = [(0, 1), (0, -1), (1, 0), (1, 1), (1, -1), (-1, 0), (-1, 1), (-1, -1)] + for d in directions: + row_number, column_number = row, column + for char_number, character in enumerate(word): + try: + if puzzle[row_number][column_number] != character: + break + except IndexError: + break + if char_number == len(word) - 1: + return row_number, column_number + row_number += d[0] + column_number += d[1] + + +def search(puzzle, word): + for row_number, row in enumerate(puzzle): + for column_number, character in enumerate(row): + stop = find_stop(row_number, column_number, word, puzzle) + if stop: + return (row_number, column_number), stop diff --git a/exercises/word-search/word_search.py b/exercises/word-search/word_search.py index 61fe69b21d..d856f03fcd 100644 --- a/exercises/word-search/word_search.py +++ b/exercises/word-search/word_search.py @@ -1,27 +1,2 @@ -class Point(object): - def __init__(self, x, y): - self.x = x - self.y = y - - def __repr__(self): - return 'Point({}:{})'.format(self.x, self.y) - - def __add__(self, other): - return Point(self.x + other.x, self.y + other.y) - - def __sub__(self, other): - return Point(self.x - other.x, self.y - other.y) - - def __eq__(self, other): - return self.x == other.x and self.y == other.y - - def __ne__(self, other): - return not(self == other) - - -class WordSearch(object): - def __init__(self, puzzle): - pass - - def search(self, word): - return None +def search(): + pass diff --git a/exercises/word-search/word_search_test.py b/exercises/word-search/word_search_test.py index f279638c44..776fbb8190 100644 --- a/exercises/word-search/word_search_test.py +++ b/exercises/word-search/word_search_test.py @@ -1,83 +1,53 @@ import unittest -from word_search import WordSearch, Point +from word_search import search class WordSearchTests(unittest.TestCase): - @classmethod - def setUpClass(self): - puzzle = ('jefblpepre\n' - 'camdcimgtc\n' - 'oivokprjsm\n' - 'pbwasqroua\n' - 'rixilelhrs\n' - 'wolcqlirpc\n' - 'screeaumgr\n' - 'alxhpburyi\n' - 'jalaycalmp\n' - 'clojurermt') - self.example = WordSearch(puzzle) + puzzle = ['jefblpepre', + 'camdcimgtc', + 'oivokprjsm', + 'pbwasqroua', + 'rixilelhrs', + 'wolcqlirpc', + 'screeaumgr', + 'alxhpburyi', + 'jalaycalmp', + 'clojurermt'] def test_horizontal_words_left_to_right(self): - self.assertEqual( - self.example.search('clojure'), - (Point(0, 9), Point(6, 9)) - ) + self.assertEqual(search(WordSearchTests.puzzle, 'clojure'), ((9, 0), (9, 6))) def test_horizontal_words_right_to_left(self): - self.assertEqual( - self.example.search('elixir'), - (Point(5, 4), Point(0, 4)) - ) + self.assertEqual(search(WordSearchTests.puzzle, 'elixir'), ((4, 5), (4, 0))) def test_vertical_words_top_to_bottom(self): - self.assertEqual( - self.example.search('ecmascript'), - (Point(9, 0), Point(9, 9)) - ) + self.assertEqual(search(WordSearchTests.puzzle, 'ecmascript'), ((0, 9), (9, 9))) def test_vertical_words_bottom_to_top(self): - self.assertEqual( - self.example.search('rust'), - (Point(8, 4), Point(8, 1)) - ) - - def test_diagonal_words_top_left_to_bottom_right(self): - self.assertEqual( - self.example.search('java'), - (Point(0, 0), Point(3, 3)) - ) - - def test_diagonal_upper_bottom_right_to_top_left(self): - self.assertEqual( - self.example.search('lua'), - (Point(7, 8), Point(5, 6)) - ) - - def test_diagonal_upper_bottom_left_to_top_right(self): - self.assertEqual( - self.example.search('lisp'), - (Point(2, 5), Point(5, 2)) - ) - - def test_diagonal_upper_top_right_to_bottom_left(self): - self.assertEqual( - self.example.search('ruby'), - (Point(7, 5), Point(4, 8)) - ) + self.assertEqual(search(WordSearchTests.puzzle, 'rust'), ((4, 8), (1, 8))) + + def test_diagonal_top_left_to_bottom_right(self): + self.assertEqual(search(WordSearchTests.puzzle, 'java'), ((0, 0), (3, 3))) + + def test_diagonal_bottom_right_to_top_left(self): + self.assertEqual(search(WordSearchTests.puzzle, 'lua'), ((8, 7), (6, 5))) + + def test_diagonal_bottom_left_to_top_right(self): + self.assertEqual(search(WordSearchTests.puzzle, 'lisp'), ((5, 2), (2, 5))) + + def test_diagonal_top_right_to_bottom_left(self): + self.assertEqual(search(WordSearchTests.puzzle, 'ruby'), ((5, 7), (8, 4))) def test_words_that_are_not_in_the_puzzle(self): - self.assertIsNone(self.example.search('haskell')) + self.assertIsNone(search(WordSearchTests.puzzle, 'haskell')) def test_search_differently_sized_puzzles(self): - puzzle = ('qwertyuiopz\n' - 'luamsicrexe\n' - 'abcdefghijk') - self.assertEqual( - WordSearch(puzzle).search('exercism'), - (Point(10, 1), Point(3, 1)) - ) + puzzle = ['qwertyuiopz', + 'luamsicrexe', + 'abcdefghijk'] + self.assertEqual(search(puzzle, 'exercism'), ((1, 10), (1, 3))) if __name__ == '__main__':