diff --git a/exercises/concept/black-jack/.meta/exemplar.py b/exercises/concept/black-jack/.meta/exemplar.py index 27c7a5dc07e..77ea78f0fe6 100644 --- a/exercises/concept/black-jack/.meta/exemplar.py +++ b/exercises/concept/black-jack/.meta/exemplar.py @@ -16,10 +16,10 @@ def value_of_card(card): 3. '2' - '10' = numerical value. """ - if card in ('JQK'): + if card in ("JQK"): value = 10 - elif card == 'A': + elif card == "A": value = 1 else: @@ -65,8 +65,8 @@ def value_of_ace(card_one, card_two): 3. '2' - '10' = numerical value. """ - card_one_value = 11 if card_one == 'A' else value_of_card(card_one) - card_two_value = 11 if card_two == 'A' else value_of_card(card_two) + card_one_value = 11 if card_one == "A" else value_of_card(card_one) + card_two_value = 11 if card_two == "A" else value_of_card(card_two) ace_value = 1 if 11 + (card_one_value + card_two_value) > 21 else 11 @@ -84,7 +84,9 @@ def is_blackjack(card_one, card_two): 3. '2' - '10' = numerical value. """ - return (card_one == 'A' or card_two == 'A') and (value_of_card(card_one) == 10 or value_of_card(card_two) == 10) + return (card_one == "A" or card_two == "A") and ( + value_of_card(card_one) == 10 or value_of_card(card_two) == 10 + ) def can_split_pairs(card_one, card_two): diff --git a/exercises/concept/black-jack/black_jack_test.py b/exercises/concept/black-jack/black_jack_test.py index 0962781f0a4..4899dc5993e 100644 --- a/exercises/concept/black-jack/black_jack_test.py +++ b/exercises/concept/black-jack/black_jack_test.py @@ -2,113 +2,169 @@ import pytest from black_jack import ( - value_of_card, - higher_card, - value_of_ace, - is_blackjack, - can_split_pairs, - can_double_down - ) + value_of_card, + higher_card, + value_of_ace, + is_blackjack, + can_split_pairs, + can_double_down, +) class BlackJackTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_value_of_card(self): - test_data = [('2', 2), ('5', 5), ('8', 8), - ('A', 1), ('10', 10), ('J', 10), - ('Q', 10), ('K', 10)] + test_data = [ + ("2", 2), + ("5", 5), + ("8", 8), + ("A", 1), + ("10", 10), + ("J", 10), + ("Q", 10), + ("K", 10), + ] for variant, (card, expected) in enumerate(test_data, 1): - with self.subTest(f'variation #{variant}', card=card, expected=expected): + with self.subTest(f"variation #{variant}", card=card, expected=expected): actual_result = value_of_card(card) - error_msg = (f'Called value_of_card({card}). ' - f'The function returned {actual_result} as the value of the {card} card, ' - f'but the test expected {expected} as the {card} card value.') + error_msg = ( + f"Called value_of_card({card}). " + f"The function returned {actual_result} as the value of the {card} card, " + f"but the test expected {expected} as the {card} card value." + ) self.assertEqual(actual_result, expected, msg=error_msg) - @pytest.mark.task(taskno=2) def test_higher_card(self): - test_data = [('A', 'A', ('A', 'A')), - ('10', 'J', ('10', 'J')), - ('3', 'A', '3'), - ('3', '6', '6'), - ('Q', '10', ('Q', '10')), - ('4', '4', ('4', '4')), - ('9', '10', '10'), - ('6', '9', '9'), - ('4', '8', '8')] + test_data = [ + ("A", "A", ("A", "A")), + ("10", "J", ("10", "J")), + ("3", "A", "3"), + ("3", "6", "6"), + ("Q", "10", ("Q", "10")), + ("4", "4", ("4", "4")), + ("9", "10", "10"), + ("6", "9", "9"), + ("4", "8", "8"), + ] for variant, (card_one, card_two, expected) in enumerate(test_data, 1): - with self.subTest(f'variation #{variant}', card_one=card_one, card_two=card_two, expected=expected): + with self.subTest( + f"variation #{variant}", + card_one=card_one, + card_two=card_two, + expected=expected, + ): actual_result = higher_card(card_one, card_two) - error_msg = (f'Called higher_card({card_one}, {card_two}). ' - f'The function returned {actual_result}, ' - f'but the test expected {expected} as the result for the cards {card_one, card_two}.') + error_msg = ( + f"Called higher_card({card_one}, {card_two}). " + f"The function returned {actual_result}, " + f"but the test expected {expected} as the result for the cards {card_one, card_two}." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=3) def test_value_of_ace(self): - test_data = [('2', '3', 11), ('3', '6', 11), ('5', '2', 11), - ('8', '2', 11), ('5', '5', 11), ('Q', 'A', 1), - ('10', '2', 1), ('7', '8', 1), ('J', '9', 1), - ('K', 'K', 1), ('2', 'A', 1), ('A', '2', 1)] + test_data = [ + ("2", "3", 11), + ("3", "6", 11), + ("5", "2", 11), + ("8", "2", 11), + ("5", "5", 11), + ("Q", "A", 1), + ("10", "2", 1), + ("7", "8", 1), + ("J", "9", 1), + ("K", "K", 1), + ("2", "A", 1), + ("A", "2", 1), + ] for variant, (card_one, card_two, ace_value) in enumerate(test_data, 1): - with self.subTest(f'variation #{variant}', card_one=card_one, card_two=card_two, ace_value=ace_value): + with self.subTest( + f"variation #{variant}", + card_one=card_one, + card_two=card_two, + ace_value=ace_value, + ): actual_result = value_of_ace(card_one, card_two) - error_msg = (f'Called value_of_ace({card_one}, {card_two}). ' - f'The function returned {actual_result}, ' - f'but the test expected {ace_value} as the value of an ace card ' - f'when the hand includes {card_one, card_two}.') + error_msg = ( + f"Called value_of_ace({card_one}, {card_two}). " + f"The function returned {actual_result}, " + f"but the test expected {ace_value} as the value of an ace card " + f"when the hand includes {card_one, card_two}." + ) - self.assertEqual(value_of_ace(card_one, card_two), ace_value, msg=error_msg) + self.assertEqual( + value_of_ace(card_one, card_two), ace_value, msg=error_msg + ) @pytest.mark.task(taskno=4) def test_is_blackjack(self): - test_data = [(('A', 'K'), True), (('10', 'A'), True), - (('10', '9'), False), (('A', 'A'), False), - (('4', '7'), False), (('9', '2'), False), - (('Q', 'K'), False)] + test_data = [ + (("A", "K"), True), + (("10", "A"), True), + (("10", "9"), False), + (("A", "A"), False), + (("4", "7"), False), + (("9", "2"), False), + (("Q", "K"), False), + ] for variant, (hand, expected) in enumerate(test_data, 1): - with self.subTest(f'variation #{variant}', hand=hand, expected=expected): + with self.subTest(f"variation #{variant}", hand=hand, expected=expected): actual_result = is_blackjack(*hand) - error_msg = (f'Called is_blackjack({hand[0]}, {hand[1]}). ' - f'The function returned {actual_result}, ' - f'but hand {hand} {"is" if expected else "is not"} a blackjack.') + error_msg = ( + f"Called is_blackjack({hand[0]}, {hand[1]}). " + f"The function returned {actual_result}, " + f'but hand {hand} {"is" if expected else "is not"} a blackjack.' + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=5) def test_can_split_pairs(self): - test_data = [(('Q', 'K'), True), (('6', '6'), True), - (('A', 'A'), True),(('10', 'A'), False), - (('10', '9'), False)] + test_data = [ + (("Q", "K"), True), + (("6", "6"), True), + (("A", "A"), True), + (("10", "A"), False), + (("10", "9"), False), + ] for variant, (hand, expected) in enumerate(test_data, 1): - with self.subTest(f'variation #{variant}', input=hand, expected=expected): + with self.subTest(f"variation #{variant}", input=hand, expected=expected): actual_result = can_split_pairs(*hand) - error_msg = (f'Called can_split_pairs({hand[0]}, {hand[1]}). ' - f'The function returned {actual_result}, ' - f'but hand {hand} {"can" if expected else "cannot"} be split into pairs.') + error_msg = ( + f"Called can_split_pairs({hand[0]}, {hand[1]}). " + f"The function returned {actual_result}, " + f'but hand {hand} {"can" if expected else "cannot"} be split into pairs.' + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=6) def test_can_double_down(self): - test_data = [(('A', '9'), True), (('K', 'A'), True), - (('4', '5'), True),(('A', 'A'), False), - (('10', '2'), False), (('10', '9'), False)] + test_data = [ + (("A", "9"), True), + (("K", "A"), True), + (("4", "5"), True), + (("A", "A"), False), + (("10", "2"), False), + (("10", "9"), False), + ] for variant, (hand, expected) in enumerate(test_data, 1): - with self.subTest(f'variation #{variant}', hand=hand, expected=expected): + with self.subTest(f"variation #{variant}", hand=hand, expected=expected): actual_result = can_double_down(*hand) - error_msg = (f'Called can_double_down({hand[0]}, {hand[1]}). ' - f'The function returned {actual_result}, ' - f'but hand {hand} {"can" if expected else "cannot"} be doubled down.') + error_msg = ( + f"Called can_double_down({hand[0]}, {hand[1]}). " + f"The function returned {actual_result}, " + f'but hand {hand} {"can" if expected else "cannot"} be doubled down.' + ) self.assertEqual(actual_result, expected, msg=error_msg) diff --git a/exercises/concept/card-games/lists_test.py b/exercises/concept/card-games/lists_test.py index e55011294ae..68266e2f2db 100644 --- a/exercises/concept/card-games/lists_test.py +++ b/exercises/concept/card-games/lists_test.py @@ -18,56 +18,99 @@ class CardGamesTest(unittest.TestCase): def test_get_rounds(self): input_data = [0, 1, 10, 27, 99, 666] - result_data = [[0, 1, 2], [1, 2, 3], - [10, 11, 12], [27, 28, 29], - [99, 100, 101], [666, 667, 668]] - - for variant, (number, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', number=number, expected=expected): + result_data = [ + [0, 1, 2], + [1, 2, 3], + [10, 11, 12], + [27, 28, 29], + [99, 100, 101], + [666, 667, 668], + ] + + for variant, (number, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", number=number, expected=expected + ): actual_result = get_rounds(number) - error_message = (f'Called get_rounds({number}). ' - f'The function returned {actual_result}, ' - f'but the tests expected rounds {expected} ' - f'given the current round {number}.') + error_message = ( + f"Called get_rounds({number}). " + f"The function returned {actual_result}, " + f"but the tests expected rounds {expected} " + f"given the current round {number}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_concatenate_rounds(self): - input_data = [([], []), ([0, 1], []), ([], [1, 2]), - ([1], [2]), ([27, 28, 29], [35, 36]), - ([1, 2, 3], [4, 5, 6])] - - result_data = [[], [0, 1], [1, 2], [1, 2], - [27, 28, 29, 35, 36], - [1, 2, 3, 4, 5, 6]] - - for variant, ((rounds_1, rounds_2), expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', rounds_1=rounds_1, rounds_2=rounds_2, expected=expected): + input_data = [ + ([], []), + ([0, 1], []), + ([], [1, 2]), + ([1], [2]), + ([27, 28, 29], [35, 36]), + ([1, 2, 3], [4, 5, 6]), + ] + + result_data = [ + [], + [0, 1], + [1, 2], + [1, 2], + [27, 28, 29, 35, 36], + [1, 2, 3, 4, 5, 6], + ] + + for variant, ((rounds_1, rounds_2), expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", + rounds_1=rounds_1, + rounds_2=rounds_2, + expected=expected, + ): actual_result = concatenate_rounds(rounds_1, rounds_2) - error_message = (f'Called concatenate_rounds({rounds_1}, {rounds_2}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} as the concatenation ' - f'of {rounds_1} and {rounds_2}.') + error_message = ( + f"Called concatenate_rounds({rounds_1}, {rounds_2}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} as the concatenation " + f"of {rounds_1} and {rounds_2}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_list_contains_round(self): - input_data = [([], 1), ([1, 2, 3], 0), - ([27, 28, 29, 35, 36], 30), - ([1], 1), ([1, 2, 3], 1), - ([27, 28, 29, 35, 36], 29)] + input_data = [ + ([], 1), + ([1, 2, 3], 0), + ([27, 28, 29, 35, 36], 30), + ([1], 1), + ([1, 2, 3], 1), + ([27, 28, 29, 35, 36], 29), + ] result_data = [False, False, False, True, True, True] - for variant, ((rounds, round_number), expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', rounds=rounds, round_number=round_number, expected=expected): + for variant, ((rounds, round_number), expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", + rounds=rounds, + round_number=round_number, + expected=expected, + ): actual_result = list_contains_round(rounds, round_number) - error_message = (f'Called list_contains_round({rounds}, {round_number}). ' - f'The function returned {actual_result}, but round {round_number} ' - f'{"is" if expected else "is not"} in {rounds}.') + error_message = ( + f"Called list_contains_round({rounds}, {round_number}). " + f"The function returned {actual_result}, but round {round_number} " + f'{"is" if expected else "is not"} in {rounds}.' + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -77,31 +120,46 @@ def test_card_average(self): input_data = [[1], [5, 6, 7], [1, 2, 3, 4], [1, 10, 100]] result_data = [1.0, 6.0, 2.5, 37.0] - for variant, (hand, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', hand=hand, expected=expected): + for variant, (hand, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", hand=hand, expected=expected): actual_result = card_average(hand) - error_message = (f'Called card_average({hand}). ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} as the average of {hand}.') + error_message = ( + f"Called card_average({hand}). " + f"The function returned {actual_result}, but " + f"the tests expected {expected} as the average of {hand}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=5) def test_approx_average_is_average(self): - input_data = [[0, 1, 5], [3, 6, 9, 12, 150], [1, 2, 3, 5, 9], - [2, 3, 4, 7, 8], [1, 2, 3], [2, 3, 4], - [2, 3, 4, 8, 8], [1, 2, 4, 5, 8]] + input_data = [ + [0, 1, 5], + [3, 6, 9, 12, 150], + [1, 2, 3, 5, 9], + [2, 3, 4, 7, 8], + [1, 2, 3], + [2, 3, 4], + [2, 3, 4, 8, 8], + [1, 2, 4, 5, 8], + ] result_data = [False, False, False, False, True, True, True, True] - for variant, (hand, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', hand=hand, expected=expected): + for variant, (hand, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", hand=hand, expected=expected): actual_result = approx_average_is_average(hand) - error_message = (f'Called approx_average_is_average({hand}). ' - f'The function returned {actual_result}, but ' - f'the hand {hand} {"does" if expected else "does not"} ' - f'yield the same approximate average.') + error_message = ( + f"Called approx_average_is_average({hand}). " + f"The function returned {actual_result}, but " + f'the hand {hand} {"does" if expected else "does not"} ' + f"yield the same approximate average." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -111,13 +169,19 @@ def test_average_even_is_average_odd(self): input_data = [[5, 6, 8], [1, 2, 3, 4], [1, 2, 3], [5, 6, 7], [1, 3, 5, 7, 9]] result_data = [False, False, True, True, True] - for variant, (input_hand, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', input_hand=input_hand, expected=expected): + for variant, (input_hand, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_hand=input_hand, expected=expected + ): actual_result = average_even_is_average_odd(input_hand) - error_message = (f'Called average_even_is_average_odd({input_hand}). ' - f'The function returned {actual_result}, but ' - f'the hand {"does" if expected else "does not"} ' - f'yield the same odd-even average.') + error_message = ( + f"Called average_even_is_average_odd({input_hand}). " + f"The function returned {actual_result}, but " + f'the hand {"does" if expected else "does not"} ' + f"yield the same odd-even average." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -127,11 +191,17 @@ def test_maybe_double_last(self): input_data = [(1, 2, 11), (5, 9, 11), (5, 9, 10), (1, 2, 3), (1, 11, 8)] result_data = [[1, 2, 22], [5, 9, 22], [5, 9, 10], [1, 2, 3], [1, 11, 8]] - for variant, (hand, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', hand=list(hand), expected=expected): + for variant, (hand, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", hand=list(hand), expected=expected + ): actual_result = maybe_double_last(list(hand)) - error_message = (f'Called maybe_double_last({list(hand)}). ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} as the maybe-doubled version of {list(hand)}.') + error_message = ( + f"Called maybe_double_last({list(hand)}). " + f"The function returned {actual_result}, but " + f"the tests expected {expected} as the maybe-doubled version of {list(hand)}." + ) self.assertEqual(actual_result, expected, msg=error_message) diff --git a/exercises/concept/cater-waiter/.meta/exemplar.py b/exercises/concept/cater-waiter/.meta/exemplar.py index 8f48c520f2e..d458dbf3eb2 100644 --- a/exercises/concept/cater-waiter/.meta/exemplar.py +++ b/exercises/concept/cater-waiter/.meta/exemplar.py @@ -1,13 +1,14 @@ """Functions for compiling dishes and ingredients for a catering company.""" - -from sets_categories_data import (VEGAN, - VEGETARIAN, - KETO, - PALEO, - OMNIVORE, - ALCOHOLS, - SPECIAL_INGREDIENTS) +from sets_categories_data import ( + VEGAN, + VEGETARIAN, + KETO, + PALEO, + OMNIVORE, + ALCOHOLS, + SPECIAL_INGREDIENTS, +) def clean_ingredients(dish_name, dish_ingredients): @@ -36,9 +37,9 @@ def check_drinks(drink_name, drink_ingredients): """ if not ALCOHOLS.isdisjoint(drink_ingredients): - return drink_name + ' Cocktail' + return drink_name + " Cocktail" - return drink_name + ' Mocktail' + return drink_name + " Mocktail" def categorize_dish(dish_name, dish_ingredients): @@ -54,15 +55,17 @@ def categorize_dish(dish_name, dish_ingredients): """ - categories = ((VEGAN, 'VEGAN'), - (VEGETARIAN, 'VEGETARIAN'), - (KETO, 'KETO'), - (PALEO, 'PALEO'), - (OMNIVORE, 'OMNIVORE')) + categories = ( + (VEGAN, "VEGAN"), + (VEGETARIAN, "VEGETARIAN"), + (KETO, "KETO"), + (PALEO, "PALEO"), + (OMNIVORE, "OMNIVORE"), + ) for category in categories: if set(dish_ingredients) <= category[0]: - return dish_name + ': ' + category[1] + return dish_name + ": " + category[1] return None diff --git a/exercises/concept/cater-waiter/sets.py b/exercises/concept/cater-waiter/sets.py index e726e3d6646..27441875951 100644 --- a/exercises/concept/cater-waiter/sets.py +++ b/exercises/concept/cater-waiter/sets.py @@ -1,13 +1,14 @@ """Functions for compiling dishes and ingredients for a catering company.""" - -from sets_categories_data import (VEGAN, - VEGETARIAN, - KETO, - PALEO, - OMNIVORE, - ALCOHOLS, - SPECIAL_INGREDIENTS) +from sets_categories_data import ( + VEGAN, + VEGETARIAN, + KETO, + PALEO, + OMNIVORE, + ALCOHOLS, + SPECIAL_INGREDIENTS, +) def clean_ingredients(dish_name, dish_ingredients): diff --git a/exercises/concept/cater-waiter/sets_categories_data.py b/exercises/concept/cater-waiter/sets_categories_data.py index dc3b1a6d7da..3b6b1324da2 100644 --- a/exercises/concept/cater-waiter/sets_categories_data.py +++ b/exercises/concept/cater-waiter/sets_categories_data.py @@ -1,212 +1,1131 @@ # pylint: disable-all # flake8: noqa, VEGAN = { - 'chives', 'nutritional yeast', 'tomato', 'orange zest', 'pareve puff pastry', 'cashews', 'tofu', - 'rice vinegar', 'black pepper', 'cardamom powder', 'mustard seeds', 'parev shortcrust pastry', - 'scallions', 'water', 'chinese eggplants', 'lemon juice', 'smoked paprika', 'cloves', 'basmati rice', - 'cayenne pepper', 'green onions', 'sunflower oil', 'mixed herbs', 'garlic paste', 'parsley', - 'fresh red chili', 'flour', 'garlic', 'oregano', 'green beans', 'harissa', 'brandy', 'fresh basil', - 'coriander', 'vinegar', 'thyme', 'coriander seeds', 'clove powder', 'pomegranate seeds', - 'sugar', 'yukon gold potato', 'sesame oil', 'cinnamon powder', 'butternut squash', 'allspice powder', - 'red pepper flakes', 'soy sauce', 'sesame seeds', 'cornstarch', 'mango powder', 'vegetable stock', - 'raisins', 'barley malt', 'olive oil', 'ground almonds', 'white rice', 'garlic powder', 'walnuts', - 'saffron powder', 'red chili powder', 'turmeric powder', 'spring onions', 'yeast', 'khmeli suneli', - 'peanuts', 'bulgur', 'cilantro', 'onion', 'calabash nutmeg', 'black-eyed peas', 'grains of selim', - 'zucchini', 'currants', 'spaghetti', 'figs', 'red bell pepper', 'lemon zest', 'ground turmeric', - 'chili flakes', 'chickpea flour', 'hing', 'slivered almonds', 'vegetable oil', 'serrano chili', - 'salt', 'yellow onions', 'salt', 'coriander powder', 'orange zest', 'garam masala', 'yellow onion', - 'smoked tofu', 'bell pepper', 'apples', 'brown sugar', 'coconut oil', 'orange juice', - 'sorghum stems', 'dried blueberries', 'tomato paste', 'curry leaves', 'vegetarian worcestershire sauce', - 'hot water', 'fresh ginger', 'firm tofu', 'eggplants', 'bell pepper', 'siracha', 'carrot', 'nigella seeds', - 'vegan butter', "za'atar", 'baking soda', 'brown sugar', 'dried cranberries', 'kosher salt', 'mangoes', - 'vegan unsweetened yoghurt', 'black peppercorn', 'vinegar', 'dill', 'barberries', 'honey', 'tomatoes', - 'yellow split peas', 'persian cucumber', 'turmeric', 'lemon', 'cumin', 'oil', 'mushrooms', 'spring onion', - 'pomegranate concentrate', 'cumin seeds', 'balsamic vinegar', 'ripe plantains', 'celeriac', 'breadcrumbs', - 'ginger', 'dried cherries', 'red onion', 'rosemary', 'chopped parsley', 'corn', 'cumin powder', 'pecans', - 'silken tofu', 'pomegranate molasses', 'carrot', 'corn flour', 'mashed potatoes' - } + "chives", + "nutritional yeast", + "tomato", + "orange zest", + "pareve puff pastry", + "cashews", + "tofu", + "rice vinegar", + "black pepper", + "cardamom powder", + "mustard seeds", + "parev shortcrust pastry", + "scallions", + "water", + "chinese eggplants", + "lemon juice", + "smoked paprika", + "cloves", + "basmati rice", + "cayenne pepper", + "green onions", + "sunflower oil", + "mixed herbs", + "garlic paste", + "parsley", + "fresh red chili", + "flour", + "garlic", + "oregano", + "green beans", + "harissa", + "brandy", + "fresh basil", + "coriander", + "vinegar", + "thyme", + "coriander seeds", + "clove powder", + "pomegranate seeds", + "sugar", + "yukon gold potato", + "sesame oil", + "cinnamon powder", + "butternut squash", + "allspice powder", + "red pepper flakes", + "soy sauce", + "sesame seeds", + "cornstarch", + "mango powder", + "vegetable stock", + "raisins", + "barley malt", + "olive oil", + "ground almonds", + "white rice", + "garlic powder", + "walnuts", + "saffron powder", + "red chili powder", + "turmeric powder", + "spring onions", + "yeast", + "khmeli suneli", + "peanuts", + "bulgur", + "cilantro", + "onion", + "calabash nutmeg", + "black-eyed peas", + "grains of selim", + "zucchini", + "currants", + "spaghetti", + "figs", + "red bell pepper", + "lemon zest", + "ground turmeric", + "chili flakes", + "chickpea flour", + "hing", + "slivered almonds", + "vegetable oil", + "serrano chili", + "salt", + "yellow onions", + "salt", + "coriander powder", + "orange zest", + "garam masala", + "yellow onion", + "smoked tofu", + "bell pepper", + "apples", + "brown sugar", + "coconut oil", + "orange juice", + "sorghum stems", + "dried blueberries", + "tomato paste", + "curry leaves", + "vegetarian worcestershire sauce", + "hot water", + "fresh ginger", + "firm tofu", + "eggplants", + "bell pepper", + "siracha", + "carrot", + "nigella seeds", + "vegan butter", + "za'atar", + "baking soda", + "brown sugar", + "dried cranberries", + "kosher salt", + "mangoes", + "vegan unsweetened yoghurt", + "black peppercorn", + "vinegar", + "dill", + "barberries", + "honey", + "tomatoes", + "yellow split peas", + "persian cucumber", + "turmeric", + "lemon", + "cumin", + "oil", + "mushrooms", + "spring onion", + "pomegranate concentrate", + "cumin seeds", + "balsamic vinegar", + "ripe plantains", + "celeriac", + "breadcrumbs", + "ginger", + "dried cherries", + "red onion", + "rosemary", + "chopped parsley", + "corn", + "cumin powder", + "pecans", + "silken tofu", + "pomegranate molasses", + "carrot", + "corn flour", + "mashed potatoes", +} VEGETARIAN = { - 'almonds', 'chives', 'limes', 'puff pastry', 'onion', 'cashews', 'red cabbage', 'red wine vinegar', - 'brussel sprouts', 'fresh corn', 'black pepper', 'lemon juice', 'roasted corn', 'eggs', - 'fresh cilantro leaves', 'shiitake mushrooms', 'sunflower oil', 'sage', 'dijon mustard', - 'blanched almonds', 'dates', 'flour', 'fresh pea tendrils', 'garlic', 'egg', 'green beans', - 'yukon gold potato', 'vermicelli noodles', 'onions', 'avocado', 'dried lasagna noodles', - 'thyme', 'cauliflower', 'basil', 'watercress', 'black beans', 'butternut squash', 'red thai chili', - 'masa', 'red chili', 'red onions', 'jalapeño chili', 'grated nutmeg', 'feta cheese', 'hazelnuts', - 'soy sauce', 'shallots', 'chipotle chili', 'vegetable bullion', 'fresh cherry tomatoes', 'olive oil', - 'milk', 'fresh cherry bocconcini', 'crema', 'marmite', 'walnuts', 'nutmeg', 'ricotta cheese', - 'chestnuts', 'mint leaves', 'lime juice', 'white wine', 'apples', 'pearl barley', 'cotija cheese', - 'zucchini', 'currants', 'leek', 'pomegranate', 'lemon zest', 'avocados', 'parmesan cheese', 'mint', - 'leeks', 'fresh artichoke hearts', 'vegetable oil', 'brazil nuts', 'red chili', 'sharp white cheddar', - 'salt', 'pepitas', 'green lentils', 'beets', 'celery', 'smoked tofu', 'fresh tomatoes', - 'puff pastry sheets', 'palm sugar', 'vegetarian fish sauce', 'oil marinated artichokes', 'hot water', - 'chickpeas', 'firm tofu', 'wombok', 'carrot', 'asparagus', 'bean sprouts', 'kosher salt', - 'pasilla chili', 'tomatillos', 'parmesan rind', 'pasta sheets', 'cream', 'butter', 'croutons', - 'lacinato kale', 'fresh or frozen fava beans', 'fresh pumpkin', 'honey', 'tomatoes', 'olives', - 'capers', 'pine nuts', 'lemon', 'cumin', 'ancho chili', 'fresh peas', 'spring roll wrappers', - 'balsamic vinegar', 'portobello mushrooms', 'breadcrumbs', 'blue cheese', 'red onion', - 'rosemary', 'pecans', 'carrot', 'corn flour', 'toasted peanuts' - } + "almonds", + "chives", + "limes", + "puff pastry", + "onion", + "cashews", + "red cabbage", + "red wine vinegar", + "brussel sprouts", + "fresh corn", + "black pepper", + "lemon juice", + "roasted corn", + "eggs", + "fresh cilantro leaves", + "shiitake mushrooms", + "sunflower oil", + "sage", + "dijon mustard", + "blanched almonds", + "dates", + "flour", + "fresh pea tendrils", + "garlic", + "egg", + "green beans", + "yukon gold potato", + "vermicelli noodles", + "onions", + "avocado", + "dried lasagna noodles", + "thyme", + "cauliflower", + "basil", + "watercress", + "black beans", + "butternut squash", + "red thai chili", + "masa", + "red chili", + "red onions", + "jalapeño chili", + "grated nutmeg", + "feta cheese", + "hazelnuts", + "soy sauce", + "shallots", + "chipotle chili", + "vegetable bullion", + "fresh cherry tomatoes", + "olive oil", + "milk", + "fresh cherry bocconcini", + "crema", + "marmite", + "walnuts", + "nutmeg", + "ricotta cheese", + "chestnuts", + "mint leaves", + "lime juice", + "white wine", + "apples", + "pearl barley", + "cotija cheese", + "zucchini", + "currants", + "leek", + "pomegranate", + "lemon zest", + "avocados", + "parmesan cheese", + "mint", + "leeks", + "fresh artichoke hearts", + "vegetable oil", + "brazil nuts", + "red chili", + "sharp white cheddar", + "salt", + "pepitas", + "green lentils", + "beets", + "celery", + "smoked tofu", + "fresh tomatoes", + "puff pastry sheets", + "palm sugar", + "vegetarian fish sauce", + "oil marinated artichokes", + "hot water", + "chickpeas", + "firm tofu", + "wombok", + "carrot", + "asparagus", + "bean sprouts", + "kosher salt", + "pasilla chili", + "tomatillos", + "parmesan rind", + "pasta sheets", + "cream", + "butter", + "croutons", + "lacinato kale", + "fresh or frozen fava beans", + "fresh pumpkin", + "honey", + "tomatoes", + "olives", + "capers", + "pine nuts", + "lemon", + "cumin", + "ancho chili", + "fresh peas", + "spring roll wrappers", + "balsamic vinegar", + "portobello mushrooms", + "breadcrumbs", + "blue cheese", + "red onion", + "rosemary", + "pecans", + "carrot", + "corn flour", + "toasted peanuts", +} PALEO = { - 'cinnamon', 'chiles de árbol', 'chives', 'limes', 'allspice', 'zucchini', 'seranno chili', 'lemon zest', - 'apple cider vinegar', 'avocados', 'cashews', 'mango', 'cilantro leaves', 'pepitas', 'white chicken', - 'chipotles', 'black pepper', 'scallions', 'pumpkin puree', 'water', 'serrano chili', 'lemon juice', - 'smoked paprika', 'homemade apricot honey preserves', 'eggs', 'salt', 'flank steak', 'fresh cilantro leaves', - 'cider vinegar', 'cloves', 'purple sweet potato', 'coconut yogurt', 'green onions', 'tilapia', - 'yellow bell pepper', 'coconut oil', 'whole chicken', 'coconut oil', 'safflower oil', 'roma tomatoes', - 'fresh red chili', 'fresh thai chili', 'shrimp', 'garlic', 'onions', 'lime', 'avocado', 'fresh parsley', - 'cauliflower', 'shredded red cabbage', 'basil', 'baking soda', 'serrano chili', - 'cherry tomatoes', 'kale', 'bacon', 'kosher salt', 'mangoes', 'lacinato kale', 'shallots', 'pineapple', - 'chipotle chili', 'white vinegar', 'honey', 'tomatoes', 'homemade tamarind concentrate', - 'mexican oregano', 'olive oil', 'pine nuts', 'garlic powder', 'coconut flour', 'green bell pepper', - 'dried apricots', 'cumin', 'nutmeg', 'kosher salt', 'onions', 'mustard seed', 'lemons', 'lime zest', - 'ground cumin', 'almond butter', 'chili powder', 'lime juice', 'paleo mayonnaise', 'pork chops', - 'cilantro', 'onion', 'red bell pepper', 'paleo parmesan cheese', 'radishes', 'avocado oil', - 'dijon mustard', 'avocado mayonnaise', 'castelfranco radicchio', 'worcestershire sauce', 'treviso' - } + "cinnamon", + "chiles de árbol", + "chives", + "limes", + "allspice", + "zucchini", + "seranno chili", + "lemon zest", + "apple cider vinegar", + "avocados", + "cashews", + "mango", + "cilantro leaves", + "pepitas", + "white chicken", + "chipotles", + "black pepper", + "scallions", + "pumpkin puree", + "water", + "serrano chili", + "lemon juice", + "smoked paprika", + "homemade apricot honey preserves", + "eggs", + "salt", + "flank steak", + "fresh cilantro leaves", + "cider vinegar", + "cloves", + "purple sweet potato", + "coconut yogurt", + "green onions", + "tilapia", + "yellow bell pepper", + "coconut oil", + "whole chicken", + "coconut oil", + "safflower oil", + "roma tomatoes", + "fresh red chili", + "fresh thai chili", + "shrimp", + "garlic", + "onions", + "lime", + "avocado", + "fresh parsley", + "cauliflower", + "shredded red cabbage", + "basil", + "baking soda", + "serrano chili", + "cherry tomatoes", + "kale", + "bacon", + "kosher salt", + "mangoes", + "lacinato kale", + "shallots", + "pineapple", + "chipotle chili", + "white vinegar", + "honey", + "tomatoes", + "homemade tamarind concentrate", + "mexican oregano", + "olive oil", + "pine nuts", + "garlic powder", + "coconut flour", + "green bell pepper", + "dried apricots", + "cumin", + "nutmeg", + "kosher salt", + "onions", + "mustard seed", + "lemons", + "lime zest", + "ground cumin", + "almond butter", + "chili powder", + "lime juice", + "paleo mayonnaise", + "pork chops", + "cilantro", + "onion", + "red bell pepper", + "paleo parmesan cheese", + "radishes", + "avocado oil", + "dijon mustard", + "avocado mayonnaise", + "castelfranco radicchio", + "worcestershire sauce", + "treviso", +} KETO = { - 'cinnamon', 'avocado oil', 'chives', 'sriacha', 'almond flour', 'crunchy peanut butter', - 'cucumbers', 'cream cheese', 'red cabbage', 'red wine vinegar', 'brussel sprouts', 'black pepper', - 'cardamom powder', 'mustard seeds', 'scallions', 'kecap manis', 'lemon juice', 'eggs', 'tahini', - 'cloves', 'green onions', 'dijon mustard', 'garlic paste', 'watermelon radishes', 'parmesan', - 'parsley', 'star anise', 'fresh cucumber', 'fresh red chili', 'shrimp', 'garlic', 'oregano', - 'fennel bulb', 'harissa', 'dutch carrot', 'fresh basil', 'avocado', 'clove powder', 'coriander seeds', - 'thyme', 'fresh parsley', 'chicken', 'cauliflower', 'basil', 'watercress', 'cinnamon powder', - 'cherry tomatoes', 'soy sauce', 'sesame seeds', 'micro cilantro', 'mozzarella cheese', 'shallots', - 'mango powder', 'chipotle chili', 'olive oil', 'spinach', 'pink peppercorns', 'coconut flour', - 'salmon steaks', 'dark soy sauce', 'red chili powder', 'turmeric powder', 'spring onions', - 'lime juice', 'ginger garlic paste', 'pork chops', 'peanuts', 'dried fenugreek leaves', 'cilantro', - 'onion', 'salmon fillets', 'toasted buckwheat', 'whole small crimini mushrooms', 'caster sugar', - 'granny smith apples', 'green cabbage', 'apple cider vinegar', 'chili flakes', 'parmesan cheese', - 'hing', 'castelfranco radicchio', 'cilantro leaves', 'fresh greek yogurt', 'roasted chicken', 'ghee', - 'flaxmeal', 'flank steak', 'salt', 'coriander powder', 'boned chicken', 'red chili flakes', - 'garam masala', 'almond meal', 'peanut oil', 'tomato paste', 'oyster sauce', - 'curry leaves', 'fresh ginger', 'cardamom', 'radishes', 'little gem lettuce heads', - 'grilled king fish', 'carrot', 'cinnamon sticks', 'heavy cream', 'asparagus', 'nigella seeds', - 'light soy sauce', 'pork belly', 'green chili', 'mangoes', 'red and green thai chili', 'butter', - 'vinegar', 'dill', 'fish sauce', 'white vinegar', 'tomatoes', 'mirin', - 'avocado mayonnaise', 'turmeric', 'lemon', 'cumin', 'fennel seeds', 'lemon juice', 'salt', - 'roasted peanuts', 'ginger', 'red onion', 'rosemary', 'cumin powder', 'cashew nuts', 'pecans', - 'green chili','whole small crimini mushrooms', 'monk fruit', 'sour cream' - } + "cinnamon", + "avocado oil", + "chives", + "sriacha", + "almond flour", + "crunchy peanut butter", + "cucumbers", + "cream cheese", + "red cabbage", + "red wine vinegar", + "brussel sprouts", + "black pepper", + "cardamom powder", + "mustard seeds", + "scallions", + "kecap manis", + "lemon juice", + "eggs", + "tahini", + "cloves", + "green onions", + "dijon mustard", + "garlic paste", + "watermelon radishes", + "parmesan", + "parsley", + "star anise", + "fresh cucumber", + "fresh red chili", + "shrimp", + "garlic", + "oregano", + "fennel bulb", + "harissa", + "dutch carrot", + "fresh basil", + "avocado", + "clove powder", + "coriander seeds", + "thyme", + "fresh parsley", + "chicken", + "cauliflower", + "basil", + "watercress", + "cinnamon powder", + "cherry tomatoes", + "soy sauce", + "sesame seeds", + "micro cilantro", + "mozzarella cheese", + "shallots", + "mango powder", + "chipotle chili", + "olive oil", + "spinach", + "pink peppercorns", + "coconut flour", + "salmon steaks", + "dark soy sauce", + "red chili powder", + "turmeric powder", + "spring onions", + "lime juice", + "ginger garlic paste", + "pork chops", + "peanuts", + "dried fenugreek leaves", + "cilantro", + "onion", + "salmon fillets", + "toasted buckwheat", + "whole small crimini mushrooms", + "caster sugar", + "granny smith apples", + "green cabbage", + "apple cider vinegar", + "chili flakes", + "parmesan cheese", + "hing", + "castelfranco radicchio", + "cilantro leaves", + "fresh greek yogurt", + "roasted chicken", + "ghee", + "flaxmeal", + "flank steak", + "salt", + "coriander powder", + "boned chicken", + "red chili flakes", + "garam masala", + "almond meal", + "peanut oil", + "tomato paste", + "oyster sauce", + "curry leaves", + "fresh ginger", + "cardamom", + "radishes", + "little gem lettuce heads", + "grilled king fish", + "carrot", + "cinnamon sticks", + "heavy cream", + "asparagus", + "nigella seeds", + "light soy sauce", + "pork belly", + "green chili", + "mangoes", + "red and green thai chili", + "butter", + "vinegar", + "dill", + "fish sauce", + "white vinegar", + "tomatoes", + "mirin", + "avocado mayonnaise", + "turmeric", + "lemon", + "cumin", + "fennel seeds", + "lemon juice", + "salt", + "roasted peanuts", + "ginger", + "red onion", + "rosemary", + "cumin powder", + "cashew nuts", + "pecans", + "green chili", + "whole small crimini mushrooms", + "monk fruit", + "sour cream", +} OMNIVORE = { - 'clams', 'prawns', 'white wine vinegar', 'date syrup', 'limes', 'tomato', 'coriander', - 'black chickpeas', 'yellow bell pepper', 'black cardamom', 'baby squid', 'pepitas', - 'red cabbage', 'baby scallops', 'green cardamom', 'black pepper', 'chaat masala', 'water', - 'lemon juice', 'tahini', 'cloves', 'white pepper', 'fennel bulbs', 'tomato puree', - 'maggi cubes', 'couscous', 'yellow mustard', 'parsley', 'sriracha', 'roma tomatoes', - 'shrimp', 'garlic', 'oregano', 'chicken wings', 'yukon gold potato', 'harissa', 'onions', - 'avocado', 'thyme', 'chicken', 'sugar', 'flat-leaf parsley', 'celery seeds', 'cherry tomatoes', - 'mayonnaise', 'scallion chutney', 'red pepper flakes', 'hazelnuts', 'soy sauce', 'sesame seeds', - 'red snapper', 'white onion', 'vegetable bullion', 'marjoram', 'pani puri', 'olive oil', 'rice', - 'serrano chili', 'tamarind concentrate', 'lime juice', 'white wine', 'beef brisket', 'cilantro', - 'onion', 'crushed red pepper flakes', 'chiles de árbol', 'fresh mint', 'zucchini', 'red bell pepper', - 'yoghurt', 'apple cider vinegar', 'parmesan cheese', 'slivered almonds', 'whole-milk yogurt', - 'anchovy fillets', 'fresh ricotta', 'mint', 'chile manzano', 'roasted chicken', 'sea salt', - 'fresh thyme', 'vegetable oil', 'salt', 'mexican crema', 'celery', 'yellow onion', - 'worcestershire sauce', 'fresh tortillas', 'tomato paste', 'oranges', 'chickpeas', - 'scotch bonnet pepper', 'shelled large shrimp', 'mussels', 'summer squash', 'salsa', - 'garlic cloves', 'fish stock', 'bell pepper', 'green bell pepper', 'carrot', 'cinnamon sticks', - 'thin sev', 'brown sugar', 'baby carrot', 'bacon', 'kosher salt', 'bay leaves', 'anaheim chili', - 'oaxaca cheese', 'butter', 'vinegar', 'crab legs', 'white vinegar', 'honey', 'tomatoes', - 'green cabbage', 'toasted bread', 'turmeric', 'lemon', 'cumin', 'black peppercorns', 'poblano chili', - 'arborio risotto rice', 'fresh corn tortillas', 'balsamic vinegar', 'rhubarb', 'ginger', - 'guajillo chile', 'filo pastry', 'leg of lamb', 'red onion', 'chipotle adobo sauce', 'rosemary', - 'chili powder', 'beer', 'carrot' - } - -SPECIAL_INGREDIENTS = {'cream','bacon', 'garlic', 'baby scallops', 'mussels', 'baby squid', 'cashews', 'salmon fillets', - 'filo pastry', 'almonds', 'milk', 'blue cheese', 'clams', 'shrimp', 'tomato puree', 'chocolate', - 'honey', 'anchovy fillets', 'bulgur', 'prawns', 'parmesan cheese', 'fish', 'shelled large shrimp', - 'gluten', 'crab legs', 'feta cheese', 'whole-milk yogurt', 'crema', 'firm tofu', 'fish stock', - 'fresh ricotta', 'tomato paste', 'fresh cherry tomatoes', 'pork chops', 'eggs', 'greek yogurt', - 'hazelnuts', 'pecans', 'brie cheese', 'oaxaca cheese', 'yellow onion', 'whey', 'silken tofu', - 'toasted bread', 'parmesan', 'beef', 'tofu', 'flour', 'tomatoes', 'red onion', 'slivered almonds', - 'strawberries', 'onions', 'pine nuts', 'cherry tomatoes', 'soy sauce', 'oyster sauce', - 'mozzarella cheese', 'roma tomatoes', 'heavy cream', 'paneer', 'pork tenderloin', 'garlic cloves', - 'swiss cheese', 'grilled king fish', 'ground almonds', 'tilapia', 'sprint onion', 'couscous', - 'walnuts', 'semolina', 'yogurt', 'cotija cheese', 'oysters', 'spaghetti', 'cheddar cheese', - 'butter', 'lobster', 'smoked tofu', 'peanuts', 'ground pork', 'fresh cherry bocconcini', - 'pork belly', 'toasted peanuts', 'roasted peanuts' - } - -ALCOHOLS = {"whiskey", "whisky", "white rum", "dark rum", "bourbon", "rye", "scotch", "vodka", - "tequila", "gin", "dry vermouth", "sweet vermouth", "prosecco","aperol", "brandy", "mezcal", - "triple sec", "coffee liqueur", "almond liqueur", "champagne", "orange curacao", "rum" - } - - -VEGAN_INTERSECTIONS = {'brown sugar', 'carrot', 'sugar', 'vegetable stock', 'fresh ginger', 'nutritional yeast', - 'cayenne pepper', 'olive oil', 'lemon', 'ginger', 'red onion', 'pomegranate molasses', - 'onion', 'water', 'chickpea flour', 'orange zest', 'coconut oil', 'smoked paprika', - 'lemon zest', 'sunflower oil', 'orange juice', 'black pepper', 'cinnamon powder', - 'mushrooms', 'cloves', 'salt', 'oil', 'vegan butter', 'turmeric', 'tomato paste', - 'mustard seeds', 'bell pepper', 'rosemary', 'vinegar', 'tomatoes', 'flour', 'soy sauce', - 'lemon juice', 'garlic'} - -VEGETARIAN_INTERSECTIONS = {'carrot', 'milk', 'basil', 'green lentils', 'vegetable bullion', 'red onions', - 'balsamic vinegar', 'lemon', 'olive oil', 'butter', 'honey', 'red chili', - 'red onion', 'breadcrumbs', 'lemon zest', 'pepitas', 'black pepper', 'fresh peas', - 'salt', 'firm tofu', 'ricotta cheese', 'kosher salt', 'watercress', 'cream', - 'parmesan cheese', 'shallots', 'rosemary', 'sage', 'tomatoes', 'walnuts', - 'lemon juice', 'thyme', 'garlic', 'eggs', 'red wine vinegar'} - -PALEO_INTERSECTIONS = {'basil', 'olive oil', 'honey', 'pine nuts', 'baking soda', 'shrimp', 'cherry tomatoes', - 'coconut oil', 'cinnamon', 'lemon zest', 'cumin', 'black pepper', 'lime', 'salt', - 'zucchini', 'kosher salt', 'chipotle chili', 'eggs', 'coconut flour', 'avocado', - 'cauliflower', 'serrano chili', 'safflower oil', 'tomatoes', 'lemon juice', 'onions', - 'garlic'} - -KETO_INTERSECTIONS = {'fresh cucumber', 'red cabbage', 'olive oil', 'ginger', 'butter', 'dill', 'red onion', - 'monk fruit', 'cherry tomatoes', 'spring onions', 'lime juice', 'fish sauce', - 'sesame seeds', 'black pepper', 'salt', 'chives', 'asparagus', 'eggs', - 'avocado mayonnaise', 'rosemary', 'cauliflower', 'flank steak', 'lemon juice', - 'garlic'} - -OMNIVORE_INTERSECTIONS = {'mint', 'carrot', 'fresh mint', 'olive oil', 'lemon', 'ginger', 'butter', 'honey', - 'leg of lamb', 'red onion', 'bay leaves', 'tamarind concentrate', - 'worcestershire sauce', 'onion', 'lime juice', 'water', 'anchovy fillets', 'celery', - 'black pepper', 'cilantro', 'chili powder', 'salt', 'mayonnaise', 'garlic cloves', - 'kosher salt', 'white onion', 'turmeric', 'rosemary', 'vinegar', 'tomatoes', - 'sea salt', 'soy sauce', 'lemon juice', 'onions', 'thyme', 'garlic', 'avocado', - 'fresh corn tortillas', 'tomato paste'} - - -EXAMPLE_INTERSECTION = {'fresh red chili', 'sugar', 'nutritional yeast', 'fresh ginger', 'red chili powder', 'garlic', - 'olive oil', 'mashed potatoes', 'garam masala', 'clove powder', 'cumin powder', 'onion', - 'chickpea flour', 'water', 'turmeric powder', 'hing', 'black pepper', 'cinnamon powder', - 'cilantro', 'salt', 'oil', 'cardamom powder', 'turmeric', 'garlic paste', 'mustard seeds', - 'vinegar', 'mangoes', 'nigella seeds', 'serrano chili', 'flour', 'soy sauce', 'coriander seeds', - 'coriander powder', 'lemon juice', 'mango powder', 'curry leaves'} + "clams", + "prawns", + "white wine vinegar", + "date syrup", + "limes", + "tomato", + "coriander", + "black chickpeas", + "yellow bell pepper", + "black cardamom", + "baby squid", + "pepitas", + "red cabbage", + "baby scallops", + "green cardamom", + "black pepper", + "chaat masala", + "water", + "lemon juice", + "tahini", + "cloves", + "white pepper", + "fennel bulbs", + "tomato puree", + "maggi cubes", + "couscous", + "yellow mustard", + "parsley", + "sriracha", + "roma tomatoes", + "shrimp", + "garlic", + "oregano", + "chicken wings", + "yukon gold potato", + "harissa", + "onions", + "avocado", + "thyme", + "chicken", + "sugar", + "flat-leaf parsley", + "celery seeds", + "cherry tomatoes", + "mayonnaise", + "scallion chutney", + "red pepper flakes", + "hazelnuts", + "soy sauce", + "sesame seeds", + "red snapper", + "white onion", + "vegetable bullion", + "marjoram", + "pani puri", + "olive oil", + "rice", + "serrano chili", + "tamarind concentrate", + "lime juice", + "white wine", + "beef brisket", + "cilantro", + "onion", + "crushed red pepper flakes", + "chiles de árbol", + "fresh mint", + "zucchini", + "red bell pepper", + "yoghurt", + "apple cider vinegar", + "parmesan cheese", + "slivered almonds", + "whole-milk yogurt", + "anchovy fillets", + "fresh ricotta", + "mint", + "chile manzano", + "roasted chicken", + "sea salt", + "fresh thyme", + "vegetable oil", + "salt", + "mexican crema", + "celery", + "yellow onion", + "worcestershire sauce", + "fresh tortillas", + "tomato paste", + "oranges", + "chickpeas", + "scotch bonnet pepper", + "shelled large shrimp", + "mussels", + "summer squash", + "salsa", + "garlic cloves", + "fish stock", + "bell pepper", + "green bell pepper", + "carrot", + "cinnamon sticks", + "thin sev", + "brown sugar", + "baby carrot", + "bacon", + "kosher salt", + "bay leaves", + "anaheim chili", + "oaxaca cheese", + "butter", + "vinegar", + "crab legs", + "white vinegar", + "honey", + "tomatoes", + "green cabbage", + "toasted bread", + "turmeric", + "lemon", + "cumin", + "black peppercorns", + "poblano chili", + "arborio risotto rice", + "fresh corn tortillas", + "balsamic vinegar", + "rhubarb", + "ginger", + "guajillo chile", + "filo pastry", + "leg of lamb", + "red onion", + "chipotle adobo sauce", + "rosemary", + "chili powder", + "beer", + "carrot", +} + +SPECIAL_INGREDIENTS = { + "cream", + "bacon", + "garlic", + "baby scallops", + "mussels", + "baby squid", + "cashews", + "salmon fillets", + "filo pastry", + "almonds", + "milk", + "blue cheese", + "clams", + "shrimp", + "tomato puree", + "chocolate", + "honey", + "anchovy fillets", + "bulgur", + "prawns", + "parmesan cheese", + "fish", + "shelled large shrimp", + "gluten", + "crab legs", + "feta cheese", + "whole-milk yogurt", + "crema", + "firm tofu", + "fish stock", + "fresh ricotta", + "tomato paste", + "fresh cherry tomatoes", + "pork chops", + "eggs", + "greek yogurt", + "hazelnuts", + "pecans", + "brie cheese", + "oaxaca cheese", + "yellow onion", + "whey", + "silken tofu", + "toasted bread", + "parmesan", + "beef", + "tofu", + "flour", + "tomatoes", + "red onion", + "slivered almonds", + "strawberries", + "onions", + "pine nuts", + "cherry tomatoes", + "soy sauce", + "oyster sauce", + "mozzarella cheese", + "roma tomatoes", + "heavy cream", + "paneer", + "pork tenderloin", + "garlic cloves", + "swiss cheese", + "grilled king fish", + "ground almonds", + "tilapia", + "sprint onion", + "couscous", + "walnuts", + "semolina", + "yogurt", + "cotija cheese", + "oysters", + "spaghetti", + "cheddar cheese", + "butter", + "lobster", + "smoked tofu", + "peanuts", + "ground pork", + "fresh cherry bocconcini", + "pork belly", + "toasted peanuts", + "roasted peanuts", +} + +ALCOHOLS = { + "whiskey", + "whisky", + "white rum", + "dark rum", + "bourbon", + "rye", + "scotch", + "vodka", + "tequila", + "gin", + "dry vermouth", + "sweet vermouth", + "prosecco", + "aperol", + "brandy", + "mezcal", + "triple sec", + "coffee liqueur", + "almond liqueur", + "champagne", + "orange curacao", + "rum", +} + + +VEGAN_INTERSECTIONS = { + "brown sugar", + "carrot", + "sugar", + "vegetable stock", + "fresh ginger", + "nutritional yeast", + "cayenne pepper", + "olive oil", + "lemon", + "ginger", + "red onion", + "pomegranate molasses", + "onion", + "water", + "chickpea flour", + "orange zest", + "coconut oil", + "smoked paprika", + "lemon zest", + "sunflower oil", + "orange juice", + "black pepper", + "cinnamon powder", + "mushrooms", + "cloves", + "salt", + "oil", + "vegan butter", + "turmeric", + "tomato paste", + "mustard seeds", + "bell pepper", + "rosemary", + "vinegar", + "tomatoes", + "flour", + "soy sauce", + "lemon juice", + "garlic", +} + +VEGETARIAN_INTERSECTIONS = { + "carrot", + "milk", + "basil", + "green lentils", + "vegetable bullion", + "red onions", + "balsamic vinegar", + "lemon", + "olive oil", + "butter", + "honey", + "red chili", + "red onion", + "breadcrumbs", + "lemon zest", + "pepitas", + "black pepper", + "fresh peas", + "salt", + "firm tofu", + "ricotta cheese", + "kosher salt", + "watercress", + "cream", + "parmesan cheese", + "shallots", + "rosemary", + "sage", + "tomatoes", + "walnuts", + "lemon juice", + "thyme", + "garlic", + "eggs", + "red wine vinegar", +} + +PALEO_INTERSECTIONS = { + "basil", + "olive oil", + "honey", + "pine nuts", + "baking soda", + "shrimp", + "cherry tomatoes", + "coconut oil", + "cinnamon", + "lemon zest", + "cumin", + "black pepper", + "lime", + "salt", + "zucchini", + "kosher salt", + "chipotle chili", + "eggs", + "coconut flour", + "avocado", + "cauliflower", + "serrano chili", + "safflower oil", + "tomatoes", + "lemon juice", + "onions", + "garlic", +} + +KETO_INTERSECTIONS = { + "fresh cucumber", + "red cabbage", + "olive oil", + "ginger", + "butter", + "dill", + "red onion", + "monk fruit", + "cherry tomatoes", + "spring onions", + "lime juice", + "fish sauce", + "sesame seeds", + "black pepper", + "salt", + "chives", + "asparagus", + "eggs", + "avocado mayonnaise", + "rosemary", + "cauliflower", + "flank steak", + "lemon juice", + "garlic", +} + +OMNIVORE_INTERSECTIONS = { + "mint", + "carrot", + "fresh mint", + "olive oil", + "lemon", + "ginger", + "butter", + "honey", + "leg of lamb", + "red onion", + "bay leaves", + "tamarind concentrate", + "worcestershire sauce", + "onion", + "lime juice", + "water", + "anchovy fillets", + "celery", + "black pepper", + "cilantro", + "chili powder", + "salt", + "mayonnaise", + "garlic cloves", + "kosher salt", + "white onion", + "turmeric", + "rosemary", + "vinegar", + "tomatoes", + "sea salt", + "soy sauce", + "lemon juice", + "onions", + "thyme", + "garlic", + "avocado", + "fresh corn tortillas", + "tomato paste", +} + + +EXAMPLE_INTERSECTION = { + "fresh red chili", + "sugar", + "nutritional yeast", + "fresh ginger", + "red chili powder", + "garlic", + "olive oil", + "mashed potatoes", + "garam masala", + "clove powder", + "cumin powder", + "onion", + "chickpea flour", + "water", + "turmeric powder", + "hing", + "black pepper", + "cinnamon powder", + "cilantro", + "salt", + "oil", + "cardamom powder", + "turmeric", + "garlic paste", + "mustard seeds", + "vinegar", + "mangoes", + "nigella seeds", + "serrano chili", + "flour", + "soy sauce", + "coriander seeds", + "coriander powder", + "lemon juice", + "mango powder", + "curry leaves", +} example_dishes = [ - {'salt', 'breadcrumbs', 'water', 'flour', 'celeriac', 'chickpea flour', 'soy sauce', 'parsley', - 'sunflower oil', 'lemon', 'black pepper'}, - - {'cornstarch', 'salt', 'vegetable oil', 'sugar', 'vegetable stock', 'water', 'tofu', 'soy sauce', - 'lemon zest', 'lemon juice', 'black pepper', 'ginger', 'garlic'}, - - {'salt', 'mixed herbs', 'silken tofu', 'smoked tofu', 'nutritional yeast', 'turmeric', 'soy sauce', - 'garlic', 'lemon juice', 'olive oil', 'black pepper', 'spaghetti'}, - - {'salt', 'mushrooms', 'sugar', 'barley malt', 'nutritional yeast', 'fresh basil', 'olive oil', - 'honey', 'yeast', 'red onion', 'bell pepper', 'cashews', 'oregano', 'rosemary', 'garlic powder', - 'tomatoes', 'water', 'flour', 'red pepper flakes', 'garlic'}, - - {'mango powder', 'oil', 'salt', 'cardamom powder', 'fresh red chili', 'sugar', 'fresh ginger', - 'turmeric', 'red chili powder', 'curry leaves', 'garlic paste', 'mustard seeds', 'vinegar', - 'mashed potatoes', 'garam masala', 'mangoes', 'nigella seeds', 'clove powder', 'serrano chili', - 'cumin powder', 'onion', 'water', 'chickpea flour', 'coriander seeds', 'turmeric powder', 'hing', - 'coriander powder', 'cinnamon powder', 'cilantro', 'garlic'}, - - {'mango powder', 'oil', 'salt', 'cardamom powder', 'fresh red chili', 'sugar', 'fresh ginger', - 'turmeric', 'red chili powder', 'curry leaves', 'garlic paste', 'mustard seeds', 'vinegar', - 'mashed potatoes', 'garam masala', 'mangoes', 'nigella seeds', 'clove powder', 'serrano chili', - 'cumin powder', 'onion', 'water', 'chickpea flour', 'coriander seeds', 'turmeric powder', 'hing', - 'coriander powder', 'cinnamon powder', 'cilantro', 'garlic'} - ] + { + "salt", + "breadcrumbs", + "water", + "flour", + "celeriac", + "chickpea flour", + "soy sauce", + "parsley", + "sunflower oil", + "lemon", + "black pepper", + }, + { + "cornstarch", + "salt", + "vegetable oil", + "sugar", + "vegetable stock", + "water", + "tofu", + "soy sauce", + "lemon zest", + "lemon juice", + "black pepper", + "ginger", + "garlic", + }, + { + "salt", + "mixed herbs", + "silken tofu", + "smoked tofu", + "nutritional yeast", + "turmeric", + "soy sauce", + "garlic", + "lemon juice", + "olive oil", + "black pepper", + "spaghetti", + }, + { + "salt", + "mushrooms", + "sugar", + "barley malt", + "nutritional yeast", + "fresh basil", + "olive oil", + "honey", + "yeast", + "red onion", + "bell pepper", + "cashews", + "oregano", + "rosemary", + "garlic powder", + "tomatoes", + "water", + "flour", + "red pepper flakes", + "garlic", + }, + { + "mango powder", + "oil", + "salt", + "cardamom powder", + "fresh red chili", + "sugar", + "fresh ginger", + "turmeric", + "red chili powder", + "curry leaves", + "garlic paste", + "mustard seeds", + "vinegar", + "mashed potatoes", + "garam masala", + "mangoes", + "nigella seeds", + "clove powder", + "serrano chili", + "cumin powder", + "onion", + "water", + "chickpea flour", + "coriander seeds", + "turmeric powder", + "hing", + "coriander powder", + "cinnamon powder", + "cilantro", + "garlic", + }, + { + "mango powder", + "oil", + "salt", + "cardamom powder", + "fresh red chili", + "sugar", + "fresh ginger", + "turmeric", + "red chili powder", + "curry leaves", + "garlic paste", + "mustard seeds", + "vinegar", + "mashed potatoes", + "garam masala", + "mangoes", + "nigella seeds", + "clove powder", + "serrano chili", + "cumin powder", + "onion", + "water", + "chickpea flour", + "coriander seeds", + "turmeric powder", + "hing", + "coriander powder", + "cinnamon powder", + "cilantro", + "garlic", + }, +] diff --git a/exercises/concept/cater-waiter/sets_test.py b/exercises/concept/cater-waiter/sets_test.py index ec93507ae65..cef1183d463 100644 --- a/exercises/concept/cater-waiter/sets_test.py +++ b/exercises/concept/cater-waiter/sets_test.py @@ -2,40 +2,46 @@ import pytest # pylint: disable=deprecated-module -from sets import (clean_ingredients, - check_drinks, - categorize_dish, - tag_special_ingredients, - compile_ingredients, - separate_appetizers, - singleton_ingredients) - - -from sets_categories_data import (VEGAN, - VEGETARIAN, - KETO, - PALEO, - OMNIVORE, - ALCOHOLS, - SPECIAL_INGREDIENTS, - VEGAN_INTERSECTIONS, - VEGETARIAN_INTERSECTIONS, - PALEO_INTERSECTIONS, - KETO_INTERSECTIONS, - OMNIVORE_INTERSECTIONS) - -from sets_test_data import (recipes_with_duplicates, - recipes_without_duplicates, - all_drinks, - drink_names, - dishes_categorized, - dishes_to_special_label, - dishes_labeled, - ingredients_only, - dishes_and_appetizers, - dishes_cleaned, - dishes_and_overlap, - singletons) +from sets import ( + clean_ingredients, + check_drinks, + categorize_dish, + tag_special_ingredients, + compile_ingredients, + separate_appetizers, + singleton_ingredients, +) + + +from sets_categories_data import ( + VEGAN, + VEGETARIAN, + KETO, + PALEO, + OMNIVORE, + ALCOHOLS, + SPECIAL_INGREDIENTS, + VEGAN_INTERSECTIONS, + VEGETARIAN_INTERSECTIONS, + PALEO_INTERSECTIONS, + KETO_INTERSECTIONS, + OMNIVORE_INTERSECTIONS, +) + +from sets_test_data import ( + recipes_with_duplicates, + recipes_without_duplicates, + all_drinks, + drink_names, + dishes_categorized, + dishes_to_special_label, + dishes_labeled, + ingredients_only, + dishes_and_appetizers, + dishes_cleaned, + dishes_and_overlap, + singletons, +) class SetsTest(unittest.TestCase): @@ -45,51 +51,86 @@ def test_clean_ingredients(self): test_data = zip(recipes_with_duplicates[::3], recipes_without_duplicates[::3]) for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", inputs="recipes with duplicated ingredients", - result="recipe ingredients de-duped"): - - error_msg = (f"Expected the ingredient list for {item[0]} to be de-duplicated, " - "but the ingredients were not cleaned as expected.") - - self.assertEqual(clean_ingredients(item[0], item[1]), (result[1], result[2]), msg=error_msg) + with self.subTest( + f"variation #{variant}", + inputs="recipes with duplicated ingredients", + result="recipe ingredients de-duped", + ): + + error_msg = ( + f"Expected the ingredient list for {item[0]} to be de-duplicated, " + "but the ingredients were not cleaned as expected." + ) + + self.assertEqual( + clean_ingredients(item[0], item[1]), + (result[1], result[2]), + msg=error_msg, + ) @pytest.mark.task(taskno=2) def test_check_drinks(self): test_data = zip(all_drinks[::2], drink_names[::2]) for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", iputs="all drinks", results="drinks classified"): + with self.subTest( + f"variation #{variant}", iputs="all drinks", results="drinks classified" + ): - error_msg = f"Expected {result} for {item}, but got something else instead." - self.assertEqual(check_drinks(item[0], item[1]), (result), msg=error_msg) + error_msg = ( + f"Expected {result} for {item}, but got something else instead." + ) + self.assertEqual( + check_drinks(item[0], item[1]), (result), msg=error_msg + ) @pytest.mark.task(taskno=3) def test_categorize_dish(self): - test_data = zip(sorted(recipes_without_duplicates, reverse=True)[::3], dishes_categorized[::3]) + test_data = zip( + sorted(recipes_without_duplicates, reverse=True)[::3], + dishes_categorized[::3], + ) for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", inputs="all recipes list", results="categorized dishes"): + with self.subTest( + f"variation #{variant}", + inputs="all recipes list", + results="categorized dishes", + ): error_message = f"Expected category {result} for {item[0]}, but got a different category instead." - self.assertEqual(categorize_dish(item[1], item[2]), (result), msg=error_message) + self.assertEqual( + categorize_dish(item[1], item[2]), (result), msg=error_message + ) @pytest.mark.task(taskno=4) def test_tag_special_ingredients(self): test_data = zip(dishes_to_special_label[::3], dishes_labeled[::3]) - for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", inputs="all recipes list", results="special ingredients tagged"): - - error_message = f"Expected {result} for {item}, but got something else instead." - self.assertEqual(tag_special_ingredients(item), (result), msg=error_message) + for variant, (item, result) in enumerate(test_data, start=1): + with self.subTest( + f"variation #{variant}", + inputs="all recipes list", + results="special ingredients tagged", + ): + + error_message = ( + f"Expected {result} for {item}, but got something else instead." + ) + self.assertEqual( + tag_special_ingredients(item), (result), msg=error_message + ) @pytest.mark.task(taskno=5) def test_compile_ingredients(self): test_data = zip(ingredients_only, [VEGAN, VEGETARIAN, PALEO, KETO, OMNIVORE]) for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", inputs="all ingredients for all recipes", - result="combined list of ingredients for all dishes"): + with self.subTest( + f"variation #{variant}", + inputs="all ingredients for all recipes", + result="combined list of ingredients for all dishes", + ): error_message = "Expected a proper set of combined ingredients, but something went wrong." self.assertEqual(compile_ingredients(item), (result), msg=error_message) @@ -99,21 +140,38 @@ def test_separate_appetizers(self): test_data = zip(dishes_and_appetizers, dishes_cleaned) for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", inputs="dishes with appetizers", results="appetizers only"): + with self.subTest( + f"variation #{variant}", + inputs="dishes with appetizers", + results="appetizers only", + ): error_message = "Expected only appetizers returned, but some dishes remain in the group." result_type_error = f"You returned {type(separate_appetizers(item[0], item[1]))}, but a list was expected." - self.assertIsInstance(separate_appetizers(item[0], item[1]), list, msg=result_type_error) - self.assertEqual(sorted(separate_appetizers(item[0], item[1])), (sorted(result)), msg=error_message) + self.assertIsInstance( + separate_appetizers(item[0], item[1]), list, msg=result_type_error + ) + self.assertEqual( + sorted(separate_appetizers(item[0], item[1])), + (sorted(result)), + msg=error_message, + ) @pytest.mark.task(taskno=7) def test_singleton_ingredients(self): test_data = zip(dishes_and_overlap, singletons) for variant, (item, result) in enumerate(test_data, start=1): - with self.subTest(f"variation #{variant}", inputs="overlapping ingredients", - results="ingredients in only one dish"): - - error_message = ("Expected only ingredients that belong to exactly " - "one dish, but got multi-dish ingredients instead.") - self.assertEqual(singleton_ingredients(item[0], item[1]), (result), msg=error_message) + with self.subTest( + f"variation #{variant}", + inputs="overlapping ingredients", + results="ingredients in only one dish", + ): + + error_message = ( + "Expected only ingredients that belong to exactly " + "one dish, but got multi-dish ingredients instead." + ) + self.assertEqual( + singleton_ingredients(item[0], item[1]), (result), msg=error_message + ) diff --git a/exercises/concept/cater-waiter/sets_test_data.py b/exercises/concept/cater-waiter/sets_test_data.py index 23a8ccd652e..4279525433b 100644 --- a/exercises/concept/cater-waiter/sets_test_data.py +++ b/exercises/concept/cater-waiter/sets_test_data.py @@ -1,208 +1,3226 @@ # pylint: disable-all # flake8: noqa, -from sets_categories_data import (VEGAN_INTERSECTIONS, - VEGETARIAN_INTERSECTIONS, - PALEO_INTERSECTIONS, - KETO_INTERSECTIONS, - OMNIVORE_INTERSECTIONS) +from sets_categories_data import ( + VEGAN_INTERSECTIONS, + VEGETARIAN_INTERSECTIONS, + PALEO_INTERSECTIONS, + KETO_INTERSECTIONS, + OMNIVORE_INTERSECTIONS, +) ################################### # Data for test_clean_ingredients # ################################### -recipes_with_duplicates = [('Kisir with Warm Pita', ['bulgur', 'pomegranate molasses', 'chopped parsley', 'lemon juice', 'tomato', 'persian cucumber', 'tomato paste', 'spring onion', 'water', 'olive oil', 'bulgur', 'bulgur', 'pomegranate molasses', 'pomegranate molasses', 'pomegranate molasses', 'chopped parsley', 'lemon juice', 'tomato', 'tomato', 'persian cucumber', 'tomato paste', 'tomato paste', 'tomato paste']), - ('Shakshuka', ['vegan unsweetened yoghurt', 'yellow onion', 'firm tofu', 'smoked paprika', 'tomatoes', 'tomato paste', 'sugar', 'cloves', 'cumin', "za'atar", 'olive oil', 'harissa', 'red bell pepper']), - ('Vegetarian Khoresh Bademjan', ['yellow split peas', 'tomato paste', 'black pepper', 'pomegranate concentrate', 'yellow onions', 'slivered almonds', 'ground turmeric', 'barberries', 'basmati rice', 'lemon juice', 'hot water', 'cayenne pepper', 'chinese eggplants', 'salt', 'orange juice', 'saffron powder', 'vegan butter', 'orange zest', 'kosher salt', 'yellow split peas', 'yellow split peas', 'tomato paste', 'tomato paste', 'tomato paste', 'black pepper']), - ('Baked Kelewele', ['smoked paprika', 'black peppercorn', 'red onion', 'grains of selim', 'cayenne pepper', 'calabash nutmeg', 'coconut oil', 'cloves', 'fresh ginger', 'salt', 'ripe plantains', 'smoked paprika', 'black peppercorn', 'black peppercorn', 'red onion', 'grains of selim', 'grains of selim', 'grains of selim']), - ('Waakye', ['baking soda', 'sorghum stems', 'coconut oil', 'black-eyed peas', 'water', 'salt', 'white rice', 'baking soda', 'baking soda', 'sorghum stems', 'sorghum stems', 'sorghum stems', 'coconut oil']), - ('Georgian Eggplant Rolls with Walnuts', ['pomegranate seeds', 'oil', 'coriander', 'garlic', 'khmeli suneli', 'eggplants', 'black pepper', 'vinegar', 'walnuts', 'water', 'salt']), - ('Burmese Tofu with Garlic, Ginger and Chili Sauce', ['soy sauce', 'oil', 'chili flakes', 'garlic', 'brown sugar', 'ginger', 'peanuts', 'rice vinegar', 'spring onions', 'water', 'turmeric', 'salt', 'chickpea flour', 'soy sauce', 'soy sauce', 'oil', 'oil', 'oil', 'chili flakes', 'garlic', 'brown sugar', 'brown sugar', 'ginger', 'peanuts', 'peanuts', 'peanuts']), - ('Celeriac Schnitzel', ['soy sauce', 'parsley', 'lemon', 'sunflower oil', 'black pepper', 'celeriac', 'breadcrumbs', 'water', 'salt', 'flour', 'chickpea flour']), - ('Sticky Lemon Tofu', ['soy sauce', 'vegetable stock', 'tofu', 'cornstarch', 'lemon juice', 'lemon zest', 'garlic', 'ginger', 'black pepper', 'sugar', 'water', 'salt', 'vegetable oil', 'soy sauce', 'soy sauce', 'vegetable stock', 'vegetable stock', 'vegetable stock', 'tofu']), - ('Vegan Carbonara', ['soy sauce', 'smoked tofu', 'lemon juice', 'nutritional yeast', 'mixed herbs', 'garlic', 'black pepper', 'silken tofu', 'turmeric', 'salt', 'olive oil', 'spaghetti', 'soy sauce', 'smoked tofu', 'smoked tofu', 'lemon juice', 'nutritional yeast', 'nutritional yeast', 'nutritional yeast']), - ('Vegan Pizza with Caramelized Onions', ['mushrooms', 'rosemary', 'garlic', 'red pepper flakes', 'yeast', 'barley malt', 'water', 'olive oil', 'garlic powder', 'oregano', 'honey', 'nutritional yeast', 'red onion', 'tomatoes', 'cashews', 'sugar', 'bell pepper', 'flour', 'salt', 'fresh basil', 'mushrooms', 'mushrooms', 'rosemary', 'rosemary', 'rosemary', 'garlic']), - ('Cheela with Spicy Mango Chutney', ['clove powder', 'oil', 'cinnamon powder', 'nigella seeds', 'curry leaves', 'coriander seeds', 'garlic', 'mangoes', 'mashed potatoes', 'cardamom powder', 'vinegar', 'water', 'mustard seeds', 'coriander powder', 'cumin powder', 'mango powder', 'garam masala', 'red chili powder', 'hing', 'garlic paste', 'turmeric powder', 'cilantro', 'sugar', 'onion', 'serrano chili', 'fresh ginger', 'turmeric', 'salt', 'fresh red chili', 'chickpea flour']), - ('Sweet and Spicy Crispy Green Beans', ['soy sauce', 'pomegranate molasses', 'sesame oil', 'green beans', 'sunflower oil', 'scallions', 'garlic', 'carrot', 'ginger', 'sesame seeds', 'tomato paste', 'bell pepper', 'siracha', 'soy sauce', 'soy sauce', 'pomegranate molasses', 'pomegranate molasses', 'pomegranate molasses', 'sesame oil', 'green beans', 'sunflower oil', 'sunflower oil', 'scallions', 'garlic', 'garlic', 'garlic']), - ('Vegan Mini Savory Mince Pies', ['mushrooms', 'cinnamon powder', 'rosemary', 'corn flour', 'ginger', 'brown sugar', 'carrot', 'black pepper', 'raisins', 'butternut squash', 'vegetarian worcestershire sauce', 'parev shortcrust pastry', 'olive oil', 'vegetable stock', 'dried cherries', 'lemon juice', 'lemon zest', 'figs', 'dried cranberries', 'apples', 'pecans', 'onion', 'orange juice', 'currants', 'dried blueberries', 'salt', 'brandy', 'orange zest', 'allspice powder']), - ('Roasted Corn and Zucchini Salad', ['green onions', 'lemon juice', 'lemon zest', 'dill', 'corn', 'tomatoes', 'black pepper', 'zucchini', 'olive oil', 'green onions', 'green onions', 'lemon juice', 'lemon juice', 'lemon juice', 'lemon zest']), - ('Golden Potato Salad', ['mustard seeds', 'cumin seeds', 'lemon juice', 'garlic', 'black pepper', 'balsamic vinegar', 'yukon gold potato', 'chives', 'turmeric', 'salt', 'olive oil', 'mustard seeds', 'cumin seeds', 'cumin seeds', 'lemon juice', 'garlic', 'garlic', 'garlic']), - ('Carrot Puff Pastry Tart', ['olive oil', 'lemon', 'lemon juice', 'pareve puff pastry', 'brown sugar', 'red onion', 'carrot', 'garlic', 'black pepper', 'thyme', 'vegan butter', 'water', 'salt', 'ground almonds', 'olive oil', 'olive oil', 'lemon', 'lemon', 'lemon', 'lemon juice']), - - ('Mushroom Lasagna', ['nutmeg', 'garlic', 'black pepper', 'onions', 'butter', 'parmesan cheese', 'portobello mushrooms', 'flour', 'dried lasagna noodles', 'olive oil', 'milk', 'kosher salt']), - ('Nut Wellington', ['sage', 'puff pastry sheets', 'hazelnuts', 'almonds', 'black pepper', 'thyme', 'marmite', 'breadcrumbs', 'walnuts', 'dates', 'eggs', 'olive oil', 'brazil nuts', 'leeks', 'chestnuts', 'cashews', 'apples', 'pecans', 'butter', 'salt', 'sage', 'sage', 'puff pastry sheets', 'puff pastry sheets', 'puff pastry sheets', 'hazelnuts', 'almonds', 'black pepper', 'black pepper', 'thyme', 'marmite', 'marmite', 'marmite']), - ('White Cheddar Scalloped Potatoes', ['shallots', 'garlic', 'cream', 'thyme', 'breadcrumbs', 'sharp white cheddar', 'yukon gold potato', 'milk', 'kosher salt']), - ('Winter Cobb Salad', ['smoked tofu', 'shiitake mushrooms', 'red wine vinegar', 'garlic', 'tomatoes', 'black pepper', 'avocados', 'blue cheese', 'onion', 'lacinato kale', 'eggs', 'olive oil', 'smoked tofu', 'smoked tofu', 'shiitake mushrooms', 'shiitake mushrooms', 'shiitake mushrooms', 'red wine vinegar']), - ('Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing', ['honey', 'lemon', 'dijon mustard', 'feta cheese', 'red wine vinegar', 'red onion', 'watercress', 'green lentils', 'currants', 'capers', 'pepitas', 'fresh pumpkin', 'olive oil', 'honey', 'lemon', 'lemon', 'dijon mustard', 'feta cheese', 'feta cheese', 'feta cheese']), - ('Cambodian-Style Vegetable Spring Rolls', ['lime juice', 'toasted peanuts', 'firm tofu', 'garlic', 'corn flour', 'bean sprouts', 'carrot', 'palm sugar', 'shallots', 'red chili', 'vermicelli noodles', 'wombok', 'soy sauce', 'sunflower oil', 'spring roll wrappers', 'vegetarian fish sauce', 'lime juice', 'lime juice', 'toasted peanuts', 'toasted peanuts', 'toasted peanuts', 'firm tofu']), - ('Summer Minestrone Cups', ['fresh peas', 'rosemary', 'garlic', 'chickpeas', 'carrot', 'leek', 'green lentils', 'red chili', 'olive oil', 'croutons', 'fresh corn', 'lemon zest', 'green beans', 'parmesan rind', 'basil', 'tomatoes', 'vegetable bullion', 'parmesan cheese', 'celery', 'mint']), - ('Fried Zucchini with Balsamic and Chili Dressing', ['honey', 'lemon juice', 'garlic', 'red onion', 'red thai chili', 'pomegranate', 'balsamic vinegar', 'mint leaves', 'zucchini', 'olive oil', 'honey', 'honey', 'lemon juice', 'lemon juice', 'lemon juice', 'garlic', 'red onion', 'red thai chili', 'red thai chili', 'pomegranate', 'balsamic vinegar', 'balsamic vinegar', 'balsamic vinegar']), - ('Barley Risotto', ['sage', 'beets', 'pearl barley', 'brussel sprouts', 'rosemary', 'garlic', 'carrot', 'red onion', 'black pepper', 'thyme', 'butternut squash', 'vegetable bullion', 'parmesan cheese', 'olive oil', 'white wine']), - ('Cherry Tomato, Watercress and Fava Bean Salad', ['fresh peas', 'fresh cherry tomatoes', 'garlic', 'watercress', 'balsamic vinegar', 'fresh or frozen fava beans', 'fresh cherry bocconcini', 'salt', 'olive oil', 'fresh peas', 'fresh peas', 'fresh cherry tomatoes', 'fresh cherry tomatoes', 'fresh cherry tomatoes', 'garlic']), - ('Fresh Garden Peas over Cauliflower Almond Puree', ['red onions', 'lemon', 'fresh peas', 'garlic', 'grated nutmeg', 'cream', 'cauliflower', 'blanched almonds', 'fresh pea tendrils', 'olive oil', 'vegetable oil', 'red onions', 'lemon', 'lemon', 'fresh peas', 'garlic', 'garlic', 'garlic']), - ('Walnut Ravioli with Artichokes and Tomatoes', ['pine nuts', 'oil marinated artichokes', 'olives', 'rosemary', 'fresh tomatoes', 'ricotta cheese', 'black pepper', 'fresh artichoke hearts', 'walnuts', 'pasta sheets', 'lemon juice', 'lemon zest', 'basil', 'red onion', 'butter', 'salt', 'pine nuts', 'pine nuts', 'oil marinated artichokes', 'oil marinated artichokes', 'oil marinated artichokes', 'olives']), - ('Asparagus Puffs', ['eggs', 'asparagus', 'lemon juice', 'red onion', 'ricotta cheese', 'black pepper', 'thyme', 'salt', 'parmesan cheese', 'puff pastry', 'chives']), - ('Grilled Tofu Tacos', ['cotija cheese', 'masa', 'fresh cilantro leaves', 'jalapeño chili', 'chipotle chili', 'firm tofu', 'garlic', 'carrot', 'roasted corn', 'tomatillos', 'pepitas', 'ancho chili', 'crema', 'red onions', 'pasilla chili', 'lemon', 'hot water', 'lemon juice', 'tomatoes', 'avocado', 'cumin', 'red cabbage', 'limes', 'black beans', 'cotija cheese', 'cotija cheese', 'masa', 'masa', 'masa', 'fresh cilantro leaves', 'jalapeño chili', 'chipotle chili', 'chipotle chili', 'firm tofu', 'garlic', 'garlic', 'garlic']), - - ('Zucchini Fritters with Lemon-Thyme Coconut Yogurt', ['baking soda', 'coconut flour', 'lemon juice', 'lemon zest', 'eggs', 'coconut yogurt', 'black pepper', 'fresh thai chili', 'coconut oil', 'chives', 'zucchini', 'salt']), - ('Avocado Deviled Eggs', ['lime juice', 'fresh cilantro leaves', 'eggs', 'seranno chili', 'avocado', 'pepitas', 'salt', 'garlic powder', 'lime juice', 'lime juice', 'fresh cilantro leaves', 'fresh cilantro leaves', 'fresh cilantro leaves', 'eggs']), - ('Grilled Flank Steak with Caesar Salad', ['pine nuts', 'white vinegar', 'chipotle chili', 'scallions', 'garlic', 'paleo parmesan cheese', 'black pepper', 'avocado oil', 'treviso', 'olive oil', 'radishes', 'flank steak', 'dijon mustard', 'castelfranco radicchio', 'worcestershire sauce', 'fresh parsley', 'cherry tomatoes', 'salt', 'avocado mayonnaise', 'pine nuts', 'white vinegar', 'white vinegar', 'chipotle chili', 'scallions', 'scallions', 'scallions']), - ('Pumpkin Bread Crostini', ['coconut flour', 'garlic', 'black pepper', 'cloves', 'eggs', 'olive oil', 'onions', 'honey', 'apple cider vinegar', 'almond butter', 'baking soda', 'nutmeg', 'pumpkin puree', 'cinnamon', 'shrimp', 'basil', 'coconut oil', 'cherry tomatoes', 'salt', 'fresh red chili', 'coconut flour', 'coconut flour', 'garlic', 'garlic', 'garlic', 'black pepper']), - ('BLT Bites', ['mustard seed', 'onion', 'kale', 'cherry tomatoes', 'bacon', 'paleo mayonnaise']), - ('Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes', ['purple sweet potato', 'chiles de árbol', 'garlic', 'tomatoes', 'safflower oil', 'black pepper', 'mexican oregano', 'avocados', 'shallots', 'cumin', 'olive oil', 'lemons', 'whole chicken', 'limes', 'kosher salt', 'purple sweet potato', 'purple sweet potato', 'chiles de árbol', 'chiles de árbol', 'chiles de árbol', 'garlic', 'tomatoes', 'safflower oil', 'safflower oil', 'black pepper', 'mexican oregano', 'mexican oregano', 'mexican oregano']), - ('Chicken with Tamarind and Apricot Sauce', ['garlic', 'black pepper', 'dried apricots', 'roma tomatoes', 'water', 'olive oil', 'honey', 'cinnamon', 'ground cumin', 'cider vinegar', 'chili powder', 'safflower oil', 'homemade tamarind concentrate', 'white chicken', 'allspice', 'chipotles', 'salt', 'homemade apricot honey preserves', 'kosher salt']), - ('Grilled Fish Tacos with Cauliflower Tortillas', ['green onions', 'serrano chili', 'shredded red cabbage', 'smoked paprika', 'mango', 'eggs', 'black pepper', 'cilantro', 'cauliflower', 'avocado', 'lime', 'cumin', 'salt', 'tilapia', 'green onions', 'green onions', 'serrano chili', 'serrano chili', 'serrano chili', 'shredded red cabbage']), - ('Grilled Pork Chops with Mango Pineapple Salsa', ['cilantro leaves', 'lime', 'pineapple', 'chipotle chili', 'garlic', 'mangoes', 'cauliflower', 'avocado', 'serrano chili', 'pork chops', 'lime zest', 'lacinato kale', 'onions', 'cilantro leaves', 'lime', 'lime', 'pineapple', 'chipotle chili', 'chipotle chili', 'chipotle chili']), - ('Grilled Shrimp and Pesto over Zucchini Noodles', ['pine nuts', 'shrimp', 'green bell pepper', 'lemon juice', 'basil', 'lemon zest', 'garlic', 'tomatoes', 'cashews', 'yellow bell pepper', 'cumin', 'zucchini', 'salt', 'olive oil', 'red bell pepper', 'pine nuts', 'pine nuts', 'shrimp', 'shrimp', 'shrimp', 'green bell pepper']), - - ('Cauliflower Pizza with Roasted Tomatoes and Chicken', ['parmesan', 'almond meal', 'rosemary', 'mozzarella cheese', 'roasted chicken', 'tomato paste', 'cauliflower', 'cherry tomatoes', 'eggs', 'fresh basil', 'olive oil']), - ('Flank Steak with Chimichurri and Asparagus', ['white vinegar', 'asparagus', 'flank steak', 'chipotle chili', 'scallions', 'garlic', 'black pepper', 'cauliflower', 'sour cream', 'fresh parsley', 'salt', 'olive oil', 'white vinegar', 'white vinegar', 'asparagus', 'asparagus', 'asparagus', 'flank steak', 'chipotle chili', 'scallions', 'scallions', 'garlic', 'black pepper', 'black pepper', 'black pepper']), - ('Kingfish Lettuce Cups', ['soy sauce', 'watermelon radishes', 'lime juice', 'fish sauce', 'mirin', 'little gem lettuce heads', 'peanut oil', 'garlic', 'sesame seeds', 'oyster sauce', 'spring onions', 'avocado', 'grilled king fish', 'red cabbage']), - ('Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', ['clove powder', 'curry leaves', 'coriander seeds', 'ginger', 'cardamom powder', 'vinegar', 'mustard seeds', 'mango powder', 'garam masala', 'red chili powder', 'chicken', 'hing', 'turmeric powder', 'tomatoes', 'ginger garlic paste', 'fresh greek yogurt', 'fresh ginger', 'monk fruit', 'turmeric', 'cashew nuts', 'salt', 'fresh red chili', 'cinnamon powder', 'nigella seeds', 'whole small crimini mushrooms', 'brussel sprouts', 'garlic', 'mangoes', 'heavy cream', 'cloves', 'coriander powder', 'cumin powder', 'cardamom', 'green chili', 'cinnamon', 'garlic paste', 'red chili flakes', 'lemon juice', 'cilantro', 'butter', 'dried fenugreek leaves', 'boned chicken', 'clove powder', 'clove powder', 'curry leaves', 'curry leaves', 'curry leaves', 'coriander seeds']), - ('Prawn and Herb Omelette', ['green onions', 'parsley', 'sesame seeds', 'black pepper', 'chives', 'eggs', 'fennel bulb', 'tahini', 'olive oil', 'harissa', 'shrimp', 'lemon juice', 'dill', 'butter', 'onion', 'fresh cucumber', 'monk fruit', 'salt', 'green onions', 'parsley', 'parsley', 'sesame seeds', 'black pepper', 'black pepper', 'black pepper']), - ('Satay Steak Skewers', ['sriacha', 'apple cider vinegar', 'lime juice', 'fish sauce', 'red and green thai chili', 'flank steak', 'carrot', 'peanuts', 'cucumbers', 'roasted peanuts', 'crunchy peanut butter', 'kecap manis', 'monk fruit', 'micro cilantro', 'olive oil', 'sriacha', 'sriacha', 'apple cider vinegar', 'apple cider vinegar', 'apple cider vinegar', 'lime juice']), - ('Parmesan Crackers and Spinach Crackers with Salmon Pate', ['spinach', 'parmesan cheese', 'coconut flour', 'chili flakes', 'garlic', 'black pepper', 'cream cheese', 'ghee', 'lemon juice', 'flaxmeal', 'red onion', 'salt', 'salmon fillets', 'pecans', 'almond flour', 'cumin', 'fresh cucumber', 'cherry tomatoes', 'chives', 'avocado mayonnaise']), - ('Pork Chops with Grilled Castelfranco Radicchio and Asparagus', ['rosemary', 'garlic', 'black pepper', 'thyme', 'avocado oil', 'eggs', 'oregano', 'asparagus', 'lemon', 'dijon mustard', 'basil', 'castelfranco radicchio', 'dill', 'butter', 'pork chops', 'monk fruit', 'salt', 'avocado mayonnaise', 'rosemary', 'rosemary', 'garlic', 'garlic', 'garlic', 'black pepper', 'thyme', 'avocado oil', 'avocado oil', 'eggs', 'oregano', 'oregano', 'oregano']), - ('Seared Salmon with Pickled Vegetable and Watercress Salad', ['lime juice', 'caster sugar', 'toasted buckwheat', 'lemon juice', 'red wine vinegar', 'red onion', 'dutch carrot', 'salmon steaks', 'watercress', 'pink peppercorns', 'shallots', 'fennel seeds', 'red cabbage', 'radishes']), - ('Braised Pork Belly with Apple Salad', ['cilantro leaves', 'green cabbage', 'lemon juice', 'pork belly', 'dark soy sauce', 'granny smith apples', 'ginger', 'light soy sauce', 'sesame seeds', 'black pepper', 'cinnamon sticks', 'spring onions', 'star anise', 'monk fruit', 'olive oil', 'cilantro leaves', 'cilantro leaves', 'green cabbage', 'green cabbage', 'green cabbage', 'lemon juice']), - - ('Beachside Snapper', ['lime juice', 'salsa', 'green bell pepper', 'anaheim chili', 'black pepper', 'olive oil', 'yellow mustard', 'red bell pepper', 'soy sauce', 'mexican crema', 'mayonnaise', 'white onion', 'garlic cloves', 'fresh corn tortillas', 'red onion', 'tomatoes', 'limes', 'worcestershire sauce', 'butter', 'yellow bell pepper', 'salt', 'red snapper', 'lime juice', 'salsa', 'salsa', 'green bell pepper', 'anaheim chili', 'anaheim chili', 'anaheim chili']), - ('Governor Shrimp Tacos', ['lime juice', 'poblano chili', 'tomato paste', 'black pepper', 'chipotle adobo sauce', 'chile manzano', 'roma tomatoes', 'pepitas', 'oaxaca cheese', 'white onion', 'shelled large shrimp', 'garlic cloves', 'fresh corn tortillas', 'red onion', 'worcestershire sauce', 'avocado', 'butter', 'kosher salt', 'lime juice', 'lime juice', 'poblano chili', 'poblano chili', 'poblano chili', 'tomato paste']), - ('Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole', ['fresh tortillas', 'shrimp', 'garlic', 'chickpeas', 'black pepper', 'slivered almonds', 'guajillo chile', 'bacon', 'sea salt', 'butter', 'onion', 'avocado', 'olive oil']), - ('Burnt Masala Wings with Classic Coleslaw', ['lime juice', 'green cabbage', 'chiles de árbol', 'green cardamom', 'ginger', 'carrot', 'sriracha', 'black pepper', 'cinnamon sticks', 'celery seeds', 'cloves', 'black cardamom', 'olive oil', 'chicken wings', 'apple cider vinegar', 'mayonnaise', 'honey', 'black peppercorns', 'lemon juice', 'garlic cloves', 'tamarind concentrate', 'cilantro', 'butter', 'serrano chili', 'red cabbage', 'kosher salt', 'lime juice', 'lime juice', 'green cabbage', 'green cabbage', 'green cabbage', 'chiles de árbol', 'green cardamom', 'ginger', 'ginger', 'carrot', 'sriracha', 'sriracha', 'sriracha']), - ('Dahi Puri with Black Chickpeas', ['whole-milk yogurt', 'chaat masala', 'ginger', 'pani puri', 'scallion chutney', 'yukon gold potato', 'black chickpeas', 'thin sev', 'date syrup', 'red onion', 'roasted chicken', 'chili powder', 'tamarind concentrate', 'cumin', 'turmeric', 'mint']), - ('Brisket with Grilled Rhubarb, Onions, and Fennel', ['white vinegar', 'parsley', 'yellow onion', 'rhubarb', 'garlic', 'brown sugar', 'black pepper', 'thyme', 'crushed red pepper flakes', 'fennel bulbs', 'beer', 'marjoram', 'vegetable oil', 'soy sauce', 'oregano', 'lemon', 'red onion', 'chili powder', 'cilantro', 'beef brisket', 'balsamic vinegar', 'worcestershire sauce', 'celery', 'mint', 'kosher salt', 'white vinegar', 'white vinegar', 'parsley', 'parsley', 'parsley', 'yellow onion']), - ('Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous', ['oranges', 'rosemary', 'garlic', 'anchovy fillets', 'couscous', 'carrot', 'sesame seeds', 'fresh thyme', 'vinegar', 'olive oil', 'tahini', 'harissa', 'onions', 'honey', 'fresh mint', 'leg of lamb', 'tomatoes', 'baby carrot', 'vegetable bullion', 'filo pastry', 'celery', 'bay leaves', 'yoghurt', 'oranges', 'rosemary', 'rosemary', 'garlic', 'anchovy fillets', 'anchovy fillets', 'anchovy fillets']), - ('Baked Chicken Jollof Rice', ['tomato puree', 'garlic', 'ginger', 'tomato', 'carrot', 'thyme', 'white pepper', 'water', 'maggi cubes', 'chicken', 'rice', 'coriander', 'scotch bonnet pepper', 'bell pepper', 'onion', 'turmeric', 'salt', 'tomato puree', 'tomato puree', 'garlic', 'garlic', 'garlic', 'ginger']), - ('Seafood Risotto', ['garlic', 'tomato paste', 'baby scallops', 'mussels', 'water', 'crab legs', 'olive oil', 'baby squid', 'fish stock', 'lemon juice', 'white onion', 'arborio risotto rice', 'clams', 'parmesan cheese', 'flat-leaf parsley', 'cherry tomatoes', 'prawns', 'white wine']), - ('Lamb over Marinated Summer Squash with Hazelnuts and Ricotta', ['toasted bread', 'rosemary', 'hazelnuts', 'anchovy fillets', 'garlic', 'carrot', 'summer squash', 'black pepper', 'red pepper flakes', 'vinegar', 'sea salt', 'zucchini', 'olive oil', 'onions', 'white wine vinegar', 'fresh mint', 'leg of lamb', 'lemon', 'fresh ricotta', 'sugar', 'celery', 'bay leaves', 'kosher salt', 'toasted bread', 'toasted bread', 'rosemary', 'rosemary', 'rosemary', 'hazelnuts', 'anchovy fillets', 'garlic', 'garlic', 'carrot', 'summer squash', 'summer squash', 'summer squash']) - ] - -recipes_without_duplicates = [('kisir_with_warm_pita', 'Kisir with Warm Pita', {'water', 'chopped parsley', 'pomegranate molasses', 'spring onion', 'lemon juice', 'olive oil', 'bulgur', 'tomato paste', 'tomato', 'persian cucumber'}), - ('shakshuka', 'Shakshuka', {'smoked paprika', 'tomatoes', 'cumin', 'firm tofu', 'olive oil', 'harissa', 'yellow onion', 'sugar', "za'atar", 'tomato paste', 'cloves', 'red bell pepper', 'vegan unsweetened yoghurt'}), - ('vegetarian_khoresh_bademjan', 'Vegetarian Khoresh Bademjan', {'pomegranate concentrate', 'saffron powder', 'cayenne pepper', 'barberries', 'salt', 'yellow onions', 'yellow split peas', 'slivered almonds', 'ground turmeric', 'orange zest', 'lemon juice', 'kosher salt', 'hot water', 'basmati rice', 'black pepper', 'orange juice', 'tomato paste', 'vegan butter', 'chinese eggplants'}), - ('baked_kelewele', 'Baked Kelewele', {'salt', 'coconut oil', 'smoked paprika', 'cayenne pepper', 'red onion', 'fresh ginger', 'calabash nutmeg', 'grains of selim', 'black peppercorn', 'cloves', 'ripe plantains'}), - ('waakye', 'Waakye', {'salt', 'coconut oil', 'water', 'white rice', 'sorghum stems', 'black-eyed peas', 'baking soda'}), - ('georgian_eggplant_rolls_with_walnuts', 'Georgian Eggplant Rolls with Walnuts', {'salt', 'coriander', 'pomegranate seeds', 'oil', 'water', 'vinegar', 'garlic', 'eggplants', 'black pepper', 'khmeli suneli', 'walnuts'}), - ('burmese_tofu_with_garlic,_ginger_and_chili_sauce', 'Burmese Tofu with Garlic, Ginger and Chili Sauce', {'salt', 'rice vinegar', 'oil', 'water', 'turmeric', 'chili flakes', 'spring onions', 'brown sugar', 'garlic', 'chickpea flour', 'ginger', 'soy sauce', 'peanuts'}), - ('celeriac_schnitzel', 'Celeriac Schnitzel', {'salt', 'parsley', 'water', 'sunflower oil', 'flour', 'breadcrumbs', 'lemon', 'celeriac', 'chickpea flour', 'soy sauce', 'black pepper'}), - ('sticky_lemon_tofu', 'Sticky Lemon Tofu', {'salt', 'water', 'tofu', 'cornstarch', 'vegetable stock', 'vegetable oil', 'lemon juice', 'garlic', 'black pepper', 'ginger', 'soy sauce', 'sugar', 'lemon zest'}), - ('vegan_carbonara', 'Vegan Carbonara', {'salt', 'turmeric', 'spaghetti', 'lemon juice', 'olive oil', 'garlic', 'black pepper', 'nutritional yeast', 'soy sauce', 'smoked tofu', 'silken tofu', 'mixed herbs'}), - ('vegan_pizza_with_caramelized_onions', 'Vegan Pizza with Caramelized Onions', {'red pepper flakes', 'garlic', 'cashews', 'fresh basil', 'flour', 'tomatoes', 'red onion', 'oregano', 'nutritional yeast', 'rosemary', 'water', 'bell pepper', 'honey', 'barley malt', 'olive oil', 'salt', 'garlic powder', 'mushrooms', 'yeast', 'sugar'}), - ('cheela_with_spicy_mango_chutney', 'Cheela with Spicy Mango Chutney', {'hing', 'curry leaves', 'mangoes', 'garlic', 'nigella seeds', 'garlic paste', 'coriander seeds', 'oil', 'turmeric', 'red chili powder', 'coriander powder', 'cardamom powder', 'turmeric powder', 'clove powder', 'water', 'cumin powder', 'fresh ginger', 'vinegar', 'cinnamon powder', 'cilantro', 'chickpea flour', 'onion', 'salt', 'mango powder', 'fresh red chili', 'mashed potatoes', 'mustard seeds', 'serrano chili', 'garam masala', 'sugar'}), - ('sweet_and_spicy_crispy_green_beans', 'Sweet and Spicy Crispy Green Beans', {'sesame oil', 'siracha', 'sunflower oil', 'pomegranate molasses', 'sesame seeds', 'green beans', 'carrot', 'scallions', 'garlic', 'ginger', 'soy sauce', 'tomato paste', 'bell pepper'}), - ('vegan_mini_savory_mince_pies', 'Vegan Mini Savory Mince Pies', {'apples', 'brandy', 'pecans', 'raisins', 'brown sugar', 'lemon zest', 'dried blueberries', 'vegetarian worcestershire sauce', 'orange zest', 'butternut squash', 'corn flour', 'rosemary', 'vegetable stock', 'carrot', 'figs', 'cinnamon powder', 'olive oil', 'orange juice', 'black pepper', 'onion', 'dried cherries', 'salt', 'dried cranberries', 'parev shortcrust pastry', 'mushrooms', 'allspice powder', 'lemon juice', 'ginger', 'currants'}), - ('roasted_corn_and_zucchini_salad', 'Roasted Corn and Zucchini Salad', {'zucchini', 'tomatoes', 'green onions', 'corn', 'lemon juice', 'olive oil', 'black pepper', 'lemon zest', 'dill'}), - ('golden_potato_salad', 'Golden Potato Salad', {'salt', 'yukon gold potato', 'turmeric', 'balsamic vinegar', 'cumin seeds', 'lemon juice', 'olive oil', 'garlic', 'mustard seeds', 'black pepper', 'chives'}), - ('carrot_puff_pastry_tart', 'Carrot Puff Pastry Tart', {'salt', 'water', 'lemon', 'thyme', 'red onion', 'carrot', 'lemon juice', 'pareve puff pastry', 'ground almonds', 'brown sugar', 'olive oil', 'garlic', 'black pepper', 'vegan butter'}), - - ('mushroom_lasagna', 'Mushroom Lasagna', {'dried lasagna noodles', 'portobello mushrooms', 'nutmeg', 'flour', 'kosher salt', 'milk', 'olive oil', 'garlic', 'onions', 'butter', 'black pepper', 'parmesan cheese'}), - ('nut_wellington', 'Nut Wellington', {'apples', 'eggs', 'hazelnuts', 'pecans', 'thyme', 'dates', 'cashews', 'breadcrumbs', 'almonds', 'marmite', 'sage', 'leeks', 'olive oil', 'black pepper', 'walnuts', 'salt', 'chestnuts', 'brazil nuts', 'butter', 'puff pastry sheets'}), - ('white_cheddar_scalloped_potatoes', 'White Cheddar Scalloped Potatoes', {'yukon gold potato', 'shallots', 'cream', 'thyme', 'breadcrumbs', 'sharp white cheddar', 'kosher salt', 'milk', 'garlic'}), - ('winter_cobb_salad', 'Winter Cobb Salad', {'lacinato kale', 'eggs', 'red wine vinegar', 'shiitake mushrooms', 'tomatoes', 'avocados', 'olive oil', 'blue cheese', 'garlic', 'black pepper', 'onion', 'smoked tofu'}), - ('roast_pumpkin_and_lentil_salad_with_roasted_lemon_dressing', 'Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing', {'red wine vinegar', 'dijon mustard', 'lemon', 'honey', 'red onion', 'feta cheese', 'olive oil', 'capers', 'pepitas', 'fresh pumpkin', 'watercress', 'green lentils', 'currants'}), - ('cambodian-style_vegetable_spring_rolls', 'Cambodian-Style Vegetable Spring Rolls', {'sunflower oil', 'vegetarian fish sauce', 'shallots', 'vermicelli noodles', 'wombok', 'firm tofu', 'lime juice', 'corn flour', 'palm sugar', 'bean sprouts', 'spring roll wrappers', 'garlic', 'red chili', 'soy sauce', 'toasted peanuts', 'carrot'}), - ('summer_minestrone_cups', 'Summer Minestrone Cups', {'leek', 'garlic', 'lemon zest', 'tomatoes', 'red chili', 'chickpeas', 'rosemary', 'carrot', 'vegetable bullion', 'fresh corn', 'fresh peas', 'green beans', 'olive oil', 'parmesan cheese', 'croutons', 'celery', 'mint', 'basil', 'green lentils', 'parmesan rind'}), - ('fried_zucchini_with_balsamic_and_chili_dressing', 'Fried Zucchini with Balsamic and Chili Dressing', {'zucchini', 'balsamic vinegar', 'honey', 'red onion', 'lemon juice', 'olive oil', 'mint leaves', 'garlic', 'red thai chili', 'pomegranate'}), - ('barley_risotto', 'Barley Risotto', {'beets', 'white wine', 'thyme', 'red onion', 'carrot', 'butternut squash', 'olive oil', 'sage', 'garlic', 'brussel sprouts', 'rosemary', 'black pepper', 'parmesan cheese', 'pearl barley', 'vegetable bullion'}), - ('cherry_tomato,_watercress_and_fava_bean_salad', 'Cherry Tomato, Watercress and Fava Bean Salad', {'salt', 'fresh or frozen fava beans', 'fresh peas', 'balsamic vinegar', 'olive oil', 'garlic', 'watercress', 'fresh cherry bocconcini', 'fresh cherry tomatoes'}), - ('fresh_garden_peas_over_cauliflower_almond_puree', 'Fresh Garden Peas over Cauliflower Almond Puree', {'grated nutmeg', 'red onions', 'lemon', 'fresh peas', 'cream', 'vegetable oil', 'olive oil', 'garlic', 'blanched almonds', 'cauliflower', 'fresh pea tendrils'}), - ('walnut_ravioli_with_artichokes_and_tomatoes', 'Walnut Ravioli with Artichokes and Tomatoes', {'salt', 'fresh tomatoes', 'ricotta cheese', 'lemon zest', 'olives', 'red onion', 'lemon juice', 'black pepper', 'rosemary', 'butter', 'basil', 'fresh artichoke hearts', 'pasta sheets', 'pine nuts', 'walnuts', 'oil marinated artichokes'}), - ('asparagus_puffs', 'Asparagus Puffs', {'salt', 'asparagus', 'ricotta cheese', 'thyme', 'puff pastry', 'red onion', 'eggs', 'lemon juice', 'black pepper', 'parmesan cheese', 'chives'}), - ('grilled_tofu_tacos', 'Grilled Tofu Tacos', {'carrot', 'red cabbage', 'ancho chili', 'limes', 'hot water', 'garlic', 'roasted corn', 'masa', 'pasilla chili', 'lemon', 'tomatoes', 'cumin', 'fresh cilantro leaves', 'chipotle chili', 'red onions', 'pepitas', 'tomatillos', 'black beans', 'cotija cheese', 'crema', 'firm tofu', 'lemon juice', 'jalapeño chili', 'avocado'}), - - ('zucchini_fritters_with_lemon-thyme_coconut_yogurt', 'Zucchini Fritters with Lemon-Thyme Coconut Yogurt', {'salt', 'coconut oil', 'eggs', 'fresh thai chili', 'coconut yogurt', 'zucchini', 'lemon juice', 'black pepper', 'coconut flour', 'chives', 'lemon zest', 'baking soda'}), - ('avocado_deviled_eggs', 'Avocado Deviled Eggs', {'salt', 'eggs', 'garlic powder', 'seranno chili', 'avocado', 'lime juice', 'pepitas', 'fresh cilantro leaves'}), - ('grilled_flank_steak_with_caesar_salad', 'Grilled Flank Steak with Caesar Salad', {'flank steak', 'avocado oil', 'treviso', 'scallions', 'garlic', 'cherry tomatoes', 'pine nuts', 'white vinegar', 'chipotle chili', 'dijon mustard', 'olive oil', 'avocado mayonnaise', 'black pepper', 'paleo parmesan cheese', 'castelfranco radicchio', 'fresh parsley', 'salt', 'worcestershire sauce', 'radishes'}), - ('pumpkin_bread_crostini', 'Pumpkin Bread Crostini', {'eggs', 'nutmeg', 'cinnamon', 'garlic', 'pumpkin puree', 'apple cider vinegar', 'cherry tomatoes', 'onions', 'coconut flour', 'cloves', 'shrimp', 'coconut oil', 'honey', 'olive oil', 'black pepper', 'almond butter', 'salt', 'fresh red chili', 'basil', 'baking soda'}), - ('blt_bites', 'BLT Bites', {'paleo mayonnaise', 'bacon', 'kale', 'cherry tomatoes', 'mustard seed', 'onion'}), - ('roasted_chicken_with_roasted_tomatoes,_avocado,_and_sweet_potatoes', 'Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes', {'safflower oil', 'shallots', 'whole chicken', 'lemons', 'tomatoes', 'purple sweet potato', 'avocados', 'limes', 'kosher salt', 'olive oil', 'mexican oregano', 'garlic', 'black pepper', 'cumin', 'chiles de árbol'}), - ('chicken_with_tamarind_and_apricot_sauce', 'Chicken with Tamarind and Apricot Sauce', {'cinnamon', 'garlic', 'cider vinegar', 'chipotles', 'homemade tamarind concentrate', 'roma tomatoes', 'white chicken', 'ground cumin', 'water', 'safflower oil', 'allspice', 'dried apricots', 'honey', 'olive oil', 'black pepper', 'salt', 'homemade apricot honey preserves', 'kosher salt', 'chili powder'}), - ('grilled_fish_tacos_with_cauliflower_tortillas', 'Grilled Fish Tacos with Cauliflower Tortillas', {'salt', 'eggs', 'smoked paprika', 'shredded red cabbage', 'mango', 'green onions', 'lime', 'cumin', 'tilapia', 'cilantro', 'black pepper', 'serrano chili', 'cauliflower', 'avocado'}), - ('grilled_pork_chops_with_mango_pineapple_salsa', 'Grilled Pork Chops with Mango Pineapple Salsa', {'pork chops', 'lacinato kale', 'chipotle chili', 'serrano chili', 'lime zest', 'pineapple', 'lime', 'garlic', 'onions', 'mangoes', 'cauliflower', 'avocado', 'cilantro leaves'}), - ('grilled_shrimp_and_pesto_over_zucchini_noodles', 'Grilled Shrimp and Pesto over Zucchini Noodles', {'salt', 'green bell pepper', 'cashews', 'zucchini', 'tomatoes', 'red bell pepper', 'cumin', 'lemon juice', 'yellow bell pepper', 'olive oil', 'garlic', 'pine nuts', 'basil', 'lemon zest', 'shrimp'}), - - ('cauliflower_pizza_with_roasted_tomatoes_and_chicken', 'Cauliflower Pizza with Roasted Tomatoes and Chicken', {'roasted chicken', 'eggs', 'fresh basil', 'olive oil', 'almond meal', 'cherry tomatoes', 'rosemary', 'cauliflower', 'mozzarella cheese', 'tomato paste', 'parmesan'}), - ('flank_steak_with_chimichurri_and_asparagus', 'Flank Steak with Chimichurri and Asparagus', {'fresh parsley', 'salt', 'asparagus', 'chipotle chili', 'flank steak', 'scallions', 'olive oil', 'garlic', 'black pepper', 'cauliflower', 'white vinegar', 'sour cream'}), - ('kingfish_lettuce_cups', 'Kingfish Lettuce Cups', {'oyster sauce', 'fish sauce', 'spring onions', 'sesame seeds', 'grilled king fish', 'little gem lettuce heads', 'mirin', 'red cabbage', 'lime juice', 'peanut oil', 'garlic', 'watermelon radishes', 'soy sauce', 'avocado'}), - ('butter_chicken_with_grilled_mushrooms,_brussel_sprouts_and_mango_chutney', 'Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', {'hing', 'curry leaves', 'cashew nuts', 'green chili', 'cinnamon', 'mangoes', 'garlic', 'nigella seeds', 'garlic paste', 'coriander seeds', 'turmeric', 'ginger garlic paste', 'tomatoes', 'red chili powder', 'coriander powder', 'cardamom powder', 'turmeric powder', 'clove powder', 'cloves', 'heavy cream', 'cardamom', 'fresh greek yogurt', 'monk fruit', 'fresh ginger', 'cumin powder', 'vinegar', 'cinnamon powder', 'cilantro', 'brussel sprouts', 'whole small crimini mushrooms', 'salt', 'boned chicken', 'red chili flakes', 'mango powder', 'fresh red chili', 'lemon juice', 'garam masala', 'butter', 'ginger', 'mustard seeds', 'chicken', 'dried fenugreek leaves'}), - ('prawn_and_herb_omelette', 'Prawn and Herb Omelette', {'salt', 'parsley', 'eggs', 'fresh cucumber', 'sesame seeds', 'green onions', 'monk fruit', 'lemon juice', 'olive oil', 'tahini', 'harissa', 'black pepper', 'butter', 'onion', 'fennel bulb', 'chives', 'shrimp', 'dill'}), - ('satay_steak_skewers', 'Satay Steak Skewers', {'flank steak', 'red and green thai chili', 'kecap manis', 'fish sauce', 'monk fruit', 'micro cilantro', 'carrot', 'apple cider vinegar', 'sriacha', 'lime juice', 'olive oil', 'cucumbers', 'roasted peanuts', 'crunchy peanut butter', 'peanuts'}), - ('parmesan_crackers_and_spinach_crackers_with_salmon_pate', 'Parmesan Crackers and Spinach Crackers with Salmon Pate', {'fresh cucumber', 'pecans', 'ghee', 'garlic', 'chives', 'flaxmeal', 'chili flakes', 'almond flour', 'salmon fillets', 'red onion', 'cherry tomatoes', 'coconut flour', 'cumin', 'spinach', 'cream cheese', 'avocado mayonnaise', 'black pepper', 'parmesan cheese', 'salt', 'lemon juice'}), - ('pork_chops_with_grilled_castelfranco_radicchio_and_asparagus', 'Pork Chops with Grilled Castelfranco Radicchio and Asparagus', {'pork chops', 'salt', 'asparagus', 'eggs', 'dijon mustard', 'avocado oil', 'lemon', 'thyme', 'monk fruit', 'oregano', 'avocado mayonnaise', 'garlic', 'black pepper', 'rosemary', 'butter', 'basil', 'castelfranco radicchio', 'dill'}), - ('seared_salmon_with_pickled_vegetable_and_watercress_salad', 'Seared Salmon with Pickled Vegetable and Watercress Salad', {'red wine vinegar', 'caster sugar', 'salmon steaks', 'radishes', 'shallots', 'red onion', 'pink peppercorns', 'toasted buckwheat', 'lemon juice', 'lime juice', 'red cabbage', 'watercress', 'fennel seeds', 'dutch carrot'}), - ('braised_pork_belly_with_apple_salad', 'Braised Pork Belly with Apple Salad', {'spring onions', 'dark soy sauce', 'light soy sauce', 'pork belly', 'monk fruit', 'green cabbage', 'star anise', 'sesame seeds', 'lemon juice', 'olive oil', 'black pepper', 'ginger', 'cinnamon sticks', 'granny smith apples', 'cilantro leaves'}), - - ('beachside_snapper', 'Beachside Snapper', {'yellow mustard', 'mayonnaise', 'limes', 'white onion', 'red snapper', 'fresh corn tortillas', 'tomatoes', 'red onion', 'lime juice', 'soy sauce', 'mexican crema', 'salsa', 'garlic cloves', 'green bell pepper', 'olive oil', 'black pepper', 'salt', 'yellow bell pepper', 'worcestershire sauce', 'anaheim chili', 'butter', 'red bell pepper'}), - ('governor_shrimp_tacos', 'Governor Shrimp Tacos', {'chile manzano', 'worcestershire sauce', 'oaxaca cheese', 'garlic cloves', 'red onion', 'avocado', 'lime juice', 'kosher salt', 'white onion', 'chipotle adobo sauce', 'poblano chili', 'fresh corn tortillas', 'butter', 'black pepper', 'pepitas', 'tomato paste', 'roma tomatoes', 'shelled large shrimp'}), - ('shrimp,_bacon_and_crispy_chickpea_tacos_with_salsa_de_guacamole', 'Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole', {'fresh tortillas', 'slivered almonds', 'bacon', 'sea salt', 'chickpeas', 'olive oil', 'guajillo chile', 'garlic', 'butter', 'black pepper', 'onion', 'shrimp', 'avocado'}), - ('burnt_masala_wings_with_classic_coleslaw', 'Burnt Masala Wings with Classic Coleslaw', {'mayonnaise', 'carrot', 'red cabbage', 'green cabbage', 'apple cider vinegar', 'lime juice', 'cloves', 'cinnamon sticks', 'sriracha', 'celery seeds', 'chicken wings', 'garlic cloves', 'honey', 'olive oil', 'cilantro', 'black pepper', 'chiles de árbol', 'tamarind concentrate', 'green cardamom', 'black cardamom', 'lemon juice', 'kosher salt', 'serrano chili', 'ginger', 'black peppercorns', 'butter'}), - ('dahi_puri_with_black_chickpeas', 'Dahi Puri with Black Chickpeas', {'roasted chicken', 'scallion chutney', 'yukon gold potato', 'turmeric', 'black chickpeas', 'whole-milk yogurt', 'chili powder', 'red onion', 'pani puri', 'ginger', 'mint', 'thin sev', 'date syrup', 'cumin', 'chaat masala', 'tamarind concentrate'}), - ('brisket_with_grilled_rhubarb,_onions,_and_fennel', 'Brisket with Grilled Rhubarb, Onions, and Fennel', {'crushed red pepper flakes', 'rhubarb', 'thyme', 'yellow onion', 'garlic', 'brown sugar', 'beer', 'lemon', 'red onion', 'oregano', 'soy sauce', 'white vinegar', 'beef brisket', 'parsley', 'marjoram', 'balsamic vinegar', 'vegetable oil', 'fennel bulbs', 'cilantro', 'black pepper', 'worcestershire sauce', 'celery', 'kosher salt', 'mint', 'chili powder'}), - ('roast_leg_of_lamb_with_crispy_moroccan_carrots_&_couscous', 'Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous', {'bay leaves', 'fresh thyme', 'carrot', 'tahini', 'garlic', 'baby carrot', 'oranges', 'filo pastry', 'tomatoes', 'harissa', 'onions', 'rosemary', 'leg of lamb', 'vegetable bullion', 'sesame seeds', 'honey', 'anchovy fillets', 'vinegar', 'olive oil', 'couscous', 'fresh mint', 'celery', 'yoghurt'}), - ('baked_chicken_jollof_rice', 'Baked Chicken Jollof Rice', {'coriander', 'salt', 'white pepper', 'water', 'bell pepper', 'turmeric', 'rice', 'scotch bonnet pepper', 'chicken', 'thyme', 'maggi cubes', 'garlic', 'ginger', 'onion', 'tomato', 'carrot', 'tomato puree'}), - ('seafood_risotto', 'Seafood Risotto', {'white wine', 'water', 'clams', 'crab legs', 'baby squid', 'lemon juice', 'parmesan cheese', 'olive oil', 'white onion', 'garlic', 'arborio risotto rice', 'fish stock', 'mussels', 'flat-leaf parsley', 'tomato paste', 'prawns', 'baby scallops', 'cherry tomatoes'}), - ('lamb_over_marinated_summer_squash_with_hazelnuts_and_ricotta', 'Lamb over Marinated Summer Squash with Hazelnuts and Ricotta', {'red pepper flakes', 'hazelnuts', 'zucchini', 'bay leaves', 'carrot', 'garlic', 'white wine vinegar', 'toasted bread', 'lemon', 'onions', 'rosemary', 'leg of lamb', 'summer squash', 'sea salt', 'anchovy fillets', 'vinegar', 'olive oil', 'black pepper', 'fresh mint', 'celery', 'kosher salt', 'fresh ricotta', 'sugar'}) - ] +recipes_with_duplicates = [ + ( + "Kisir with Warm Pita", + [ + "bulgur", + "pomegranate molasses", + "chopped parsley", + "lemon juice", + "tomato", + "persian cucumber", + "tomato paste", + "spring onion", + "water", + "olive oil", + "bulgur", + "bulgur", + "pomegranate molasses", + "pomegranate molasses", + "pomegranate molasses", + "chopped parsley", + "lemon juice", + "tomato", + "tomato", + "persian cucumber", + "tomato paste", + "tomato paste", + "tomato paste", + ], + ), + ( + "Shakshuka", + [ + "vegan unsweetened yoghurt", + "yellow onion", + "firm tofu", + "smoked paprika", + "tomatoes", + "tomato paste", + "sugar", + "cloves", + "cumin", + "za'atar", + "olive oil", + "harissa", + "red bell pepper", + ], + ), + ( + "Vegetarian Khoresh Bademjan", + [ + "yellow split peas", + "tomato paste", + "black pepper", + "pomegranate concentrate", + "yellow onions", + "slivered almonds", + "ground turmeric", + "barberries", + "basmati rice", + "lemon juice", + "hot water", + "cayenne pepper", + "chinese eggplants", + "salt", + "orange juice", + "saffron powder", + "vegan butter", + "orange zest", + "kosher salt", + "yellow split peas", + "yellow split peas", + "tomato paste", + "tomato paste", + "tomato paste", + "black pepper", + ], + ), + ( + "Baked Kelewele", + [ + "smoked paprika", + "black peppercorn", + "red onion", + "grains of selim", + "cayenne pepper", + "calabash nutmeg", + "coconut oil", + "cloves", + "fresh ginger", + "salt", + "ripe plantains", + "smoked paprika", + "black peppercorn", + "black peppercorn", + "red onion", + "grains of selim", + "grains of selim", + "grains of selim", + ], + ), + ( + "Waakye", + [ + "baking soda", + "sorghum stems", + "coconut oil", + "black-eyed peas", + "water", + "salt", + "white rice", + "baking soda", + "baking soda", + "sorghum stems", + "sorghum stems", + "sorghum stems", + "coconut oil", + ], + ), + ( + "Georgian Eggplant Rolls with Walnuts", + [ + "pomegranate seeds", + "oil", + "coriander", + "garlic", + "khmeli suneli", + "eggplants", + "black pepper", + "vinegar", + "walnuts", + "water", + "salt", + ], + ), + ( + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + [ + "soy sauce", + "oil", + "chili flakes", + "garlic", + "brown sugar", + "ginger", + "peanuts", + "rice vinegar", + "spring onions", + "water", + "turmeric", + "salt", + "chickpea flour", + "soy sauce", + "soy sauce", + "oil", + "oil", + "oil", + "chili flakes", + "garlic", + "brown sugar", + "brown sugar", + "ginger", + "peanuts", + "peanuts", + "peanuts", + ], + ), + ( + "Celeriac Schnitzel", + [ + "soy sauce", + "parsley", + "lemon", + "sunflower oil", + "black pepper", + "celeriac", + "breadcrumbs", + "water", + "salt", + "flour", + "chickpea flour", + ], + ), + ( + "Sticky Lemon Tofu", + [ + "soy sauce", + "vegetable stock", + "tofu", + "cornstarch", + "lemon juice", + "lemon zest", + "garlic", + "ginger", + "black pepper", + "sugar", + "water", + "salt", + "vegetable oil", + "soy sauce", + "soy sauce", + "vegetable stock", + "vegetable stock", + "vegetable stock", + "tofu", + ], + ), + ( + "Vegan Carbonara", + [ + "soy sauce", + "smoked tofu", + "lemon juice", + "nutritional yeast", + "mixed herbs", + "garlic", + "black pepper", + "silken tofu", + "turmeric", + "salt", + "olive oil", + "spaghetti", + "soy sauce", + "smoked tofu", + "smoked tofu", + "lemon juice", + "nutritional yeast", + "nutritional yeast", + "nutritional yeast", + ], + ), + ( + "Vegan Pizza with Caramelized Onions", + [ + "mushrooms", + "rosemary", + "garlic", + "red pepper flakes", + "yeast", + "barley malt", + "water", + "olive oil", + "garlic powder", + "oregano", + "honey", + "nutritional yeast", + "red onion", + "tomatoes", + "cashews", + "sugar", + "bell pepper", + "flour", + "salt", + "fresh basil", + "mushrooms", + "mushrooms", + "rosemary", + "rosemary", + "rosemary", + "garlic", + ], + ), + ( + "Cheela with Spicy Mango Chutney", + [ + "clove powder", + "oil", + "cinnamon powder", + "nigella seeds", + "curry leaves", + "coriander seeds", + "garlic", + "mangoes", + "mashed potatoes", + "cardamom powder", + "vinegar", + "water", + "mustard seeds", + "coriander powder", + "cumin powder", + "mango powder", + "garam masala", + "red chili powder", + "hing", + "garlic paste", + "turmeric powder", + "cilantro", + "sugar", + "onion", + "serrano chili", + "fresh ginger", + "turmeric", + "salt", + "fresh red chili", + "chickpea flour", + ], + ), + ( + "Sweet and Spicy Crispy Green Beans", + [ + "soy sauce", + "pomegranate molasses", + "sesame oil", + "green beans", + "sunflower oil", + "scallions", + "garlic", + "carrot", + "ginger", + "sesame seeds", + "tomato paste", + "bell pepper", + "siracha", + "soy sauce", + "soy sauce", + "pomegranate molasses", + "pomegranate molasses", + "pomegranate molasses", + "sesame oil", + "green beans", + "sunflower oil", + "sunflower oil", + "scallions", + "garlic", + "garlic", + "garlic", + ], + ), + ( + "Vegan Mini Savory Mince Pies", + [ + "mushrooms", + "cinnamon powder", + "rosemary", + "corn flour", + "ginger", + "brown sugar", + "carrot", + "black pepper", + "raisins", + "butternut squash", + "vegetarian worcestershire sauce", + "parev shortcrust pastry", + "olive oil", + "vegetable stock", + "dried cherries", + "lemon juice", + "lemon zest", + "figs", + "dried cranberries", + "apples", + "pecans", + "onion", + "orange juice", + "currants", + "dried blueberries", + "salt", + "brandy", + "orange zest", + "allspice powder", + ], + ), + ( + "Roasted Corn and Zucchini Salad", + [ + "green onions", + "lemon juice", + "lemon zest", + "dill", + "corn", + "tomatoes", + "black pepper", + "zucchini", + "olive oil", + "green onions", + "green onions", + "lemon juice", + "lemon juice", + "lemon juice", + "lemon zest", + ], + ), + ( + "Golden Potato Salad", + [ + "mustard seeds", + "cumin seeds", + "lemon juice", + "garlic", + "black pepper", + "balsamic vinegar", + "yukon gold potato", + "chives", + "turmeric", + "salt", + "olive oil", + "mustard seeds", + "cumin seeds", + "cumin seeds", + "lemon juice", + "garlic", + "garlic", + "garlic", + ], + ), + ( + "Carrot Puff Pastry Tart", + [ + "olive oil", + "lemon", + "lemon juice", + "pareve puff pastry", + "brown sugar", + "red onion", + "carrot", + "garlic", + "black pepper", + "thyme", + "vegan butter", + "water", + "salt", + "ground almonds", + "olive oil", + "olive oil", + "lemon", + "lemon", + "lemon", + "lemon juice", + ], + ), + ( + "Mushroom Lasagna", + [ + "nutmeg", + "garlic", + "black pepper", + "onions", + "butter", + "parmesan cheese", + "portobello mushrooms", + "flour", + "dried lasagna noodles", + "olive oil", + "milk", + "kosher salt", + ], + ), + ( + "Nut Wellington", + [ + "sage", + "puff pastry sheets", + "hazelnuts", + "almonds", + "black pepper", + "thyme", + "marmite", + "breadcrumbs", + "walnuts", + "dates", + "eggs", + "olive oil", + "brazil nuts", + "leeks", + "chestnuts", + "cashews", + "apples", + "pecans", + "butter", + "salt", + "sage", + "sage", + "puff pastry sheets", + "puff pastry sheets", + "puff pastry sheets", + "hazelnuts", + "almonds", + "black pepper", + "black pepper", + "thyme", + "marmite", + "marmite", + "marmite", + ], + ), + ( + "White Cheddar Scalloped Potatoes", + [ + "shallots", + "garlic", + "cream", + "thyme", + "breadcrumbs", + "sharp white cheddar", + "yukon gold potato", + "milk", + "kosher salt", + ], + ), + ( + "Winter Cobb Salad", + [ + "smoked tofu", + "shiitake mushrooms", + "red wine vinegar", + "garlic", + "tomatoes", + "black pepper", + "avocados", + "blue cheese", + "onion", + "lacinato kale", + "eggs", + "olive oil", + "smoked tofu", + "smoked tofu", + "shiitake mushrooms", + "shiitake mushrooms", + "shiitake mushrooms", + "red wine vinegar", + ], + ), + ( + "Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing", + [ + "honey", + "lemon", + "dijon mustard", + "feta cheese", + "red wine vinegar", + "red onion", + "watercress", + "green lentils", + "currants", + "capers", + "pepitas", + "fresh pumpkin", + "olive oil", + "honey", + "lemon", + "lemon", + "dijon mustard", + "feta cheese", + "feta cheese", + "feta cheese", + ], + ), + ( + "Cambodian-Style Vegetable Spring Rolls", + [ + "lime juice", + "toasted peanuts", + "firm tofu", + "garlic", + "corn flour", + "bean sprouts", + "carrot", + "palm sugar", + "shallots", + "red chili", + "vermicelli noodles", + "wombok", + "soy sauce", + "sunflower oil", + "spring roll wrappers", + "vegetarian fish sauce", + "lime juice", + "lime juice", + "toasted peanuts", + "toasted peanuts", + "toasted peanuts", + "firm tofu", + ], + ), + ( + "Summer Minestrone Cups", + [ + "fresh peas", + "rosemary", + "garlic", + "chickpeas", + "carrot", + "leek", + "green lentils", + "red chili", + "olive oil", + "croutons", + "fresh corn", + "lemon zest", + "green beans", + "parmesan rind", + "basil", + "tomatoes", + "vegetable bullion", + "parmesan cheese", + "celery", + "mint", + ], + ), + ( + "Fried Zucchini with Balsamic and Chili Dressing", + [ + "honey", + "lemon juice", + "garlic", + "red onion", + "red thai chili", + "pomegranate", + "balsamic vinegar", + "mint leaves", + "zucchini", + "olive oil", + "honey", + "honey", + "lemon juice", + "lemon juice", + "lemon juice", + "garlic", + "red onion", + "red thai chili", + "red thai chili", + "pomegranate", + "balsamic vinegar", + "balsamic vinegar", + "balsamic vinegar", + ], + ), + ( + "Barley Risotto", + [ + "sage", + "beets", + "pearl barley", + "brussel sprouts", + "rosemary", + "garlic", + "carrot", + "red onion", + "black pepper", + "thyme", + "butternut squash", + "vegetable bullion", + "parmesan cheese", + "olive oil", + "white wine", + ], + ), + ( + "Cherry Tomato, Watercress and Fava Bean Salad", + [ + "fresh peas", + "fresh cherry tomatoes", + "garlic", + "watercress", + "balsamic vinegar", + "fresh or frozen fava beans", + "fresh cherry bocconcini", + "salt", + "olive oil", + "fresh peas", + "fresh peas", + "fresh cherry tomatoes", + "fresh cherry tomatoes", + "fresh cherry tomatoes", + "garlic", + ], + ), + ( + "Fresh Garden Peas over Cauliflower Almond Puree", + [ + "red onions", + "lemon", + "fresh peas", + "garlic", + "grated nutmeg", + "cream", + "cauliflower", + "blanched almonds", + "fresh pea tendrils", + "olive oil", + "vegetable oil", + "red onions", + "lemon", + "lemon", + "fresh peas", + "garlic", + "garlic", + "garlic", + ], + ), + ( + "Walnut Ravioli with Artichokes and Tomatoes", + [ + "pine nuts", + "oil marinated artichokes", + "olives", + "rosemary", + "fresh tomatoes", + "ricotta cheese", + "black pepper", + "fresh artichoke hearts", + "walnuts", + "pasta sheets", + "lemon juice", + "lemon zest", + "basil", + "red onion", + "butter", + "salt", + "pine nuts", + "pine nuts", + "oil marinated artichokes", + "oil marinated artichokes", + "oil marinated artichokes", + "olives", + ], + ), + ( + "Asparagus Puffs", + [ + "eggs", + "asparagus", + "lemon juice", + "red onion", + "ricotta cheese", + "black pepper", + "thyme", + "salt", + "parmesan cheese", + "puff pastry", + "chives", + ], + ), + ( + "Grilled Tofu Tacos", + [ + "cotija cheese", + "masa", + "fresh cilantro leaves", + "jalapeño chili", + "chipotle chili", + "firm tofu", + "garlic", + "carrot", + "roasted corn", + "tomatillos", + "pepitas", + "ancho chili", + "crema", + "red onions", + "pasilla chili", + "lemon", + "hot water", + "lemon juice", + "tomatoes", + "avocado", + "cumin", + "red cabbage", + "limes", + "black beans", + "cotija cheese", + "cotija cheese", + "masa", + "masa", + "masa", + "fresh cilantro leaves", + "jalapeño chili", + "chipotle chili", + "chipotle chili", + "firm tofu", + "garlic", + "garlic", + "garlic", + ], + ), + ( + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + [ + "baking soda", + "coconut flour", + "lemon juice", + "lemon zest", + "eggs", + "coconut yogurt", + "black pepper", + "fresh thai chili", + "coconut oil", + "chives", + "zucchini", + "salt", + ], + ), + ( + "Avocado Deviled Eggs", + [ + "lime juice", + "fresh cilantro leaves", + "eggs", + "seranno chili", + "avocado", + "pepitas", + "salt", + "garlic powder", + "lime juice", + "lime juice", + "fresh cilantro leaves", + "fresh cilantro leaves", + "fresh cilantro leaves", + "eggs", + ], + ), + ( + "Grilled Flank Steak with Caesar Salad", + [ + "pine nuts", + "white vinegar", + "chipotle chili", + "scallions", + "garlic", + "paleo parmesan cheese", + "black pepper", + "avocado oil", + "treviso", + "olive oil", + "radishes", + "flank steak", + "dijon mustard", + "castelfranco radicchio", + "worcestershire sauce", + "fresh parsley", + "cherry tomatoes", + "salt", + "avocado mayonnaise", + "pine nuts", + "white vinegar", + "white vinegar", + "chipotle chili", + "scallions", + "scallions", + "scallions", + ], + ), + ( + "Pumpkin Bread Crostini", + [ + "coconut flour", + "garlic", + "black pepper", + "cloves", + "eggs", + "olive oil", + "onions", + "honey", + "apple cider vinegar", + "almond butter", + "baking soda", + "nutmeg", + "pumpkin puree", + "cinnamon", + "shrimp", + "basil", + "coconut oil", + "cherry tomatoes", + "salt", + "fresh red chili", + "coconut flour", + "coconut flour", + "garlic", + "garlic", + "garlic", + "black pepper", + ], + ), + ( + "BLT Bites", + [ + "mustard seed", + "onion", + "kale", + "cherry tomatoes", + "bacon", + "paleo mayonnaise", + ], + ), + ( + "Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes", + [ + "purple sweet potato", + "chiles de árbol", + "garlic", + "tomatoes", + "safflower oil", + "black pepper", + "mexican oregano", + "avocados", + "shallots", + "cumin", + "olive oil", + "lemons", + "whole chicken", + "limes", + "kosher salt", + "purple sweet potato", + "purple sweet potato", + "chiles de árbol", + "chiles de árbol", + "chiles de árbol", + "garlic", + "tomatoes", + "safflower oil", + "safflower oil", + "black pepper", + "mexican oregano", + "mexican oregano", + "mexican oregano", + ], + ), + ( + "Chicken with Tamarind and Apricot Sauce", + [ + "garlic", + "black pepper", + "dried apricots", + "roma tomatoes", + "water", + "olive oil", + "honey", + "cinnamon", + "ground cumin", + "cider vinegar", + "chili powder", + "safflower oil", + "homemade tamarind concentrate", + "white chicken", + "allspice", + "chipotles", + "salt", + "homemade apricot honey preserves", + "kosher salt", + ], + ), + ( + "Grilled Fish Tacos with Cauliflower Tortillas", + [ + "green onions", + "serrano chili", + "shredded red cabbage", + "smoked paprika", + "mango", + "eggs", + "black pepper", + "cilantro", + "cauliflower", + "avocado", + "lime", + "cumin", + "salt", + "tilapia", + "green onions", + "green onions", + "serrano chili", + "serrano chili", + "serrano chili", + "shredded red cabbage", + ], + ), + ( + "Grilled Pork Chops with Mango Pineapple Salsa", + [ + "cilantro leaves", + "lime", + "pineapple", + "chipotle chili", + "garlic", + "mangoes", + "cauliflower", + "avocado", + "serrano chili", + "pork chops", + "lime zest", + "lacinato kale", + "onions", + "cilantro leaves", + "lime", + "lime", + "pineapple", + "chipotle chili", + "chipotle chili", + "chipotle chili", + ], + ), + ( + "Grilled Shrimp and Pesto over Zucchini Noodles", + [ + "pine nuts", + "shrimp", + "green bell pepper", + "lemon juice", + "basil", + "lemon zest", + "garlic", + "tomatoes", + "cashews", + "yellow bell pepper", + "cumin", + "zucchini", + "salt", + "olive oil", + "red bell pepper", + "pine nuts", + "pine nuts", + "shrimp", + "shrimp", + "shrimp", + "green bell pepper", + ], + ), + ( + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + [ + "parmesan", + "almond meal", + "rosemary", + "mozzarella cheese", + "roasted chicken", + "tomato paste", + "cauliflower", + "cherry tomatoes", + "eggs", + "fresh basil", + "olive oil", + ], + ), + ( + "Flank Steak with Chimichurri and Asparagus", + [ + "white vinegar", + "asparagus", + "flank steak", + "chipotle chili", + "scallions", + "garlic", + "black pepper", + "cauliflower", + "sour cream", + "fresh parsley", + "salt", + "olive oil", + "white vinegar", + "white vinegar", + "asparagus", + "asparagus", + "asparagus", + "flank steak", + "chipotle chili", + "scallions", + "scallions", + "garlic", + "black pepper", + "black pepper", + "black pepper", + ], + ), + ( + "Kingfish Lettuce Cups", + [ + "soy sauce", + "watermelon radishes", + "lime juice", + "fish sauce", + "mirin", + "little gem lettuce heads", + "peanut oil", + "garlic", + "sesame seeds", + "oyster sauce", + "spring onions", + "avocado", + "grilled king fish", + "red cabbage", + ], + ), + ( + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + [ + "clove powder", + "curry leaves", + "coriander seeds", + "ginger", + "cardamom powder", + "vinegar", + "mustard seeds", + "mango powder", + "garam masala", + "red chili powder", + "chicken", + "hing", + "turmeric powder", + "tomatoes", + "ginger garlic paste", + "fresh greek yogurt", + "fresh ginger", + "monk fruit", + "turmeric", + "cashew nuts", + "salt", + "fresh red chili", + "cinnamon powder", + "nigella seeds", + "whole small crimini mushrooms", + "brussel sprouts", + "garlic", + "mangoes", + "heavy cream", + "cloves", + "coriander powder", + "cumin powder", + "cardamom", + "green chili", + "cinnamon", + "garlic paste", + "red chili flakes", + "lemon juice", + "cilantro", + "butter", + "dried fenugreek leaves", + "boned chicken", + "clove powder", + "clove powder", + "curry leaves", + "curry leaves", + "curry leaves", + "coriander seeds", + ], + ), + ( + "Prawn and Herb Omelette", + [ + "green onions", + "parsley", + "sesame seeds", + "black pepper", + "chives", + "eggs", + "fennel bulb", + "tahini", + "olive oil", + "harissa", + "shrimp", + "lemon juice", + "dill", + "butter", + "onion", + "fresh cucumber", + "monk fruit", + "salt", + "green onions", + "parsley", + "parsley", + "sesame seeds", + "black pepper", + "black pepper", + "black pepper", + ], + ), + ( + "Satay Steak Skewers", + [ + "sriacha", + "apple cider vinegar", + "lime juice", + "fish sauce", + "red and green thai chili", + "flank steak", + "carrot", + "peanuts", + "cucumbers", + "roasted peanuts", + "crunchy peanut butter", + "kecap manis", + "monk fruit", + "micro cilantro", + "olive oil", + "sriacha", + "sriacha", + "apple cider vinegar", + "apple cider vinegar", + "apple cider vinegar", + "lime juice", + ], + ), + ( + "Parmesan Crackers and Spinach Crackers with Salmon Pate", + [ + "spinach", + "parmesan cheese", + "coconut flour", + "chili flakes", + "garlic", + "black pepper", + "cream cheese", + "ghee", + "lemon juice", + "flaxmeal", + "red onion", + "salt", + "salmon fillets", + "pecans", + "almond flour", + "cumin", + "fresh cucumber", + "cherry tomatoes", + "chives", + "avocado mayonnaise", + ], + ), + ( + "Pork Chops with Grilled Castelfranco Radicchio and Asparagus", + [ + "rosemary", + "garlic", + "black pepper", + "thyme", + "avocado oil", + "eggs", + "oregano", + "asparagus", + "lemon", + "dijon mustard", + "basil", + "castelfranco radicchio", + "dill", + "butter", + "pork chops", + "monk fruit", + "salt", + "avocado mayonnaise", + "rosemary", + "rosemary", + "garlic", + "garlic", + "garlic", + "black pepper", + "thyme", + "avocado oil", + "avocado oil", + "eggs", + "oregano", + "oregano", + "oregano", + ], + ), + ( + "Seared Salmon with Pickled Vegetable and Watercress Salad", + [ + "lime juice", + "caster sugar", + "toasted buckwheat", + "lemon juice", + "red wine vinegar", + "red onion", + "dutch carrot", + "salmon steaks", + "watercress", + "pink peppercorns", + "shallots", + "fennel seeds", + "red cabbage", + "radishes", + ], + ), + ( + "Braised Pork Belly with Apple Salad", + [ + "cilantro leaves", + "green cabbage", + "lemon juice", + "pork belly", + "dark soy sauce", + "granny smith apples", + "ginger", + "light soy sauce", + "sesame seeds", + "black pepper", + "cinnamon sticks", + "spring onions", + "star anise", + "monk fruit", + "olive oil", + "cilantro leaves", + "cilantro leaves", + "green cabbage", + "green cabbage", + "green cabbage", + "lemon juice", + ], + ), + ( + "Beachside Snapper", + [ + "lime juice", + "salsa", + "green bell pepper", + "anaheim chili", + "black pepper", + "olive oil", + "yellow mustard", + "red bell pepper", + "soy sauce", + "mexican crema", + "mayonnaise", + "white onion", + "garlic cloves", + "fresh corn tortillas", + "red onion", + "tomatoes", + "limes", + "worcestershire sauce", + "butter", + "yellow bell pepper", + "salt", + "red snapper", + "lime juice", + "salsa", + "salsa", + "green bell pepper", + "anaheim chili", + "anaheim chili", + "anaheim chili", + ], + ), + ( + "Governor Shrimp Tacos", + [ + "lime juice", + "poblano chili", + "tomato paste", + "black pepper", + "chipotle adobo sauce", + "chile manzano", + "roma tomatoes", + "pepitas", + "oaxaca cheese", + "white onion", + "shelled large shrimp", + "garlic cloves", + "fresh corn tortillas", + "red onion", + "worcestershire sauce", + "avocado", + "butter", + "kosher salt", + "lime juice", + "lime juice", + "poblano chili", + "poblano chili", + "poblano chili", + "tomato paste", + ], + ), + ( + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", + [ + "fresh tortillas", + "shrimp", + "garlic", + "chickpeas", + "black pepper", + "slivered almonds", + "guajillo chile", + "bacon", + "sea salt", + "butter", + "onion", + "avocado", + "olive oil", + ], + ), + ( + "Burnt Masala Wings with Classic Coleslaw", + [ + "lime juice", + "green cabbage", + "chiles de árbol", + "green cardamom", + "ginger", + "carrot", + "sriracha", + "black pepper", + "cinnamon sticks", + "celery seeds", + "cloves", + "black cardamom", + "olive oil", + "chicken wings", + "apple cider vinegar", + "mayonnaise", + "honey", + "black peppercorns", + "lemon juice", + "garlic cloves", + "tamarind concentrate", + "cilantro", + "butter", + "serrano chili", + "red cabbage", + "kosher salt", + "lime juice", + "lime juice", + "green cabbage", + "green cabbage", + "green cabbage", + "chiles de árbol", + "green cardamom", + "ginger", + "ginger", + "carrot", + "sriracha", + "sriracha", + "sriracha", + ], + ), + ( + "Dahi Puri with Black Chickpeas", + [ + "whole-milk yogurt", + "chaat masala", + "ginger", + "pani puri", + "scallion chutney", + "yukon gold potato", + "black chickpeas", + "thin sev", + "date syrup", + "red onion", + "roasted chicken", + "chili powder", + "tamarind concentrate", + "cumin", + "turmeric", + "mint", + ], + ), + ( + "Brisket with Grilled Rhubarb, Onions, and Fennel", + [ + "white vinegar", + "parsley", + "yellow onion", + "rhubarb", + "garlic", + "brown sugar", + "black pepper", + "thyme", + "crushed red pepper flakes", + "fennel bulbs", + "beer", + "marjoram", + "vegetable oil", + "soy sauce", + "oregano", + "lemon", + "red onion", + "chili powder", + "cilantro", + "beef brisket", + "balsamic vinegar", + "worcestershire sauce", + "celery", + "mint", + "kosher salt", + "white vinegar", + "white vinegar", + "parsley", + "parsley", + "parsley", + "yellow onion", + ], + ), + ( + "Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous", + [ + "oranges", + "rosemary", + "garlic", + "anchovy fillets", + "couscous", + "carrot", + "sesame seeds", + "fresh thyme", + "vinegar", + "olive oil", + "tahini", + "harissa", + "onions", + "honey", + "fresh mint", + "leg of lamb", + "tomatoes", + "baby carrot", + "vegetable bullion", + "filo pastry", + "celery", + "bay leaves", + "yoghurt", + "oranges", + "rosemary", + "rosemary", + "garlic", + "anchovy fillets", + "anchovy fillets", + "anchovy fillets", + ], + ), + ( + "Baked Chicken Jollof Rice", + [ + "tomato puree", + "garlic", + "ginger", + "tomato", + "carrot", + "thyme", + "white pepper", + "water", + "maggi cubes", + "chicken", + "rice", + "coriander", + "scotch bonnet pepper", + "bell pepper", + "onion", + "turmeric", + "salt", + "tomato puree", + "tomato puree", + "garlic", + "garlic", + "garlic", + "ginger", + ], + ), + ( + "Seafood Risotto", + [ + "garlic", + "tomato paste", + "baby scallops", + "mussels", + "water", + "crab legs", + "olive oil", + "baby squid", + "fish stock", + "lemon juice", + "white onion", + "arborio risotto rice", + "clams", + "parmesan cheese", + "flat-leaf parsley", + "cherry tomatoes", + "prawns", + "white wine", + ], + ), + ( + "Lamb over Marinated Summer Squash with Hazelnuts and Ricotta", + [ + "toasted bread", + "rosemary", + "hazelnuts", + "anchovy fillets", + "garlic", + "carrot", + "summer squash", + "black pepper", + "red pepper flakes", + "vinegar", + "sea salt", + "zucchini", + "olive oil", + "onions", + "white wine vinegar", + "fresh mint", + "leg of lamb", + "lemon", + "fresh ricotta", + "sugar", + "celery", + "bay leaves", + "kosher salt", + "toasted bread", + "toasted bread", + "rosemary", + "rosemary", + "rosemary", + "hazelnuts", + "anchovy fillets", + "garlic", + "garlic", + "carrot", + "summer squash", + "summer squash", + "summer squash", + ], + ), +] + +recipes_without_duplicates = [ + ( + "kisir_with_warm_pita", + "Kisir with Warm Pita", + { + "water", + "chopped parsley", + "pomegranate molasses", + "spring onion", + "lemon juice", + "olive oil", + "bulgur", + "tomato paste", + "tomato", + "persian cucumber", + }, + ), + ( + "shakshuka", + "Shakshuka", + { + "smoked paprika", + "tomatoes", + "cumin", + "firm tofu", + "olive oil", + "harissa", + "yellow onion", + "sugar", + "za'atar", + "tomato paste", + "cloves", + "red bell pepper", + "vegan unsweetened yoghurt", + }, + ), + ( + "vegetarian_khoresh_bademjan", + "Vegetarian Khoresh Bademjan", + { + "pomegranate concentrate", + "saffron powder", + "cayenne pepper", + "barberries", + "salt", + "yellow onions", + "yellow split peas", + "slivered almonds", + "ground turmeric", + "orange zest", + "lemon juice", + "kosher salt", + "hot water", + "basmati rice", + "black pepper", + "orange juice", + "tomato paste", + "vegan butter", + "chinese eggplants", + }, + ), + ( + "baked_kelewele", + "Baked Kelewele", + { + "salt", + "coconut oil", + "smoked paprika", + "cayenne pepper", + "red onion", + "fresh ginger", + "calabash nutmeg", + "grains of selim", + "black peppercorn", + "cloves", + "ripe plantains", + }, + ), + ( + "waakye", + "Waakye", + { + "salt", + "coconut oil", + "water", + "white rice", + "sorghum stems", + "black-eyed peas", + "baking soda", + }, + ), + ( + "georgian_eggplant_rolls_with_walnuts", + "Georgian Eggplant Rolls with Walnuts", + { + "salt", + "coriander", + "pomegranate seeds", + "oil", + "water", + "vinegar", + "garlic", + "eggplants", + "black pepper", + "khmeli suneli", + "walnuts", + }, + ), + ( + "burmese_tofu_with_garlic,_ginger_and_chili_sauce", + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + { + "salt", + "rice vinegar", + "oil", + "water", + "turmeric", + "chili flakes", + "spring onions", + "brown sugar", + "garlic", + "chickpea flour", + "ginger", + "soy sauce", + "peanuts", + }, + ), + ( + "celeriac_schnitzel", + "Celeriac Schnitzel", + { + "salt", + "parsley", + "water", + "sunflower oil", + "flour", + "breadcrumbs", + "lemon", + "celeriac", + "chickpea flour", + "soy sauce", + "black pepper", + }, + ), + ( + "sticky_lemon_tofu", + "Sticky Lemon Tofu", + { + "salt", + "water", + "tofu", + "cornstarch", + "vegetable stock", + "vegetable oil", + "lemon juice", + "garlic", + "black pepper", + "ginger", + "soy sauce", + "sugar", + "lemon zest", + }, + ), + ( + "vegan_carbonara", + "Vegan Carbonara", + { + "salt", + "turmeric", + "spaghetti", + "lemon juice", + "olive oil", + "garlic", + "black pepper", + "nutritional yeast", + "soy sauce", + "smoked tofu", + "silken tofu", + "mixed herbs", + }, + ), + ( + "vegan_pizza_with_caramelized_onions", + "Vegan Pizza with Caramelized Onions", + { + "red pepper flakes", + "garlic", + "cashews", + "fresh basil", + "flour", + "tomatoes", + "red onion", + "oregano", + "nutritional yeast", + "rosemary", + "water", + "bell pepper", + "honey", + "barley malt", + "olive oil", + "salt", + "garlic powder", + "mushrooms", + "yeast", + "sugar", + }, + ), + ( + "cheela_with_spicy_mango_chutney", + "Cheela with Spicy Mango Chutney", + { + "hing", + "curry leaves", + "mangoes", + "garlic", + "nigella seeds", + "garlic paste", + "coriander seeds", + "oil", + "turmeric", + "red chili powder", + "coriander powder", + "cardamom powder", + "turmeric powder", + "clove powder", + "water", + "cumin powder", + "fresh ginger", + "vinegar", + "cinnamon powder", + "cilantro", + "chickpea flour", + "onion", + "salt", + "mango powder", + "fresh red chili", + "mashed potatoes", + "mustard seeds", + "serrano chili", + "garam masala", + "sugar", + }, + ), + ( + "sweet_and_spicy_crispy_green_beans", + "Sweet and Spicy Crispy Green Beans", + { + "sesame oil", + "siracha", + "sunflower oil", + "pomegranate molasses", + "sesame seeds", + "green beans", + "carrot", + "scallions", + "garlic", + "ginger", + "soy sauce", + "tomato paste", + "bell pepper", + }, + ), + ( + "vegan_mini_savory_mince_pies", + "Vegan Mini Savory Mince Pies", + { + "apples", + "brandy", + "pecans", + "raisins", + "brown sugar", + "lemon zest", + "dried blueberries", + "vegetarian worcestershire sauce", + "orange zest", + "butternut squash", + "corn flour", + "rosemary", + "vegetable stock", + "carrot", + "figs", + "cinnamon powder", + "olive oil", + "orange juice", + "black pepper", + "onion", + "dried cherries", + "salt", + "dried cranberries", + "parev shortcrust pastry", + "mushrooms", + "allspice powder", + "lemon juice", + "ginger", + "currants", + }, + ), + ( + "roasted_corn_and_zucchini_salad", + "Roasted Corn and Zucchini Salad", + { + "zucchini", + "tomatoes", + "green onions", + "corn", + "lemon juice", + "olive oil", + "black pepper", + "lemon zest", + "dill", + }, + ), + ( + "golden_potato_salad", + "Golden Potato Salad", + { + "salt", + "yukon gold potato", + "turmeric", + "balsamic vinegar", + "cumin seeds", + "lemon juice", + "olive oil", + "garlic", + "mustard seeds", + "black pepper", + "chives", + }, + ), + ( + "carrot_puff_pastry_tart", + "Carrot Puff Pastry Tart", + { + "salt", + "water", + "lemon", + "thyme", + "red onion", + "carrot", + "lemon juice", + "pareve puff pastry", + "ground almonds", + "brown sugar", + "olive oil", + "garlic", + "black pepper", + "vegan butter", + }, + ), + ( + "mushroom_lasagna", + "Mushroom Lasagna", + { + "dried lasagna noodles", + "portobello mushrooms", + "nutmeg", + "flour", + "kosher salt", + "milk", + "olive oil", + "garlic", + "onions", + "butter", + "black pepper", + "parmesan cheese", + }, + ), + ( + "nut_wellington", + "Nut Wellington", + { + "apples", + "eggs", + "hazelnuts", + "pecans", + "thyme", + "dates", + "cashews", + "breadcrumbs", + "almonds", + "marmite", + "sage", + "leeks", + "olive oil", + "black pepper", + "walnuts", + "salt", + "chestnuts", + "brazil nuts", + "butter", + "puff pastry sheets", + }, + ), + ( + "white_cheddar_scalloped_potatoes", + "White Cheddar Scalloped Potatoes", + { + "yukon gold potato", + "shallots", + "cream", + "thyme", + "breadcrumbs", + "sharp white cheddar", + "kosher salt", + "milk", + "garlic", + }, + ), + ( + "winter_cobb_salad", + "Winter Cobb Salad", + { + "lacinato kale", + "eggs", + "red wine vinegar", + "shiitake mushrooms", + "tomatoes", + "avocados", + "olive oil", + "blue cheese", + "garlic", + "black pepper", + "onion", + "smoked tofu", + }, + ), + ( + "roast_pumpkin_and_lentil_salad_with_roasted_lemon_dressing", + "Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing", + { + "red wine vinegar", + "dijon mustard", + "lemon", + "honey", + "red onion", + "feta cheese", + "olive oil", + "capers", + "pepitas", + "fresh pumpkin", + "watercress", + "green lentils", + "currants", + }, + ), + ( + "cambodian-style_vegetable_spring_rolls", + "Cambodian-Style Vegetable Spring Rolls", + { + "sunflower oil", + "vegetarian fish sauce", + "shallots", + "vermicelli noodles", + "wombok", + "firm tofu", + "lime juice", + "corn flour", + "palm sugar", + "bean sprouts", + "spring roll wrappers", + "garlic", + "red chili", + "soy sauce", + "toasted peanuts", + "carrot", + }, + ), + ( + "summer_minestrone_cups", + "Summer Minestrone Cups", + { + "leek", + "garlic", + "lemon zest", + "tomatoes", + "red chili", + "chickpeas", + "rosemary", + "carrot", + "vegetable bullion", + "fresh corn", + "fresh peas", + "green beans", + "olive oil", + "parmesan cheese", + "croutons", + "celery", + "mint", + "basil", + "green lentils", + "parmesan rind", + }, + ), + ( + "fried_zucchini_with_balsamic_and_chili_dressing", + "Fried Zucchini with Balsamic and Chili Dressing", + { + "zucchini", + "balsamic vinegar", + "honey", + "red onion", + "lemon juice", + "olive oil", + "mint leaves", + "garlic", + "red thai chili", + "pomegranate", + }, + ), + ( + "barley_risotto", + "Barley Risotto", + { + "beets", + "white wine", + "thyme", + "red onion", + "carrot", + "butternut squash", + "olive oil", + "sage", + "garlic", + "brussel sprouts", + "rosemary", + "black pepper", + "parmesan cheese", + "pearl barley", + "vegetable bullion", + }, + ), + ( + "cherry_tomato,_watercress_and_fava_bean_salad", + "Cherry Tomato, Watercress and Fava Bean Salad", + { + "salt", + "fresh or frozen fava beans", + "fresh peas", + "balsamic vinegar", + "olive oil", + "garlic", + "watercress", + "fresh cherry bocconcini", + "fresh cherry tomatoes", + }, + ), + ( + "fresh_garden_peas_over_cauliflower_almond_puree", + "Fresh Garden Peas over Cauliflower Almond Puree", + { + "grated nutmeg", + "red onions", + "lemon", + "fresh peas", + "cream", + "vegetable oil", + "olive oil", + "garlic", + "blanched almonds", + "cauliflower", + "fresh pea tendrils", + }, + ), + ( + "walnut_ravioli_with_artichokes_and_tomatoes", + "Walnut Ravioli with Artichokes and Tomatoes", + { + "salt", + "fresh tomatoes", + "ricotta cheese", + "lemon zest", + "olives", + "red onion", + "lemon juice", + "black pepper", + "rosemary", + "butter", + "basil", + "fresh artichoke hearts", + "pasta sheets", + "pine nuts", + "walnuts", + "oil marinated artichokes", + }, + ), + ( + "asparagus_puffs", + "Asparagus Puffs", + { + "salt", + "asparagus", + "ricotta cheese", + "thyme", + "puff pastry", + "red onion", + "eggs", + "lemon juice", + "black pepper", + "parmesan cheese", + "chives", + }, + ), + ( + "grilled_tofu_tacos", + "Grilled Tofu Tacos", + { + "carrot", + "red cabbage", + "ancho chili", + "limes", + "hot water", + "garlic", + "roasted corn", + "masa", + "pasilla chili", + "lemon", + "tomatoes", + "cumin", + "fresh cilantro leaves", + "chipotle chili", + "red onions", + "pepitas", + "tomatillos", + "black beans", + "cotija cheese", + "crema", + "firm tofu", + "lemon juice", + "jalapeño chili", + "avocado", + }, + ), + ( + "zucchini_fritters_with_lemon-thyme_coconut_yogurt", + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + { + "salt", + "coconut oil", + "eggs", + "fresh thai chili", + "coconut yogurt", + "zucchini", + "lemon juice", + "black pepper", + "coconut flour", + "chives", + "lemon zest", + "baking soda", + }, + ), + ( + "avocado_deviled_eggs", + "Avocado Deviled Eggs", + { + "salt", + "eggs", + "garlic powder", + "seranno chili", + "avocado", + "lime juice", + "pepitas", + "fresh cilantro leaves", + }, + ), + ( + "grilled_flank_steak_with_caesar_salad", + "Grilled Flank Steak with Caesar Salad", + { + "flank steak", + "avocado oil", + "treviso", + "scallions", + "garlic", + "cherry tomatoes", + "pine nuts", + "white vinegar", + "chipotle chili", + "dijon mustard", + "olive oil", + "avocado mayonnaise", + "black pepper", + "paleo parmesan cheese", + "castelfranco radicchio", + "fresh parsley", + "salt", + "worcestershire sauce", + "radishes", + }, + ), + ( + "pumpkin_bread_crostini", + "Pumpkin Bread Crostini", + { + "eggs", + "nutmeg", + "cinnamon", + "garlic", + "pumpkin puree", + "apple cider vinegar", + "cherry tomatoes", + "onions", + "coconut flour", + "cloves", + "shrimp", + "coconut oil", + "honey", + "olive oil", + "black pepper", + "almond butter", + "salt", + "fresh red chili", + "basil", + "baking soda", + }, + ), + ( + "blt_bites", + "BLT Bites", + { + "paleo mayonnaise", + "bacon", + "kale", + "cherry tomatoes", + "mustard seed", + "onion", + }, + ), + ( + "roasted_chicken_with_roasted_tomatoes,_avocado,_and_sweet_potatoes", + "Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes", + { + "safflower oil", + "shallots", + "whole chicken", + "lemons", + "tomatoes", + "purple sweet potato", + "avocados", + "limes", + "kosher salt", + "olive oil", + "mexican oregano", + "garlic", + "black pepper", + "cumin", + "chiles de árbol", + }, + ), + ( + "chicken_with_tamarind_and_apricot_sauce", + "Chicken with Tamarind and Apricot Sauce", + { + "cinnamon", + "garlic", + "cider vinegar", + "chipotles", + "homemade tamarind concentrate", + "roma tomatoes", + "white chicken", + "ground cumin", + "water", + "safflower oil", + "allspice", + "dried apricots", + "honey", + "olive oil", + "black pepper", + "salt", + "homemade apricot honey preserves", + "kosher salt", + "chili powder", + }, + ), + ( + "grilled_fish_tacos_with_cauliflower_tortillas", + "Grilled Fish Tacos with Cauliflower Tortillas", + { + "salt", + "eggs", + "smoked paprika", + "shredded red cabbage", + "mango", + "green onions", + "lime", + "cumin", + "tilapia", + "cilantro", + "black pepper", + "serrano chili", + "cauliflower", + "avocado", + }, + ), + ( + "grilled_pork_chops_with_mango_pineapple_salsa", + "Grilled Pork Chops with Mango Pineapple Salsa", + { + "pork chops", + "lacinato kale", + "chipotle chili", + "serrano chili", + "lime zest", + "pineapple", + "lime", + "garlic", + "onions", + "mangoes", + "cauliflower", + "avocado", + "cilantro leaves", + }, + ), + ( + "grilled_shrimp_and_pesto_over_zucchini_noodles", + "Grilled Shrimp and Pesto over Zucchini Noodles", + { + "salt", + "green bell pepper", + "cashews", + "zucchini", + "tomatoes", + "red bell pepper", + "cumin", + "lemon juice", + "yellow bell pepper", + "olive oil", + "garlic", + "pine nuts", + "basil", + "lemon zest", + "shrimp", + }, + ), + ( + "cauliflower_pizza_with_roasted_tomatoes_and_chicken", + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + { + "roasted chicken", + "eggs", + "fresh basil", + "olive oil", + "almond meal", + "cherry tomatoes", + "rosemary", + "cauliflower", + "mozzarella cheese", + "tomato paste", + "parmesan", + }, + ), + ( + "flank_steak_with_chimichurri_and_asparagus", + "Flank Steak with Chimichurri and Asparagus", + { + "fresh parsley", + "salt", + "asparagus", + "chipotle chili", + "flank steak", + "scallions", + "olive oil", + "garlic", + "black pepper", + "cauliflower", + "white vinegar", + "sour cream", + }, + ), + ( + "kingfish_lettuce_cups", + "Kingfish Lettuce Cups", + { + "oyster sauce", + "fish sauce", + "spring onions", + "sesame seeds", + "grilled king fish", + "little gem lettuce heads", + "mirin", + "red cabbage", + "lime juice", + "peanut oil", + "garlic", + "watermelon radishes", + "soy sauce", + "avocado", + }, + ), + ( + "butter_chicken_with_grilled_mushrooms,_brussel_sprouts_and_mango_chutney", + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + { + "hing", + "curry leaves", + "cashew nuts", + "green chili", + "cinnamon", + "mangoes", + "garlic", + "nigella seeds", + "garlic paste", + "coriander seeds", + "turmeric", + "ginger garlic paste", + "tomatoes", + "red chili powder", + "coriander powder", + "cardamom powder", + "turmeric powder", + "clove powder", + "cloves", + "heavy cream", + "cardamom", + "fresh greek yogurt", + "monk fruit", + "fresh ginger", + "cumin powder", + "vinegar", + "cinnamon powder", + "cilantro", + "brussel sprouts", + "whole small crimini mushrooms", + "salt", + "boned chicken", + "red chili flakes", + "mango powder", + "fresh red chili", + "lemon juice", + "garam masala", + "butter", + "ginger", + "mustard seeds", + "chicken", + "dried fenugreek leaves", + }, + ), + ( + "prawn_and_herb_omelette", + "Prawn and Herb Omelette", + { + "salt", + "parsley", + "eggs", + "fresh cucumber", + "sesame seeds", + "green onions", + "monk fruit", + "lemon juice", + "olive oil", + "tahini", + "harissa", + "black pepper", + "butter", + "onion", + "fennel bulb", + "chives", + "shrimp", + "dill", + }, + ), + ( + "satay_steak_skewers", + "Satay Steak Skewers", + { + "flank steak", + "red and green thai chili", + "kecap manis", + "fish sauce", + "monk fruit", + "micro cilantro", + "carrot", + "apple cider vinegar", + "sriacha", + "lime juice", + "olive oil", + "cucumbers", + "roasted peanuts", + "crunchy peanut butter", + "peanuts", + }, + ), + ( + "parmesan_crackers_and_spinach_crackers_with_salmon_pate", + "Parmesan Crackers and Spinach Crackers with Salmon Pate", + { + "fresh cucumber", + "pecans", + "ghee", + "garlic", + "chives", + "flaxmeal", + "chili flakes", + "almond flour", + "salmon fillets", + "red onion", + "cherry tomatoes", + "coconut flour", + "cumin", + "spinach", + "cream cheese", + "avocado mayonnaise", + "black pepper", + "parmesan cheese", + "salt", + "lemon juice", + }, + ), + ( + "pork_chops_with_grilled_castelfranco_radicchio_and_asparagus", + "Pork Chops with Grilled Castelfranco Radicchio and Asparagus", + { + "pork chops", + "salt", + "asparagus", + "eggs", + "dijon mustard", + "avocado oil", + "lemon", + "thyme", + "monk fruit", + "oregano", + "avocado mayonnaise", + "garlic", + "black pepper", + "rosemary", + "butter", + "basil", + "castelfranco radicchio", + "dill", + }, + ), + ( + "seared_salmon_with_pickled_vegetable_and_watercress_salad", + "Seared Salmon with Pickled Vegetable and Watercress Salad", + { + "red wine vinegar", + "caster sugar", + "salmon steaks", + "radishes", + "shallots", + "red onion", + "pink peppercorns", + "toasted buckwheat", + "lemon juice", + "lime juice", + "red cabbage", + "watercress", + "fennel seeds", + "dutch carrot", + }, + ), + ( + "braised_pork_belly_with_apple_salad", + "Braised Pork Belly with Apple Salad", + { + "spring onions", + "dark soy sauce", + "light soy sauce", + "pork belly", + "monk fruit", + "green cabbage", + "star anise", + "sesame seeds", + "lemon juice", + "olive oil", + "black pepper", + "ginger", + "cinnamon sticks", + "granny smith apples", + "cilantro leaves", + }, + ), + ( + "beachside_snapper", + "Beachside Snapper", + { + "yellow mustard", + "mayonnaise", + "limes", + "white onion", + "red snapper", + "fresh corn tortillas", + "tomatoes", + "red onion", + "lime juice", + "soy sauce", + "mexican crema", + "salsa", + "garlic cloves", + "green bell pepper", + "olive oil", + "black pepper", + "salt", + "yellow bell pepper", + "worcestershire sauce", + "anaheim chili", + "butter", + "red bell pepper", + }, + ), + ( + "governor_shrimp_tacos", + "Governor Shrimp Tacos", + { + "chile manzano", + "worcestershire sauce", + "oaxaca cheese", + "garlic cloves", + "red onion", + "avocado", + "lime juice", + "kosher salt", + "white onion", + "chipotle adobo sauce", + "poblano chili", + "fresh corn tortillas", + "butter", + "black pepper", + "pepitas", + "tomato paste", + "roma tomatoes", + "shelled large shrimp", + }, + ), + ( + "shrimp,_bacon_and_crispy_chickpea_tacos_with_salsa_de_guacamole", + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", + { + "fresh tortillas", + "slivered almonds", + "bacon", + "sea salt", + "chickpeas", + "olive oil", + "guajillo chile", + "garlic", + "butter", + "black pepper", + "onion", + "shrimp", + "avocado", + }, + ), + ( + "burnt_masala_wings_with_classic_coleslaw", + "Burnt Masala Wings with Classic Coleslaw", + { + "mayonnaise", + "carrot", + "red cabbage", + "green cabbage", + "apple cider vinegar", + "lime juice", + "cloves", + "cinnamon sticks", + "sriracha", + "celery seeds", + "chicken wings", + "garlic cloves", + "honey", + "olive oil", + "cilantro", + "black pepper", + "chiles de árbol", + "tamarind concentrate", + "green cardamom", + "black cardamom", + "lemon juice", + "kosher salt", + "serrano chili", + "ginger", + "black peppercorns", + "butter", + }, + ), + ( + "dahi_puri_with_black_chickpeas", + "Dahi Puri with Black Chickpeas", + { + "roasted chicken", + "scallion chutney", + "yukon gold potato", + "turmeric", + "black chickpeas", + "whole-milk yogurt", + "chili powder", + "red onion", + "pani puri", + "ginger", + "mint", + "thin sev", + "date syrup", + "cumin", + "chaat masala", + "tamarind concentrate", + }, + ), + ( + "brisket_with_grilled_rhubarb,_onions,_and_fennel", + "Brisket with Grilled Rhubarb, Onions, and Fennel", + { + "crushed red pepper flakes", + "rhubarb", + "thyme", + "yellow onion", + "garlic", + "brown sugar", + "beer", + "lemon", + "red onion", + "oregano", + "soy sauce", + "white vinegar", + "beef brisket", + "parsley", + "marjoram", + "balsamic vinegar", + "vegetable oil", + "fennel bulbs", + "cilantro", + "black pepper", + "worcestershire sauce", + "celery", + "kosher salt", + "mint", + "chili powder", + }, + ), + ( + "roast_leg_of_lamb_with_crispy_moroccan_carrots_&_couscous", + "Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous", + { + "bay leaves", + "fresh thyme", + "carrot", + "tahini", + "garlic", + "baby carrot", + "oranges", + "filo pastry", + "tomatoes", + "harissa", + "onions", + "rosemary", + "leg of lamb", + "vegetable bullion", + "sesame seeds", + "honey", + "anchovy fillets", + "vinegar", + "olive oil", + "couscous", + "fresh mint", + "celery", + "yoghurt", + }, + ), + ( + "baked_chicken_jollof_rice", + "Baked Chicken Jollof Rice", + { + "coriander", + "salt", + "white pepper", + "water", + "bell pepper", + "turmeric", + "rice", + "scotch bonnet pepper", + "chicken", + "thyme", + "maggi cubes", + "garlic", + "ginger", + "onion", + "tomato", + "carrot", + "tomato puree", + }, + ), + ( + "seafood_risotto", + "Seafood Risotto", + { + "white wine", + "water", + "clams", + "crab legs", + "baby squid", + "lemon juice", + "parmesan cheese", + "olive oil", + "white onion", + "garlic", + "arborio risotto rice", + "fish stock", + "mussels", + "flat-leaf parsley", + "tomato paste", + "prawns", + "baby scallops", + "cherry tomatoes", + }, + ), + ( + "lamb_over_marinated_summer_squash_with_hazelnuts_and_ricotta", + "Lamb over Marinated Summer Squash with Hazelnuts and Ricotta", + { + "red pepper flakes", + "hazelnuts", + "zucchini", + "bay leaves", + "carrot", + "garlic", + "white wine vinegar", + "toasted bread", + "lemon", + "onions", + "rosemary", + "leg of lamb", + "summer squash", + "sea salt", + "anchovy fillets", + "vinegar", + "olive oil", + "black pepper", + "fresh mint", + "celery", + "kosher salt", + "fresh ricotta", + "sugar", + }, + ), +] ############################## # Data for test_check_drinks # ############################## -all_drinks = [('Amaretto Sour', ['almond liqueur', 'bourbon', 'cherries', 'egg white', 'lemon juice', 'lemon twist', 'simple syrup']), - ('Aperol Spritz', ['aperol', 'prosecco', 'soda water']), - ('Bannana Punch', ['banana', 'ginger ale', 'lemonade', 'orange juice', 'pineapple juice', 'sugar', 'water']), - ('Beet Sumac Soda', ['beet', 'club soda', 'fresh lemon juice', 'sugar', 'sumac']), - ('Better Than Celery Juice', ['apple cider vinegar', 'black pepper', 'celery stalks', 'club soda', 'granny smith apples', 'kosher salt', 'parsley']), - ('Black & Blue Berries', ['blackberries', 'blueberries', 'honey', 'lemon juice', 'soda water']), - ('Bloody Mary', ['celery', 'celery salt', 'lemon juice', 'pepper', 'tomato juice', 'vodka', 'worcestershire sauce']), - ('Bloody Shame', ['V8 juice', 'black pepper', 'celery', 'salt', 'tabasco sauce']), - ('Chai Blossom', ['chai tea bags', 'club soda', 'fresh lime juice', 'lemon twists', 'start anise pods', 'sugar']), - ('Chile-lime Pineapple Soda', ['chiles de árbol', 'club soda', 'fresh pineapple juice', 'kosher salt', 'lime juice', 'lime wedges', 'pink peppercorns', 'sugar']), - ('Citrus Fizz', ['organic marmalade cordial', 'seedlip grove 42', 'sparkling water']), - ('Dry Martini', ['dry vermouth', 'gin', 'lemon twist', 'olives']), - ('Espresso Martini', ['coffee liqueur', 'espresso', 'sugar syrup', 'vodka']), - ('Fermented Grape Soda', ['red seedless grapes', 'sugar', 'washed organic ginger']), - ('French 75', ['champagne', 'gin', 'lemon juice', 'sugar syrup']), - ('Gimlet', ['gin', 'lime juice', 'sugar syrup']), - ('Gin Fizz', ['gin', 'lemon juice', 'soda water', 'sugar syrup']), - ('Huckleberry Shrub', ['club soda', 'huckleberries', 'sugar', 'white wine vinegar']), - ('Mai Tai', ['cherries', 'lime juice', 'lime wedge', 'mint leaves', 'orange curacao', 'orgeat syrup', 'rum', 'sugar syrup']), - ('Mango Mule', ['cucumber', 'fresh lime juice', 'ginger beer', 'honey syrup', 'ice', 'mango puree']), - ('Manhattan', ['bitters', 'cherry', 'rye', 'sweet vermouth']), - ('Maple-Ginger Cider Switchel', ['apple cider vinegar', 'club soda', 'fresh ginger', 'fresh lime juice', 'maple syrup', 'mint sprigs']), - ('Margarita', ['lime juice', 'salt', 'simple syrup', 'tequila', 'triple sec']), - ('Mojito', ['lime', 'mint leaves', 'soda water', 'sugar syrup', 'white rum']), - ('Moscow Mule', ['ginger beer', 'lime', 'lime juice', 'vodka']), - ('Negroni', ['bitters', 'gin', 'sweet vermouth']), - ('Old Fashioned', ['bitters', 'bourbon', 'orange juice', 'orange slices', 'sugar']), - ('PG13 Singapore Sling', ['fresh lime juice', 'mango juice', 'mint sprigs', 'pineapple juice', 'pomegranate juice', 'tonic water']), - ('Penicillin', ['ginger', 'honey simple syrup', 'lemon juice', 'scotch']), - ('Pina Colada', ['cherries', 'coconut milk', 'cream of coconut', 'dark rum', 'fresh pineapple', 'lime juice', 'white rum']), - ('Raspberry Almond Soda', ['almonds', 'club soda', 'kosher salt', 'limes', 'ripe raspberries', 'sugar']), - ('Salted Meyer Lemon and Sage Presse', ['club soda meyer lemons', 'kosher salt', 'sage leaves', 'simple syrup']), - ('Salted Watermelon Juice', ['cubed watermelon', 'kosher salt', 'lime wedges']), - ('Shirley Tonic', ['cinnamon sticks', 'club soda', 'ginger', 'lemon twists', 'pomegranate juice', 'sugar', 'whole cloves']), - ('Shirley ginger', ['brooklyn crafted lemon lime ginger beer', 'club soda', 'grenadine', 'lime juice']), - ('Spiced Hibiscus Tea', ['cinnamon sticks', 'dried hibiscus flowers', 'ginger', 'honey', 'lemon juice', 'lemon wheels', 'whole allspice']), - ('Turmeric Tonic', ['agave syrup', 'cayenne pepper', 'lemon', 'peeled ginger', 'peeled turmeric', 'sparkling water']), - ('Virgin Cucumber Gimlet', [';ime juice', 'club soda', 'muddled cucumber', 'simple syrup']), - ('Whiskey Sour', ['cherry', 'lemon juice', 'lemon slices', 'superfine sugar', 'whiskey']) - ] - -drink_names = ['Amaretto Sour Cocktail','Aperol Spritz Cocktail','Bannana Punch Mocktail','Beet Sumac Soda Mocktail', - 'Better Than Celery Juice Mocktail','Black & Blue Berries Mocktail','Bloody Mary Cocktail', - 'Bloody Shame Mocktail','Chai Blossom Mocktail','Chile-lime Pineapple Soda Mocktail', - 'Citrus Fizz Mocktail','Dry Martini Cocktail','Espresso Martini Cocktail','Fermented Grape Soda Mocktail', - 'French 75 Cocktail','Gimlet Cocktail','Gin Fizz Cocktail','Huckleberry Shrub Mocktail', - 'Mai Tai Cocktail','Mango Mule Mocktail','Manhattan Cocktail','Maple-Ginger Cider Switchel Mocktail', - 'Margarita Cocktail','Mojito Cocktail','Moscow Mule Cocktail','Negroni Cocktail', - 'Old Fashioned Cocktail','PG13 Singapore Sling Mocktail','Penicillin Cocktail','Pina Colada Cocktail', - 'Raspberry Almond Soda Mocktail','Salted Meyer Lemon and Sage Presse Mocktail', - 'Salted Watermelon Juice Mocktail','Shirley Tonic Mocktail','Shirley ginger Mocktail', - 'Spiced Hibiscus Tea Mocktail','Turmeric Tonic Mocktail','Virgin Cucumber Gimlet Mocktail', - 'Whiskey Sour Cocktail'] +all_drinks = [ + ( + "Amaretto Sour", + [ + "almond liqueur", + "bourbon", + "cherries", + "egg white", + "lemon juice", + "lemon twist", + "simple syrup", + ], + ), + ("Aperol Spritz", ["aperol", "prosecco", "soda water"]), + ( + "Bannana Punch", + [ + "banana", + "ginger ale", + "lemonade", + "orange juice", + "pineapple juice", + "sugar", + "water", + ], + ), + ("Beet Sumac Soda", ["beet", "club soda", "fresh lemon juice", "sugar", "sumac"]), + ( + "Better Than Celery Juice", + [ + "apple cider vinegar", + "black pepper", + "celery stalks", + "club soda", + "granny smith apples", + "kosher salt", + "parsley", + ], + ), + ( + "Black & Blue Berries", + ["blackberries", "blueberries", "honey", "lemon juice", "soda water"], + ), + ( + "Bloody Mary", + [ + "celery", + "celery salt", + "lemon juice", + "pepper", + "tomato juice", + "vodka", + "worcestershire sauce", + ], + ), + ("Bloody Shame", ["V8 juice", "black pepper", "celery", "salt", "tabasco sauce"]), + ( + "Chai Blossom", + [ + "chai tea bags", + "club soda", + "fresh lime juice", + "lemon twists", + "start anise pods", + "sugar", + ], + ), + ( + "Chile-lime Pineapple Soda", + [ + "chiles de árbol", + "club soda", + "fresh pineapple juice", + "kosher salt", + "lime juice", + "lime wedges", + "pink peppercorns", + "sugar", + ], + ), + ( + "Citrus Fizz", + ["organic marmalade cordial", "seedlip grove 42", "sparkling water"], + ), + ("Dry Martini", ["dry vermouth", "gin", "lemon twist", "olives"]), + ("Espresso Martini", ["coffee liqueur", "espresso", "sugar syrup", "vodka"]), + ("Fermented Grape Soda", ["red seedless grapes", "sugar", "washed organic ginger"]), + ("French 75", ["champagne", "gin", "lemon juice", "sugar syrup"]), + ("Gimlet", ["gin", "lime juice", "sugar syrup"]), + ("Gin Fizz", ["gin", "lemon juice", "soda water", "sugar syrup"]), + ( + "Huckleberry Shrub", + ["club soda", "huckleberries", "sugar", "white wine vinegar"], + ), + ( + "Mai Tai", + [ + "cherries", + "lime juice", + "lime wedge", + "mint leaves", + "orange curacao", + "orgeat syrup", + "rum", + "sugar syrup", + ], + ), + ( + "Mango Mule", + [ + "cucumber", + "fresh lime juice", + "ginger beer", + "honey syrup", + "ice", + "mango puree", + ], + ), + ("Manhattan", ["bitters", "cherry", "rye", "sweet vermouth"]), + ( + "Maple-Ginger Cider Switchel", + [ + "apple cider vinegar", + "club soda", + "fresh ginger", + "fresh lime juice", + "maple syrup", + "mint sprigs", + ], + ), + ("Margarita", ["lime juice", "salt", "simple syrup", "tequila", "triple sec"]), + ("Mojito", ["lime", "mint leaves", "soda water", "sugar syrup", "white rum"]), + ("Moscow Mule", ["ginger beer", "lime", "lime juice", "vodka"]), + ("Negroni", ["bitters", "gin", "sweet vermouth"]), + ("Old Fashioned", ["bitters", "bourbon", "orange juice", "orange slices", "sugar"]), + ( + "PG13 Singapore Sling", + [ + "fresh lime juice", + "mango juice", + "mint sprigs", + "pineapple juice", + "pomegranate juice", + "tonic water", + ], + ), + ("Penicillin", ["ginger", "honey simple syrup", "lemon juice", "scotch"]), + ( + "Pina Colada", + [ + "cherries", + "coconut milk", + "cream of coconut", + "dark rum", + "fresh pineapple", + "lime juice", + "white rum", + ], + ), + ( + "Raspberry Almond Soda", + ["almonds", "club soda", "kosher salt", "limes", "ripe raspberries", "sugar"], + ), + ( + "Salted Meyer Lemon and Sage Presse", + ["club soda meyer lemons", "kosher salt", "sage leaves", "simple syrup"], + ), + ("Salted Watermelon Juice", ["cubed watermelon", "kosher salt", "lime wedges"]), + ( + "Shirley Tonic", + [ + "cinnamon sticks", + "club soda", + "ginger", + "lemon twists", + "pomegranate juice", + "sugar", + "whole cloves", + ], + ), + ( + "Shirley ginger", + [ + "brooklyn crafted lemon lime ginger beer", + "club soda", + "grenadine", + "lime juice", + ], + ), + ( + "Spiced Hibiscus Tea", + [ + "cinnamon sticks", + "dried hibiscus flowers", + "ginger", + "honey", + "lemon juice", + "lemon wheels", + "whole allspice", + ], + ), + ( + "Turmeric Tonic", + [ + "agave syrup", + "cayenne pepper", + "lemon", + "peeled ginger", + "peeled turmeric", + "sparkling water", + ], + ), + ( + "Virgin Cucumber Gimlet", + [";ime juice", "club soda", "muddled cucumber", "simple syrup"], + ), + ( + "Whiskey Sour", + ["cherry", "lemon juice", "lemon slices", "superfine sugar", "whiskey"], + ), +] + +drink_names = [ + "Amaretto Sour Cocktail", + "Aperol Spritz Cocktail", + "Bannana Punch Mocktail", + "Beet Sumac Soda Mocktail", + "Better Than Celery Juice Mocktail", + "Black & Blue Berries Mocktail", + "Bloody Mary Cocktail", + "Bloody Shame Mocktail", + "Chai Blossom Mocktail", + "Chile-lime Pineapple Soda Mocktail", + "Citrus Fizz Mocktail", + "Dry Martini Cocktail", + "Espresso Martini Cocktail", + "Fermented Grape Soda Mocktail", + "French 75 Cocktail", + "Gimlet Cocktail", + "Gin Fizz Cocktail", + "Huckleberry Shrub Mocktail", + "Mai Tai Cocktail", + "Mango Mule Mocktail", + "Manhattan Cocktail", + "Maple-Ginger Cider Switchel Mocktail", + "Margarita Cocktail", + "Mojito Cocktail", + "Moscow Mule Cocktail", + "Negroni Cocktail", + "Old Fashioned Cocktail", + "PG13 Singapore Sling Mocktail", + "Penicillin Cocktail", + "Pina Colada Cocktail", + "Raspberry Almond Soda Mocktail", + "Salted Meyer Lemon and Sage Presse Mocktail", + "Salted Watermelon Juice Mocktail", + "Shirley Tonic Mocktail", + "Shirley ginger Mocktail", + "Spiced Hibiscus Tea Mocktail", + "Turmeric Tonic Mocktail", + "Virgin Cucumber Gimlet Mocktail", + "Whiskey Sour Cocktail", +] ################################# @@ -211,67 +3229,69 @@ all_dishes = recipes_without_duplicates -dishes_categorized = ['Zucchini Fritters with Lemon-Thyme Coconut Yogurt: PALEO', - 'Winter Cobb Salad: VEGETARIAN', - 'White Cheddar Scalloped Potatoes: VEGETARIAN', - 'Walnut Ravioli with Artichokes and Tomatoes: VEGETARIAN', - 'Waakye: VEGAN', - 'Vegetarian Khoresh Bademjan: VEGAN', - 'Vegan Pizza with Caramelized Onions: VEGAN', - 'Vegan Mini Savory Mince Pies: VEGAN', - 'Vegan Carbonara: VEGAN', - 'Sweet and Spicy Crispy Green Beans: VEGAN', - 'Summer Minestrone Cups: VEGETARIAN', - 'Sticky Lemon Tofu: VEGAN', - 'Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole: OMNIVORE', - 'Shakshuka: VEGAN', - 'Seared Salmon with Pickled Vegetable and Watercress Salad: KETO', - 'Seafood Risotto: OMNIVORE', - 'Satay Steak Skewers: KETO', - 'Roasted Corn and Zucchini Salad: VEGAN', - 'Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes: PALEO', - 'Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing: VEGETARIAN', - 'Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous: OMNIVORE', - 'Pumpkin Bread Crostini: PALEO', - 'Prawn and Herb Omelette: KETO', - 'Pork Chops with Grilled Castelfranco Radicchio and Asparagus: KETO', - 'Parmesan Crackers and Spinach Crackers with Salmon Pate: KETO', - 'Nut Wellington: VEGETARIAN', - 'Mushroom Lasagna: VEGETARIAN', - 'Lamb over Marinated Summer Squash with Hazelnuts and Ricotta: OMNIVORE', - 'Kisir with Warm Pita: VEGAN', - 'Kingfish Lettuce Cups: KETO', - 'Grilled Tofu Tacos: VEGETARIAN', - 'Grilled Shrimp and Pesto over Zucchini Noodles: PALEO', - 'Grilled Pork Chops with Mango Pineapple Salsa: PALEO', - 'Grilled Flank Steak with Caesar Salad: PALEO', - 'Grilled Fish Tacos with Cauliflower Tortillas: PALEO', - 'Governor Shrimp Tacos: OMNIVORE', - 'Golden Potato Salad: VEGAN', - 'Georgian Eggplant Rolls with Walnuts: VEGAN', - 'Fried Zucchini with Balsamic and Chili Dressing: VEGETARIAN', - 'Fresh Garden Peas over Cauliflower Almond Puree: VEGETARIAN', - 'Flank Steak with Chimichurri and Asparagus: KETO', - 'Dahi Puri with Black Chickpeas: OMNIVORE', - 'Chicken with Tamarind and Apricot Sauce: PALEO', - 'Cherry Tomato, Watercress and Fava Bean Salad: VEGETARIAN', - 'Cheela with Spicy Mango Chutney: VEGAN', - 'Celeriac Schnitzel: VEGAN', - 'Cauliflower Pizza with Roasted Tomatoes and Chicken: KETO', - 'Carrot Puff Pastry Tart: VEGAN', - 'Cambodian-Style Vegetable Spring Rolls: VEGETARIAN', - 'Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney: KETO', - 'Burnt Masala Wings with Classic Coleslaw: OMNIVORE', - 'Burmese Tofu with Garlic, Ginger and Chili Sauce: VEGAN', - 'Brisket with Grilled Rhubarb, Onions, and Fennel: OMNIVORE', - 'Braised Pork Belly with Apple Salad: KETO', - 'BLT Bites: PALEO', - 'Beachside Snapper: OMNIVORE', - 'Barley Risotto: VEGETARIAN', - 'Baked Kelewele: VEGAN', - 'Baked Chicken Jollof Rice: OMNIVORE', - 'Avocado Deviled Eggs: PALEO', - 'Asparagus Puffs: VEGETARIAN'] +dishes_categorized = [ + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt: PALEO", + "Winter Cobb Salad: VEGETARIAN", + "White Cheddar Scalloped Potatoes: VEGETARIAN", + "Walnut Ravioli with Artichokes and Tomatoes: VEGETARIAN", + "Waakye: VEGAN", + "Vegetarian Khoresh Bademjan: VEGAN", + "Vegan Pizza with Caramelized Onions: VEGAN", + "Vegan Mini Savory Mince Pies: VEGAN", + "Vegan Carbonara: VEGAN", + "Sweet and Spicy Crispy Green Beans: VEGAN", + "Summer Minestrone Cups: VEGETARIAN", + "Sticky Lemon Tofu: VEGAN", + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole: OMNIVORE", + "Shakshuka: VEGAN", + "Seared Salmon with Pickled Vegetable and Watercress Salad: KETO", + "Seafood Risotto: OMNIVORE", + "Satay Steak Skewers: KETO", + "Roasted Corn and Zucchini Salad: VEGAN", + "Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes: PALEO", + "Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing: VEGETARIAN", + "Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous: OMNIVORE", + "Pumpkin Bread Crostini: PALEO", + "Prawn and Herb Omelette: KETO", + "Pork Chops with Grilled Castelfranco Radicchio and Asparagus: KETO", + "Parmesan Crackers and Spinach Crackers with Salmon Pate: KETO", + "Nut Wellington: VEGETARIAN", + "Mushroom Lasagna: VEGETARIAN", + "Lamb over Marinated Summer Squash with Hazelnuts and Ricotta: OMNIVORE", + "Kisir with Warm Pita: VEGAN", + "Kingfish Lettuce Cups: KETO", + "Grilled Tofu Tacos: VEGETARIAN", + "Grilled Shrimp and Pesto over Zucchini Noodles: PALEO", + "Grilled Pork Chops with Mango Pineapple Salsa: PALEO", + "Grilled Flank Steak with Caesar Salad: PALEO", + "Grilled Fish Tacos with Cauliflower Tortillas: PALEO", + "Governor Shrimp Tacos: OMNIVORE", + "Golden Potato Salad: VEGAN", + "Georgian Eggplant Rolls with Walnuts: VEGAN", + "Fried Zucchini with Balsamic and Chili Dressing: VEGETARIAN", + "Fresh Garden Peas over Cauliflower Almond Puree: VEGETARIAN", + "Flank Steak with Chimichurri and Asparagus: KETO", + "Dahi Puri with Black Chickpeas: OMNIVORE", + "Chicken with Tamarind and Apricot Sauce: PALEO", + "Cherry Tomato, Watercress and Fava Bean Salad: VEGETARIAN", + "Cheela with Spicy Mango Chutney: VEGAN", + "Celeriac Schnitzel: VEGAN", + "Cauliflower Pizza with Roasted Tomatoes and Chicken: KETO", + "Carrot Puff Pastry Tart: VEGAN", + "Cambodian-Style Vegetable Spring Rolls: VEGETARIAN", + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney: KETO", + "Burnt Masala Wings with Classic Coleslaw: OMNIVORE", + "Burmese Tofu with Garlic, Ginger and Chili Sauce: VEGAN", + "Brisket with Grilled Rhubarb, Onions, and Fennel: OMNIVORE", + "Braised Pork Belly with Apple Salad: KETO", + "BLT Bites: PALEO", + "Beachside Snapper: OMNIVORE", + "Barley Risotto: VEGETARIAN", + "Baked Kelewele: VEGAN", + "Baked Chicken Jollof Rice: OMNIVORE", + "Avocado Deviled Eggs: PALEO", + "Asparagus Puffs: VEGETARIAN", +] ######################################### @@ -279,38 +3299,79 @@ ######################################### -dupes = ['Baked Kelewele', 'Barley Risotto', 'Burmese Tofu with Garlic, Ginger and Chili Sauce', - 'Cambodian-Style Vegetable Spring Rolls', 'Fried Zucchini with Balsamic and Chili Dressing', - 'Kisir with Warm Pita', 'Shakshuka', 'Summer Minestrone Cups', 'Vegetarian Khoresh Bademjan'] +dupes = [ + "Baked Kelewele", + "Barley Risotto", + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + "Cambodian-Style Vegetable Spring Rolls", + "Fried Zucchini with Balsamic and Chili Dressing", + "Kisir with Warm Pita", + "Shakshuka", + "Summer Minestrone Cups", + "Vegetarian Khoresh Bademjan", +] -nondupes = ['Brisket with Grilled Rhubarb, Onions, and Fennel', 'Burnt Masala Wings with Classic Coleslaw', - 'Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', - 'Cauliflower Pizza with Roasted Tomatoes and Chicken', 'Dahi Puri with Black Chickpeas', - 'Flank Steak with Chimichurri and Asparagus', 'Kingfish Lettuce Cups', - 'Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole'] +nondupes = [ + "Brisket with Grilled Rhubarb, Onions, and Fennel", + "Burnt Masala Wings with Classic Coleslaw", + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + "Dahi Puri with Black Chickpeas", + "Flank Steak with Chimichurri and Asparagus", + "Kingfish Lettuce Cups", + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", +] group_1 = [item for item in recipes_with_duplicates if item[0] in dupes] -group_2 = [(item[1], item[2]) for item in recipes_without_duplicates if item[1] in nondupes] +group_2 = [ + (item[1], item[2]) for item in recipes_without_duplicates if item[1] in nondupes +] dishes_to_special_label = sorted(group_1 + group_2) -dishes_labeled = [('Baked Kelewele', {'red onion'}), - ('Barley Risotto', {'garlic', 'red onion', 'parmesan cheese'}), - ('Brisket with Grilled Rhubarb, Onions, and Fennel', {'soy sauce', 'garlic', 'red onion', 'yellow onion'}), - ('Burmese Tofu with Garlic, Ginger and Chili Sauce', {'soy sauce', 'garlic', 'peanuts'}), - ('Burnt Masala Wings with Classic Coleslaw', {'honey', 'butter', 'garlic cloves'}), - ('Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', {'heavy cream', 'garlic', 'butter', 'tomatoes'}), - ('Cambodian-Style Vegetable Spring Rolls', {'soy sauce', 'firm tofu', 'garlic', 'toasted peanuts'}), - ('Cauliflower Pizza with Roasted Tomatoes and Chicken', {'parmesan', 'mozzarella cheese', 'tomato paste', 'cherry tomatoes', 'eggs'}), - ('Dahi Puri with Black Chickpeas', {'red onion', 'whole-milk yogurt'}), - ('Flank Steak with Chimichurri and Asparagus', {'garlic'}), - ('Fried Zucchini with Balsamic and Chili Dressing', {'honey', 'garlic', 'red onion'}), - ('Kingfish Lettuce Cups', {'soy sauce', 'oyster sauce', 'garlic', 'grilled king fish'}), - ('Kisir with Warm Pita', {'bulgur', 'tomato paste'}), - ('Shakshuka', {'tomatoes', 'tomato paste', 'firm tofu', 'yellow onion'}), - ('Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole', {'shrimp', 'garlic', 'butter', 'slivered almonds', 'bacon'}), - ('Summer Minestrone Cups', {'garlic', 'tomatoes', 'parmesan cheese'}), - ('Vegetarian Khoresh Bademjan', {'slivered almonds', 'tomato paste'})] +dishes_labeled = [ + ("Baked Kelewele", {"red onion"}), + ("Barley Risotto", {"garlic", "red onion", "parmesan cheese"}), + ( + "Brisket with Grilled Rhubarb, Onions, and Fennel", + {"soy sauce", "garlic", "red onion", "yellow onion"}, + ), + ( + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + {"soy sauce", "garlic", "peanuts"}, + ), + ("Burnt Masala Wings with Classic Coleslaw", {"honey", "butter", "garlic cloves"}), + ( + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + {"heavy cream", "garlic", "butter", "tomatoes"}, + ), + ( + "Cambodian-Style Vegetable Spring Rolls", + {"soy sauce", "firm tofu", "garlic", "toasted peanuts"}, + ), + ( + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + {"parmesan", "mozzarella cheese", "tomato paste", "cherry tomatoes", "eggs"}, + ), + ("Dahi Puri with Black Chickpeas", {"red onion", "whole-milk yogurt"}), + ("Flank Steak with Chimichurri and Asparagus", {"garlic"}), + ( + "Fried Zucchini with Balsamic and Chili Dressing", + {"honey", "garlic", "red onion"}, + ), + ( + "Kingfish Lettuce Cups", + {"soy sauce", "oyster sauce", "garlic", "grilled king fish"}, + ), + ("Kisir with Warm Pita", {"bulgur", "tomato paste"}), + ("Shakshuka", {"tomatoes", "tomato paste", "firm tofu", "yellow onion"}), + ( + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", + {"shrimp", "garlic", "butter", "slivered almonds", "bacon"}, + ), + ("Summer Minestrone Cups", {"garlic", "tomatoes", "parmesan cheese"}), + ("Vegetarian Khoresh Bademjan", {"slivered almonds", "tomato paste"}), +] ##################################### @@ -318,76 +3379,1105 @@ ##################################### -ingredients_only = [[{'bulgur', 'pomegranate molasses', 'chopped parsley', 'lemon juice', 'tomato', 'persian cucumber', 'tomato paste', 'spring onion', 'water', 'olive oil'}, - {'vegan unsweetened yoghurt', 'yellow onion', 'firm tofu', 'smoked paprika', 'tomatoes', 'tomato paste', 'sugar', 'cloves', 'cumin', "za'atar", 'olive oil', 'harissa', 'red bell pepper'}, - {'yellow split peas', 'tomato paste', 'black pepper', 'pomegranate concentrate', 'yellow onions', 'slivered almonds', 'ground turmeric', 'barberries', 'basmati rice', 'lemon juice', 'hot water', 'cayenne pepper', 'chinese eggplants', 'salt', 'orange juice', 'saffron powder', 'vegan butter', 'orange zest', 'kosher salt'}, - {'smoked paprika', 'black peppercorn', 'red onion', 'grains of selim', 'cayenne pepper', 'calabash nutmeg', 'coconut oil', 'cloves', 'fresh ginger', 'salt', 'ripe plantains'}, - {'baking soda', 'sorghum stems', 'coconut oil', 'black-eyed peas', 'water', 'salt', 'white rice'}, - {'pomegranate seeds', 'oil', 'coriander', 'garlic', 'khmeli suneli', 'eggplants', 'black pepper', 'vinegar', 'walnuts', 'water', 'salt'}, - {'soy sauce', 'oil', 'chili flakes', 'garlic', 'brown sugar', 'ginger', 'peanuts', 'rice vinegar', 'spring onions', 'water', 'turmeric', 'salt', 'chickpea flour'}, - {'soy sauce', 'parsley', 'lemon', 'sunflower oil', 'black pepper', 'celeriac', 'breadcrumbs', 'water', 'salt', 'flour', 'chickpea flour'}, - {'soy sauce', 'vegetable stock', 'tofu', 'cornstarch', 'lemon juice', 'lemon zest', 'garlic', 'ginger', 'black pepper', 'sugar', 'water', 'salt', 'vegetable oil'}, - {'soy sauce', 'smoked tofu', 'lemon juice', 'nutritional yeast', 'mixed herbs', 'garlic', 'black pepper', 'silken tofu', 'turmeric', 'salt', 'olive oil', 'spaghetti'}, - {'mushrooms', 'rosemary', 'garlic', 'red pepper flakes', 'yeast', 'barley malt', 'water', 'olive oil', 'garlic powder', 'oregano', 'honey', 'nutritional yeast', 'red onion', 'tomatoes', 'cashews', 'sugar', 'bell pepper', 'flour', 'salt', 'fresh basil'}, - {'clove powder', 'oil', 'cinnamon powder', 'nigella seeds', 'curry leaves', 'coriander seeds', 'garlic', 'mangoes', 'mashed potatoes', 'cardamom powder', 'vinegar', 'water', 'mustard seeds', 'coriander powder', 'cumin powder', 'mango powder', 'garam masala', 'red chili powder', 'hing', 'garlic paste', 'turmeric powder', 'cilantro', 'sugar', 'onion', 'serrano chili', 'fresh ginger', 'turmeric', 'salt', 'fresh red chili', 'chickpea flour'}, - {'soy sauce', 'pomegranate molasses', 'sesame oil', 'green beans', 'sunflower oil', 'scallions', 'garlic', 'carrot', 'ginger', 'sesame seeds', 'tomato paste', 'bell pepper', 'siracha'}, - {'mushrooms', 'cinnamon powder', 'rosemary', 'corn flour', 'ginger', 'brown sugar', 'carrot', 'black pepper', 'raisins', 'butternut squash', 'vegetarian worcestershire sauce', 'parev shortcrust pastry', 'olive oil', 'vegetable stock', 'dried cherries', 'lemon juice', 'lemon zest', 'figs', 'dried cranberries', 'apples', 'pecans', 'onion', 'orange juice', 'currants', 'dried blueberries', 'salt', 'brandy', 'orange zest', 'allspice powder'}, - {'green onions', 'lemon juice', 'lemon zest', 'dill', 'corn', 'tomatoes', 'black pepper', 'zucchini', 'olive oil'}, - {'mustard seeds', 'cumin seeds', 'lemon juice', 'garlic', 'black pepper', 'balsamic vinegar', 'yukon gold potato', 'chives', 'turmeric', 'salt', 'olive oil'}, - {'olive oil', 'lemon', 'lemon juice', 'pareve puff pastry', 'brown sugar', 'red onion', 'carrot', 'garlic', 'black pepper', 'thyme', 'vegan butter', 'water', 'salt', 'ground almonds'} - ], - - [{'nutmeg', 'garlic', 'black pepper', 'onions', 'butter', 'parmesan cheese', 'portobello mushrooms', 'flour', 'dried lasagna noodles', 'olive oil', 'milk', 'kosher salt'}, - {'sage', 'puff pastry sheets', 'hazelnuts', 'almonds', 'black pepper', 'thyme', 'marmite', 'breadcrumbs', 'walnuts', 'dates', 'eggs', 'olive oil', 'brazil nuts', 'leeks', 'chestnuts', 'cashews', 'apples', 'pecans', 'butter', 'salt'}, - {'shallots', 'garlic', 'cream', 'thyme', 'breadcrumbs', 'sharp white cheddar', 'yukon gold potato', 'milk', 'kosher salt'}, - {'smoked tofu', 'shiitake mushrooms', 'red wine vinegar', 'garlic', 'tomatoes', 'black pepper', 'avocados', 'blue cheese', 'onion', 'lacinato kale', 'eggs', 'olive oil'}, - {'honey', 'lemon', 'dijon mustard', 'feta cheese', 'red wine vinegar', 'red onion', 'watercress', 'green lentils', 'currants', 'capers', 'pepitas', 'fresh pumpkin', 'olive oil'}, - {'lime juice', 'toasted peanuts', 'firm tofu', 'garlic', 'corn flour', 'bean sprouts', 'carrot', 'palm sugar', 'shallots', 'red chili', 'vermicelli noodles', 'wombok', 'soy sauce', 'sunflower oil', 'spring roll wrappers', 'vegetarian fish sauce'}, - {'fresh peas', 'rosemary', 'garlic', 'chickpeas', 'carrot', 'leek', 'green lentils', 'red chili', 'olive oil', 'croutons', 'fresh corn', 'lemon zest', 'green beans', 'parmesan rind', 'basil', 'tomatoes', 'vegetable bullion', 'parmesan cheese', 'celery', 'mint'}, - {'honey', 'lemon juice', 'garlic', 'red onion', 'red thai chili', 'pomegranate', 'balsamic vinegar', 'mint leaves', 'zucchini', 'olive oil'}, - {'sage', 'beets', 'pearl barley', 'brussel sprouts', 'rosemary', 'garlic', 'carrot', 'red onion', 'black pepper', 'thyme', 'butternut squash', 'vegetable bullion', 'parmesan cheese', 'olive oil', 'white wine'}, - {'fresh peas', 'fresh cherry tomatoes', 'garlic', 'watercress', 'balsamic vinegar', 'fresh or frozen fava beans', 'fresh cherry bocconcini', 'salt', 'olive oil'}, - {'red onions', 'lemon', 'fresh peas', 'garlic', 'grated nutmeg', 'cream', 'cauliflower', 'blanched almonds', 'fresh pea tendrils', 'olive oil', 'vegetable oil'}, - {'pine nuts', 'oil marinated artichokes', 'olives', 'rosemary', 'fresh tomatoes', 'ricotta cheese', 'black pepper', 'fresh artichoke hearts', 'walnuts', 'pasta sheets', 'lemon juice', 'lemon zest', 'basil', 'red onion', 'butter', 'salt'}, - {'egg', 'asparagus', 'lemon juice', 'red onion', 'ricotta cheese', 'black pepper', 'thyme', 'salt', 'parmesan cheese', 'puff pastry', 'chives'}, - {'cotija cheese', 'masa', 'fresh cilantro leaves', 'jalapeño chili', 'chipotle chili', 'firm tofu', 'garlic', 'carrot', 'roasted corn', 'tomatillos', 'pepitas', 'ancho chili', 'crema', 'red onions', 'pasilla chili', 'lemon', 'hot water', 'lemon juice', 'tomatoes', 'avocado', 'cumin', 'red cabbage', 'limes', 'black beans'} - ], - - [{'baking soda', 'coconut flour', 'lemon juice', 'lemon zest', 'eggs', 'coconut yogurt', 'black pepper', 'fresh thai chili', 'coconut oil', 'chives', 'zucchini', 'salt'}, - {'lime juice', 'fresh cilantro leaves', 'eggs', 'seranno chili', 'avocado', 'pepitas', 'salt', 'garlic powder'}, - {'pine nuts', 'white vinegar', 'chipotle chili', 'scallions', 'garlic', 'paleo parmesan cheese', 'black pepper', 'avocado oil', 'treviso', 'olive oil', 'radishes', 'flank steak', 'dijon mustard', 'castelfranco radicchio', 'worcestershire sauce', 'fresh parsley', 'cherry tomatoes', 'salt', 'avocado mayonnaise'}, - {'coconut flour', 'garlic', 'black pepper', 'cloves', 'eggs', 'olive oil', 'onions', 'honey', 'apple cider vinegar', 'almond butter', 'baking soda', 'nutmeg', 'pumpkin puree', 'cinnamon', 'shrimp', 'basil', 'coconut oil', 'cherry tomatoes', 'salt', 'fresh red chili'}, - {'mustard seed', 'onion', 'kale', 'cherry tomatoes', 'bacon', 'paleo mayonnaise'}, - {'purple sweet potato', 'chiles de árbol', 'garlic', 'tomatoes', 'safflower oil', 'black pepper', 'mexican oregano', 'avocados', 'shallots', 'cumin', 'olive oil', 'lemons', 'whole chicken', 'limes', 'kosher salt'}, - {'garlic', 'black pepper', 'dried apricots', 'roma tomatoes', 'water', 'olive oil', 'honey', 'cinnamon', 'ground cumin', 'cider vinegar', 'chili powder', 'safflower oil', 'homemade tamarind concentrate', 'white chicken', 'allspice', 'chipotles', 'salt', 'homemade apricot honey preserves', 'kosher salt'}, - {'green onions', 'serrano chili', 'shredded red cabbage', 'smoked paprika', 'mango', 'eggs', 'black pepper', 'cilantro', 'cauliflower', 'avocado', 'lime', 'cumin', 'salt', 'tilapia'}, - {'cilantro leaves', 'lime', 'pineapple', 'chipotle chili', 'garlic', 'mangoes', 'cauliflower', 'avocado', 'serrano chili', 'pork chops', 'lime zest', 'lacinato kale', 'onions'}, - {'pine nuts', 'shrimp', 'green bell pepper', 'lemon juice', 'basil', 'lemon zest', 'garlic', 'tomatoes', 'cashews', 'yellow bell pepper', 'cumin', 'zucchini', 'salt', 'olive oil', 'red bell pepper'} - ], - - [{'parmesan', 'almond meal', 'rosemary', 'mozzarella cheese', 'roasted chicken', 'tomato paste', 'cauliflower', 'cherry tomatoes', 'eggs', 'fresh basil', 'olive oil'}, - {'white vinegar', 'asparagus', 'flank steak', 'chipotle chili', 'scallions', 'garlic', 'black pepper', 'cauliflower', 'sour cream', 'fresh parsley', 'salt', 'olive oil'}, - {'soy sauce', 'watermelon radishes', 'lime juice', 'fish sauce', 'mirin', 'little gem lettuce heads', 'peanut oil', 'garlic', 'sesame seeds', 'oyster sauce', 'spring onions', 'avocado', 'grilled king fish', 'red cabbage'}, - {'clove powder', 'curry leaves', 'coriander seeds', 'ginger', 'cardamom powder', 'vinegar', 'mustard seeds', 'mango powder', 'garam masala', 'red chili powder', 'chicken', 'hing', 'turmeric powder', 'tomatoes', 'ginger garlic paste', 'fresh greek yogurt', 'fresh ginger', 'monk fruit', 'turmeric', 'cashew nuts', 'salt', 'fresh red chili', 'cinnamon powder', 'nigella seeds', 'whole small crimini mushrooms', 'brussel sprouts', 'garlic', 'mangoes', 'heavy cream', 'cloves', 'coriander powder', 'cumin powder', 'cardamom', 'green chili', 'cinnamon', 'garlic paste', 'red chili flakes', 'lemon juice', 'cilantro', 'butter', 'dried fenugreek leaves', 'boned chicken'}, - {'green onions', 'parsley', 'sesame seeds', 'black pepper', 'chives', 'eggs', 'fennel bulb', 'tahini', 'olive oil', 'harissa', 'shrimp', 'lemon juice', 'dill', 'butter', 'onion', 'fresh cucumber', 'monk fruit', 'salt'}, - {'sriacha', 'apple cider vinegar', 'lime juice', 'fish sauce', 'red and green thai chili', 'flank steak', 'carrot', 'peanuts', 'cucumbers', 'roasted peanuts', 'crunchy peanut butter', 'kecap manis', 'monk fruit', 'micro cilantro', 'olive oil'}, - {'spinach', 'parmesan cheese', 'coconut flour', 'chili flakes', 'garlic', 'black pepper', 'cream cheese', 'ghee', 'lemon juice', 'flaxmeal', 'red onion', 'salt', 'salmon fillets', 'pecans', 'almond flour', 'cumin', 'fresh cucumber', 'cherry tomatoes', 'chives', 'avocado mayonnaise'}, - {'rosemary', 'garlic', 'black pepper', 'thyme', 'avocado oil', 'eggs', 'oregano', 'asparagus', 'lemon', 'dijon mustard', 'basil', 'castelfranco radicchio', 'dill', 'butter', 'pork chops', 'monk fruit', 'salt', 'avocado mayonnaise'}, - {'lime juice', 'caster sugar', 'toasted buckwheat', 'lemon juice', 'red wine vinegar', 'red onion', 'dutch carrot', 'salmon steaks', 'watercress', 'pink peppercorns', 'shallots', 'fennel seeds', 'red cabbage', 'radishes'}, - {'cilantro leaves', 'green cabbage', 'lemon juice', 'pork belly', 'dark soy sauce', 'granny smith apples', 'ginger', 'light soy sauce', 'sesame seeds', 'black pepper', 'cinnamon sticks', 'spring onions', 'star anise', 'monk fruit', 'olive oil'} - ], - - [{'lime juice', 'salsa', 'green bell pepper', 'anaheim chili', 'black pepper', 'olive oil', 'yellow mustard', 'red bell pepper', 'soy sauce', 'mexican crema', 'mayonnaise', 'white onion', 'garlic cloves', 'fresh corn tortillas', 'red onion', 'tomatoes', 'limes', 'worcestershire sauce', 'butter', 'yellow bell pepper', 'salt', 'red snapper'}, - {'lime juice', 'poblano chili', 'tomato paste', 'black pepper', 'chipotle adobo sauce', 'chile manzano', 'roma tomatoes', 'pepitas', 'oaxaca cheese', 'white onion', 'shelled large shrimp', 'garlic cloves', 'fresh corn tortillas', 'red onion', 'worcestershire sauce', 'avocado', 'butter', 'kosher salt'}, - {'fresh tortillas', 'shrimp', 'garlic', 'chickpeas', 'black pepper', 'slivered almonds', 'guajillo chile', 'bacon', 'sea salt', 'butter', 'onion', 'avocado', 'olive oil'}, - {'lime juice', 'green cabbage', 'chiles de árbol', 'green cardamom', 'ginger', 'carrot', 'sriracha', 'black pepper', 'cinnamon sticks', 'celery seeds', 'cloves', 'black cardamom', 'olive oil', 'chicken wings', 'apple cider vinegar', 'mayonnaise', 'honey', 'black peppercorns', 'lemon juice', 'garlic cloves', 'tamarind concentrate', 'cilantro', 'butter', 'serrano chili', 'red cabbage', 'kosher salt'}, - {'whole-milk yogurt', 'chaat masala', 'ginger', 'pani puri', 'scallion chutney', 'yukon gold potato', 'black chickpeas', 'thin sev', 'date syrup', 'red onion', 'roasted chicken', 'chili powder', 'tamarind concentrate', 'cumin', 'turmeric', 'mint'}, - {'white vinegar', 'parsley', 'yellow onion', 'rhubarb', 'garlic', 'brown sugar', 'black pepper', 'thyme', 'crushed red pepper flakes', 'fennel bulbs', 'beer', 'marjoram', 'vegetable oil', 'soy sauce', 'oregano', 'lemon', 'red onion', 'chili powder', 'cilantro', 'beef brisket', 'balsamic vinegar', 'worcestershire sauce', 'celery', 'mint', 'kosher salt'}, - {'oranges', 'rosemary', 'garlic', 'anchovy fillets', 'couscous', 'carrot', 'sesame seeds', 'fresh thyme', 'vinegar', 'olive oil', 'tahini', 'harissa', 'onions', 'honey', 'fresh mint', 'leg of lamb', 'tomatoes', 'baby carrot', 'vegetable bullion', 'filo pastry', 'celery', 'bay leaves', 'yoghurt'}, - {'tomato puree', 'garlic', 'ginger', 'tomato', 'carrot', 'thyme', 'white pepper', 'water', 'maggi cubes', 'chicken', 'rice', 'coriander', 'scotch bonnet pepper', 'bell pepper', 'onion', 'turmeric', 'salt'}, - {'garlic', 'tomato paste', 'baby scallops', 'mussels', 'water', 'crab legs', 'olive oil', 'baby squid', 'fish stock', 'lemon juice', 'white onion', 'arborio risotto rice', 'clams', 'parmesan cheese', 'flat-leaf parsley', 'cherry tomatoes', 'prawns', 'white wine'}, - {'toasted bread', 'rosemary', 'hazelnuts', 'anchovy fillets', 'garlic', 'carrot', 'summer squash', 'black pepper', 'red pepper flakes', 'vinegar', 'sea salt', 'zucchini', 'olive oil', 'onions', 'white wine vinegar', 'fresh mint', 'leg of lamb', 'lemon', 'fresh ricotta', 'sugar', 'celery', 'bay leaves', 'kosher salt'} - ]] +ingredients_only = [ + [ + { + "bulgur", + "pomegranate molasses", + "chopped parsley", + "lemon juice", + "tomato", + "persian cucumber", + "tomato paste", + "spring onion", + "water", + "olive oil", + }, + { + "vegan unsweetened yoghurt", + "yellow onion", + "firm tofu", + "smoked paprika", + "tomatoes", + "tomato paste", + "sugar", + "cloves", + "cumin", + "za'atar", + "olive oil", + "harissa", + "red bell pepper", + }, + { + "yellow split peas", + "tomato paste", + "black pepper", + "pomegranate concentrate", + "yellow onions", + "slivered almonds", + "ground turmeric", + "barberries", + "basmati rice", + "lemon juice", + "hot water", + "cayenne pepper", + "chinese eggplants", + "salt", + "orange juice", + "saffron powder", + "vegan butter", + "orange zest", + "kosher salt", + }, + { + "smoked paprika", + "black peppercorn", + "red onion", + "grains of selim", + "cayenne pepper", + "calabash nutmeg", + "coconut oil", + "cloves", + "fresh ginger", + "salt", + "ripe plantains", + }, + { + "baking soda", + "sorghum stems", + "coconut oil", + "black-eyed peas", + "water", + "salt", + "white rice", + }, + { + "pomegranate seeds", + "oil", + "coriander", + "garlic", + "khmeli suneli", + "eggplants", + "black pepper", + "vinegar", + "walnuts", + "water", + "salt", + }, + { + "soy sauce", + "oil", + "chili flakes", + "garlic", + "brown sugar", + "ginger", + "peanuts", + "rice vinegar", + "spring onions", + "water", + "turmeric", + "salt", + "chickpea flour", + }, + { + "soy sauce", + "parsley", + "lemon", + "sunflower oil", + "black pepper", + "celeriac", + "breadcrumbs", + "water", + "salt", + "flour", + "chickpea flour", + }, + { + "soy sauce", + "vegetable stock", + "tofu", + "cornstarch", + "lemon juice", + "lemon zest", + "garlic", + "ginger", + "black pepper", + "sugar", + "water", + "salt", + "vegetable oil", + }, + { + "soy sauce", + "smoked tofu", + "lemon juice", + "nutritional yeast", + "mixed herbs", + "garlic", + "black pepper", + "silken tofu", + "turmeric", + "salt", + "olive oil", + "spaghetti", + }, + { + "mushrooms", + "rosemary", + "garlic", + "red pepper flakes", + "yeast", + "barley malt", + "water", + "olive oil", + "garlic powder", + "oregano", + "honey", + "nutritional yeast", + "red onion", + "tomatoes", + "cashews", + "sugar", + "bell pepper", + "flour", + "salt", + "fresh basil", + }, + { + "clove powder", + "oil", + "cinnamon powder", + "nigella seeds", + "curry leaves", + "coriander seeds", + "garlic", + "mangoes", + "mashed potatoes", + "cardamom powder", + "vinegar", + "water", + "mustard seeds", + "coriander powder", + "cumin powder", + "mango powder", + "garam masala", + "red chili powder", + "hing", + "garlic paste", + "turmeric powder", + "cilantro", + "sugar", + "onion", + "serrano chili", + "fresh ginger", + "turmeric", + "salt", + "fresh red chili", + "chickpea flour", + }, + { + "soy sauce", + "pomegranate molasses", + "sesame oil", + "green beans", + "sunflower oil", + "scallions", + "garlic", + "carrot", + "ginger", + "sesame seeds", + "tomato paste", + "bell pepper", + "siracha", + }, + { + "mushrooms", + "cinnamon powder", + "rosemary", + "corn flour", + "ginger", + "brown sugar", + "carrot", + "black pepper", + "raisins", + "butternut squash", + "vegetarian worcestershire sauce", + "parev shortcrust pastry", + "olive oil", + "vegetable stock", + "dried cherries", + "lemon juice", + "lemon zest", + "figs", + "dried cranberries", + "apples", + "pecans", + "onion", + "orange juice", + "currants", + "dried blueberries", + "salt", + "brandy", + "orange zest", + "allspice powder", + }, + { + "green onions", + "lemon juice", + "lemon zest", + "dill", + "corn", + "tomatoes", + "black pepper", + "zucchini", + "olive oil", + }, + { + "mustard seeds", + "cumin seeds", + "lemon juice", + "garlic", + "black pepper", + "balsamic vinegar", + "yukon gold potato", + "chives", + "turmeric", + "salt", + "olive oil", + }, + { + "olive oil", + "lemon", + "lemon juice", + "pareve puff pastry", + "brown sugar", + "red onion", + "carrot", + "garlic", + "black pepper", + "thyme", + "vegan butter", + "water", + "salt", + "ground almonds", + }, + ], + [ + { + "nutmeg", + "garlic", + "black pepper", + "onions", + "butter", + "parmesan cheese", + "portobello mushrooms", + "flour", + "dried lasagna noodles", + "olive oil", + "milk", + "kosher salt", + }, + { + "sage", + "puff pastry sheets", + "hazelnuts", + "almonds", + "black pepper", + "thyme", + "marmite", + "breadcrumbs", + "walnuts", + "dates", + "eggs", + "olive oil", + "brazil nuts", + "leeks", + "chestnuts", + "cashews", + "apples", + "pecans", + "butter", + "salt", + }, + { + "shallots", + "garlic", + "cream", + "thyme", + "breadcrumbs", + "sharp white cheddar", + "yukon gold potato", + "milk", + "kosher salt", + }, + { + "smoked tofu", + "shiitake mushrooms", + "red wine vinegar", + "garlic", + "tomatoes", + "black pepper", + "avocados", + "blue cheese", + "onion", + "lacinato kale", + "eggs", + "olive oil", + }, + { + "honey", + "lemon", + "dijon mustard", + "feta cheese", + "red wine vinegar", + "red onion", + "watercress", + "green lentils", + "currants", + "capers", + "pepitas", + "fresh pumpkin", + "olive oil", + }, + { + "lime juice", + "toasted peanuts", + "firm tofu", + "garlic", + "corn flour", + "bean sprouts", + "carrot", + "palm sugar", + "shallots", + "red chili", + "vermicelli noodles", + "wombok", + "soy sauce", + "sunflower oil", + "spring roll wrappers", + "vegetarian fish sauce", + }, + { + "fresh peas", + "rosemary", + "garlic", + "chickpeas", + "carrot", + "leek", + "green lentils", + "red chili", + "olive oil", + "croutons", + "fresh corn", + "lemon zest", + "green beans", + "parmesan rind", + "basil", + "tomatoes", + "vegetable bullion", + "parmesan cheese", + "celery", + "mint", + }, + { + "honey", + "lemon juice", + "garlic", + "red onion", + "red thai chili", + "pomegranate", + "balsamic vinegar", + "mint leaves", + "zucchini", + "olive oil", + }, + { + "sage", + "beets", + "pearl barley", + "brussel sprouts", + "rosemary", + "garlic", + "carrot", + "red onion", + "black pepper", + "thyme", + "butternut squash", + "vegetable bullion", + "parmesan cheese", + "olive oil", + "white wine", + }, + { + "fresh peas", + "fresh cherry tomatoes", + "garlic", + "watercress", + "balsamic vinegar", + "fresh or frozen fava beans", + "fresh cherry bocconcini", + "salt", + "olive oil", + }, + { + "red onions", + "lemon", + "fresh peas", + "garlic", + "grated nutmeg", + "cream", + "cauliflower", + "blanched almonds", + "fresh pea tendrils", + "olive oil", + "vegetable oil", + }, + { + "pine nuts", + "oil marinated artichokes", + "olives", + "rosemary", + "fresh tomatoes", + "ricotta cheese", + "black pepper", + "fresh artichoke hearts", + "walnuts", + "pasta sheets", + "lemon juice", + "lemon zest", + "basil", + "red onion", + "butter", + "salt", + }, + { + "egg", + "asparagus", + "lemon juice", + "red onion", + "ricotta cheese", + "black pepper", + "thyme", + "salt", + "parmesan cheese", + "puff pastry", + "chives", + }, + { + "cotija cheese", + "masa", + "fresh cilantro leaves", + "jalapeño chili", + "chipotle chili", + "firm tofu", + "garlic", + "carrot", + "roasted corn", + "tomatillos", + "pepitas", + "ancho chili", + "crema", + "red onions", + "pasilla chili", + "lemon", + "hot water", + "lemon juice", + "tomatoes", + "avocado", + "cumin", + "red cabbage", + "limes", + "black beans", + }, + ], + [ + { + "baking soda", + "coconut flour", + "lemon juice", + "lemon zest", + "eggs", + "coconut yogurt", + "black pepper", + "fresh thai chili", + "coconut oil", + "chives", + "zucchini", + "salt", + }, + { + "lime juice", + "fresh cilantro leaves", + "eggs", + "seranno chili", + "avocado", + "pepitas", + "salt", + "garlic powder", + }, + { + "pine nuts", + "white vinegar", + "chipotle chili", + "scallions", + "garlic", + "paleo parmesan cheese", + "black pepper", + "avocado oil", + "treviso", + "olive oil", + "radishes", + "flank steak", + "dijon mustard", + "castelfranco radicchio", + "worcestershire sauce", + "fresh parsley", + "cherry tomatoes", + "salt", + "avocado mayonnaise", + }, + { + "coconut flour", + "garlic", + "black pepper", + "cloves", + "eggs", + "olive oil", + "onions", + "honey", + "apple cider vinegar", + "almond butter", + "baking soda", + "nutmeg", + "pumpkin puree", + "cinnamon", + "shrimp", + "basil", + "coconut oil", + "cherry tomatoes", + "salt", + "fresh red chili", + }, + { + "mustard seed", + "onion", + "kale", + "cherry tomatoes", + "bacon", + "paleo mayonnaise", + }, + { + "purple sweet potato", + "chiles de árbol", + "garlic", + "tomatoes", + "safflower oil", + "black pepper", + "mexican oregano", + "avocados", + "shallots", + "cumin", + "olive oil", + "lemons", + "whole chicken", + "limes", + "kosher salt", + }, + { + "garlic", + "black pepper", + "dried apricots", + "roma tomatoes", + "water", + "olive oil", + "honey", + "cinnamon", + "ground cumin", + "cider vinegar", + "chili powder", + "safflower oil", + "homemade tamarind concentrate", + "white chicken", + "allspice", + "chipotles", + "salt", + "homemade apricot honey preserves", + "kosher salt", + }, + { + "green onions", + "serrano chili", + "shredded red cabbage", + "smoked paprika", + "mango", + "eggs", + "black pepper", + "cilantro", + "cauliflower", + "avocado", + "lime", + "cumin", + "salt", + "tilapia", + }, + { + "cilantro leaves", + "lime", + "pineapple", + "chipotle chili", + "garlic", + "mangoes", + "cauliflower", + "avocado", + "serrano chili", + "pork chops", + "lime zest", + "lacinato kale", + "onions", + }, + { + "pine nuts", + "shrimp", + "green bell pepper", + "lemon juice", + "basil", + "lemon zest", + "garlic", + "tomatoes", + "cashews", + "yellow bell pepper", + "cumin", + "zucchini", + "salt", + "olive oil", + "red bell pepper", + }, + ], + [ + { + "parmesan", + "almond meal", + "rosemary", + "mozzarella cheese", + "roasted chicken", + "tomato paste", + "cauliflower", + "cherry tomatoes", + "eggs", + "fresh basil", + "olive oil", + }, + { + "white vinegar", + "asparagus", + "flank steak", + "chipotle chili", + "scallions", + "garlic", + "black pepper", + "cauliflower", + "sour cream", + "fresh parsley", + "salt", + "olive oil", + }, + { + "soy sauce", + "watermelon radishes", + "lime juice", + "fish sauce", + "mirin", + "little gem lettuce heads", + "peanut oil", + "garlic", + "sesame seeds", + "oyster sauce", + "spring onions", + "avocado", + "grilled king fish", + "red cabbage", + }, + { + "clove powder", + "curry leaves", + "coriander seeds", + "ginger", + "cardamom powder", + "vinegar", + "mustard seeds", + "mango powder", + "garam masala", + "red chili powder", + "chicken", + "hing", + "turmeric powder", + "tomatoes", + "ginger garlic paste", + "fresh greek yogurt", + "fresh ginger", + "monk fruit", + "turmeric", + "cashew nuts", + "salt", + "fresh red chili", + "cinnamon powder", + "nigella seeds", + "whole small crimini mushrooms", + "brussel sprouts", + "garlic", + "mangoes", + "heavy cream", + "cloves", + "coriander powder", + "cumin powder", + "cardamom", + "green chili", + "cinnamon", + "garlic paste", + "red chili flakes", + "lemon juice", + "cilantro", + "butter", + "dried fenugreek leaves", + "boned chicken", + }, + { + "green onions", + "parsley", + "sesame seeds", + "black pepper", + "chives", + "eggs", + "fennel bulb", + "tahini", + "olive oil", + "harissa", + "shrimp", + "lemon juice", + "dill", + "butter", + "onion", + "fresh cucumber", + "monk fruit", + "salt", + }, + { + "sriacha", + "apple cider vinegar", + "lime juice", + "fish sauce", + "red and green thai chili", + "flank steak", + "carrot", + "peanuts", + "cucumbers", + "roasted peanuts", + "crunchy peanut butter", + "kecap manis", + "monk fruit", + "micro cilantro", + "olive oil", + }, + { + "spinach", + "parmesan cheese", + "coconut flour", + "chili flakes", + "garlic", + "black pepper", + "cream cheese", + "ghee", + "lemon juice", + "flaxmeal", + "red onion", + "salt", + "salmon fillets", + "pecans", + "almond flour", + "cumin", + "fresh cucumber", + "cherry tomatoes", + "chives", + "avocado mayonnaise", + }, + { + "rosemary", + "garlic", + "black pepper", + "thyme", + "avocado oil", + "eggs", + "oregano", + "asparagus", + "lemon", + "dijon mustard", + "basil", + "castelfranco radicchio", + "dill", + "butter", + "pork chops", + "monk fruit", + "salt", + "avocado mayonnaise", + }, + { + "lime juice", + "caster sugar", + "toasted buckwheat", + "lemon juice", + "red wine vinegar", + "red onion", + "dutch carrot", + "salmon steaks", + "watercress", + "pink peppercorns", + "shallots", + "fennel seeds", + "red cabbage", + "radishes", + }, + { + "cilantro leaves", + "green cabbage", + "lemon juice", + "pork belly", + "dark soy sauce", + "granny smith apples", + "ginger", + "light soy sauce", + "sesame seeds", + "black pepper", + "cinnamon sticks", + "spring onions", + "star anise", + "monk fruit", + "olive oil", + }, + ], + [ + { + "lime juice", + "salsa", + "green bell pepper", + "anaheim chili", + "black pepper", + "olive oil", + "yellow mustard", + "red bell pepper", + "soy sauce", + "mexican crema", + "mayonnaise", + "white onion", + "garlic cloves", + "fresh corn tortillas", + "red onion", + "tomatoes", + "limes", + "worcestershire sauce", + "butter", + "yellow bell pepper", + "salt", + "red snapper", + }, + { + "lime juice", + "poblano chili", + "tomato paste", + "black pepper", + "chipotle adobo sauce", + "chile manzano", + "roma tomatoes", + "pepitas", + "oaxaca cheese", + "white onion", + "shelled large shrimp", + "garlic cloves", + "fresh corn tortillas", + "red onion", + "worcestershire sauce", + "avocado", + "butter", + "kosher salt", + }, + { + "fresh tortillas", + "shrimp", + "garlic", + "chickpeas", + "black pepper", + "slivered almonds", + "guajillo chile", + "bacon", + "sea salt", + "butter", + "onion", + "avocado", + "olive oil", + }, + { + "lime juice", + "green cabbage", + "chiles de árbol", + "green cardamom", + "ginger", + "carrot", + "sriracha", + "black pepper", + "cinnamon sticks", + "celery seeds", + "cloves", + "black cardamom", + "olive oil", + "chicken wings", + "apple cider vinegar", + "mayonnaise", + "honey", + "black peppercorns", + "lemon juice", + "garlic cloves", + "tamarind concentrate", + "cilantro", + "butter", + "serrano chili", + "red cabbage", + "kosher salt", + }, + { + "whole-milk yogurt", + "chaat masala", + "ginger", + "pani puri", + "scallion chutney", + "yukon gold potato", + "black chickpeas", + "thin sev", + "date syrup", + "red onion", + "roasted chicken", + "chili powder", + "tamarind concentrate", + "cumin", + "turmeric", + "mint", + }, + { + "white vinegar", + "parsley", + "yellow onion", + "rhubarb", + "garlic", + "brown sugar", + "black pepper", + "thyme", + "crushed red pepper flakes", + "fennel bulbs", + "beer", + "marjoram", + "vegetable oil", + "soy sauce", + "oregano", + "lemon", + "red onion", + "chili powder", + "cilantro", + "beef brisket", + "balsamic vinegar", + "worcestershire sauce", + "celery", + "mint", + "kosher salt", + }, + { + "oranges", + "rosemary", + "garlic", + "anchovy fillets", + "couscous", + "carrot", + "sesame seeds", + "fresh thyme", + "vinegar", + "olive oil", + "tahini", + "harissa", + "onions", + "honey", + "fresh mint", + "leg of lamb", + "tomatoes", + "baby carrot", + "vegetable bullion", + "filo pastry", + "celery", + "bay leaves", + "yoghurt", + }, + { + "tomato puree", + "garlic", + "ginger", + "tomato", + "carrot", + "thyme", + "white pepper", + "water", + "maggi cubes", + "chicken", + "rice", + "coriander", + "scotch bonnet pepper", + "bell pepper", + "onion", + "turmeric", + "salt", + }, + { + "garlic", + "tomato paste", + "baby scallops", + "mussels", + "water", + "crab legs", + "olive oil", + "baby squid", + "fish stock", + "lemon juice", + "white onion", + "arborio risotto rice", + "clams", + "parmesan cheese", + "flat-leaf parsley", + "cherry tomatoes", + "prawns", + "white wine", + }, + { + "toasted bread", + "rosemary", + "hazelnuts", + "anchovy fillets", + "garlic", + "carrot", + "summer squash", + "black pepper", + "red pepper flakes", + "vinegar", + "sea salt", + "zucchini", + "olive oil", + "onions", + "white wine vinegar", + "fresh mint", + "leg of lamb", + "lemon", + "fresh ricotta", + "sugar", + "celery", + "bay leaves", + "kosher salt", + }, + ], +] ##################################### @@ -395,49 +4485,241 @@ ##################################### -vegan = ['Kisir with Warm Pita', 'Shakshuka', 'Vegetarian Khoresh Bademjan', 'Baked Kelewele', 'Waakye', 'Georgian Eggplant Rolls with Walnuts', 'Burmese Tofu with Garlic, Ginger and Chili Sauce', 'Celeriac Schnitzel', 'Sticky Lemon Tofu', 'Vegan Carbonara', 'Vegan Pizza with Caramelized Onions', 'Cheela with Spicy Mango Chutney', 'Sweet and Spicy Crispy Green Beans', 'Vegan Mini Savory Mince Pies', 'Roasted Corn and Zucchini Salad', 'Golden Potato Salad', 'Carrot Puff Pastry Tart', 'Kisir with Warm Pita', 'Baked Kelewele', 'Burmese Tofu with Garlic, Ginger and Chili Sauce', 'Vegan Carbonara', 'Sweet and Spicy Crispy Green Beans', 'Golden Potato Salad'] -vegan_appetizers = ['Georgian Eggplant Rolls with Walnuts', 'Cheela with Spicy Mango Chutney', 'Vegan Mini Savory Mince Pies', 'Carrot Puff Pastry Tart', 'Georgian Eggplant Rolls with Walnuts', 'Carrot Puff Pastry Tart'] -vegan_dishes = ['Golden Potato Salad', 'Roasted Corn and Zucchini Salad', 'Sticky Lemon Tofu', 'Shakshuka', 'Burmese Tofu with Garlic, Ginger and Chili Sauce', 'Vegan Pizza with Caramelized Onions', 'Celeriac Schnitzel', 'Waakye', 'Vegan Carbonara', 'Sweet and Spicy Crispy Green Beans', 'Vegetarian Khoresh Bademjan', 'Baked Kelewele', 'Kisir with Warm Pita'] -vegan_appetizer_names = ['Georgian Eggplant Rolls with Walnuts','Cheela with Spicy Mango Chutney','Vegan Mini Savory Mince Pies','Carrot Puff Pastry Tart'] +vegan = [ + "Kisir with Warm Pita", + "Shakshuka", + "Vegetarian Khoresh Bademjan", + "Baked Kelewele", + "Waakye", + "Georgian Eggplant Rolls with Walnuts", + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + "Celeriac Schnitzel", + "Sticky Lemon Tofu", + "Vegan Carbonara", + "Vegan Pizza with Caramelized Onions", + "Cheela with Spicy Mango Chutney", + "Sweet and Spicy Crispy Green Beans", + "Vegan Mini Savory Mince Pies", + "Roasted Corn and Zucchini Salad", + "Golden Potato Salad", + "Carrot Puff Pastry Tart", + "Kisir with Warm Pita", + "Baked Kelewele", + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + "Vegan Carbonara", + "Sweet and Spicy Crispy Green Beans", + "Golden Potato Salad", +] +vegan_appetizers = [ + "Georgian Eggplant Rolls with Walnuts", + "Cheela with Spicy Mango Chutney", + "Vegan Mini Savory Mince Pies", + "Carrot Puff Pastry Tart", + "Georgian Eggplant Rolls with Walnuts", + "Carrot Puff Pastry Tart", +] +vegan_dishes = [ + "Golden Potato Salad", + "Roasted Corn and Zucchini Salad", + "Sticky Lemon Tofu", + "Shakshuka", + "Burmese Tofu with Garlic, Ginger and Chili Sauce", + "Vegan Pizza with Caramelized Onions", + "Celeriac Schnitzel", + "Waakye", + "Vegan Carbonara", + "Sweet and Spicy Crispy Green Beans", + "Vegetarian Khoresh Bademjan", + "Baked Kelewele", + "Kisir with Warm Pita", +] +vegan_appetizer_names = [ + "Georgian Eggplant Rolls with Walnuts", + "Cheela with Spicy Mango Chutney", + "Vegan Mini Savory Mince Pies", + "Carrot Puff Pastry Tart", +] -vegetarian = ['Mushroom Lasagna', 'Nut Wellington', 'Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing', 'Cambodian-Style Vegetable Spring Rolls', 'Summer Minestrone Cups', 'Fried Zucchini with Balsamic and Chili Dressing', 'Barley Risotto', 'Cherry Tomato, Watercress and Fava Bean Salad', 'Fresh Garden Peas over Cauliflower Almond Puree', 'Walnut Ravioli with Artichokes and Tomatoes', 'Asparagus Puffs', 'Grilled Tofu Tacos', 'Mushroom Lasagna', 'Cambodian-Style Vegetable Spring Rolls', 'Barley Risotto', 'Walnut Ravioli with Artichokes and Tomatoes'] -vegetarian_appetizers = ['Cambodian-Style Vegetable Spring Rolls', 'Summer Minestrone Cups', 'Asparagus Puffs', 'Grilled Tofu Tacos', 'Cambodian-Style Vegetable Spring Rolls', 'Grilled Tofu Tacos'] -vegetarian_dishes = ['Walnut Ravioli with Artichokes and Tomatoes', 'Mushroom Lasagna', 'Fried Zucchini with Balsamic and Chili Dressing', 'Barley Risotto', 'Nut Wellington', 'Cherry Tomato, Watercress and Fava Bean Salad', 'Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing', 'Fresh Garden Peas over Cauliflower Almond Puree'] -vegetarian_appetizer_names = ['Cambodian-Style Vegetable Spring Rolls','Summer Minestrone Cups','Asparagus Puffs','Grilled Tofu Tacos'] +vegetarian = [ + "Mushroom Lasagna", + "Nut Wellington", + "Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing", + "Cambodian-Style Vegetable Spring Rolls", + "Summer Minestrone Cups", + "Fried Zucchini with Balsamic and Chili Dressing", + "Barley Risotto", + "Cherry Tomato, Watercress and Fava Bean Salad", + "Fresh Garden Peas over Cauliflower Almond Puree", + "Walnut Ravioli with Artichokes and Tomatoes", + "Asparagus Puffs", + "Grilled Tofu Tacos", + "Mushroom Lasagna", + "Cambodian-Style Vegetable Spring Rolls", + "Barley Risotto", + "Walnut Ravioli with Artichokes and Tomatoes", +] +vegetarian_appetizers = [ + "Cambodian-Style Vegetable Spring Rolls", + "Summer Minestrone Cups", + "Asparagus Puffs", + "Grilled Tofu Tacos", + "Cambodian-Style Vegetable Spring Rolls", + "Grilled Tofu Tacos", +] +vegetarian_dishes = [ + "Walnut Ravioli with Artichokes and Tomatoes", + "Mushroom Lasagna", + "Fried Zucchini with Balsamic and Chili Dressing", + "Barley Risotto", + "Nut Wellington", + "Cherry Tomato, Watercress and Fava Bean Salad", + "Roast Pumpkin and Lentil Salad with Roasted Lemon Dressing", + "Fresh Garden Peas over Cauliflower Almond Puree", +] +vegetarian_appetizer_names = [ + "Cambodian-Style Vegetable Spring Rolls", + "Summer Minestrone Cups", + "Asparagus Puffs", + "Grilled Tofu Tacos", +] -paleo = ['Zucchini Fritters with Lemon-Thyme Coconut Yogurt', 'Avocado Deviled Eggs', 'Grilled Flank Steak with Caesar Salad', 'Pumpkin Bread Crostini', 'BLT Bites', 'Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes', 'Chicken with Tamarind and Apricot Sauce', 'Grilled Fish Tacos with Cauliflower Tortillas', 'Grilled Pork Chops with Mango Pineapple Salsa', 'Grilled Shrimp and Pesto over Zucchini Noodles', 'Zucchini Fritters with Lemon-Thyme Coconut Yogurt', 'Pumpkin Bread Crostini', 'Chicken with Tamarind and Apricot Sauce', 'Grilled Shrimp and Pesto over Zucchini Noodles'] -paleo_appetizers = ['Zucchini Fritters with Lemon-Thyme Coconut Yogurt', 'Avocado Deviled Eggs', 'Pumpkin Bread Crostini', 'BLT Bites', 'Zucchini Fritters with Lemon-Thyme Coconut Yogurt', 'BLT Bites'] -paleo_dishes = ['Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes', 'Grilled Flank Steak with Caesar Salad', 'Grilled Fish Tacos with Cauliflower Tortillas', 'Grilled Pork Chops with Mango Pineapple Salsa', 'Grilled Shrimp and Pesto over Zucchini Noodles', 'Chicken with Tamarind and Apricot Sauce'] -paleo_appetizer_names = ['Zucchini Fritters with Lemon-Thyme Coconut Yogurt','Avocado Deviled Eggs','Pumpkin Bread Crostini','BLT Bites'] +paleo = [ + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + "Avocado Deviled Eggs", + "Grilled Flank Steak with Caesar Salad", + "Pumpkin Bread Crostini", + "BLT Bites", + "Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes", + "Chicken with Tamarind and Apricot Sauce", + "Grilled Fish Tacos with Cauliflower Tortillas", + "Grilled Pork Chops with Mango Pineapple Salsa", + "Grilled Shrimp and Pesto over Zucchini Noodles", + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + "Pumpkin Bread Crostini", + "Chicken with Tamarind and Apricot Sauce", + "Grilled Shrimp and Pesto over Zucchini Noodles", +] +paleo_appetizers = [ + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + "Avocado Deviled Eggs", + "Pumpkin Bread Crostini", + "BLT Bites", + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + "BLT Bites", +] +paleo_dishes = [ + "Roasted Chicken with Roasted Tomatoes, Avocado, and Sweet Potatoes", + "Grilled Flank Steak with Caesar Salad", + "Grilled Fish Tacos with Cauliflower Tortillas", + "Grilled Pork Chops with Mango Pineapple Salsa", + "Grilled Shrimp and Pesto over Zucchini Noodles", + "Chicken with Tamarind and Apricot Sauce", +] +paleo_appetizer_names = [ + "Zucchini Fritters with Lemon-Thyme Coconut Yogurt", + "Avocado Deviled Eggs", + "Pumpkin Bread Crostini", + "BLT Bites", +] -keto = ['Cauliflower Pizza with Roasted Tomatoes and Chicken', 'Flank Steak with Chimichurri and Asparagus', 'Kingfish Lettuce Cups', 'Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', 'Prawn and Herb Omelette', 'Satay Steak Skewers', 'Parmesan Crackers and Spinach Crackers with Salmon Pate', 'Pork Chops with Grilled Castelfranco Radicchio and Asparagus', 'Seared Salmon with Pickled Vegetable and Watercress Salad', 'Braised Pork Belly with Apple Salad', 'Cauliflower Pizza with Roasted Tomatoes and Chicken', 'Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', 'Parmesan Crackers and Spinach Crackers with Salmon Pate', 'Braised Pork Belly with Apple Salad'] -keto_appetizers = ['Kingfish Lettuce Cups', 'Prawn and Herb Omelette', 'Satay Steak Skewers', 'Parmesan Crackers and Spinach Crackers with Salmon Pate', 'Kingfish Lettuce Cups', 'Parmesan Crackers and Spinach Crackers with Salmon Pate'] -keto_dishes = ['Cauliflower Pizza with Roasted Tomatoes and Chicken', 'Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney', 'Braised Pork Belly with Apple Salad', 'Seared Salmon with Pickled Vegetable and Watercress Salad', 'Pork Chops with Grilled Castelfranco Radicchio and Asparagus', 'Flank Steak with Chimichurri and Asparagus'] -keto_appetizer_names = ['Kingfish Lettuce Cups','Prawn and Herb Omelette','Satay Steak Skewers','Parmesan Crackers and Spinach Crackers with Salmon Pate'] +keto = [ + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + "Flank Steak with Chimichurri and Asparagus", + "Kingfish Lettuce Cups", + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + "Prawn and Herb Omelette", + "Satay Steak Skewers", + "Parmesan Crackers and Spinach Crackers with Salmon Pate", + "Pork Chops with Grilled Castelfranco Radicchio and Asparagus", + "Seared Salmon with Pickled Vegetable and Watercress Salad", + "Braised Pork Belly with Apple Salad", + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + "Parmesan Crackers and Spinach Crackers with Salmon Pate", + "Braised Pork Belly with Apple Salad", +] +keto_appetizers = [ + "Kingfish Lettuce Cups", + "Prawn and Herb Omelette", + "Satay Steak Skewers", + "Parmesan Crackers and Spinach Crackers with Salmon Pate", + "Kingfish Lettuce Cups", + "Parmesan Crackers and Spinach Crackers with Salmon Pate", +] +keto_dishes = [ + "Cauliflower Pizza with Roasted Tomatoes and Chicken", + "Butter Chicken with Grilled Mushrooms, Brussel Sprouts and Mango Chutney", + "Braised Pork Belly with Apple Salad", + "Seared Salmon with Pickled Vegetable and Watercress Salad", + "Pork Chops with Grilled Castelfranco Radicchio and Asparagus", + "Flank Steak with Chimichurri and Asparagus", +] +keto_appetizer_names = [ + "Kingfish Lettuce Cups", + "Prawn and Herb Omelette", + "Satay Steak Skewers", + "Parmesan Crackers and Spinach Crackers with Salmon Pate", +] -omnivore = ['Beachside Snapper', 'Governor Shrimp Tacos', 'Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole', 'Burnt Masala Wings with Classic Coleslaw', 'Dahi Puri with Black Chickpeas', 'Brisket with Grilled Rhubarb, Onions, and Fennel', 'Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous', 'Baked Chicken Jollof Rice', 'Seafood Risotto', 'Lamb over Marinated Summer Squash with Hazelnuts and Ricotta', 'Beachside Snapper', 'Burnt Masala Wings with Classic Coleslaw', 'Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous', 'Lamb over Marinated Summer Squash with Hazelnuts and Ricotta'] -omnivore_appetizers = ['Governor Shrimp Tacos', 'Burnt Masala Wings with Classic Coleslaw', 'Dahi Puri with Black Chickpeas', 'Seafood Risotto', 'Governor Shrimp Tacos', 'Seafood Risotto'] -omnivore_dishes = ['Lamb over Marinated Summer Squash with Hazelnuts and Ricotta', 'Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole', 'Brisket with Grilled Rhubarb, Onions, and Fennel', 'Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous', 'Beachside Snapper', 'Baked Chicken Jollof Rice'] -omnivore_appetizer_names = ['Governor Shrimp Tacos','Burnt Masala Wings with Classic Coleslaw','Dahi Puri with Black Chickpeas','Seafood Risotto'] +omnivore = [ + "Beachside Snapper", + "Governor Shrimp Tacos", + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", + "Burnt Masala Wings with Classic Coleslaw", + "Dahi Puri with Black Chickpeas", + "Brisket with Grilled Rhubarb, Onions, and Fennel", + "Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous", + "Baked Chicken Jollof Rice", + "Seafood Risotto", + "Lamb over Marinated Summer Squash with Hazelnuts and Ricotta", + "Beachside Snapper", + "Burnt Masala Wings with Classic Coleslaw", + "Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous", + "Lamb over Marinated Summer Squash with Hazelnuts and Ricotta", +] +omnivore_appetizers = [ + "Governor Shrimp Tacos", + "Burnt Masala Wings with Classic Coleslaw", + "Dahi Puri with Black Chickpeas", + "Seafood Risotto", + "Governor Shrimp Tacos", + "Seafood Risotto", +] +omnivore_dishes = [ + "Lamb over Marinated Summer Squash with Hazelnuts and Ricotta", + "Shrimp, Bacon and Crispy Chickpea Tacos with Salsa de Guacamole", + "Brisket with Grilled Rhubarb, Onions, and Fennel", + "Roast Leg of Lamb with Crispy Moroccan Carrots & Couscous", + "Beachside Snapper", + "Baked Chicken Jollof Rice", +] +omnivore_appetizer_names = [ + "Governor Shrimp Tacos", + "Burnt Masala Wings with Classic Coleslaw", + "Dahi Puri with Black Chickpeas", + "Seafood Risotto", +] -dishes_and_appetizers = ((vegan, vegan_appetizers), - (vegetarian, vegetarian_appetizers), - (paleo, paleo_appetizers), - (keto, keto_appetizers), - (omnivore, omnivore_appetizers) - ) +dishes_and_appetizers = ( + (vegan, vegan_appetizers), + (vegetarian, vegetarian_appetizers), + (paleo, paleo_appetizers), + (keto, keto_appetizers), + (omnivore, omnivore_appetizers), +) -dishes_cleaned = (vegan_dishes, - vegetarian_dishes, - paleo_dishes, - keto_dishes, - omnivore_dishes - ) +dishes_cleaned = ( + vegan_dishes, + vegetarian_dishes, + paleo_dishes, + keto_dishes, + omnivore_dishes, +) ####################################### @@ -445,15 +4727,498 @@ ####################################### -intersections = (VEGAN_INTERSECTIONS, VEGETARIAN_INTERSECTIONS, PALEO_INTERSECTIONS, - KETO_INTERSECTIONS, OMNIVORE_INTERSECTIONS) +intersections = ( + VEGAN_INTERSECTIONS, + VEGETARIAN_INTERSECTIONS, + PALEO_INTERSECTIONS, + KETO_INTERSECTIONS, + OMNIVORE_INTERSECTIONS, +) -dishes_and_overlap = [(item[0], item[1]) for item in zip(ingredients_only, intersections)] +dishes_and_overlap = [ + (item[0], item[1]) for item in zip(ingredients_only, intersections) +] ingredients = (set.union(*group) for group in ingredients_only) -singletons = (item[0] ^ item[1] for item in zip(ingredients, intersections)) +singletons = (item[0] ^ item[1] for item in zip(ingredients, intersections)) -backup_singletons = [{'black-eyed peas', 'coriander', 'cashews', 'yellow split peas', 'pomegranate seeds', 'cumin', 'mangoes', 'pomegranate concentrate', 'red chili powder', 'slivered almonds', 'black peppercorn', 'cornstarch', 'smoked tofu', 'curry leaves', 'zucchini', 'currants', 'dried cranberries', 'yukon gold potato', 'tofu', 'yeast', 'fresh basil', 'hot water', 'ripe plantains', 'calabash nutmeg', 'green beans', 'kosher salt', 'grains of selim', 'vegetarian worcestershire sauce', 'cumin seeds', 'figs', 'ground turmeric', 'white rice', 'harissa', 'garlic powder', 'scallions', 'barberries', 'walnuts', 'basmati rice', 'saffron powder', 'butternut squash', 'thyme', 'tomato', 'chopped parsley', 'hing', 'coriander seeds', 'turmeric powder', 'eggplants', 'sesame oil', "za'atar", 'pareve puff pastry', 'firm tofu', 'yellow onions', 'coriander powder', 'parsley', 'garlic paste', 'rice vinegar', 'sorghum stems', 'spring onions', 'raisins', 'chinese eggplants', 'garam masala', 'ground almonds', 'baking soda', 'clove powder', 'allspice powder', 'parev shortcrust pastry', 'dill', 'nigella seeds', 'dried blueberries', 'cardamom powder', 'cilantro', 'serrano chili', 'breadcrumbs', 'mango powder', 'dried cherries', 'oregano', 'fresh red chili', 'pecans', 'chives', 'spaghetti', 'mixed herbs', 'brandy', 'cumin powder', 'silken tofu', 'yellow onion', 'balsamic vinegar', 'persian cucumber', 'red bell pepper', 'peanuts', 'siracha', 'red pepper flakes', 'spring onion', 'vegan unsweetened yoghurt', 'corn', 'khmeli suneli', 'barley malt', 'green onions', 'apples', 'corn flour', 'honey', 'celeriac', 'bulgur', 'sesame seeds', 'mashed potatoes', 'chili flakes', 'vegetable oil'}, -{'vegetarian fish sauce', 'cashews', 'white wine', 'portobello mushrooms', 'marmite', 'dates', 'tomatillos', 'cumin', 'chestnuts', 'beets', 'masa', 'mint', 'smoked tofu', 'fresh pea tendrils', 'puff pastry sheets', 'zucchini', 'currants', 'hazelnuts', 'croutons', 'pearl barley', 'dijon mustard', 'yukon gold potato', 'fresh tomatoes', 'vermicelli noodles', 'fresh cherry tomatoes', 'celery', 'hot water', 'green beans', 'grated nutmeg', 'roasted corn', 'palm sugar', 'ancho chili', 'fresh corn', 'spring roll wrappers', 'cotija cheese', 'parmesan rind', 'pasta sheets', 'brazil nuts', 'cauliflower', 'butternut squash', 'mint leaves', 'fresh cherry bocconcini', 'crema', 'blue cheese', 'chickpeas', 'pasilla chili', 'black beans', 'wombok', 'capers', 'pine nuts', 'egg', 'shiitake mushrooms', 'red thai chili', 'jalapeño chili', 'toasted peanuts', 'brussel sprouts', 'lime juice', 'leeks', 'flour', 'dried lasagna noodles', 'onions', 'limes', 'chipotle chili', 'lacinato kale', 'fresh pumpkin', 'almonds', 'olives', 'onion', 'fresh artichoke hearts', 'leek', 'pecans', 'chives', 'blanched almonds', 'nutmeg', 'fresh or frozen fava beans', 'soy sauce', 'avocados', 'bean sprouts', 'asparagus', 'feta cheese', 'sharp white cheddar', 'apples', 'sunflower oil', 'corn flour', 'avocado', 'puff pastry', 'red cabbage', 'pomegranate', 'fresh cilantro leaves', 'oil marinated artichokes', 'vegetable oil'}, -{'treviso', 'cashews', 'mexican oregano', 'pumpkin puree', 'purple sweet potato', 'homemade apricot honey preserves', 'apple cider vinegar', 'homemade tamarind concentrate', 'paleo parmesan cheese', 'pineapple', 'green bell pepper', 'chipotles', 'nutmeg', 'ground cumin', 'coconut yogurt', 'kale', 'mangoes', 'red bell pepper', 'dried apricots', 'garlic powder', 'pepitas', 'white vinegar', 'scallions', 'avocados', 'shredded red cabbage', 'smoked paprika', 'lime juice', 'flank steak', 'fresh parsley', 'shallots', 'chiles de árbol', 'yellow bell pepper', 'white chicken', 'whole chicken', 'chili powder', 'bacon', 'avocado mayonnaise', 'cilantro', 'limes', 'lemons', 'green onions', 'avocado oil', 'cloves', 'lacinato kale', 'lime zest', 'paleo mayonnaise', 'radishes', 'mango', 'dijon mustard', 'mustard seed', 'cider vinegar', 'pork chops', 'castelfranco radicchio', 'water', 'allspice', 'seranno chili', 'cilantro leaves', 'onion', 'tilapia', 'fresh cilantro leaves', 'worcestershire sauce', 'almond butter', 'fresh thai chili', 'fresh red chili', 'chives', 'roma tomatoes'}, -{'dried fenugreek leaves', 'apple cider vinegar', 'cinnamon sticks', 'roasted chicken', 'cumin', 'mangoes', 'heavy cream', 'micro cilantro', 'white vinegar', 'red chili powder', 'cinnamon powder', 'mustard seeds', 'red wine vinegar', 'mirin', 'cinnamon', 'green chili', 'avocado oil', 'curry leaves', 'star anise', 'dijon mustard', 'crunchy peanut butter', 'grilled king fish', 'chicken', 'fresh basil', 'cashew nuts', 'pink peppercorns', 'pork belly', 'spinach', 'watercress', 'whole small crimini mushrooms', 'coconut flour', 'fresh ginger', 'fennel bulb', 'harissa', 'tahini', 'mozzarella cheese', 'scallions', 'sriacha', 'fresh parsley', 'thyme', 'light soy sauce', 'cream cheese', 'hing', 'coriander seeds', 'sour cream', 'turmeric powder', 'castelfranco radicchio', 'parmesan', 'toasted buckwheat', 'coriander powder', 'dark soy sauce', 'granny smith apples', 'parsley', 'shrimp', 'garlic paste', 'roasted peanuts', 'turmeric', 'carrot', 'garam masala', 'clove powder', 'cucumbers', 'tomato paste', 'almond meal', 'dutch carrot', 'brussel sprouts', 'red and green thai chili', 'shallots', 'nigella seeds', 'cardamom powder', 'watermelon radishes', 'flaxmeal', 'cilantro', 'fennel seeds', 'chipotle chili', 'ghee', 'parmesan cheese', 'radishes', 'pork chops', 'cilantro leaves', 'fresh greek yogurt', 'cardamom', 'mango powder', 'onion', 'oregano', 'fresh red chili', 'pecans', 'salmon fillets', 'basil', 'green cabbage', 'cumin powder', 'almond flour', 'lemon', 'boned chicken', 'oyster sauce', 'soy sauce', 'little gem lettuce heads', 'peanut oil', 'peanuts', 'caster sugar', 'salmon steaks', 'ginger garlic paste', 'green onions', 'vinegar', 'cloves', 'kecap manis', 'avocado', 'chili flakes', 'red chili flakes', 'tomatoes'}, -{'coriander', 'white wine', 'fish stock', 'apple cider vinegar', 'salsa', 'rhubarb', 'beef brisket', 'cinnamon sticks', 'cumin', 'roasted chicken', 'chicken wings', 'white vinegar', 'sriracha', 'slivered almonds', 'fresh thyme', 'scotch bonnet pepper', 'zucchini', 'hazelnuts', 'pani puri', 'yukon gold potato', 'toasted bread', 'chicken', 'yoghurt', 'maggi cubes', 'couscous', 'roma tomatoes', 'celery seeds', 'chaat masala', 'white pepper', 'black cardamom', 'harissa', 'red snapper', 'green cardamom', 'crushed red pepper flakes', 'tahini', 'mexican crema', 'chiles de árbol', 'tomato', 'baby squid', 'mussels', 'chipotle adobo sauce', 'shelled large shrimp', 'tomato puree', 'chickpeas', 'fresh tortillas', 'flat-leaf parsley', 'anaheim chili', 'parsley', 'shrimp', 'chile manzano', 'vegetable bullion', 'prawns', 'cherry tomatoes', 'marjoram', 'beer', 'green bell pepper', 'date syrup', 'guajillo chile', 'baby scallops', 'yellow mustard', 'black chickpeas', 'bell pepper', 'filo pastry', 'thin sev', 'bacon', 'white wine vinegar', 'limes', 'rice', 'serrano chili', 'brown sugar', 'parmesan cheese', 'poblano chili', 'fennel bulbs', 'clams', 'baby carrot', 'arborio risotto rice', 'oregano', 'oaxaca cheese', 'green cabbage', 'yellow onion', 'balsamic vinegar', 'whole-milk yogurt', 'sugar', 'red bell pepper', 'pepitas', 'red pepper flakes', 'oranges', 'yellow bell pepper', 'summer squash', 'cloves', 'red cabbage', 'black peppercorns', 'fresh ricotta', 'crab legs', 'scallion chutney', 'sesame seeds', 'vegetable oil'}] \ No newline at end of file +backup_singletons = [ + { + "black-eyed peas", + "coriander", + "cashews", + "yellow split peas", + "pomegranate seeds", + "cumin", + "mangoes", + "pomegranate concentrate", + "red chili powder", + "slivered almonds", + "black peppercorn", + "cornstarch", + "smoked tofu", + "curry leaves", + "zucchini", + "currants", + "dried cranberries", + "yukon gold potato", + "tofu", + "yeast", + "fresh basil", + "hot water", + "ripe plantains", + "calabash nutmeg", + "green beans", + "kosher salt", + "grains of selim", + "vegetarian worcestershire sauce", + "cumin seeds", + "figs", + "ground turmeric", + "white rice", + "harissa", + "garlic powder", + "scallions", + "barberries", + "walnuts", + "basmati rice", + "saffron powder", + "butternut squash", + "thyme", + "tomato", + "chopped parsley", + "hing", + "coriander seeds", + "turmeric powder", + "eggplants", + "sesame oil", + "za'atar", + "pareve puff pastry", + "firm tofu", + "yellow onions", + "coriander powder", + "parsley", + "garlic paste", + "rice vinegar", + "sorghum stems", + "spring onions", + "raisins", + "chinese eggplants", + "garam masala", + "ground almonds", + "baking soda", + "clove powder", + "allspice powder", + "parev shortcrust pastry", + "dill", + "nigella seeds", + "dried blueberries", + "cardamom powder", + "cilantro", + "serrano chili", + "breadcrumbs", + "mango powder", + "dried cherries", + "oregano", + "fresh red chili", + "pecans", + "chives", + "spaghetti", + "mixed herbs", + "brandy", + "cumin powder", + "silken tofu", + "yellow onion", + "balsamic vinegar", + "persian cucumber", + "red bell pepper", + "peanuts", + "siracha", + "red pepper flakes", + "spring onion", + "vegan unsweetened yoghurt", + "corn", + "khmeli suneli", + "barley malt", + "green onions", + "apples", + "corn flour", + "honey", + "celeriac", + "bulgur", + "sesame seeds", + "mashed potatoes", + "chili flakes", + "vegetable oil", + }, + { + "vegetarian fish sauce", + "cashews", + "white wine", + "portobello mushrooms", + "marmite", + "dates", + "tomatillos", + "cumin", + "chestnuts", + "beets", + "masa", + "mint", + "smoked tofu", + "fresh pea tendrils", + "puff pastry sheets", + "zucchini", + "currants", + "hazelnuts", + "croutons", + "pearl barley", + "dijon mustard", + "yukon gold potato", + "fresh tomatoes", + "vermicelli noodles", + "fresh cherry tomatoes", + "celery", + "hot water", + "green beans", + "grated nutmeg", + "roasted corn", + "palm sugar", + "ancho chili", + "fresh corn", + "spring roll wrappers", + "cotija cheese", + "parmesan rind", + "pasta sheets", + "brazil nuts", + "cauliflower", + "butternut squash", + "mint leaves", + "fresh cherry bocconcini", + "crema", + "blue cheese", + "chickpeas", + "pasilla chili", + "black beans", + "wombok", + "capers", + "pine nuts", + "egg", + "shiitake mushrooms", + "red thai chili", + "jalapeño chili", + "toasted peanuts", + "brussel sprouts", + "lime juice", + "leeks", + "flour", + "dried lasagna noodles", + "onions", + "limes", + "chipotle chili", + "lacinato kale", + "fresh pumpkin", + "almonds", + "olives", + "onion", + "fresh artichoke hearts", + "leek", + "pecans", + "chives", + "blanched almonds", + "nutmeg", + "fresh or frozen fava beans", + "soy sauce", + "avocados", + "bean sprouts", + "asparagus", + "feta cheese", + "sharp white cheddar", + "apples", + "sunflower oil", + "corn flour", + "avocado", + "puff pastry", + "red cabbage", + "pomegranate", + "fresh cilantro leaves", + "oil marinated artichokes", + "vegetable oil", + }, + { + "treviso", + "cashews", + "mexican oregano", + "pumpkin puree", + "purple sweet potato", + "homemade apricot honey preserves", + "apple cider vinegar", + "homemade tamarind concentrate", + "paleo parmesan cheese", + "pineapple", + "green bell pepper", + "chipotles", + "nutmeg", + "ground cumin", + "coconut yogurt", + "kale", + "mangoes", + "red bell pepper", + "dried apricots", + "garlic powder", + "pepitas", + "white vinegar", + "scallions", + "avocados", + "shredded red cabbage", + "smoked paprika", + "lime juice", + "flank steak", + "fresh parsley", + "shallots", + "chiles de árbol", + "yellow bell pepper", + "white chicken", + "whole chicken", + "chili powder", + "bacon", + "avocado mayonnaise", + "cilantro", + "limes", + "lemons", + "green onions", + "avocado oil", + "cloves", + "lacinato kale", + "lime zest", + "paleo mayonnaise", + "radishes", + "mango", + "dijon mustard", + "mustard seed", + "cider vinegar", + "pork chops", + "castelfranco radicchio", + "water", + "allspice", + "seranno chili", + "cilantro leaves", + "onion", + "tilapia", + "fresh cilantro leaves", + "worcestershire sauce", + "almond butter", + "fresh thai chili", + "fresh red chili", + "chives", + "roma tomatoes", + }, + { + "dried fenugreek leaves", + "apple cider vinegar", + "cinnamon sticks", + "roasted chicken", + "cumin", + "mangoes", + "heavy cream", + "micro cilantro", + "white vinegar", + "red chili powder", + "cinnamon powder", + "mustard seeds", + "red wine vinegar", + "mirin", + "cinnamon", + "green chili", + "avocado oil", + "curry leaves", + "star anise", + "dijon mustard", + "crunchy peanut butter", + "grilled king fish", + "chicken", + "fresh basil", + "cashew nuts", + "pink peppercorns", + "pork belly", + "spinach", + "watercress", + "whole small crimini mushrooms", + "coconut flour", + "fresh ginger", + "fennel bulb", + "harissa", + "tahini", + "mozzarella cheese", + "scallions", + "sriacha", + "fresh parsley", + "thyme", + "light soy sauce", + "cream cheese", + "hing", + "coriander seeds", + "sour cream", + "turmeric powder", + "castelfranco radicchio", + "parmesan", + "toasted buckwheat", + "coriander powder", + "dark soy sauce", + "granny smith apples", + "parsley", + "shrimp", + "garlic paste", + "roasted peanuts", + "turmeric", + "carrot", + "garam masala", + "clove powder", + "cucumbers", + "tomato paste", + "almond meal", + "dutch carrot", + "brussel sprouts", + "red and green thai chili", + "shallots", + "nigella seeds", + "cardamom powder", + "watermelon radishes", + "flaxmeal", + "cilantro", + "fennel seeds", + "chipotle chili", + "ghee", + "parmesan cheese", + "radishes", + "pork chops", + "cilantro leaves", + "fresh greek yogurt", + "cardamom", + "mango powder", + "onion", + "oregano", + "fresh red chili", + "pecans", + "salmon fillets", + "basil", + "green cabbage", + "cumin powder", + "almond flour", + "lemon", + "boned chicken", + "oyster sauce", + "soy sauce", + "little gem lettuce heads", + "peanut oil", + "peanuts", + "caster sugar", + "salmon steaks", + "ginger garlic paste", + "green onions", + "vinegar", + "cloves", + "kecap manis", + "avocado", + "chili flakes", + "red chili flakes", + "tomatoes", + }, + { + "coriander", + "white wine", + "fish stock", + "apple cider vinegar", + "salsa", + "rhubarb", + "beef brisket", + "cinnamon sticks", + "cumin", + "roasted chicken", + "chicken wings", + "white vinegar", + "sriracha", + "slivered almonds", + "fresh thyme", + "scotch bonnet pepper", + "zucchini", + "hazelnuts", + "pani puri", + "yukon gold potato", + "toasted bread", + "chicken", + "yoghurt", + "maggi cubes", + "couscous", + "roma tomatoes", + "celery seeds", + "chaat masala", + "white pepper", + "black cardamom", + "harissa", + "red snapper", + "green cardamom", + "crushed red pepper flakes", + "tahini", + "mexican crema", + "chiles de árbol", + "tomato", + "baby squid", + "mussels", + "chipotle adobo sauce", + "shelled large shrimp", + "tomato puree", + "chickpeas", + "fresh tortillas", + "flat-leaf parsley", + "anaheim chili", + "parsley", + "shrimp", + "chile manzano", + "vegetable bullion", + "prawns", + "cherry tomatoes", + "marjoram", + "beer", + "green bell pepper", + "date syrup", + "guajillo chile", + "baby scallops", + "yellow mustard", + "black chickpeas", + "bell pepper", + "filo pastry", + "thin sev", + "bacon", + "white wine vinegar", + "limes", + "rice", + "serrano chili", + "brown sugar", + "parmesan cheese", + "poblano chili", + "fennel bulbs", + "clams", + "baby carrot", + "arborio risotto rice", + "oregano", + "oaxaca cheese", + "green cabbage", + "yellow onion", + "balsamic vinegar", + "whole-milk yogurt", + "sugar", + "red bell pepper", + "pepitas", + "red pepper flakes", + "oranges", + "yellow bell pepper", + "summer squash", + "cloves", + "red cabbage", + "black peppercorns", + "fresh ricotta", + "crab legs", + "scallion chutney", + "sesame seeds", + "vegetable oil", + }, +] diff --git a/exercises/concept/chaitanas-colossal-coaster/list_methods_test.py b/exercises/concept/chaitanas-colossal-coaster/list_methods_test.py index 7a754b78e12..39ff7147b98 100644 --- a/exercises/concept/chaitanas-colossal-coaster/list_methods_test.py +++ b/exercises/concept/chaitanas-colossal-coaster/list_methods_test.py @@ -18,10 +18,22 @@ class ListMethodsTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_add_me_to_the_queue(self): test_data = [ - ((['Tony', 'Bruce'], ['RobotGuy', 'WW'], 0, 'HawkEye'), ['RobotGuy', 'WW', 'HawkEye']), - ((['Tony', 'Bruce'], ['RobotGuy', 'WW'], 1, 'RichieRich'), ['Tony', 'Bruce', 'RichieRich']), - ((['Agatha', 'Pepper', 'Valkyrie'], ['Drax', 'Nebula'], 1, 'Okoye'), ['Agatha', 'Pepper', 'Valkyrie', 'Okoye']), - ((['Agatha', 'Pepper', 'Valkyrie'], ['Drax', 'Nebula'], 0, 'Gamora'), ['Drax', 'Nebula', 'Gamora']), + ( + (["Tony", "Bruce"], ["RobotGuy", "WW"], 0, "HawkEye"), + ["RobotGuy", "WW", "HawkEye"], + ), + ( + (["Tony", "Bruce"], ["RobotGuy", "WW"], 1, "RichieRich"), + ["Tony", "Bruce", "RichieRich"], + ), + ( + (["Agatha", "Pepper", "Valkyrie"], ["Drax", "Nebula"], 1, "Okoye"), + ["Agatha", "Pepper", "Valkyrie", "Okoye"], + ), + ( + (["Agatha", "Pepper", "Valkyrie"], ["Drax", "Nebula"], 0, "Gamora"), + ["Drax", "Nebula", "Gamora"], + ), ] for variant, (params, expected) in enumerate(test_data, start=1): @@ -29,23 +41,38 @@ def test_add_me_to_the_queue(self): # That mutation wrecks havoc with the verification and error messaging. express_queue, normal_queue, ticket_type, person_name = deepcopy(params) - with self.subTest(f'variation #{variant}', params=params, expected=expected): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = add_me_to_the_queue(*params) error_message = ( - f'\nCalled add_me_to_the_queue{express_queue, normal_queue, ticket_type, person_name}.\n' - f'The function returned {actual_result},\n' - f' but the tests expected {expected} after {person_name} was added.') + f"\nCalled add_me_to_the_queue{express_queue, normal_queue, ticket_type, person_name}.\n" + f"The function returned {actual_result},\n" + f" but the tests expected {expected} after {person_name} was added." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=1) def test_add_me_to_the_queue_validate_queue(self): test_data = [ - ((['Tony', 'Bruce'], ['RobotGuy', 'WW'], 0, 'HawkEye'), ['RobotGuy', 'WW', 'HawkEye']), - ((['Tony', 'Bruce'], ['RobotGuy', 'WW'], 1, 'RichieRich'), ['Tony', 'Bruce', 'RichieRich']), - ((['Agatha', 'Pepper', 'Valkyrie'], ['Drax', 'Nebula'], 1, 'Okoye'), ['Agatha', 'Pepper', 'Valkyrie', 'Okoye']), - ((['Agatha', 'Pepper', 'Valkyrie'], ['Drax', 'Nebula'], 0, 'Gamora'), ['Drax', 'Nebula', 'Gamora']), + ( + (["Tony", "Bruce"], ["RobotGuy", "WW"], 0, "HawkEye"), + ["RobotGuy", "WW", "HawkEye"], + ), + ( + (["Tony", "Bruce"], ["RobotGuy", "WW"], 1, "RichieRich"), + ["Tony", "Bruce", "RichieRich"], + ), + ( + (["Agatha", "Pepper", "Valkyrie"], ["Drax", "Nebula"], 1, "Okoye"), + ["Agatha", "Pepper", "Valkyrie", "Okoye"], + ), + ( + (["Agatha", "Pepper", "Valkyrie"], ["Drax", "Nebula"], 0, "Gamora"), + ["Drax", "Nebula", "Gamora"], + ), ] for variant, (params, expected) in enumerate(test_data, start=1): @@ -54,26 +81,31 @@ def test_add_me_to_the_queue_validate_queue(self): express_queue, normal_queue, ticket_type, person_name = deepcopy(params) express, normal, ticket, name = params - with self.subTest(f'variation #{variant}', - express=express, normal=normal, - ticket=ticket, name=name, expected=expected): + with self.subTest( + f"variation #{variant}", + express=express, + normal=normal, + ticket=ticket, + name=name, + expected=expected, + ): actual_result = add_me_to_the_queue(express, normal, ticket, name) if type == 1: error_message = ( - f'\nCalled add_me_to_the_queue{express_queue, normal_queue, ticket_type, person_name}.\n' - f'The queue == {express}, but the tests expected\n' - f'queue == {expected} after {person_name} was added.' + f"\nCalled add_me_to_the_queue{express_queue, normal_queue, ticket_type, person_name}.\n" + f"The queue == {express}, but the tests expected\n" + f"queue == {expected} after {person_name} was added." ) self.assertIs(actual_result, express, msg=error_message) if type == 0: error_message = ( - f'\nCalled add_me_to_the_queue{express_queue, normal_queue, ticket_type, person_name}.\n' - f'The queue == {normal}, but the tests expected \n' - f'queue == {expected} after {person_name} was added.' + f"\nCalled add_me_to_the_queue{express_queue, normal_queue, ticket_type, person_name}.\n" + f"The queue == {normal}, but the tests expected \n" + f"queue == {expected} after {person_name} was added." ) self.assertIs(actual_result, normal, msg=error_message) @@ -81,21 +113,25 @@ def test_add_me_to_the_queue_validate_queue(self): @pytest.mark.task(taskno=2) def test_find_my_friend(self): test_data = [ - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 'Natasha'), - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 'Steve'), - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 'Rocket'), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], "Natasha"), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], "Steve"), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], "Rocket"), ] - result_data = (0,1,4) + result_data = (0, 1, 4) - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', params=params, expected=expected): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = find_my_friend(*params) error_message = ( - f'\nCalled find_my_friend{params}.\n' - f'The function returned {actual_result}, but\n' - f'the tests expected {expected} when looking for\n' - f'{params[-1]} in the queue.' + f"\nCalled find_my_friend{params}.\n" + f"The function returned {actual_result}, but\n" + f"the tests expected {expected} when looking for\n" + f"{params[-1]} in the queue." ) self.assertIs(actual_result, expected, msg=error_message) @@ -103,30 +139,34 @@ def test_find_my_friend(self): @pytest.mark.task(taskno=3) def test_add_me_with_my_friends(self): test_data = [ - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 0, 'Bucky'), - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 1, 'Bucky'), - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 5, 'Bucky'), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], 0, "Bucky"), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], 1, "Bucky"), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], 5, "Bucky"), ] result_data = [ - ['Bucky', 'Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], - ['Natasha', 'Bucky', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], - ['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket', 'Bucky'], + ["Bucky", "Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], + ["Natasha", "Bucky", "Steve", "Tchalla", "Wanda", "Rocket"], + ["Natasha", "Steve", "Tchalla", "Wanda", "Rocket", "Bucky"], ] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): # Deepcopy() is needed here because the task expects the input lists to be mutated. # That mutation wrecks havoc with the verification and error messaging. queue, index, person_name = deepcopy(params) - with self.subTest(f'variation #{variant}', params=params, expected=expected): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = add_me_with_my_friends(*params) error_message = ( - f'\nCalled add_me_with_my_friends{queue, index, person_name}.\n' - f'The function returned {actual_result}, but\n' - f'the tests expected {expected} when adding\n' - f'{person_name} to position {index} in the queue.' + f"\nCalled add_me_with_my_friends{queue, index, person_name}.\n" + f"The function returned {actual_result}, but\n" + f"the tests expected {expected} when adding\n" + f"{person_name} to position {index} in the queue." ) self.assertEqual(actual_result, expected, msg=error_message) @@ -134,30 +174,34 @@ def test_add_me_with_my_friends(self): @pytest.mark.task(taskno=3) def test_add_me_with_my_friends_validate_queue(self): test_data = [ - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 0, 'Bucky'), - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 1, 'Bucky'), - (['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], 5, 'Bucky'), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], 0, "Bucky"), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], 1, "Bucky"), + (["Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], 5, "Bucky"), ] result_data = [ - ['Bucky', 'Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], - ['Natasha', 'Bucky', 'Steve', 'Tchalla', 'Wanda', 'Rocket'], - ['Natasha', 'Steve', 'Tchalla', 'Wanda', 'Rocket', 'Bucky'], + ["Bucky", "Natasha", "Steve", "Tchalla", "Wanda", "Rocket"], + ["Natasha", "Bucky", "Steve", "Tchalla", "Wanda", "Rocket"], + ["Natasha", "Steve", "Tchalla", "Wanda", "Rocket", "Bucky"], ] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): # Deepcopy() is needed here because the task expects the input lists to be mutated. # That mutation wrecks havoc with the verification and error messaging. start_queue, add_index, person_name = deepcopy(params) queue, _, _ = params - with self.subTest(f'variation #{variant}', params=params, expected=expected): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = add_me_with_my_friends(*params) error_message = ( - f'\nCalled add_me_with_my_friends{start_queue, add_index, person_name}.\n' - f'The function returned {actual_result},\n' - 'but the original queue was unmodified. The tests expected the \n' - f'*original* queue to be modified by adding "{person_name}".' + f"\nCalled add_me_with_my_friends{start_queue, add_index, person_name}.\n" + f"The function returned {actual_result},\n" + "but the original queue was unmodified. The tests expected the \n" + f'*original* queue to be modified by adding "{person_name}".' ) self.assertIs(actual_result, queue, msg=error_message) @@ -165,30 +209,34 @@ def test_add_me_with_my_friends_validate_queue(self): @pytest.mark.task(taskno=4) def test_remove_the_mean_person(self): test_data = [ - (['Natasha', 'Steve', 'Ultron', 'Wanda', 'Rocket'], 'Ultron'), - (['Natasha', 'Steve', 'Wanda', 'Rocket', 'Ultron'], 'Rocket'), - (['Ultron', 'Natasha', 'Steve', 'Wanda', 'Rocket'], 'Steve'), + (["Natasha", "Steve", "Ultron", "Wanda", "Rocket"], "Ultron"), + (["Natasha", "Steve", "Wanda", "Rocket", "Ultron"], "Rocket"), + (["Ultron", "Natasha", "Steve", "Wanda", "Rocket"], "Steve"), ] result_data = [ - ['Natasha', 'Steve', 'Wanda', 'Rocket'], - ['Natasha', 'Steve', 'Wanda', 'Ultron'], - ['Ultron', 'Natasha', 'Wanda', 'Rocket'], + ["Natasha", "Steve", "Wanda", "Rocket"], + ["Natasha", "Steve", "Wanda", "Ultron"], + ["Ultron", "Natasha", "Wanda", "Rocket"], ] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): # Deepcopy() is needed here because the task expects the input lists to be mutated. # That mutation wrecks havoc with the verification and error messaging. start_queue, person_name = deepcopy(params) - with self.subTest(f'variation #{variant}', params=params, expected=expected): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = remove_the_mean_person(*params) error_message = ( - f'\nCalled remove_the_mean_person{start_queue, person_name}.\n' - f'The function returned {actual_result}, but\n' - f'the tests expected {expected} when removing\n' - f'{person_name} from the queue.' + f"\nCalled remove_the_mean_person{start_queue, person_name}.\n" + f"The function returned {actual_result}, but\n" + f"the tests expected {expected} when removing\n" + f"{person_name} from the queue." ) self.assertEqual(actual_result, expected, msg=error_message) @@ -196,65 +244,92 @@ def test_remove_the_mean_person(self): @pytest.mark.task(taskno=4) def test_remove_the_mean_person_validate_queue(self): test_data = [ - (['Natasha', 'Steve', 'Ultron', 'Wanda', 'Rocket'], 'Ultron'), - (['Natasha', 'Steve', 'Wanda', 'Rocket', 'Ultron'], 'Rocket'), - (['Ultron', 'Natasha', 'Steve', 'Wanda', 'Rocket'], 'Steve'), + (["Natasha", "Steve", "Ultron", "Wanda", "Rocket"], "Ultron"), + (["Natasha", "Steve", "Wanda", "Rocket", "Ultron"], "Rocket"), + (["Ultron", "Natasha", "Steve", "Wanda", "Rocket"], "Steve"), ] result_data = [ - ['Natasha', 'Steve', 'Wanda', 'Rocket'], - ['Natasha', 'Steve', 'Wanda', 'Ultron'], - ['Ultron', 'Natasha', 'Wanda', 'Rocket'], + ["Natasha", "Steve", "Wanda", "Rocket"], + ["Natasha", "Steve", "Wanda", "Ultron"], + ["Ultron", "Natasha", "Wanda", "Rocket"], ] - - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): # Deepcopy() is needed here because the task expects the input lists to be mutated. # That mutation wrecks havoc with the verification and error messaging. start_queue, person_name = deepcopy(params) queue, _ = params - with self.subTest(f'variation #{variant}', params=params, expected=expected): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = remove_the_mean_person(*params) error_message = ( - f'\nCalled remove_the_mean_person{start_queue, person_name}.\n' - f'The function returned {actual_result}, queue == {queue}.\n' - f'But the tests expected queue == {expected} when removing\n' - f'{person_name}.' + f"\nCalled remove_the_mean_person{start_queue, person_name}.\n" + f"The function returned {actual_result}, queue == {queue}.\n" + f"But the tests expected queue == {expected} when removing\n" + f"{person_name}." ) self.assertIs(actual_result, queue, msg=error_message) - @pytest.mark.task(taskno=5) def test_how_many_namefellows(self): - test_data = [(['Natasha', 'Steve', 'Ultron', 'Natasha', 'Rocket'], 'Bucky'), - (['Natasha', 'Steve', 'Ultron', 'Rocket'], 'Natasha'), - (['Natasha', 'Steve', 'Ultron', 'Natasha', 'Rocket'], 'Natasha')] + test_data = [ + (["Natasha", "Steve", "Ultron", "Natasha", "Rocket"], "Bucky"), + (["Natasha", "Steve", "Ultron", "Rocket"], "Natasha"), + (["Natasha", "Steve", "Ultron", "Natasha", "Rocket"], "Natasha"), + ] - result_data = (0,1,2) + result_data = (0, 1, 2) - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', params=params, expected=expected): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = how_many_namefellows(*params) - error_message = (f'Called how_many_namefellows{params}. ' - f'The function returned {actual_result}, but ' - f'The tests expected {expected} when counting ' - f'namefellows in the queue for {params[-1]}.') + error_message = ( + f"Called how_many_namefellows{params}. " + f"The function returned {actual_result}, but " + f"The tests expected {expected} when counting " + f"namefellows in the queue for {params[-1]}." + ) self.assertIs(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=6) def test_remove_the_last_person(self): test_data = [ - (['Natasha', 'Steve', 'Ultron', 'Natasha', 'Rocket'], ['Natasha', 'Steve', 'Ultron', 'Natasha'], 'Rocket'), - (['Wanda', 'Natasha', 'Steve', 'Rocket', 'Ultron'], ['Wanda', 'Natasha', 'Steve', 'Rocket'], 'Ultron'), - (['Steve', 'Wanda', 'Rocket', 'Ultron', 'Natasha'], ['Steve', 'Wanda', 'Rocket', 'Ultron'], 'Natasha') + ( + ["Natasha", "Steve", "Ultron", "Natasha", "Rocket"], + ["Natasha", "Steve", "Ultron", "Natasha"], + "Rocket", + ), + ( + ["Wanda", "Natasha", "Steve", "Rocket", "Ultron"], + ["Wanda", "Natasha", "Steve", "Rocket"], + "Ultron", + ), + ( + ["Steve", "Wanda", "Rocket", "Ultron", "Natasha"], + ["Steve", "Wanda", "Rocket", "Ultron"], + "Natasha", + ), ] for variant, (queue, modified, expected) in enumerate(test_data, start=1): - with self.subTest(f'variation #{variant}', queue=queue, modified=modified, expected=expected): + with self.subTest( + f"variation #{variant}", + queue=queue, + modified=modified, + expected=expected, + ): # Deepcopy() is needed here because the task expects the input lists to be mutated. # That mutation wrecks havoc with the verification and error messaging. @@ -263,43 +338,68 @@ def test_remove_the_last_person(self): actual_result = remove_the_last_person(queue) expected_queue = modified - error_message = (f'\nCalled remove_the_last_person({unmodified_queue}).\n' - f'The function was expected to remove and return the name "{expected_result}" ' - f'and change the queue to {expected_queue},\n' - f'but the name "{actual_result}" was returned and the queue == {queue}.') - - self.assertEqual((actual_result, queue), (expected_result, expected_queue), msg=error_message) + error_message = ( + f"\nCalled remove_the_last_person({unmodified_queue}).\n" + f'The function was expected to remove and return the name "{expected_result}" ' + f"and change the queue to {expected_queue},\n" + f'but the name "{actual_result}" was returned and the queue == {queue}.' + ) + self.assertEqual( + (actual_result, queue), + (expected_result, expected_queue), + msg=error_message, + ) @pytest.mark.task(taskno=7) def test_sorted_names(self): - test_data =( - (['Steve', 'Ultron', 'Natasha', 'Rocket'], ['Natasha', 'Rocket', 'Steve', 'Ultron']), - (['Agatha', 'Pepper', 'Valkyrie', 'Drax', 'Nebula'], ['Agatha', 'Drax', 'Nebula', 'Pepper', 'Valkyrie']), - (['Gamora', 'Loki', 'Tony', 'Peggy', 'Okoye'], ['Gamora', 'Loki', 'Okoye', 'Peggy', 'Tony']), + test_data = ( + ( + ["Steve", "Ultron", "Natasha", "Rocket"], + ["Natasha", "Rocket", "Steve", "Ultron"], + ), + ( + ["Agatha", "Pepper", "Valkyrie", "Drax", "Nebula"], + ["Agatha", "Drax", "Nebula", "Pepper", "Valkyrie"], + ), + ( + ["Gamora", "Loki", "Tony", "Peggy", "Okoye"], + ["Gamora", "Loki", "Okoye", "Peggy", "Tony"], + ), ) for variant, (queue, expected) in enumerate(test_data, start=1): - with self.subTest(f'variation #{variant}', queue=queue, expected=expected): + with self.subTest(f"variation #{variant}", queue=queue, expected=expected): actual_result = sorted_names(queue) expected_result = expected - error_message = (f'\nCalled sorted_names({queue}).\n' - f'The function returned {actual_result}, but \n' - f'the tests expect {expected_result}.') + error_message = ( + f"\nCalled sorted_names({queue}).\n" + f"The function returned {actual_result}, but \n" + f"the tests expect {expected_result}." + ) self.assertEqual(actual_result, expected_result, msg=error_message) @pytest.mark.task(taskno=7) def test_sorted_names_validate_queue(self): test_data = ( - (['Steve', 'Ultron', 'Natasha', 'Rocket'], ['Natasha', 'Rocket', 'Steve', 'Ultron']), - (['Agatha', 'Pepper', 'Valkyrie', 'Drax', 'Nebula'], ['Agatha', 'Drax', 'Nebula', 'Pepper', 'Valkyrie']), - (['Gamora', 'Loki', 'Tony', 'Peggy', 'Okoye'], ['Gamora', 'Loki', 'Okoye', 'Peggy', 'Tony']), + ( + ["Steve", "Ultron", "Natasha", "Rocket"], + ["Natasha", "Rocket", "Steve", "Ultron"], + ), + ( + ["Agatha", "Pepper", "Valkyrie", "Drax", "Nebula"], + ["Agatha", "Drax", "Nebula", "Pepper", "Valkyrie"], + ), + ( + ["Gamora", "Loki", "Tony", "Peggy", "Okoye"], + ["Gamora", "Loki", "Okoye", "Peggy", "Tony"], + ), ) for variant, (queue, expected) in enumerate(test_data, start=1): - with self.subTest(f'variation #{variant}', queue=queue, expected=expected): + with self.subTest(f"variation #{variant}", queue=queue, expected=expected): # Deepcopy() is needed here because the input lists might be mutated. # That mutation wrecks havoc with the verification and error messaging. @@ -307,10 +407,12 @@ def test_sorted_names_validate_queue(self): actual_result = sorted_names(queue) expected_result = expected - error_message = (f'\nCalled sorted_names({original_queue}).\n' - f'The function returned {actual_result}, \n' - f'with a queue == {queue}.\n' - f'The tests expect {expected_result}, \n' - f'with a queue == {original_queue}.') + error_message = ( + f"\nCalled sorted_names({original_queue}).\n" + f"The function returned {actual_result}, \n" + f"with a queue == {queue}.\n" + f"The tests expect {expected_result}, \n" + f"with a queue == {original_queue}." + ) self.assertIsNot(actual_result, queue, msg=error_message) diff --git a/exercises/concept/currency-exchange/.meta/exemplar.py b/exercises/concept/currency-exchange/.meta/exemplar.py index 1cd9b2262ee..c80aae602f0 100644 --- a/exercises/concept/currency-exchange/.meta/exemplar.py +++ b/exercises/concept/currency-exchange/.meta/exemplar.py @@ -5,6 +5,7 @@ Overview of exchanging currency when travelling: https://www.compareremit.com/money-transfer-tips/guide-to-exchanging-currency-for-overseas-travel/ """ + def exchange_money(budget, exchange_rate): """ diff --git a/exercises/concept/currency-exchange/exchange.py b/exercises/concept/currency-exchange/exchange.py index b58df5cbe48..2d38cb28785 100644 --- a/exercises/concept/currency-exchange/exchange.py +++ b/exercises/concept/currency-exchange/exchange.py @@ -6,7 +6,6 @@ """ - def exchange_money(budget, exchange_rate): """ diff --git a/exercises/concept/currency-exchange/exchange_test.py b/exercises/concept/currency-exchange/exchange_test.py index fd3754cc19d..41c224255af 100644 --- a/exercises/concept/currency-exchange/exchange_test.py +++ b/exercises/concept/currency-exchange/exchange_test.py @@ -7,7 +7,8 @@ get_value_of_bills, get_number_of_bills, get_leftover_of_bills, - exchangeable_value) + exchangeable_value, +) class CurrencyExchangeTest(unittest.TestCase): @@ -16,19 +17,25 @@ def test_exchange_money(self): test_data = [(100000, 0.8), (700000, 10.0)] result_data = [125000, 70000] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): budget, exchange_rate = params - with self.subTest(f"variation #{variant}", - budget=budget, - exchange_rate=exchange_rate, - expected=expected): + with self.subTest( + f"variation #{variant}", + budget=budget, + exchange_rate=exchange_rate, + expected=expected, + ): actual_result = exchange_money(*params) - error_message = (f'Called exchange_money{budget, exchange_rate}. ' - f'The function returned {actual_result}, but ' - f'The tests expected {expected} when exchanging' - f' {budget} at a rate of {exchange_rate}.') + error_message = ( + f"Called exchange_money{budget, exchange_rate}. " + f"The function returned {actual_result}, but " + f"The tests expected {expected} when exchanging" + f" {budget} at a rate of {exchange_rate}." + ) self.assertAlmostEqual(actual_result, expected, msg=error_message) @@ -37,18 +44,24 @@ def test_get_change(self): test_data = [(463000, 5000), (1250, 120), (15000, 1380)] result_data = [458000, 1130, 13620] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): budget, exchanging_value = params - with self.subTest(f"variation #{variant}", - budget=budget, - exchanging_value=exchanging_value, - expected=expected): + with self.subTest( + f"variation #{variant}", + budget=budget, + exchanging_value=exchanging_value, + expected=expected, + ): actual_result = get_change(*params) - error_message = (f'Called get_change{budget, exchanging_value}. ' - f'The function returned {actual_result}, but ' - f'The tests expected {expected} left in your budget.') + error_message = ( + f"Called get_change{budget, exchanging_value}. " + f"The function returned {actual_result}, but " + f"The tests expected {expected} left in your budget." + ) self.assertAlmostEqual(actual_result, expected, msg=error_message) @@ -57,18 +70,24 @@ def test_get_value_of_bills(self): test_data = [(10000, 128), (50, 360), (200, 200)] result_data = [1280000, 18000, 40000] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): denomination, number_of_bills = params - with self.subTest(f"variation #{variant}", - denomination=denomination, - number_of_bills=number_of_bills, - expected=expected): + with self.subTest( + f"variation #{variant}", + denomination=denomination, + number_of_bills=number_of_bills, + expected=expected, + ): actual_result = get_value_of_bills(*params) - error_message = (f'Called get_value_of_bills{denomination, number_of_bills}. ' - f'The function returned {actual_result}, but ' - f'The tests expected {expected} for the bills value.') + error_message = ( + f"Called get_value_of_bills{denomination, number_of_bills}. " + f"The function returned {actual_result}, but " + f"The tests expected {expected} for the bills value." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -77,18 +96,24 @@ def test_get_number_of_bills(self): test_data = [(163270, 50000), (54361, 1000)] result_data = [3, 54] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): amount, denomination = params - with self.subTest(f"variation #{variant}", - amount=amount, - denomination=denomination, - expected=expected): + with self.subTest( + f"variation #{variant}", + amount=amount, + denomination=denomination, + expected=expected, + ): actual_result = get_number_of_bills(amount, denomination) - error_message = (f'Called get_number_of_bills{amount, denomination}. ' - f'The function returned {actual_result} bills, but ' - f'The tests expected {expected} bills.') + error_message = ( + f"Called get_number_of_bills{amount, denomination}. " + f"The function returned {actual_result} bills, but " + f"The tests expected {expected} bills." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -97,45 +122,61 @@ def test_get_leftover_of_bills(self): test_data = [(10.1, 10), (654321.0, 5), (3.14, 2)] result_data = [0.1, 1.0, 1.14] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): amount, denomination = params - with self.subTest(f"variation #{variant}", - amount=amount, - denomination=denomination, - expected=expected): + with self.subTest( + f"variation #{variant}", + amount=amount, + denomination=denomination, + expected=expected, + ): actual_result = get_leftover_of_bills(*params) - error_message = (f'Called get_leftover_of_bills{amount, denomination}. ' - f'The function returned {actual_result}, but ' - f'The tests expected {expected} as the leftover amount.') + error_message = ( + f"Called get_leftover_of_bills{amount, denomination}. " + f"The function returned {actual_result}, but " + f"The tests expected {expected} as the leftover amount." + ) self.assertAlmostEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=6) def test_exchangeable_value(self): - test_data = [(100000, 10.61, 10, 1), - (1500, 0.84, 25, 40), - (470000, 1050, 30, 10000000000), - (470000, 0.00000009, 30, 700), - (425.33, 0.0009, 30, 700)] + test_data = [ + (100000, 10.61, 10, 1), + (1500, 0.84, 25, 40), + (470000, 1050, 30, 10000000000), + (470000, 0.00000009, 30, 700), + (425.33, 0.0009, 30, 700), + ] result_data = [8568, 1400, 0, 4017094016600, 363300] - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): budget, exchange_rate, spread, denomination = params - with self.subTest(f"variation #{variant}", - budget=budget, - exchange_rate=exchange_rate, - spread=spread, - denomination=denomination, - expected=expected): - - actual_result = exchangeable_value(budget, exchange_rate, spread, denomination) - error_message = (f'Called exchangeable_value{budget, exchange_rate, spread, denomination}. ' - f'The function returned {actual_result}, but ' - f'The tests expected {expected} as the maximum ' - f'value of the new currency .') + with self.subTest( + f"variation #{variant}", + budget=budget, + exchange_rate=exchange_rate, + spread=spread, + denomination=denomination, + expected=expected, + ): + + actual_result = exchangeable_value( + budget, exchange_rate, spread, denomination + ) + error_message = ( + f"Called exchangeable_value{budget, exchange_rate, spread, denomination}. " + f"The function returned {actual_result}, but " + f"The tests expected {expected} as the maximum " + f"value of the new currency ." + ) self.assertEqual(actual_result, expected, msg=error_message) diff --git a/exercises/concept/electric-bill/electric_bill_test.py b/exercises/concept/electric-bill/electric_bill_test.py index ffbd2fa5a6a..7e4e3d1be11 100644 --- a/exercises/concept/electric-bill/electric_bill_test.py +++ b/exercises/concept/electric-bill/electric_bill_test.py @@ -1,10 +1,12 @@ import unittest import pytest -from electric_bill import (get_extra_hours, - get_kW_amount, - get_kwh_amount, - get_efficiency, - get_cost) +from electric_bill import ( + get_extra_hours, + get_kW_amount, + get_kwh_amount, + get_efficiency, + get_cost, +) class ElecticBillTest(unittest.TestCase): @@ -14,47 +16,76 @@ def test_get_extra_hours(self): input_data = [25, 10, 5, 2, 1, 120, 21] output_data = [4, 13, 8, 5, 4, 3, 0] - for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): - error_msg=f'Expected: {output_data} but got a different amount.' - self.assertEqual(get_extra_hours(input_data), output_data, msg=error_msg) + for variant, (input_data, output_data) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, output_data=output_data + ): + error_msg = f"Expected: {output_data} but got a different amount." + self.assertEqual( + get_extra_hours(input_data), output_data, msg=error_msg + ) @pytest.mark.task(taskno=2) def test_get_kW_amount(self): input_data = [1000, 2200, 2900, 900, 1160] output_data = [1, 2.2, 2.9, 0.9, 1.2] - for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): - error_msg=f'Expected: {output_data} but got a different amount.' + for variant, (input_data, output_data) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, output_data=output_data + ): + error_msg = f"Expected: {output_data} but got a different amount." self.assertEqual(get_kW_amount(input_data), output_data, msg=error_msg) @pytest.mark.task(taskno=3) - def test_get_kwh_amount(self): + def test_get_kwh_amount(self): input_data = (5000000, 2141241, 43252135, 5324623462, 4321512) output_data = [1, 0, 12, 1479, 1] - for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): - error_msg=f'Expected: {output_data} but got a different amount.' + for variant, (input_data, output_data) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, output_data=output_data + ): + error_msg = f"Expected: {output_data} but got a different amount." self.assertEqual(get_kwh_amount(input_data), output_data, msg=error_msg) @pytest.mark.task(taskno=4) - def test_get_efficiency(self): + def test_get_efficiency(self): input_data = [80.0, 99.99, 0.8, 40.0] output_data = [0.8, 0.9999, 0.008, 0.4] - for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): - error_msg=f'Expected: {output_data} but got a different value.' - self.assertAlmostEqual(get_efficiency(input_data), output_data, msg=error_msg) + for variant, (input_data, output_data) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, output_data=output_data + ): + error_msg = f"Expected: {output_data} but got a different value." + self.assertAlmostEqual( + get_efficiency(input_data), output_data, msg=error_msg + ) @pytest.mark.task(taskno=5) def test_get_cost(self): - input_data = ((5000000, 80.0, 0.25), (2141241, 99.99, 2), (43252135, 0.8, 4), (4321512, 40.0, 2)) + input_data = ( + (5000000, 80.0, 0.25), + (2141241, 99.99, 2), + (43252135, 0.8, 4), + (4321512, 40.0, 2), + ) output_data = (0.3125, 0, 6000, 5) - - for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): - error_msg=f'Expected: {output_data} but got a different value.' + + for variant, (input_data, output_data) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, output_data=output_data + ): + error_msg = f"Expected: {output_data} but got a different value." self.assertEqual(get_cost(*input_data), output_data, msg=error_msg) diff --git a/exercises/concept/ellens-alien-game/.meta/exemplar.py b/exercises/concept/ellens-alien-game/.meta/exemplar.py index ace31649c75..0c4d33cdd4f 100644 --- a/exercises/concept/ellens-alien-game/.meta/exemplar.py +++ b/exercises/concept/ellens-alien-game/.meta/exemplar.py @@ -46,9 +46,9 @@ def hit(self): :return: None """ - #There are two valid interpretations for this method/task. - #The one below, and `self.health = max(0, self.health - 1)` - #The tests for this task reflect this ambiguity. + # There are two valid interpretations for this method/task. + # The one below, and `self.health = max(0, self.health - 1)` + # The tests for this task reflect this ambiguity. self.health -= 1 def is_alive(self): @@ -80,11 +80,12 @@ def collision_detection(self, other): pass + def new_aliens_collection(positions): """Create a list of Alien instances from a list of coordinate tuples. - :param positions: list - List of tuples of (x, y) coordinates. + :param positions: list - List of tuples of (x, y) coordinates. - :return: list - List of Alien objects. - """ + :return: list - List of Alien objects. + """ return [Alien(position[0], position[1]) for position in positions] diff --git a/exercises/concept/ellens-alien-game/classes.py b/exercises/concept/ellens-alien-game/classes.py index a9a3d1edae4..ddc2d9bd778 100644 --- a/exercises/concept/ellens-alien-game/classes.py +++ b/exercises/concept/ellens-alien-game/classes.py @@ -22,4 +22,4 @@ class Alien: pass -#TODO: create the new_aliens_collection() function below to call your Alien class with a list of coordinates. +# TODO: create the new_aliens_collection() function below to call your Alien class with a list of coordinates. diff --git a/exercises/concept/ellens-alien-game/classes_test.py b/exercises/concept/ellens-alien-game/classes_test.py index 3d2b986be4d..92d340a2965 100644 --- a/exercises/concept/ellens-alien-game/classes_test.py +++ b/exercises/concept/ellens-alien-game/classes_test.py @@ -6,17 +6,21 @@ from classes import Alien except ImportError as import_fail: # pylint: disable=raise-missing-from - raise ImportError("\n\nMISSING CLASS --> We tried to import the 'Alien' class from " - "your classes.py file, but could not find it." - "Did you misname or forget to create it?") from None + raise ImportError( + "\n\nMISSING CLASS --> We tried to import the 'Alien' class from " + "your classes.py file, but could not find it." + "Did you misname or forget to create it?" + ) from None try: from classes import new_aliens_collection except ImportError as err: - raise ImportError("\n\nMISSING FUNCTION --> We tried to import the " - "new_aliens_collection() function " - "from your classes.py file, but could not find it. " - "Did you misname or forget to create it?") from None + raise ImportError( + "\n\nMISSING FUNCTION --> We tried to import the " + "new_aliens_collection() function " + "from your classes.py file, but could not find it. " + "Did you misname or forget to create it?" + ) from None class ClassesTest(unittest.TestCase): @@ -26,19 +30,25 @@ def test_alien_has_correct_initial_coordinates(self): """Test that the Alien class gets correctly initialised.""" alien = Alien(2, -1) - error_message = (f'Created a new Alien by calling Alien(2, -1). ' - f'The Alien was initialized to position ' - f'{(alien.x_coordinate, alien.y_coordinate)}, but the tests expected ' - f'the object to be at position (2, -1)') + error_message = ( + f"Created a new Alien by calling Alien(2, -1). " + f"The Alien was initialized to position " + f"{(alien.x_coordinate, alien.y_coordinate)}, but the tests expected " + f"the object to be at position (2, -1)" + ) - self.assertEqual((2, -1), (alien.x_coordinate, alien.y_coordinate), msg=error_message) + self.assertEqual( + (2, -1), (alien.x_coordinate, alien.y_coordinate), msg=error_message + ) @pytest.mark.task(taskno=1) def test_alien_has_health(self): alien = Alien(0, 0) - error_message = (f'Created a new Alien by calling Alien(0, 0). ' - f'The new Alien has a health of {alien.health}, ' - f'but the tests expect health = 3') + error_message = ( + f"Created a new Alien by calling Alien(0, 0). " + f"The new Alien has a health of {alien.health}, " + f"but the tests expect health = 3" + ) self.assertEqual(3, alien.health, msg=error_message) @@ -49,21 +59,28 @@ def test_alien_instance_variables(self): alien_one = Alien(-8, -1) alien_two = Alien(2, 5) - coord_x_error = (f'Created two new Aliens by assigning ' - f'alien_one = Alien(-8, -1) and alien_two = Alien(2, 5). ' - f'Both Aliens x coordinates were {alien_two.x_coordinate}, ' - f'but the tests expect alien_one and alien_two to have ' - f'different x positions.') - - coord_y_error = (f'Created two new Aliens by assigning ' - f'alien_one = Alien(-8, -1) and alien_two = Alien(2, 5). ' - f'Both Aliens y coordinates were {alien_two.y_coordinate}, ' - f'but the tests expect alien_one and alien_two to have ' - f'different y positions.') - - self.assertFalse(alien_one.x_coordinate == alien_two.x_coordinate, msg=coord_x_error) - self.assertFalse(alien_one.y_coordinate == alien_two.y_coordinate, msg=coord_y_error) - + coord_x_error = ( + f"Created two new Aliens by assigning " + f"alien_one = Alien(-8, -1) and alien_two = Alien(2, 5). " + f"Both Aliens x coordinates were {alien_two.x_coordinate}, " + f"but the tests expect alien_one and alien_two to have " + f"different x positions." + ) + + coord_y_error = ( + f"Created two new Aliens by assigning " + f"alien_one = Alien(-8, -1) and alien_two = Alien(2, 5). " + f"Both Aliens y coordinates were {alien_two.y_coordinate}, " + f"but the tests expect alien_one and alien_two to have " + f"different y positions." + ) + + self.assertFalse( + alien_one.x_coordinate == alien_two.x_coordinate, msg=coord_x_error + ) + self.assertFalse( + alien_one.y_coordinate == alien_two.y_coordinate, msg=coord_y_error + ) @pytest.mark.task(taskno=2) def test_alien_hit_method(self): @@ -78,36 +95,43 @@ def test_alien_hit_method(self): test_data = [1, 2, 3, 4, 5, 6] result_data = [(2,), (1,), (0,), (0, -1), (0, -2), (0, -3)] - for variant, (iterations, expected) in enumerate(zip(test_data, result_data), start=1): + for variant, (iterations, expected) in enumerate( + zip(test_data, result_data), start=1 + ): alien = Alien(2, 2) - with self.subTest(f'variation #{variant}', - iterations=iterations, - expected=expected): + with self.subTest( + f"variation #{variant}", iterations=iterations, expected=expected + ): for _ in range(iterations): alien.hit() - error_message = (f'Called hit() {iterations} time(s) ' - f'on a newly created Alien. The Aliens health ' - f'is now {alien.health}, but the tests expected ' - f'it to be in {expected} after decrementing 1 health ' - f'point {iterations} time(s).') + error_message = ( + f"Called hit() {iterations} time(s) " + f"on a newly created Alien. The Aliens health " + f"is now {alien.health}, but the tests expected " + f"it to be in {expected} after decrementing 1 health " + f"point {iterations} time(s)." + ) self.assertIn(alien.health, expected, msg=error_message) - @pytest.mark.task(taskno=3) def test_alien_is_alive_method(self): alien = Alien(0, 1) - alive_error = ('Created a new Alien and called hit(). ' - 'The function is_alive() is returning False (dead) ' - 'while alien.health is greater than 0.') + alive_error = ( + "Created a new Alien and called hit(). " + "The function is_alive() is returning False (dead) " + "while alien.health is greater than 0." + ) - dead_error = ('Created a new Alien and called hit(). ' - 'The function is_alive() is returning True (alive) ' - 'while alien.health is less than or equal to 0.') + dead_error = ( + "Created a new Alien and called hit(). " + "The function is_alive() is returning True (alive) " + "while alien.health is less than or equal to 0." + ) for _ in range(5): alien.hit() @@ -121,24 +145,29 @@ def test_alien_teleport_method(self): alien = Alien(0, 0) alien.teleport(-1, -4) - error_message = ('Called alien.teleport(-1,-4) on a newly created Alien. ' - 'The Alien was found at position ' - f'{(alien.x_coordinate, alien.y_coordinate)}, but the ' - 'tests expected it at position (-1, -4).') + error_message = ( + "Called alien.teleport(-1,-4) on a newly created Alien. " + "The Alien was found at position " + f"{(alien.x_coordinate, alien.y_coordinate)}, but the " + "tests expected it at position (-1, -4)." + ) - self.assertEqual((-1, -4), (alien.x_coordinate, alien.y_coordinate), msg=error_message) + self.assertEqual( + (-1, -4), (alien.x_coordinate, alien.y_coordinate), msg=error_message + ) @pytest.mark.task(taskno=5) def test_alien_collision_detection_method(self): alien = Alien(7, 3) - error_message = ('Created a new Alien at (7,3) and called ' - 'alien.collision_detection(Alien(7, 2)). ' - f'The method returned {alien.collision_detection(Alien(7, 2))}, ' - 'but the tests expected None. ') + error_message = ( + "Created a new Alien at (7,3) and called " + "alien.collision_detection(Alien(7, 2)). " + f"The method returned {alien.collision_detection(Alien(7, 2))}, " + "but the tests expected None. " + ) self.assertIsNone(alien.collision_detection(Alien(7, 2)), msg=error_message) - @pytest.mark.task(taskno=6) def test_alien_class_variable(self): """Test class attribute/variables are identical across instances.""" @@ -146,24 +175,28 @@ def test_alien_class_variable(self): alien_one, alien_two = Alien(0, 2), Alien(-6, -1) Alien.health = 6 - created_error_message = ('Created two new Aliens and requested the ' - 'total_aliens_created attribute for each one. ' - f'Received {alien_one.total_aliens_created, alien_two.total_aliens_created} ' - f'for total_aliens_created, but the tests expect ' - f'the class attributes for each newly created Alien to be identical. ') - - health_error_message = ('Created two new Aliens and requested the ' - f'health attribute for each one. Received {alien_one.health, alien_two.health} ' - 'for health, but the tests expect the class ' - 'attributes for each newly created Alien to be identical. ') - - self.assertEqual(alien_two.total_aliens_created, - alien_one.total_aliens_created, - msg=created_error_message) - - self.assertEqual(alien_two.health, - alien_one.health, - msg=health_error_message) + created_error_message = ( + "Created two new Aliens and requested the " + "total_aliens_created attribute for each one. " + f"Received {alien_one.total_aliens_created, alien_two.total_aliens_created} " + f"for total_aliens_created, but the tests expect " + f"the class attributes for each newly created Alien to be identical. " + ) + + health_error_message = ( + "Created two new Aliens and requested the " + f"health attribute for each one. Received {alien_one.health, alien_two.health} " + "for health, but the tests expect the class " + "attributes for each newly created Alien to be identical. " + ) + + self.assertEqual( + alien_two.total_aliens_created, + alien_one.total_aliens_created, + msg=created_error_message, + ) + + self.assertEqual(alien_two.health, alien_one.health, msg=health_error_message) @pytest.mark.task(taskno=6) def test_alien_total_aliens_created(self): @@ -172,9 +205,11 @@ def test_alien_total_aliens_created(self): Alien.total_aliens_created = 0 aliens = [Alien(-2, 6)] - error_message = ('Created a new Alien and called total_aliens_created for it. ' - f'{aliens[0].total_aliens_created} was returned, but ' - 'the tests expected that total_aliens_created would equal 1.') + error_message = ( + "Created a new Alien and called total_aliens_created for it. " + f"{aliens[0].total_aliens_created} was returned, but " + "the tests expected that total_aliens_created would equal 1." + ) self.assertEqual(1, aliens[0].total_aliens_created, msg=error_message) @@ -182,15 +217,23 @@ def test_alien_total_aliens_created(self): aliens.append(Alien(-5, -5)) def error_text(alien, variable): - return ('Created two additional Aliens for the session.' - f"Alien number {alien}'s total_aliens_created variable " - f"is equal to {variable}, but the tests expected all " - 'total_aliens_created variables for all instances to be ' - 'equal to number of alien instances created (i.e. 3).') - - self.assertEqual(3, aliens[0].total_aliens_created, msg=error_text(1, aliens[0])) - self.assertEqual(3, aliens[1].total_aliens_created, msg=error_text(2, aliens[1])) - self.assertEqual(3, aliens[2].total_aliens_created, msg=error_text(3, aliens[2])) + return ( + "Created two additional Aliens for the session." + f"Alien number {alien}'s total_aliens_created variable " + f"is equal to {variable}, but the tests expected all " + "total_aliens_created variables for all instances to be " + "equal to number of alien instances created (i.e. 3)." + ) + + self.assertEqual( + 3, aliens[0].total_aliens_created, msg=error_text(1, aliens[0]) + ) + self.assertEqual( + 3, aliens[1].total_aliens_created, msg=error_text(2, aliens[1]) + ) + self.assertEqual( + 3, aliens[2].total_aliens_created, msg=error_text(3, aliens[2]) + ) @pytest.mark.task(taskno=7) def test_new_aliens_collection(self): @@ -205,8 +248,12 @@ def test_new_aliens_collection(self): self.assertIsInstance(obj, Alien, msg=error_message) for position, obj in zip(test_data, actual_result): - position_error = (f'After calling new_aliens_collection({test_data}), ' - f'found {obj} initialized to position {(obj.x_coordinate, obj.y_coordinate)}, ' - f'but the tests expected {obj} to be at position {position} instead.') - - self.assertEqual(position, (obj.x_coordinate, obj.y_coordinate), msg=position_error) + position_error = ( + f"After calling new_aliens_collection({test_data}), " + f"found {obj} initialized to position {(obj.x_coordinate, obj.y_coordinate)}, " + f"but the tests expected {obj} to be at position {position} instead." + ) + + self.assertEqual( + position, (obj.x_coordinate, obj.y_coordinate), msg=position_error + ) diff --git a/exercises/concept/ghost-gobble-arcade-game/arcade_game_test.py b/exercises/concept/ghost-gobble-arcade-game/arcade_game_test.py index 4dc3ca4c56d..70ab35e6da1 100644 --- a/exercises/concept/ghost-gobble-arcade-game/arcade_game_test.py +++ b/exercises/concept/ghost-gobble-arcade-game/arcade_game_test.py @@ -8,137 +8,163 @@ class GhostGobbleGameTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_ghost_gets_eaten(self): actual_result = eat_ghost(True, True) - error_message = ('Called eat_ghost(True, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ghost gets eaten (True).') + error_message = ( + "Called eat_ghost(True, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the ghost gets eaten (True)." + ) self.assertIs(actual_result, True, msg=error_message) @pytest.mark.task(taskno=1) def test_ghost_does_not_get_eaten_because_no_power_pellet_active(self): actual_result = eat_ghost(False, True) - error_message = ('Called eat_ghost(False, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'ghost **does not** get eaten because ' - 'no power pellet was active.') + error_message = ( + "Called eat_ghost(False, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "ghost **does not** get eaten because " + "no power pellet was active." + ) self.assertIs(actual_result, False, msg=error_message) @pytest.mark.task(taskno=1) def test_ghost_does_not_get_eaten_because_not_touching_ghost(self): actual_result = eat_ghost(True, False) - error_message = ('Called eat_ghost(True, False).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'ghost **does not** get eaten because ' - 'the player was not touching the ghost.') + error_message = ( + "Called eat_ghost(True, False)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "ghost **does not** get eaten because " + "the player was not touching the ghost." + ) self.assertIs(actual_result, False, msg=error_message) @pytest.mark.task(taskno=2) def test_score_when_eating_dot(self): actual_result = score(False, True) - error_message = ('Called score(False, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player scores because they were touching a dot.') + error_message = ( + "Called score(False, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player scores because they were touching a dot." + ) self.assertIs(actual_result, True, msg=error_message) @pytest.mark.task(taskno=2) def test_score_when_eating_power_pellet(self): actual_result = score(True, False) - error_message = ('Called score(True, False).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player scores because they ' - 'were touching a power pellet.') + error_message = ( + "Called score(True, False)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player scores because they " + "were touching a power pellet." + ) - self.assertIs(actual_result,True,msg=error_message) + self.assertIs(actual_result, True, msg=error_message) @pytest.mark.task(taskno=2) def test_no_score_when_nothing_eaten(self): actual_result = score(False, False) - error_message = ('Called score(False, False).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player **does not** score because they ' - 'were not touching anything.') - self.assertIs(actual_result, False,msg=error_message) + error_message = ( + "Called score(False, False)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player **does not** score because they " + "were not touching anything." + ) + self.assertIs(actual_result, False, msg=error_message) @pytest.mark.task(taskno=3) def test_lose_if_touching_a_ghost_without_a_power_pellet_active(self): actual_result = lose(False, True) - error_message = ('Called lose(False, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player loses because they touched a ' - 'ghost without a power pellet activated.') - self.assertIs( - actual_result, True, msg=error_message) + error_message = ( + "Called lose(False, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player loses because they touched a " + "ghost without a power pellet activated." + ) + self.assertIs(actual_result, True, msg=error_message) @pytest.mark.task(taskno=3) def test_dont_lose_if_touching_a_ghost_with_a_power_pellet_active(self): actual_result = lose(True, True) - error_message = ('Called lose(True, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player **does not** lose because when they touched a ' - 'ghost, a power pellet was active.') + error_message = ( + "Called lose(True, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player **does not** lose because when they touched a " + "ghost, a power pellet was active." + ) self.assertIs(actual_result, False, msg=error_message) @pytest.mark.task(taskno=3) def test_dont_lose_if_not_touching_a_ghost(self): actual_result = lose(True, False) - error_message = ('Called lose(True, False).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player **does not** lose because they were ' - 'not touching a ghost.') + error_message = ( + "Called lose(True, False)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player **does not** lose because they were " + "not touching a ghost." + ) self.assertIs(actual_result, False, msg=error_message) @pytest.mark.task(taskno=4) def test_win_if_all_dots_eaten(self): actual_result = win(True, False, False) - error_message = ('Called win(True, False, False).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player wins because all the dots were eaten.') + error_message = ( + "Called win(True, False, False)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player wins because all the dots were eaten." + ) self.assertIs(actual_result, True, msg=error_message) @pytest.mark.task(taskno=4) def test_dont_win_if_all_dots_eaten_but_touching_a_ghost(self): actual_result = win(True, False, True) - error_message = ('Called win(True, False, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the ' - 'player **does not** win, because ' - 'the player was touching a ghost.') + error_message = ( + "Called win(True, False, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the " + "player **does not** win, because " + "the player was touching a ghost." + ) self.assertIs(actual_result, False, msg=error_message) @pytest.mark.task(taskno=4) - def test_win_if_all_dots_eaten_and_touching_a_ghost_with_a_power_pellet_active(self): + def test_win_if_all_dots_eaten_and_touching_a_ghost_with_a_power_pellet_active( + self, + ): actual_result = win(True, True, True) - error_message = ('Called win(True, True, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the player wins, ' - f'because a power pellet was active when they ' - f'touched a ghost.') + error_message = ( + "Called win(True, True, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the player wins, " + f"because a power pellet was active when they " + f"touched a ghost." + ) self.assertIs(actual_result, True, msg=error_message) @pytest.mark.task(taskno=4) def test_dont_win_if_not_all_dots_eaten(self): actual_result = win(False, True, True) - error_message = ('Called win(False, True, True).' - f'The function returned {actual_result}, but the ' - f'tests expected that the player **does not** win, ' - f'because the player did not eat all of the dots.') + error_message = ( + "Called win(False, True, True)." + f"The function returned {actual_result}, but the " + f"tests expected that the player **does not** win, " + f"because the player did not eat all of the dots." + ) self.assertIs(actual_result, False, msg=error_message) - diff --git a/exercises/concept/guidos-gorgeous-lasagna/lasagna.py b/exercises/concept/guidos-gorgeous-lasagna/lasagna.py index a3df0ab2da0..67973cd07dd 100644 --- a/exercises/concept/guidos-gorgeous-lasagna/lasagna.py +++ b/exercises/concept/guidos-gorgeous-lasagna/lasagna.py @@ -7,11 +7,10 @@ of a module and its functions and/or classes. """ +# TODO: define the 'EXPECTED_BAKE_TIME' constant below. -#TODO: define the 'EXPECTED_BAKE_TIME' constant below. - -#TODO: Remove 'pass' and complete the 'bake_time_remaining()' function below. +# TODO: Remove 'pass' and complete the 'bake_time_remaining()' function below. def bake_time_remaining(): """Calculate the bake time remaining. @@ -26,15 +25,13 @@ def bake_time_remaining(): pass -#TODO: Define the 'preparation_time_in_minutes()' function below. +# TODO: Define the 'preparation_time_in_minutes()' function below. # You might also consider defining a 'PREPARATION_TIME' constant. # You can do that on the line below the 'EXPECTED_BAKE_TIME' constant. # This will make it easier to do calculations. - -#TODO: define the 'elapsed_time_in_minutes()' function below. - +# TODO: define the 'elapsed_time_in_minutes()' function below. # TODO: Remember to go back and add docstrings to all your functions diff --git a/exercises/concept/guidos-gorgeous-lasagna/lasagna_test.py b/exercises/concept/guidos-gorgeous-lasagna/lasagna_test.py index 4066aa8a392..5a9cbfc7764 100644 --- a/exercises/concept/guidos-gorgeous-lasagna/lasagna_test.py +++ b/exercises/concept/guidos-gorgeous-lasagna/lasagna_test.py @@ -5,25 +5,31 @@ # To that end, we are putting a try/catch around imports and throwing specific messages to help students # decode that they need to create and title their constants and functions in a specific way. try: - from lasagna import (EXPECTED_BAKE_TIME, - bake_time_remaining, - preparation_time_in_minutes, - elapsed_time_in_minutes) + from lasagna import ( + EXPECTED_BAKE_TIME, + bake_time_remaining, + preparation_time_in_minutes, + elapsed_time_in_minutes, + ) # Here, we are separating the constant import errors from the function name import errors except ImportError as import_fail: - message = import_fail.args[0].split('(', maxsplit=1) + message = import_fail.args[0].split("(", maxsplit=1) item_name = import_fail.args[0].split()[3] - if 'EXPECTED_BAKE_TIME' in item_name: + if "EXPECTED_BAKE_TIME" in item_name: # pylint: disable=raise-missing-from - raise ImportError(f'\n\nMISSING CONSTANT --> \nWe can not find or import the constant {item_name} in your' - " 'lasagna.py' file.\nDid you misname or forget to define it?") from None + raise ImportError( + f"\n\nMISSING CONSTANT --> \nWe can not find or import the constant {item_name} in your" + " 'lasagna.py' file.\nDid you misname or forget to define it?" + ) from None else: item_name = item_name[:-1] + "()'" # pylint: disable=raise-missing-from - raise ImportError("\n\nMISSING FUNCTION --> In your 'lasagna.py' file, we can not find or import the" - f' function named {item_name}. \nDid you misname or forget to define it?') from None + raise ImportError( + "\n\nMISSING FUNCTION --> In your 'lasagna.py' file, we can not find or import the" + f" function named {item_name}. \nDid you misname or forget to define it?" + ) from None # Here begins the formal test cases for the exercise. @@ -31,7 +37,7 @@ class LasagnaTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_EXPECTED_BAKE_TIME(self): - failure_msg = 'Expected a constant of EXPECTED_BAKE_TIME with a value of 40.' + failure_msg = "Expected a constant of EXPECTED_BAKE_TIME with a value of 40." self.assertEqual(EXPECTED_BAKE_TIME, 40, msg=failure_msg) @pytest.mark.task(taskno=2) @@ -39,12 +45,16 @@ def test_bake_time_remaining(self): input_data = [1, 2, 5, 10, 15, 23, 33, 39] result_data = [39, 38, 35, 30, 25, 17, 7, 1] - for variant, (time, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', time=time, expected=expected): + for variant, (time, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", time=time, expected=expected): actual_result = bake_time_remaining(time) - failure_msg = (f'Called bake_time_remaining({time}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} as the remaining bake time.') + failure_msg = ( + f"Called bake_time_remaining({time}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} as the remaining bake time." + ) self.assertEqual(actual_result, expected, msg=failure_msg) @@ -53,12 +63,18 @@ def test_preparation_time_in_minutes(self): input_data = [1, 2, 5, 8, 11, 15] result_data = [2, 4, 10, 16, 22, 30] - for variant, (layers, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', layers=layers, expected=expected): + for variant, (layers, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", layers=layers, expected=expected + ): actual_result = preparation_time_in_minutes(layers) - failure_msg = (f'Called preparation_time_in_minutes({layers}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} as the preparation time.') + failure_msg = ( + f"Called preparation_time_in_minutes({layers}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} as the preparation time." + ) self.assertEqual(actual_result, expected, msg=failure_msg) @@ -68,12 +84,18 @@ def test_elapsed_time_in_minutes(self): time_data = (3, 7, 8, 4, 15, 20) result_data = [5, 11, 18, 20, 37, 50] - for variant, (layers, time, expected) in enumerate(zip(layer_data, time_data, result_data), start=1): - with self.subTest(f'variation #{variant}', layers=layers, time=time, expected=expected): + for variant, (layers, time, expected) in enumerate( + zip(layer_data, time_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", layers=layers, time=time, expected=expected + ): actual_result = elapsed_time_in_minutes(layers, time) - failure_msg = (f'Called elapsed_time_in_minutes({layers}, {time}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} as the elapsed time.') + failure_msg = ( + f"Called elapsed_time_in_minutes({layers}, {time}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} as the elapsed time." + ) self.assertEqual(actual_result, expected, msg=failure_msg) @@ -85,13 +107,19 @@ def test_docstrings_were_written(self): :return: unexpectedly None error when __doc__ key is missing. """ - functions = [bake_time_remaining, preparation_time_in_minutes, elapsed_time_in_minutes] + functions = [ + bake_time_remaining, + preparation_time_in_minutes, + elapsed_time_in_minutes, + ] for variant, function in enumerate(functions, start=1): - with self.subTest(f'variation #{variant}', function=function): + with self.subTest(f"variation #{variant}", function=function): actual_result = function.__doc__ - failure_msg = (f'Called {function.__name__}.__doc__. {actual_result} was returned, ' - f'but the tests expected a docstring for the {function.__name__} function.') + failure_msg = ( + f"Called {function.__name__}.__doc__. {actual_result} was returned, " + f"but the tests expected a docstring for the {function.__name__} function." + ) # Check that the __doc__ key is populated for the function. self.assertIsNotNone(actual_result, msg=failure_msg) diff --git a/exercises/concept/inventory-management/dicts.py b/exercises/concept/inventory-management/dicts.py index 2600eceb27d..2ca18a4790a 100644 --- a/exercises/concept/inventory-management/dicts.py +++ b/exercises/concept/inventory-management/dicts.py @@ -52,4 +52,3 @@ def list_inventory(inventory): """ pass - diff --git a/exercises/concept/inventory-management/dicts_test.py b/exercises/concept/inventory-management/dicts_test.py index 71a8ff2b72b..5baf7c168f9 100644 --- a/exercises/concept/inventory-management/dicts_test.py +++ b/exercises/concept/inventory-management/dicts_test.py @@ -1,10 +1,12 @@ import unittest import pytest -from dicts import (create_inventory, - add_items, - decrement_items, - remove_item, - list_inventory) +from dicts import ( + create_inventory, + add_items, + decrement_items, + remove_item, + list_inventory, +) class InventoryTest(unittest.TestCase): @@ -14,8 +16,10 @@ def test_create_inventory(self): actual_result = create_inventory(["wood", "iron", "iron", "diamond", "diamond"]) expected = {"wood": 1, "iron": 2, "diamond": 2} - error_message = ('Called create_inventory(["wood", "iron", "iron", "diamond", "diamond"]). ' - f'The function returned {actual_result}, but the tests expected {expected}.') + error_message = ( + 'Called create_inventory(["wood", "iron", "iron", "diamond", "diamond"]). ' + f"The function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -23,17 +27,23 @@ def test_create_inventory(self): def test_add_one_item(self): actual_result = add_items({"wood": 4, "iron": 2}, ["iron", "iron"]) expected = {"wood": 4, "iron": 4} - error_message = ('Called add_items({"wood": 4, "iron": 2}, ["iron", "iron"]). ' - f'The function returned {actual_result}, but the tests expected {expected}.') + error_message = ( + 'Called add_items({"wood": 4, "iron": 2}, ["iron", "iron"]). ' + f"The function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_add_multiple_items(self): - actual_result = add_items({"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"]) - expected = {"wood": 3, "gold": 3, "diamond": 3} - error_message = ('Called add_items({"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"]). ' - f'The function returned {actual_result}, but the tests expected {expected}.') + actual_result = add_items( + {"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"] + ) + expected = {"wood": 3, "gold": 3, "diamond": 3} + error_message = ( + 'Called add_items({"wood": 2, "gold": 1, "diamond": 3}, ["wood", "gold", "gold"]). ' + f"The function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -41,8 +51,10 @@ def test_add_multiple_items(self): def test_add_new_item(self): actual_result = add_items({"iron": 1, "diamond": 2}, ["iron", "wood", "wood"]) expected = {"iron": 2, "diamond": 2, "wood": 2} - error_message = ('Called add_items({"iron": 1, "diamond": 2}, ["iron", "wood", "wood"]). ' - f'The function returned {actual_result}, but the tests expected {expected}.') + error_message = ( + 'Called add_items({"iron": 1, "diamond": 2}, ["iron", "wood", "wood"]). ' + f"The function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -50,52 +62,67 @@ def test_add_new_item(self): def test_add_from_empty_dict(self): actual_result = add_items({}, ["iron", "iron", "diamond"]) expected = {"iron": 2, "diamond": 1} - error_message = ('Called add_items({}, ["iron", "iron", "diamond"]). ' - f'The function returned {actual_result}, but the tests expected {expected}.') + error_message = ( + 'Called add_items({}, ["iron", "iron", "diamond"]). ' + f"The function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_decrement_items(self): - actual_result = decrement_items({"iron": 3, "diamond": 4, "gold": 2}, - ["iron", "iron", "diamond", "gold", "gold"]) + actual_result = decrement_items( + {"iron": 3, "diamond": 4, "gold": 2}, + ["iron", "iron", "diamond", "gold", "gold"], + ) expected = {"iron": 1, "diamond": 3, "gold": 0} - error_message = ('Called decrement_items({"iron": 3, "diamond": 4, "gold": 2},' - '["iron", "iron", "diamond", "gold", "gold"]). The function ' - f'returned {actual_result}, but the tests expected {expected}.') + error_message = ( + 'Called decrement_items({"iron": 3, "diamond": 4, "gold": 2},' + '["iron", "iron", "diamond", "gold", "gold"]). The function ' + f"returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_not_below_zero(self): - actual_result = decrement_items({"wood": 2, "iron": 3, "diamond": 1}, - ["wood", "wood", "wood", "iron", "diamond", "diamond"]) + actual_result = decrement_items( + {"wood": 2, "iron": 3, "diamond": 1}, + ["wood", "wood", "wood", "iron", "diamond", "diamond"], + ) expected = {"wood": 0, "iron": 2, "diamond": 0} - error_message = ('Called decrement_items({"wood": 2, "iron": 3, "diamond": 1}, ' - '["wood", "wood", "wood", "iron", "diamond", "diamond"]). The ' - f'function returned {actual_result}, but the tests expected {expected}.') + error_message = ( + 'Called decrement_items({"wood": 2, "iron": 3, "diamond": 1}, ' + '["wood", "wood", "wood", "iron", "diamond", "diamond"]). The ' + f"function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_decrement_items_not_in_inventory(self): - actual_result = decrement_items({"iron": 3, "gold": 2}, - ["iron", "wood", "iron", "diamond"]) + actual_result = decrement_items( + {"iron": 3, "gold": 2}, ["iron", "wood", "iron", "diamond"] + ) expected = {"iron": 1, "gold": 2} - error_message = ('Called decrement_items({"iron": 3, "gold": 2}, ' - '["iron", "wood", "iron", "diamond"]). The function ' - f'returned {actual_result}, but the tests ' - f'expected {expected}.') + error_message = ( + 'Called decrement_items({"iron": 3, "gold": 2}, ' + '["iron", "wood", "iron", "diamond"]). The function ' + f"returned {actual_result}, but the tests " + f"expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=4) def test_remove_item(self): actual_result = remove_item({"iron": 1, "diamond": 2, "gold": 1}, "diamond") - expected = {"iron": 1, "gold": 1} - error_message = ('Called remove_item({"iron": 1, "diamond": 2, "gold": 1}, "diamond"). ' - f'The function returned {actual_result}, but the tests expected {expected}.') + expected = {"iron": 1, "gold": 1} + error_message = ( + 'Called remove_item({"iron": 1, "diamond": 2, "gold": 1}, "diamond"). ' + f"The function returned {actual_result}, but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -103,18 +130,24 @@ def test_remove_item(self): def test_remove_item_not_in_inventory(self): actual_result = remove_item({"iron": 1, "diamond": 2, "gold": 1}, "wood") expected = {"iron": 1, "gold": 1, "diamond": 2} - error_message = ('Called remove_item({"iron": 1, "diamond": 2, "gold": 1}, "wood"). ' - f'The function returned {actual_result}, ' - f'but the tests expected {expected}.') + error_message = ( + 'Called remove_item({"iron": 1, "diamond": 2, "gold": 1}, "wood"). ' + f"The function returned {actual_result}, " + f"but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=5) def test_list_inventory(self): - actual_result = list_inventory({"coal": 15, "diamond": 3, "wood": 67, "silver": 0}) + actual_result = list_inventory( + {"coal": 15, "diamond": 3, "wood": 67, "silver": 0} + ) expected = [("coal", 15), ("diamond", 3), ("wood", 67)] - error_message = ('Called list_inventory({"coal": 15, "diamond": 3, "wood": 67, "silver": 0}). ' - f'The function returned {actual_result}, ' - f'but the tests expected {expected}.') + error_message = ( + 'Called list_inventory({"coal": 15, "diamond": 3, "wood": 67, "silver": 0}). ' + f"The function returned {actual_result}, " + f"but the tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) diff --git a/exercises/concept/little-sisters-essay/string_methods_test.py b/exercises/concept/little-sisters-essay/string_methods_test.py index 98973142eba..ad6c51b36ec 100644 --- a/exercises/concept/little-sisters-essay/string_methods_test.py +++ b/exercises/concept/little-sisters-essay/string_methods_test.py @@ -1,9 +1,11 @@ import unittest import pytest -from string_methods import (capitalize_title, - check_sentence_ending, - clean_up_spacing, - replace_word_choice) +from string_methods import ( + capitalize_title, + check_sentence_ending, + clean_up_spacing, + replace_word_choice, +) class LittleSistersEssayTest(unittest.TestCase): @@ -13,9 +15,11 @@ def test_capitalize_word(self): actual_result = capitalize_title("canopy") expected = "Canopy" - error_message = (f'Called capitalize_title("canopy"). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" for the title.') + error_message = ( + f'Called capitalize_title("canopy"). ' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" for the title.' + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -24,9 +28,11 @@ def test_capitalize_title(self): actual_result = capitalize_title("fish are cold blooded") expected = "Fish Are Cold Blooded" - error_message = (f'Called capitalize_title("fish are cold blooded"). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" for the title.') + error_message = ( + f'Called capitalize_title("fish are cold blooded"). ' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" for the title.' + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -35,9 +41,11 @@ def test_sentence_ending(self): actual_result = check_sentence_ending("Snails can sleep for 3 years.") expected = True - error_message = (f'Called check_sentence_ending("Snails can sleep for 3 years."). ' - f'The function returned {actual_result}, ' - f'but the tests expected {expected} for a period ending.') + error_message = ( + f'Called check_sentence_ending("Snails can sleep for 3 years."). ' + f"The function returned {actual_result}, " + f"but the tests expected {expected} for a period ending." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -46,9 +54,11 @@ def test_sentence_ending_without_period(self): actual_result = check_sentence_ending("Fittonia are nice") expected = False - error_message = (f'Called check_sentence_ending("Fittonia are nice"). ' - f'The function returned {actual_result}, ' - f'but the tests expected {expected} for a period ending.') + error_message = ( + f'Called check_sentence_ending("Fittonia are nice"). ' + f"The function returned {actual_result}, " + f"but the tests expected {expected} for a period ending." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -57,9 +67,11 @@ def test_remove_extra_spaces_only_start(self): actual_result = clean_up_spacing(" A rolling stone gathers no moss") expected = "A rolling stone gathers no moss" - error_message = (f'Called clean_up_spacing(" A rolling stone gathers no moss"). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" as a cleaned string.') + error_message = ( + f'Called clean_up_spacing(" A rolling stone gathers no moss"). ' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" as a cleaned string.' + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -68,9 +80,11 @@ def test_remove_extra_spaces(self): actual_result = clean_up_spacing(" Elephants can't jump. ") expected = "Elephants can't jump." - error_message = ("Called clean_up_spacing(\" Elephants can't jump. \")" - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" as a cleaned string.') + error_message = ( + 'Called clean_up_spacing(" Elephants can\'t jump. ")' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" as a cleaned string.' + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -79,9 +93,11 @@ def test_replace_word_choice(self): actual_result = replace_word_choice("Animals are cool.", "cool", "awesome") expected = "Animals are awesome." - error_message = ('Called replace_word_choice("Animals are cool.", "cool", "awesome"). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" after the word replacement.') + error_message = ( + 'Called replace_word_choice("Animals are cool.", "cool", "awesome"). ' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" after the word replacement.' + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -90,9 +106,11 @@ def test_replace_word_not_exist(self): actual_result = replace_word_choice("Animals are cool.", "small", "tiny") expected = "Animals are cool." - error_message = ('Called replace_word_choice("Animals are cool.", "small", "tiny"). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}", because the word ' - 'to be replaced is not in the sentence.') + error_message = ( + 'Called replace_word_choice("Animals are cool.", "small", "tiny"). ' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}", because the word ' + "to be replaced is not in the sentence." + ) self.assertEqual(actual_result, expected, msg=error_message) diff --git a/exercises/concept/little-sisters-vocab/.meta/exemplar.py b/exercises/concept/little-sisters-vocab/.meta/exemplar.py index c71d4902cae..8865e9a1871 100644 --- a/exercises/concept/little-sisters-vocab/.meta/exemplar.py +++ b/exercises/concept/little-sisters-vocab/.meta/exemplar.py @@ -8,7 +8,7 @@ def add_prefix_un(word): :return: str - of root word prepended with 'un'. """ - return 'un' + word + return "un" + word def make_word_groups(vocab_words): @@ -27,7 +27,7 @@ def make_word_groups(vocab_words): """ prefix = vocab_words[0] - joiner = ' :: ' + prefix + joiner = " :: " + prefix return joiner.join(vocab_words) @@ -42,8 +42,8 @@ def remove_suffix_ness(word): """ word = word[:-4] - if word[-1] == 'i': - word = word[:-1] + 'y' + if word[-1] == "i": + word = word[:-1] + "y" return word @@ -60,9 +60,9 @@ def adjective_to_verb(sentence, index): word = sentence.split()[index] - if word[-1] == '.': - word = word[:-1] + 'en' + if word[-1] == ".": + word = word[:-1] + "en" else: - word = word + 'en' + word = word + "en" return word diff --git a/exercises/concept/little-sisters-vocab/strings_test.py b/exercises/concept/little-sisters-vocab/strings_test.py index b13d4e9a357..6acfaef5f0c 100644 --- a/exercises/concept/little-sisters-vocab/strings_test.py +++ b/exercises/concept/little-sisters-vocab/strings_test.py @@ -1,126 +1,225 @@ import unittest import pytest -from strings import (add_prefix_un, - make_word_groups, - remove_suffix_ness, - adjective_to_verb) +from strings import ( + add_prefix_un, + make_word_groups, + remove_suffix_ness, + adjective_to_verb, +) class LittleSistersVocabTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_add_prefix_un(self): - input_data = ['happy', 'manageable', 'fold', 'eaten', 'avoidable', 'usual'] - result_data = [f'un{item}' for item in input_data] + input_data = ["happy", "manageable", "fold", "eaten", "avoidable", "usual"] + result_data = [f"un{item}" for item in input_data] - for variant, (word, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', word=word, expected=expected): + for variant, (word, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", word=word, expected=expected): actual_result = add_prefix_un(word) - error_message = (f'Called add_prefix_un("{word}"). ' - f'The function returned "{actual_result}", but the ' - f'tests expected "{expected}" after adding "un" as a prefix.') + error_message = ( + f'Called add_prefix_un("{word}"). ' + f'The function returned "{actual_result}", but the ' + f'tests expected "{expected}" after adding "un" as a prefix.' + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_make_word_groups_en(self): - input_data = ['en', 'circle', 'fold', 'close', 'joy', 'lighten', 'tangle', 'able', 'code', 'culture'] - expected = ('en :: encircle :: enfold :: enclose :: enjoy :: enlighten ::' - ' entangle :: enable :: encode :: enculture') + input_data = [ + "en", + "circle", + "fold", + "close", + "joy", + "lighten", + "tangle", + "able", + "code", + "culture", + ] + expected = ( + "en :: encircle :: enfold :: enclose :: enjoy :: enlighten ::" + " entangle :: enable :: encode :: enculture" + ) actual_result = make_word_groups(input_data) - error_message = (f'Called make_word_groups({input_data}). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" for the ' - 'word groups.') + error_message = ( + f"Called make_word_groups({input_data}). " + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" for the ' + "word groups." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_make_word_groups_pre(self): - input_data = ['pre', 'serve', 'dispose', 'position', 'requisite', 'digest', - 'natal', 'addressed', 'adolescent', 'assumption', 'mature', 'compute'] - expected = ('pre :: preserve :: predispose :: preposition :: prerequisite :: ' - 'predigest :: prenatal :: preaddressed :: preadolescent :: preassumption :: ' - 'premature :: precompute') + input_data = [ + "pre", + "serve", + "dispose", + "position", + "requisite", + "digest", + "natal", + "addressed", + "adolescent", + "assumption", + "mature", + "compute", + ] + expected = ( + "pre :: preserve :: predispose :: preposition :: prerequisite :: " + "predigest :: prenatal :: preaddressed :: preadolescent :: preassumption :: " + "premature :: precompute" + ) actual_result = make_word_groups(input_data) - error_message = (f'Called make_word_groups({input_data}). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" for the ' - 'word groups.') + error_message = ( + f"Called make_word_groups({input_data}). " + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" for the ' + "word groups." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_make_word_groups_auto(self): - input_data = ['auto', 'didactic', 'graph', 'mate', 'chrome', 'centric', 'complete', - 'echolalia', 'encoder', 'biography'] - expected = ('auto :: autodidactic :: autograph :: automate :: autochrome :: ' - 'autocentric :: autocomplete :: autoecholalia :: autoencoder :: ' - 'autobiography') + input_data = [ + "auto", + "didactic", + "graph", + "mate", + "chrome", + "centric", + "complete", + "echolalia", + "encoder", + "biography", + ] + expected = ( + "auto :: autodidactic :: autograph :: automate :: autochrome :: " + "autocentric :: autocomplete :: autoecholalia :: autoencoder :: " + "autobiography" + ) actual_result = make_word_groups(input_data) - error_message = (f'Called make_word_groups({input_data}). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" for the ' - 'word groups.') + error_message = ( + f"Called make_word_groups({input_data}). " + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" for the ' + "word groups." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_make_words_groups_inter(self): - input_data = ['inter', 'twine', 'connected', 'dependent', 'galactic', 'action', - 'stellar', 'cellular', 'continental', 'axial', 'operative', 'disciplinary'] - expected = ('inter :: intertwine :: interconnected :: interdependent :: ' - 'intergalactic :: interaction :: interstellar :: intercellular :: ' - 'intercontinental :: interaxial :: interoperative :: interdisciplinary') + input_data = [ + "inter", + "twine", + "connected", + "dependent", + "galactic", + "action", + "stellar", + "cellular", + "continental", + "axial", + "operative", + "disciplinary", + ] + expected = ( + "inter :: intertwine :: interconnected :: interdependent :: " + "intergalactic :: interaction :: interstellar :: intercellular :: " + "intercontinental :: interaxial :: interoperative :: interdisciplinary" + ) actual_result = make_word_groups(input_data) - error_message = (f'Called make_word_groups({input_data}). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" for the ' - 'word groups.') + error_message = ( + f"Called make_word_groups({input_data}). " + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" for the ' + "word groups." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_remove_suffix_ness(self): - input_data = ['heaviness', 'sadness', 'softness', 'crabbiness', 'lightness', 'artiness', 'edginess'] - result_data = ['heavy', 'sad', 'soft', 'crabby', 'light', 'arty', 'edgy'] - - for variant, (word, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', word=word, expected=expected): + input_data = [ + "heaviness", + "sadness", + "softness", + "crabbiness", + "lightness", + "artiness", + "edginess", + ] + result_data = ["heavy", "sad", "soft", "crabby", "light", "arty", "edgy"] + + for variant, (word, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", word=word, expected=expected): actual_result = remove_suffix_ness(word) - error_message = (f'Called remove_suffix_ness("{word}"). ' - f'The function returned "{actual_result}", ' - f'but the tests expected "{expected}" after the ' - 'suffix was removed.') + error_message = ( + f'Called remove_suffix_ness("{word}"). ' + f'The function returned "{actual_result}", ' + f'but the tests expected "{expected}" after the ' + "suffix was removed." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=4) def test_adjective_to_verb(self): - input_data = ['Look at the bright sky.', - 'His expression went dark.', - 'The bread got hard after sitting out.', - 'The butter got soft in the sun.', - 'Her eyes were light blue.', - 'The morning fog made everything damp with mist.', - 'He cut the fence pickets short by mistake.', - 'Charles made weak crying noises.', - 'The black oil got on the white dog.'] + input_data = [ + "Look at the bright sky.", + "His expression went dark.", + "The bread got hard after sitting out.", + "The butter got soft in the sun.", + "Her eyes were light blue.", + "The morning fog made everything damp with mist.", + "He cut the fence pickets short by mistake.", + "Charles made weak crying noises.", + "The black oil got on the white dog.", + ] index_data = [-2, -1, 3, 3, -2, -3, 5, 2, 1] - result_data = ['brighten', 'darken', 'harden', 'soften', - 'lighten', 'dampen', 'shorten', 'weaken', 'blacken'] - - for variant, (sentence, index, expected) in enumerate(zip(input_data, index_data, result_data), start=1): - with self.subTest(f'variation #{variant}', sentence=sentence, index=index, expected=expected): + result_data = [ + "brighten", + "darken", + "harden", + "soften", + "lighten", + "dampen", + "shorten", + "weaken", + "blacken", + ] + + for variant, (sentence, index, expected) in enumerate( + zip(input_data, index_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", + sentence=sentence, + index=index, + expected=expected, + ): actual_result = adjective_to_verb(sentence, index) - error_message = (f'Called adjective_to_verb("{sentence}", {index}). ' - f'The function returned "{actual_result}", but the tests ' - f'expected "{expected}" as the verb for ' - f'the word at index {index}.') + error_message = ( + f'Called adjective_to_verb("{sentence}", {index}). ' + f'The function returned "{actual_result}", but the tests ' + f'expected "{expected}" as the verb for ' + f"the word at index {index}." + ) self.assertEqual(actual_result, expected, msg=error_message) diff --git a/exercises/concept/locomotive-engineer/locomotive_engineer_test.py b/exercises/concept/locomotive-engineer/locomotive_engineer_test.py index 95faf9086c1..6940d2084e5 100644 --- a/exercises/concept/locomotive-engineer/locomotive_engineer_test.py +++ b/exercises/concept/locomotive-engineer/locomotive_engineer_test.py @@ -1,115 +1,284 @@ import unittest import pytest -from locomotive_engineer import (get_list_of_wagons, - fix_list_of_wagons, - add_missing_stops, - extend_route_information, - fix_wagon_depot) +from locomotive_engineer import ( + get_list_of_wagons, + fix_list_of_wagons, + add_missing_stops, + extend_route_information, + fix_wagon_depot, +) class LocomotiveEngineerTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_get_list_of_wagons(self): - input_data = [(1,5,2,7,4), (1,5), (1,), (1,9,3), (1,10,6,3,9,8,4,14,24,7)] - output_data = [[1,5,2,7,4], [1,5], [1], [1,9,3], [1,10,6,3,9,8,4,14,24,7]] + input_data = [ + (1, 5, 2, 7, 4), + (1, 5), + (1,), + (1, 9, 3), + (1, 10, 6, 3, 9, 8, 4, 14, 24, 7), + ] + output_data = [ + [1, 5, 2, 7, 4], + [1, 5], + [1], + [1, 9, 3], + [1, 10, 6, 3, 9, 8, 4, 14, 24, 7], + ] - for variant, (input_data, expected) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + for variant, (input_data, expected) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = get_list_of_wagons(*input_data) - error_msg= (f'Called get_list_of_wagons{input_data}. ' - f'The function returned {actual_result}, but the ' - f'tests expected: {expected} as the wagon list instead.') + error_msg = ( + f"Called get_list_of_wagons{input_data}. " + f"The function returned {actual_result}, but the " + f"tests expected: {expected} as the wagon list instead." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=2) def test_fix_list_of_wagons(self): - input_data = [([2, 5, 1, 7, 4, 12, 6, 3, 13], [3, 17, 6, 15]), - ([3, 27, 1, 14, 10, 4, 12, 6, 23, 17, 13, 22, 28, 19], [8, 10, 5, 9, 36, 7, 20]), - ([4, 2, 1], [8, 6, 15]), - ([3, 14, 1, 25, 7, 19, 10], [8, 6, 4, 5, 9, 21, 2, 13]) - ] - output_data = [[1, 3, 17, 6, 15, 7, 4, 12, 6, 3, 13, 2, 5], - [1, 8, 10, 5, 9, 36, 7, 20, 14, 10, 4, 12, 6, 23, 17, 13, 22, 28, 19, 3, 27], - [1, 8, 6, 15, 4, 2], - [1, 8, 6, 4, 5, 9, 21, 2, 13, 25, 7, 19, 10, 3, 14] - ] - for variant, (input_data, expected) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + input_data = [ + ([2, 5, 1, 7, 4, 12, 6, 3, 13], [3, 17, 6, 15]), + ( + [3, 27, 1, 14, 10, 4, 12, 6, 23, 17, 13, 22, 28, 19], + [8, 10, 5, 9, 36, 7, 20], + ), + ([4, 2, 1], [8, 6, 15]), + ([3, 14, 1, 25, 7, 19, 10], [8, 6, 4, 5, 9, 21, 2, 13]), + ] + output_data = [ + [1, 3, 17, 6, 15, 7, 4, 12, 6, 3, 13, 2, 5], + [ + 1, + 8, + 10, + 5, + 9, + 36, + 7, + 20, + 14, + 10, + 4, + 12, + 6, + 23, + 17, + 13, + 22, + 28, + 19, + 3, + 27, + ], + [1, 8, 6, 15, 4, 2], + [1, 8, 6, 4, 5, 9, 21, 2, 13, 25, 7, 19, 10, 3, 14], + ] + for variant, (input_data, expected) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = fix_list_of_wagons(input_data[0], input_data[1]) - error_msg= (f'Called fix_list_of_wagons({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the ' - f'tests expected: {expected} as the wagon list instead.') + error_msg = ( + f"Called fix_list_of_wagons({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the " + f"tests expected: {expected} as the wagon list instead." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=3) - def test_add_missing_stops(self): - input_data = (({'from': 'Berlin', 'to': 'Hamburg'}, {'stop_1': 'Lepzig', 'stop_2': 'Hannover', 'stop_3': 'Frankfurt'}), - ({'from': 'Paris', 'to': 'London'}, {'stop_1': 'Lille'}), - ({'from': 'New York', 'to': 'Philadelphia'},{}), - ({'from': 'Gothenburg', 'to': 'Copenhagen'}, {'stop_1': 'Kungsbacka', 'stop_2': 'Varberg', 'stop_3': 'Halmstad', 'stop_4': 'Angelholm', 'stop_5': 'Lund', 'stop_6': 'Malmo'}) - ) - output_data = [{'from': 'Berlin', 'to': 'Hamburg', 'stops': ['Lepzig', 'Hannover', 'Frankfurt']}, - {'from': 'Paris', 'to': 'London', 'stops': ['Lille']}, - {'from': 'New York', 'to': 'Philadelphia', 'stops': []}, - {'from': 'Gothenburg', 'to': 'Copenhagen', 'stops': ['Kungsbacka', 'Varberg', 'Halmstad', 'Angelholm', 'Lund', 'Malmo']} - ] - for variant, (input_data, expected) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + def test_add_missing_stops(self): + input_data = ( + ( + {"from": "Berlin", "to": "Hamburg"}, + {"stop_1": "Lepzig", "stop_2": "Hannover", "stop_3": "Frankfurt"}, + ), + ({"from": "Paris", "to": "London"}, {"stop_1": "Lille"}), + ({"from": "New York", "to": "Philadelphia"}, {}), + ( + {"from": "Gothenburg", "to": "Copenhagen"}, + { + "stop_1": "Kungsbacka", + "stop_2": "Varberg", + "stop_3": "Halmstad", + "stop_4": "Angelholm", + "stop_5": "Lund", + "stop_6": "Malmo", + }, + ), + ) + output_data = [ + { + "from": "Berlin", + "to": "Hamburg", + "stops": ["Lepzig", "Hannover", "Frankfurt"], + }, + {"from": "Paris", "to": "London", "stops": ["Lille"]}, + {"from": "New York", "to": "Philadelphia", "stops": []}, + { + "from": "Gothenburg", + "to": "Copenhagen", + "stops": [ + "Kungsbacka", + "Varberg", + "Halmstad", + "Angelholm", + "Lund", + "Malmo", + ], + }, + ] + for variant, (input_data, expected) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = add_missing_stops(input_data[0], **input_data[1]) - error_msg= (f'Called add_missing_stops({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the ' - f'tests expected: {expected} as the set of stops.') + error_msg = ( + f"Called add_missing_stops({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the " + f"tests expected: {expected} as the set of stops." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=4) - def test_extend_route_information(self): - input_data = [({'from': 'Berlin', 'to': 'Hamburg'}, {'timeOfArrival': '12:00', 'precipitation': '10', 'temperature': '5', 'caboose': 'yes'}), - ({'from': 'Paris', 'to': 'London'}, {'timeOfArrival': '10:30', 'temperature': '20', 'length': '15'}), - ({'from': 'Gothenburg', 'to': 'Copenhagen'}, {'precipitation': '1', 'timeOfArrival': '21:20', 'temperature': '-6'})] - output_data = [{'from': 'Berlin', 'to': 'Hamburg', 'timeOfArrival': '12:00', 'precipitation': '10', 'temperature': '5', 'caboose': 'yes'}, - {'from': 'Paris', 'to': 'London', 'timeOfArrival': '10:30', 'temperature': '20', 'length': '15'}, - {'from': 'Gothenburg', 'to': 'Copenhagen', 'precipitation': '1', 'timeOfArrival': '21:20', 'temperature': '-6'} - ] - - for variant, (input_data, expected) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + def test_extend_route_information(self): + input_data = [ + ( + {"from": "Berlin", "to": "Hamburg"}, + { + "timeOfArrival": "12:00", + "precipitation": "10", + "temperature": "5", + "caboose": "yes", + }, + ), + ( + {"from": "Paris", "to": "London"}, + {"timeOfArrival": "10:30", "temperature": "20", "length": "15"}, + ), + ( + {"from": "Gothenburg", "to": "Copenhagen"}, + {"precipitation": "1", "timeOfArrival": "21:20", "temperature": "-6"}, + ), + ] + output_data = [ + { + "from": "Berlin", + "to": "Hamburg", + "timeOfArrival": "12:00", + "precipitation": "10", + "temperature": "5", + "caboose": "yes", + }, + { + "from": "Paris", + "to": "London", + "timeOfArrival": "10:30", + "temperature": "20", + "length": "15", + }, + { + "from": "Gothenburg", + "to": "Copenhagen", + "precipitation": "1", + "timeOfArrival": "21:20", + "temperature": "-6", + }, + ] + + for variant, (input_data, expected) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = extend_route_information(input_data[0], input_data[1]) - error_msg= (f'Called extend_route_information({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the ' - f'tests expected: {expected} as the route dictionary.') + error_msg = ( + f"Called extend_route_information({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the " + f"tests expected: {expected} as the route dictionary." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=5) def test_fix_wagon_depot(self): input_data = ( - [[(2, 'red'), (4, 'red'), (8, 'red')], [(5, 'blue'), (9, 'blue'), (13, 'blue')], [(3, 'orange'), (7, 'orange'), (11, 'orange')]], - [[(6, 'blue'), (10, 'blue'), (14, 'blue')], [(7, 'red'), (4, 'red'), (2, 'red')], [(3, 'orange'), (11, 'orange'), (15, 'orange')]], - [[(7, 'pink'), (4, 'pink'), (2, 'pink')], [(10, 'green'), (6, 'green'), (14, 'green')], [(9, 'yellow'), (5, 'yellow'), (13, 'yellow')]], - [[(3, 'purple'), (11, 'purple'), (15, 'purple')], [(20, 'black'), (16, 'black'), (12, 'black')], [(19, 'white'), (17, 'white'), (18, 'white')]] + [ + [(2, "red"), (4, "red"), (8, "red")], + [(5, "blue"), (9, "blue"), (13, "blue")], + [(3, "orange"), (7, "orange"), (11, "orange")], + ], + [ + [(6, "blue"), (10, "blue"), (14, "blue")], + [(7, "red"), (4, "red"), (2, "red")], + [(3, "orange"), (11, "orange"), (15, "orange")], + ], + [ + [(7, "pink"), (4, "pink"), (2, "pink")], + [(10, "green"), (6, "green"), (14, "green")], + [(9, "yellow"), (5, "yellow"), (13, "yellow")], + ], + [ + [(3, "purple"), (11, "purple"), (15, "purple")], + [(20, "black"), (16, "black"), (12, "black")], + [(19, "white"), (17, "white"), (18, "white")], + ], ) output_data = ( - [[(2, 'red'), (5, 'blue'), (3, 'orange')], [(4, 'red'), (9, 'blue'), (7, 'orange')], [(8, 'red'), (13, 'blue'), (11, 'orange')]], - [[(6, 'blue'), (7, 'red'), (3, 'orange')], [(10, 'blue'), (4, 'red'), (11, 'orange')], [(14, 'blue'), (2, 'red'), (15, 'orange')]], - [[(7, 'pink'), (10, 'green'), (9, 'yellow')], [(4, 'pink'), (6, 'green'), (5, 'yellow')], [(2, 'pink'), (14, 'green'), (13, 'yellow')]], - [[(3, 'purple'), (20, 'black'), (19, 'white')], [(11, 'purple'), (16, 'black'), (17, 'white')], [(15, 'purple'), (12, 'black'), (18, 'white')]] + [ + [(2, "red"), (5, "blue"), (3, "orange")], + [(4, "red"), (9, "blue"), (7, "orange")], + [(8, "red"), (13, "blue"), (11, "orange")], + ], + [ + [(6, "blue"), (7, "red"), (3, "orange")], + [(10, "blue"), (4, "red"), (11, "orange")], + [(14, "blue"), (2, "red"), (15, "orange")], + ], + [ + [(7, "pink"), (10, "green"), (9, "yellow")], + [(4, "pink"), (6, "green"), (5, "yellow")], + [(2, "pink"), (14, "green"), (13, "yellow")], + ], + [ + [(3, "purple"), (20, "black"), (19, "white")], + [(11, "purple"), (16, "black"), (17, "white")], + [(15, "purple"), (12, "black"), (18, "white")], + ], ) - for variant, (input_data, expected) in enumerate(zip(input_data, output_data), start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + for variant, (input_data, expected) in enumerate( + zip(input_data, output_data), start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = fix_wagon_depot(input_data) - error_msg= (f'Called fix_wagon_depot({input_data}). ' - f'The function returned {actual_result}, but the ' - f'tests expected: {expected} as the wagon depot list.') + error_msg = ( + f"Called fix_wagon_depot({input_data}). " + f"The function returned {actual_result}, but the " + f"tests expected: {expected} as the wagon depot list." + ) self.assertEqual(actual_result, expected, msg=error_msg) diff --git a/exercises/concept/log-levels/.meta/exemplar.py b/exercises/concept/log-levels/.meta/exemplar.py index db45eeb0622..10d91e7e0bf 100644 --- a/exercises/concept/log-levels/.meta/exemplar.py +++ b/exercises/concept/log-levels/.meta/exemplar.py @@ -4,14 +4,14 @@ class LogLevel(Enum): """Represent different log levels by their verbose codes.""" - TRACE = 'TRC' - DEBUG = 'DBG' - INFO = 'INF' - WARNING = 'WRN' - WARN = 'WRN' - ERROR = 'ERR' - FATAL = 'FTL' - UNKNOWN = 'UKN' + TRACE = "TRC" + DEBUG = "DBG" + INFO = "INF" + WARNING = "WRN" + WARN = "WRN" + ERROR = "ERR" + FATAL = "FTL" + UNKNOWN = "UKN" class LogLevelInt(Enum): @@ -34,11 +34,11 @@ def parse_log_level(message): :return: enum - 'LogLevel.'. Return 'LogLevel.Unknown' if an unknown severity is passed. """ - str_split = message.split(':') + str_split = message.split(":") lvl = str_split[0][1:-1] if lvl in [level.value for level in LogLevel]: return LogLevel(lvl) - return LogLevel('UKN') + return LogLevel("UKN") def convert_to_short_log(log_level, message): @@ -49,7 +49,7 @@ def convert_to_short_log(log_level, message): :return: enum - 'LogLevelInt.` e.g. 'LogLevelInt.5' """ - return f'{LogLevelInt[log_level.name].value}:{message}' + return f"{LogLevelInt[log_level.name].value}:{message}" def get_warn_alias(): @@ -58,7 +58,7 @@ def get_warn_alias(): :return: enum - 'LogLevel'.' """ - return LogLevel('WRN') + return LogLevel("WRN") def get_members(): diff --git a/exercises/concept/log-levels/enums_test.py b/exercises/concept/log-levels/enums_test.py index d0fe58ffff5..dcc81ad66af 100644 --- a/exercises/concept/log-levels/enums_test.py +++ b/exercises/concept/log-levels/enums_test.py @@ -6,7 +6,7 @@ parse_log_level, convert_to_short_log, get_warn_alias, - get_members + get_members, ) @@ -14,64 +14,69 @@ class EnumsTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_parse_log_level_set_ing(self): self.assertIs( - parse_log_level('[INF]: File deleted'), + parse_log_level("[INF]: File deleted"), LogLevel.INFO, - msg='The Log level is incorrect' + msg="The Log level is incorrect", ) @pytest.mark.task(taskno=1) def test_parse_log_level_set_wrn(self): self.assertIs( - parse_log_level('[WRN]: File is being overwritten'), + parse_log_level("[WRN]: File is being overwritten"), LogLevel.WARNING, - msg='The Log level is incorrect' + msg="The Log level is incorrect", ) @pytest.mark.task(taskno=1) def test_parse_log_level_set_err(self): self.assertIs( - parse_log_level('[ERR]: Some Random Log'), + parse_log_level("[ERR]: Some Random Log"), LogLevel.ERROR, - msg='The Log level is incorrect' + msg="The Log level is incorrect", ) @pytest.mark.task(taskno=2) def test_parse_log_level_set_xyz(self): self.assertIs( - parse_log_level('[XYZ]: Some Random Log'), + parse_log_level("[XYZ]: Some Random Log"), LogLevel.UNKNOWN, - msg='The Log level is incorrect' + msg="The Log level is incorrect", ) @pytest.mark.task(taskno=3) def test_convert_to_short_log_set1(self): self.assertEqual( - convert_to_short_log(LogLevel.ERROR, 'Stack overflow'), - '6:Stack overflow', - msg='The converted short log is incorrect' + convert_to_short_log(LogLevel.ERROR, "Stack overflow"), + "6:Stack overflow", + msg="The converted short log is incorrect", ) @pytest.mark.task(taskno=3) def test_convert_to_short_log_set2(self): self.assertEqual( - convert_to_short_log(LogLevel.WARNING, 'This is a warning'), - '5:This is a warning', - msg='The converted short log is incorrect' + convert_to_short_log(LogLevel.WARNING, "This is a warning"), + "5:This is a warning", + msg="The converted short log is incorrect", ) @pytest.mark.task(taskno=4) def test_get_warn_alias(self): self.assertIs( - get_warn_alias(), - LogLevel.WARN, - msg='The warn alias returned is incorrect' + get_warn_alias(), LogLevel.WARN, msg="The warn alias returned is incorrect" ) @pytest.mark.task(taskno=5) def test_get_members(self): self.assertListEqual( get_members(), - [('TRACE', 'TRC'), ('DEBUG', 'DBG'), ('INFO', 'INF'), - ('WARNING', 'WRN'), ('ERROR', 'ERR'), ('FATAL', 'FTL'), ('UNKNOWN', 'UKN')], - msg='The Members list of the enum is incorrect' + [ + ("TRACE", "TRC"), + ("DEBUG", "DBG"), + ("INFO", "INF"), + ("WARNING", "WRN"), + ("ERROR", "ERR"), + ("FATAL", "FTL"), + ("UNKNOWN", "UKN"), + ], + msg="The Members list of the enum is incorrect", ) diff --git a/exercises/concept/making-the-grade/loops_test.py b/exercises/concept/making-the-grade/loops_test.py index 598e2b0ddf0..52ae348deb6 100644 --- a/exercises/concept/making-the-grade/loops_test.py +++ b/exercises/concept/making-the-grade/loops_test.py @@ -7,7 +7,8 @@ above_threshold, letter_grades, student_ranking, - perfect_score) + perfect_score, +) class MakingTheGradeTest(unittest.TestCase): @@ -18,70 +19,96 @@ def test_round_scores(self): # Because we the input list can be mutated, the test data has been created # as tuples, which we then convert to a list when the test runs. # this makes accurate error messages easier to create. - test_data = [tuple(), - (.5,), - (1.5,), - (90.33, 40.5, 55.44, 70.05, 30.55, 25.45, 80.45, 95.3, 38.7, 40.3), - (50, 36.03, 76.92, 40.7, 43, 78.29, 63.58, 91, 28.6, 88.0)] - result_data = [[], - [0], - [2], - [90, 40, 55, 70, 31, 25, 80, 95, 39, 40], - [50, 36, 77, 41, 43, 78, 64, 91, 29, 88]] - - for variant, (student_scores, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', student_scores=student_scores, expected=expected): + test_data = [ + tuple(), + (0.5,), + (1.5,), + (90.33, 40.5, 55.44, 70.05, 30.55, 25.45, 80.45, 95.3, 38.7, 40.3), + (50, 36.03, 76.92, 40.7, 43, 78.29, 63.58, 91, 28.6, 88.0), + ] + result_data = [ + [], + [0], + [2], + [90, 40, 55, 70, 31, 25, 80, 95, 39, 40], + [50, 36, 77, 41, 43, 78, 64, 91, 29, 88], + ] + + for variant, (student_scores, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", + student_scores=student_scores, + expected=expected, + ): # Because the test_input is a tuple, it has to be converted to a list for the function call. actual_result = round_scores(list(student_scores)) - error_message = (f'Called round_scores({list(student_scores)}). ' - f'The function returned {sorted(actual_result)} after sorting, but ' - f'the tests expected {sorted(expected)} after sorting. ' - f'One or more scores were rounded incorrectly.') + error_message = ( + f"Called round_scores({list(student_scores)}). " + f"The function returned {sorted(actual_result)} after sorting, but " + f"the tests expected {sorted(expected)} after sorting. " + f"One or more scores were rounded incorrectly." + ) # everything is sorted for easier comparison. - self.assertEqual(sorted(actual_result), sorted(expected), msg=error_message) + self.assertEqual( + sorted(actual_result), sorted(expected), msg=error_message + ) @pytest.mark.task(taskno=2) def test_count_failed_students(self): - test_data = [[89, 85, 42, 57, 90, 100, 95, 48, 70, 96], - [40, 40, 35, 70, 30, 41, 90]] - result_data = [0,4] - - for variant, (student_scores, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', - student_scores=student_scores, - expected=expected): + test_data = [ + [89, 85, 42, 57, 90, 100, 95, 48, 70, 96], + [40, 40, 35, 70, 30, 41, 90], + ] + result_data = [0, 4] + + for variant, (student_scores, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", + student_scores=student_scores, + expected=expected, + ): actual_result = count_failed_students(student_scores) - error_message = (f'Called count_failed_students({student_scores}). ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} for the ' - 'number of students who failed.') + error_message = ( + f"Called count_failed_students({student_scores}). " + f"The function returned {actual_result}, but " + f"the tests expected {expected} for the " + "number of students who failed." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_above_threshold(self): - test_data = [([40, 39, 95, 80, 25, 31, 70, 55, 40, 90], 98), - ([88, 29, 91, 64, 78, 43, 41, 77, 36, 50], 80), - ([100, 89], 100), - ([88, 29, 91, 64, 78, 43, 41, 77, 36, 50], 78), - ([], 80)] - - result_data = [[], - [88, 91], - [100], - [88, 91, 78], - []] - - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', params=params, expected=expected): + test_data = [ + ([40, 39, 95, 80, 25, 31, 70, 55, 40, 90], 98), + ([88, 29, 91, 64, 78, 43, 41, 77, 36, 50], 80), + ([100, 89], 100), + ([88, 29, 91, 64, 78, 43, 41, 77, 36, 50], 78), + ([], 80), + ] + + result_data = [[], [88, 91], [100], [88, 91, 78], []] + + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = above_threshold(*params) - error_message = (f'Called above_threshold{params}. ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} for the ' - 'scores that are above the threshold.') + error_message = ( + f"Called above_threshold{params}. " + f"The function returned {actual_result}, but " + f"the tests expected {expected} for the " + "scores that are above the threshold." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -89,67 +116,117 @@ def test_above_threshold(self): def test_letter_grades(self): test_data = [100, 97, 85, 92, 81] - result_data = [[41, 56, 71, 86], - [41, 55, 69, 83], - [41, 52, 63, 74], - [41, 54, 67, 80], - [41, 51, 61, 71]] - - for variant, (highest, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', highest=highest, expected=expected): + result_data = [ + [41, 56, 71, 86], + [41, 55, 69, 83], + [41, 52, 63, 74], + [41, 54, 67, 80], + [41, 51, 61, 71], + ] + + for variant, (highest, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", highest=highest, expected=expected + ): actual_result = letter_grades(highest) - error_message = (f'Called letter_grades({highest}). ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} for the ' - 'letter grade cutoffs.') + error_message = ( + f"Called letter_grades({highest}). " + f"The function returned {actual_result}, but " + f"the tests expected {expected} for the " + "letter grade cutoffs." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=5) def test_student_ranking(self): - test_data = [([82], ['Betty']), - ([88, 73], ['Paul', 'Ernest']), - ([100, 98, 92, 86, 70, 68, 67, 60], - ['Rui', 'Betty', 'Joci', 'Yoshi', 'Kora', 'Bern', 'Jan', 'Rose'])] - - result_data = [['1. Betty: 82'], - ['1. Paul: 88', '2. Ernest: 73'], - ['1. Rui: 100', '2. Betty: 98', '3. Joci: 92', '4. Yoshi: 86', - '5. Kora: 70', '6. Bern: 68', '7. Jan: 67', '8. Rose: 60']] - - for variant, (params, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f'variation #{variant}', params=params, expected=expected): + test_data = [ + ([82], ["Betty"]), + ([88, 73], ["Paul", "Ernest"]), + ( + [100, 98, 92, 86, 70, 68, 67, 60], + ["Rui", "Betty", "Joci", "Yoshi", "Kora", "Bern", "Jan", "Rose"], + ), + ] + + result_data = [ + ["1. Betty: 82"], + ["1. Paul: 88", "2. Ernest: 73"], + [ + "1. Rui: 100", + "2. Betty: 98", + "3. Joci: 92", + "4. Yoshi: 86", + "5. Kora: 70", + "6. Bern: 68", + "7. Jan: 67", + "8. Rose: 60", + ], + ] + + for variant, (params, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", params=params, expected=expected + ): actual_result = student_ranking(*params) - error_message = (f'Called student_ranking{params}. ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} for the ' - 'student rankings.') + error_message = ( + f"Called student_ranking{params}. " + f"The function returned {actual_result}, but " + f"the tests expected {expected} for the " + "student rankings." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=6) def test_perfect_score(self): test_data = [ - [['Joci', 100], ['Vlad', 100], ['Raiana', 100], ['Alessandro', 100]], - [['Jill', 30], ['Paul', 73]], - [], - [['Rui', 60], ['Joci', 58], ['Sara', 91], ['Kora', 93], ['Alex', 42], - ['Jan', 81], ['Lilliana', 40], ['John', 60], ['Bern', 28], ['Vlad', 55]], - - [['Yoshi', 52], ['Jan', 86], ['Raiana', 100], ['Betty', 60], - ['Joci', 100], ['Kora', 81], ['Bern', 41], ['Rose', 94]] - ] - - - result_data = [['Joci', 100],[], [], [], ['Raiana', 100]] - - for variant, (student_info, expected) in enumerate(zip(test_data, result_data), start=1): - - with self.subTest(f'variation #{variant}', student_info=student_info, expected=expected): + [["Joci", 100], ["Vlad", 100], ["Raiana", 100], ["Alessandro", 100]], + [["Jill", 30], ["Paul", 73]], + [], + [ + ["Rui", 60], + ["Joci", 58], + ["Sara", 91], + ["Kora", 93], + ["Alex", 42], + ["Jan", 81], + ["Lilliana", 40], + ["John", 60], + ["Bern", 28], + ["Vlad", 55], + ], + [ + ["Yoshi", 52], + ["Jan", 86], + ["Raiana", 100], + ["Betty", 60], + ["Joci", 100], + ["Kora", 81], + ["Bern", 41], + ["Rose", 94], + ], + ] + + result_data = [["Joci", 100], [], [], [], ["Raiana", 100]] + + for variant, (student_info, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + + with self.subTest( + f"variation #{variant}", student_info=student_info, expected=expected + ): actual_result = perfect_score(student_info) - error_message = (f'Called perfect_score({student_info}). ' - f'The function returned {actual_result}, but ' - f'the tests expected {expected} for the ' - 'first "perfect" score.') + error_message = ( + f"Called perfect_score({student_info}). " + f"The function returned {actual_result}, but " + f"the tests expected {expected} for the " + 'first "perfect" score.' + ) self.assertEqual(actual_result, expected, msg=error_message) diff --git a/exercises/concept/mecha-munch-management/.meta/exemplar.py b/exercises/concept/mecha-munch-management/.meta/exemplar.py index ea25110a3be..9a9036697f6 100644 --- a/exercises/concept/mecha-munch-management/.meta/exemplar.py +++ b/exercises/concept/mecha-munch-management/.meta/exemplar.py @@ -74,6 +74,6 @@ def update_store_inventory(fulfillment_cart, store_inventory): for key, values in fulfillment_cart.items(): store_inventory[key][0] = store_inventory[key][0] - values[0] if store_inventory[key][0] == 0: - store_inventory[key][0] = 'Out of Stock' + store_inventory[key][0] = "Out of Stock" return store_inventory diff --git a/exercises/concept/mecha-munch-management/dict_methods_test.py b/exercises/concept/mecha-munch-management/dict_methods_test.py index 4d8dab865a1..ff72fd1128b 100644 --- a/exercises/concept/mecha-munch-management/dict_methods_test.py +++ b/exercises/concept/mecha-munch-management/dict_methods_test.py @@ -19,76 +19,107 @@ update_store_inventory_data, ) + class MechaMunchManagementTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_add_item(self): for variant, (input_data, expected) in enumerate(add_item_data, start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = add_item(input_data[0], input_data[1]) - error_msg= (f'Called add_item({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected} once the item was added.') + error_msg = ( + f"Called add_item({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected} once the item was added." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=2) def test_read_notes(self): for variant, (input_data, expected) in enumerate(read_notes_data, start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = read_notes(input_data) - error_msg = (f'Called read_notes({input_data}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected} once the notes were read.') + error_msg = ( + f"Called read_notes({input_data}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected} once the notes were read." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=3) def test_update_recipes(self): for variant, (input_data, expected) in enumerate(update_recipes_data, start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = update_recipes(input_data[0], input_data[1]) - error_msg = (f'Called update_recipes({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected} once the recipes were updated.') + error_msg = ( + f"Called update_recipes({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected} once the recipes were updated." + ) self.assertEqual(actual_result, expected, msg=error_msg) @pytest.mark.task(taskno=4) def test_sort_entries(self): for variant, (input_data, expected) in enumerate(sort_entries_data, start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expecred=expected): + with self.subTest( + f"variation #{variant}", input_data=input_data, expecred=expected + ): actual_result = sort_entries(input_data) - error_msg = (f'Called sort_entries({input_data}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected} for the sorted entries.') + error_msg = ( + f"Called sort_entries({input_data}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected} for the sorted entries." + ) # Because we are asserting equal, we need to convert to an OrderedDict. # Regular dictionaries will compare equal even when they are ordered # differently from one another. See https://stackoverflow.com/a/58961124 - self.assertEqual(OrderedDict(actual_result), OrderedDict(expected), msg=error_msg) + self.assertEqual( + OrderedDict(actual_result), OrderedDict(expected), msg=error_msg + ) @pytest.mark.task(taskno=5) def test_send_to_store(self): for variant, (input_data, expected) in enumerate(send_to_store_data, start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = send_to_store(input_data[0], input_data[1]) - error_msg = (f'Called send_to_store({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected} as the fulfillment cart.') + error_msg = ( + f"Called send_to_store({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected} as the fulfillment cart." + ) # Because we are asserting equal, we need to convert to an OrderedDict. # Regular dictionaries will compare equal even when they are ordered # differently from one another. See https://stackoverflow.com/a/58961124 - self.assertEqual(OrderedDict(actual_result), OrderedDict(expected), msg=error_msg) + self.assertEqual( + OrderedDict(actual_result), OrderedDict(expected), msg=error_msg + ) @pytest.mark.task(taskno=6) def test_update_store_inventory(self): - for variant, (input_data, expected) in enumerate(update_store_inventory_data, start=1): - with self.subTest(f'variation #{variant}', input_data=input_data, expected=expected): + for variant, (input_data, expected) in enumerate( + update_store_inventory_data, start=1 + ): + with self.subTest( + f"variation #{variant}", input_data=input_data, expected=expected + ): actual_result = update_store_inventory(input_data[0], input_data[1]) - error_msg = (f'Called update_store_inventory({input_data[0]}, {input_data[1]}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected} as the store inventory.') + error_msg = ( + f"Called update_store_inventory({input_data[0]}, {input_data[1]}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected} as the store inventory." + ) self.assertEqual(actual_result, expected, msg=error_msg) diff --git a/exercises/concept/meltdown-mitigation/.meta/exemplar.py b/exercises/concept/meltdown-mitigation/.meta/exemplar.py index c2d8ddd7ede..ea37317d78b 100644 --- a/exercises/concept/meltdown-mitigation/.meta/exemplar.py +++ b/exercises/concept/meltdown-mitigation/.meta/exemplar.py @@ -47,13 +47,13 @@ def reactor_efficiency(voltage, current, theoretical_max_power): percentage_range = (generated_power / theoretical_max_power) * 100 if 80 <= percentage_range <= 100: - efficiency_level = 'green' + efficiency_level = "green" elif 60 <= percentage_range < 80: - efficiency_level = 'orange' + efficiency_level = "orange" elif 30 <= percentage_range < 60: - efficiency_level = 'red' + efficiency_level = "red" else: - efficiency_level = 'black' + efficiency_level = "black" return efficiency_level @@ -75,10 +75,10 @@ def fail_safe(temperature, neutrons_produced_per_second, threshold): operational_percentage = (output / threshold) * 100 if operational_percentage < 90: - status_code = 'LOW' + status_code = "LOW" elif operational_percentage <= 110: - status_code = 'NORMAL' + status_code = "NORMAL" else: - status_code = 'DANGER' + status_code = "DANGER" return status_code diff --git a/exercises/concept/meltdown-mitigation/conditionals_test.py b/exercises/concept/meltdown-mitigation/conditionals_test.py index 5e48ca326ca..4afea792749 100644 --- a/exercises/concept/meltdown-mitigation/conditionals_test.py +++ b/exercises/concept/meltdown-mitigation/conditionals_test.py @@ -1,13 +1,10 @@ import unittest import pytest -from conditionals import (is_criticality_balanced, - reactor_efficiency, - fail_safe) +from conditionals import is_criticality_balanced, reactor_efficiency, fail_safe class MeltdownMitigationTest(unittest.TestCase): - """Test cases for Meltdown mitigation exercise. - """ + """Test cases for Meltdown mitigation exercise.""" @pytest.mark.task(taskno=1) def test_is_criticality_balanced(self): @@ -17,22 +14,41 @@ def test_is_criticality_balanced(self): """ - test_data = ((750, 650, True), (799, 501, True), (500, 600, True), - (1000, 800, False), (800, 500, False), (800, 500.01, False), - (799.99, 500, False), (500.01, 999.99, False), (625, 800, False), - (625.99, 800, False), (625.01, 799.99, False), (799.99, 500.01, True), - (624.99, 799.99, True), (500, 1000, False), (500.01, 1000, False), - (499.99, 1000, True)) + test_data = ( + (750, 650, True), + (799, 501, True), + (500, 600, True), + (1000, 800, False), + (800, 500, False), + (800, 500.01, False), + (799.99, 500, False), + (500.01, 999.99, False), + (625, 800, False), + (625.99, 800, False), + (625.01, 799.99, False), + (799.99, 500.01, True), + (624.99, 799.99, True), + (500, 1000, False), + (500.01, 1000, False), + (499.99, 1000, True), + ) for variant, data in enumerate(test_data, start=1): temp, neutrons_emitted, expected = data - with self.subTest(f'variation #{variant}', temp=temp, neutrons_emitted=neutrons_emitted, expected=expected): + with self.subTest( + f"variation #{variant}", + temp=temp, + neutrons_emitted=neutrons_emitted, + expected=expected, + ): # pylint: disable=assignment-from-no-return actual_result = is_criticality_balanced(temp, neutrons_emitted) - failure_message = (f'Called is_criticality_balanced({temp}, {neutrons_emitted}). ' - f' The function returned {actual_result}, ' - f'but the test expected {expected} as the return value.') + failure_message = ( + f"Called is_criticality_balanced({temp}, {neutrons_emitted}). " + f" The function returned {actual_result}, " + f"but the test expected {expected} as the return value." + ) self.assertEqual(actual_result, expected, failure_message) @@ -42,21 +58,41 @@ def test_reactor_efficiency(self): theoretical_max_power = 10000 # The numbers are chosen so that current == 10 x percentage - test_data = ((1000, 'green'), (999, 'green'), (800, 'green'), - (799, 'orange'), (700, 'orange'), (600, 'orange'), - (599, 'red'), (560, 'red'), (400, 'red'), (300, 'red'), - (299, 'black'), (200, 'black'), (0, 'black')) + test_data = ( + (1000, "green"), + (999, "green"), + (800, "green"), + (799, "orange"), + (700, "orange"), + (600, "orange"), + (599, "red"), + (560, "red"), + (400, "red"), + (300, "red"), + (299, "black"), + (200, "black"), + (0, "black"), + ) for variant, data in enumerate(test_data, start=1): current, expected = data - with self.subTest(f'variation #{variant}', voltage=voltage, current=current, - theoretical_max_power=theoretical_max_power, expected=expected): + with self.subTest( + f"variation #{variant}", + voltage=voltage, + current=current, + theoretical_max_power=theoretical_max_power, + expected=expected, + ): # pylint: disable=assignment-from-no-return - actual_result = reactor_efficiency(voltage, current, theoretical_max_power) - failure_message =(f'Called reactor_efficiency({voltage}, {current}, {theoretical_max_power}). ' - f'The function returned {actual_result}, ' - f'but the test expected {expected} as the return value.') + actual_result = reactor_efficiency( + voltage, current, theoretical_max_power + ) + failure_message = ( + f"Called reactor_efficiency({voltage}, {current}, {theoretical_max_power}). " + f"The function returned {actual_result}, " + f"but the test expected {expected} as the return value." + ) self.assertEqual(actual_result, expected, failure_message) @@ -64,19 +100,36 @@ def test_reactor_efficiency(self): def test_fail_safe(self): temp = 10 threshold = 10000 - test_data = ((399, 'LOW'), (300, 'LOW'), (1, 'LOW'), - (0, 'LOW'), (901, 'NORMAL'), (1000, 'NORMAL'), - (1099, 'NORMAL'), (899, 'LOW'), (700, 'LOW'), - (400, 'LOW'), (1101, 'DANGER'), (1200, 'DANGER')) + test_data = ( + (399, "LOW"), + (300, "LOW"), + (1, "LOW"), + (0, "LOW"), + (901, "NORMAL"), + (1000, "NORMAL"), + (1099, "NORMAL"), + (899, "LOW"), + (700, "LOW"), + (400, "LOW"), + (1101, "DANGER"), + (1200, "DANGER"), + ) for variant, (neutrons_per_second, expected) in enumerate(test_data, start=1): - with self.subTest(f'variation #{variant}', temp=temp, neutrons_per_second=neutrons_per_second, - threshold=threshold, expected=expected): + with self.subTest( + f"variation #{variant}", + temp=temp, + neutrons_per_second=neutrons_per_second, + threshold=threshold, + expected=expected, + ): # pylint: disable=assignment-from-no-return actual_result = fail_safe(temp, neutrons_per_second, threshold) - failure_message = (f'Called fail_safe({temp}, {neutrons_per_second}, {threshold}). ' - f'The function returned {actual_result}, ' - f'but the test expected {expected} as the return value.') + failure_message = ( + f"Called fail_safe({temp}, {neutrons_per_second}, {threshold}). " + f"The function returned {actual_result}, " + f"but the test expected {expected} as the return value." + ) self.assertEqual(actual_result, expected, failure_message) diff --git a/exercises/concept/plane-tickets/.meta/exemplar.py b/exercises/concept/plane-tickets/.meta/exemplar.py index 8261795c66e..0d89166c749 100644 --- a/exercises/concept/plane-tickets/.meta/exemplar.py +++ b/exercises/concept/plane-tickets/.meta/exemplar.py @@ -2,7 +2,7 @@ import math -SEATS_IN_ROW = ['A', 'B', 'C', 'D'] +SEATS_IN_ROW = ["A", "B", "C", "D"] def generate_seat_letters(number): @@ -42,9 +42,9 @@ def generate_seats(number): number = number + 4 if number >= 13 else number letters = generate_seat_letters(number) for seat in range(number): - row_number = math.ceil((seat+1) / 4) + row_number = math.ceil((seat + 1) / 4) if row_number != 13: - yield f'{str(row_number)}{next(letters)}' + yield f"{str(row_number)}{next(letters)}" # return (f'{str(row_number)}{next(letters)}' for seat in range(number) # if (row_number := math.ceil((seat+1) / 4)) and row_number != 13) @@ -66,6 +66,7 @@ def assign_seats(passengers): output[passenger] = seat_number return output + def generate_codes(seat_numbers, flight_id): """Generate codes for a ticket. @@ -76,5 +77,5 @@ def generate_codes(seat_numbers, flight_id): """ for seat in seat_numbers: - base_string = f'{seat}{flight_id}' - yield base_string + '0' * (12 - len(base_string)) + base_string = f"{seat}{flight_id}" + yield base_string + "0" * (12 - len(base_string)) diff --git a/exercises/concept/plane-tickets/generators.py b/exercises/concept/plane-tickets/generators.py index 2f88c0619a5..6b8b17a4f31 100644 --- a/exercises/concept/plane-tickets/generators.py +++ b/exercises/concept/plane-tickets/generators.py @@ -36,6 +36,7 @@ def generate_seats(number): pass + def assign_seats(passengers): """Assign seats to passengers. @@ -48,6 +49,7 @@ def assign_seats(passengers): pass + def generate_codes(seat_numbers, flight_id): """Generate codes for a ticket. diff --git a/exercises/concept/plane-tickets/generators_test.py b/exercises/concept/plane-tickets/generators_test.py index 1596d424ed4..6841de3edf2 100644 --- a/exercises/concept/plane-tickets/generators_test.py +++ b/exercises/concept/plane-tickets/generators_test.py @@ -6,36 +6,49 @@ generate_seat_letters, generate_seats, assign_seats, - generate_codes + generate_codes, ) + class PlaneTicketsTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_task1_returns_generator(self): """Test if generate_seat_letters() returns a generator type.""" number = 5 - error_message = (f'Called generate_seat_letters({number}). ' - f'The function returned a {type(generate_seat_letters(number))} type, ' - f"but the tests expected the function to return a type.") + error_message = ( + f"Called generate_seat_letters({number}). " + f"The function returned a {type(generate_seat_letters(number))} type, " + f"but the tests expected the function to return a type." + ) - self.assertTrue(inspect.isgenerator(generate_seat_letters(number)), msg=error_message) + self.assertTrue( + inspect.isgenerator(generate_seat_letters(number)), msg=error_message + ) @pytest.mark.task(taskno=1) def test_generate_seat_letters(self): test_data = [1, 2, 3, 4, 5] - result_data = [["A"], - ["A", "B"], - ["A", "B", "C"], - ["A", "B", "C", "D"], - ["A", "B", "C", "D", "A"]] - - for variant, (number, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f"variation #{variant}", number=number, expected=expected): + result_data = [ + ["A"], + ["A", "B"], + ["A", "B", "C"], + ["A", "B", "C", "D"], + ["A", "B", "C", "D", "A"], + ] + + for variant, (number, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", number=number, expected=expected + ): actual_result = list(generate_seat_letters(number)) - error_message = (f'Called generate_seat_letters({number}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} when generating {number} seat(s).') + error_message = ( + f"Called generate_seat_letters({number}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} when generating {number} seat(s)." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -44,65 +57,160 @@ def test_task2_returns_generator(self): """Test if generate_seats() returns a generator type.""" number = 7 - error_message = (f'Called generate_seats({number}). ' - f'The function returned a {type(generate_seats(number))} type, ' - f"but the tests expected the function to return a type.") + error_message = ( + f"Called generate_seats({number}). " + f"The function returned a {type(generate_seats(number))} type, " + f"but the tests expected the function to return a type." + ) self.assertTrue(inspect.isgenerator(generate_seats(number)), msg=error_message) @pytest.mark.task(taskno=2) def test_generate_seats(self): test_data = [1, 2, 3, 4, 5] - result_data = [["1A"], - ["1A", "1B"], - ["1A", "1B", "1C"], - ["1A", "1B", "1C", "1D"], - ["1A", "1B", "1C", "1D", "2A"]] - - for variant, (number, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f"variation #{variant}", number=number, expected=expected): + result_data = [ + ["1A"], + ["1A", "1B"], + ["1A", "1B", "1C"], + ["1A", "1B", "1C", "1D"], + ["1A", "1B", "1C", "1D", "2A"], + ] + + for variant, (number, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", number=number, expected=expected + ): actual_result = list(generate_seats(number)) - error_message = (f'Called generate_seats({number}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} when generating {number} seat(s).') + error_message = ( + f"Called generate_seats({number}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} when generating {number} seat(s)." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_generate_seats_skips_row_13(self): test_data = [14 * 4] - result_data = [["1A", "1B", "1C", "1D", "2A", "2B", "2C", "2D", - "3A", "3B", "3C", "3D", "4A", "4B", "4C", "4D", - "5A", "5B", "5C", "5D", "6A", "6B", "6C", "6D", - "7A", "7B", "7C", "7D", "8A", "8B", "8C", "8D", - "9A", "9B", "9C", "9D", "10A", "10B", "10C", "10D", - "11A", "11B", "11C", "11D", "12A", "12B", "12C", "12D", - "14A", "14B", "14C", "14D", "15A", "15B", "15C", "15D"]] - - for variant, (number, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f"variation #{variant}", number=number, expected=expected): + result_data = [ + [ + "1A", + "1B", + "1C", + "1D", + "2A", + "2B", + "2C", + "2D", + "3A", + "3B", + "3C", + "3D", + "4A", + "4B", + "4C", + "4D", + "5A", + "5B", + "5C", + "5D", + "6A", + "6B", + "6C", + "6D", + "7A", + "7B", + "7C", + "7D", + "8A", + "8B", + "8C", + "8D", + "9A", + "9B", + "9C", + "9D", + "10A", + "10B", + "10C", + "10D", + "11A", + "11B", + "11C", + "11D", + "12A", + "12B", + "12C", + "12D", + "14A", + "14B", + "14C", + "14D", + "15A", + "15B", + "15C", + "15D", + ] + ] + + for variant, (number, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", number=number, expected=expected + ): actual_result = list(generate_seats(number)) - error_message = (f'Called generate_seats({number}). ' - f'The function returned {actual_result}, but the tests ' - f'expected: {expected}, when generating {number} seat(s).') + error_message = ( + f"Called generate_seats({number}). " + f"The function returned {actual_result}, but the tests " + f"expected: {expected}, when generating {number} seat(s)." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_assign_seats(self): - test_data = [["Passenger1", "Passenger2", "Passenger3", "Passenger4", "Passenger5"], - ["TicketNo=5644", "TicketNo=2273", "TicketNo=493", "TicketNo=5411", "TicketNo=824"]] - result_data = [{"Passenger1": "1A", "Passenger2": "1B", - "Passenger3": "1C", "Passenger4": "1D", "Passenger5": "2A"}, - {"TicketNo=5644": "1A", "TicketNo=2273": "1B", - "TicketNo=493": "1C", "TicketNo=5411": "1D", "TicketNo=824": "2A"}] - - for variant, (passengers, expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f"variation #{variant}", passengers=passengers, expected=expected): + test_data = [ + ["Passenger1", "Passenger2", "Passenger3", "Passenger4", "Passenger5"], + [ + "TicketNo=5644", + "TicketNo=2273", + "TicketNo=493", + "TicketNo=5411", + "TicketNo=824", + ], + ] + result_data = [ + { + "Passenger1": "1A", + "Passenger2": "1B", + "Passenger3": "1C", + "Passenger4": "1D", + "Passenger5": "2A", + }, + { + "TicketNo=5644": "1A", + "TicketNo=2273": "1B", + "TicketNo=493": "1C", + "TicketNo=5411": "1D", + "TicketNo=824": "2A", + }, + ] + + for variant, (passengers, expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", passengers=passengers, expected=expected + ): actual_result = assign_seats(passengers) - error_message = (f'Called assign_seats({passengers}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected}, when assigning seats.') + error_message = ( + f"Called assign_seats({passengers}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected}, when assigning seats." + ) self.assertEqual(actual_result, expected, msg=error_message) @@ -111,28 +219,44 @@ def test_task4_returns_generator(self): """Test if generate_codes() returns a generator type.""" seat_numbers, flight_id = "11B", "HA80085" - error_message = (f'Called generate_codes({seat_numbers}, {flight_id}). ' - f'The function returned a {type(generate_codes(seat_numbers, flight_id))} type, ' - f"but the tests expected the function to return a type.") - - self.assertTrue(inspect.isgenerator(generate_codes(seat_numbers, flight_id)), msg=error_message) + error_message = ( + f"Called generate_codes({seat_numbers}, {flight_id}). " + f"The function returned a {type(generate_codes(seat_numbers, flight_id))} type, " + f"but the tests expected the function to return a type." + ) + self.assertTrue( + inspect.isgenerator(generate_codes(seat_numbers, flight_id)), + msg=error_message, + ) @pytest.mark.task(taskno=4) def test_generate_codes(self): - test_data = [(["12A", "38B", "69C", "102B"],"KL1022"), - (["22C", "88B", "33A", "44B"], "DL1002")] - result_data = [['12AKL1022000', '38BKL1022000', '69CKL1022000', '102BKL102200'], - ['22CDL1002000', '88BDL1002000', '33ADL1002000', '44BDL1002000']] + test_data = [ + (["12A", "38B", "69C", "102B"], "KL1022"), + (["22C", "88B", "33A", "44B"], "DL1002"), + ] + result_data = [ + ["12AKL1022000", "38BKL1022000", "69CKL1022000", "102BKL102200"], + ["22CDL1002000", "88BDL1002000", "33ADL1002000", "44BDL1002000"], + ] - for variant, ((seat_numbers, flight_id), expected) in enumerate(zip(test_data, result_data), start=1): - with self.subTest(f"variation #{variant}", seat_numbbers=seat_numbers, - flight_id=flight_id, expected=expected): + for variant, ((seat_numbers, flight_id), expected) in enumerate( + zip(test_data, result_data), start=1 + ): + with self.subTest( + f"variation #{variant}", + seat_numbbers=seat_numbers, + flight_id=flight_id, + expected=expected, + ): actual_result = list(generate_codes(seat_numbers, flight_id)) - error_message = (f'Called generate_codes({seat_numbers}, {flight_id}). ' - f'The function returned {actual_result}, but the tests ' - f'expected {expected} when generating ticket numbers.') + error_message = ( + f"Called generate_codes({seat_numbers}, {flight_id}). " + f"The function returned {actual_result}, but the tests " + f"expected {expected} when generating ticket numbers." + ) # Note: DO NOT call the function here again, in case the student is using list.pop() # to process the input. If another call is done with that condition, diff --git a/exercises/concept/pretty-leaflet/.meta/exemplar.py b/exercises/concept/pretty-leaflet/.meta/exemplar.py index 324946816a5..9f16516a2d4 100644 --- a/exercises/concept/pretty-leaflet/.meta/exemplar.py +++ b/exercises/concept/pretty-leaflet/.meta/exemplar.py @@ -5,39 +5,47 @@ def capitalize_header(event_name: str) -> str: return event_name.capitalize() + def format_date(event_date: List[int]) -> str: date, month, year = event_date month_name = calendar.month_name[month] # pylint: disable=consider-using-f-string - return '{} {}, {}'.format(month_name, date, year) + return "{} {}, {}".format(month_name, date, year) + def display_icons(icons: List[str]) -> List[str]: displayed = [] for icon in icons: # pylint: disable=consider-using-f-string - displayed.append('{}'.format(icon)) + displayed.append("{}".format(icon)) return displayed -def print_leaflet(event_name: str, icons: List[str], authors: List[str], event_date: Optional[List[int]]=None): - row_full = ''.join(['*'] * 20) + +def print_leaflet( + event_name: str, + icons: List[str], + authors: List[str], + event_date: Optional[List[int]] = None, +): + row_full = "".join(["*"] * 20) empty_row = f'*{"":^18}*' event_name = capitalize_header(event_name) icons = display_icons(icons) - date_string = format_date(event_date) if event_date is not None else '' + date_string = format_date(event_date) if event_date is not None else "" poster = [] poster.append(row_full) poster.append(empty_row) - poster.append(f'*{event_name!r:^18}*') + poster.append(f"*{event_name!r:^18}*") poster.append(empty_row) - poster.append(f'*{date_string!s:^18}*') + poster.append(f"*{date_string!s:^18}*") poster.append(empty_row) for position, _ in enumerate(authors): - icon = icons[position] if position < len(icons) else ' ' + icon = icons[position] if position < len(icons) else " " poster.append(f'*{"":>1}{authors[position]:<11}{icon:>3}{"":>2}*') poster.append(empty_row) poster.append(row_full) - return '\n'.join(poster) + return "\n".join(poster) diff --git a/exercises/concept/pretty-leaflet/string_formatting.py b/exercises/concept/pretty-leaflet/string_formatting.py index f7f9c9edab3..b99364abaa1 100644 --- a/exercises/concept/pretty-leaflet/string_formatting.py +++ b/exercises/concept/pretty-leaflet/string_formatting.py @@ -1,11 +1,14 @@ def capitalize_header(event_name): pass + def format_date(event_date): pass + def display_icons(icons): pass + def print_leaflet(event_name, icons, authors, event_date=None): pass diff --git a/exercises/concept/pretty-leaflet/string_formatting_test.py b/exercises/concept/pretty-leaflet/string_formatting_test.py index a06ff9e4a53..bea63681c52 100644 --- a/exercises/concept/pretty-leaflet/string_formatting_test.py +++ b/exercises/concept/pretty-leaflet/string_formatting_test.py @@ -1,39 +1,54 @@ import unittest import pytest -from string_formatting import (capitalize_header, - format_date, - display_icons, - print_leaflet) +from string_formatting import ( + capitalize_header, + format_date, + display_icons, + print_leaflet, +) class PrettyLeafletTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_header(self): - failure_msg = 'Expected an empty header, but the header was not empty.' - self.assertEqual(capitalize_header(''), '', msg=failure_msg) + failure_msg = "Expected an empty header, but the header was not empty." + self.assertEqual(capitalize_header(""), "", msg=failure_msg) @pytest.mark.task(taskno=1) def test_header_event(self): - self.assertEqual(capitalize_header('Event'), 'Event', msg='Expected: "Event" for header.') + self.assertEqual( + capitalize_header("Event"), "Event", msg='Expected: "Event" for header.' + ) @pytest.mark.task(taskno=1) def test_header_event_capitalized(self): - self.assertEqual(capitalize_header('evENt'), 'Event', msg='Expected: "Event" for a capitalized header.') + self.assertEqual( + capitalize_header("evENt"), + "Event", + msg='Expected: "Event" for a capitalized header.', + ) @pytest.mark.task(taskno=2) def test_leaflet_date_day_month_year(self): - self.assertEqual(format_date([21, 2, 2021]), 'February 21, 2021', msg='Expected "February 21, 2021" for date.') + self.assertEqual( + format_date([21, 2, 2021]), + "February 21, 2021", + msg='Expected "February 21, 2021" for date.', + ) @pytest.mark.task(taskno=3) def test_leaflet_method_get_icons_fox_clover_fish(self): - failure_msg = 'Expected an array of three unicode icons: [Fox, Clover, Fish] for the method display_icons().' - self.assertEqual(display_icons(['\U0001F98A', '\U0001F340', '\U0001F420']), ['🦊', '🍀', '🐠'], msg=failure_msg) - + failure_msg = "Expected an array of three unicode icons: [Fox, Clover, Fish] for the method display_icons()." + self.assertEqual( + display_icons(["\U0001f98a", "\U0001f340", "\U0001f420"]), + ["🦊", "🍀", "🐠"], + msg=failure_msg, + ) @pytest.mark.task(taskno=4) def test_print_leaflet_concert(self): - handbill = ('''******************** + handbill = """******************** * * * 'Concert' * * * @@ -43,15 +58,20 @@ def test_print_leaflet_concert(self): * Benjamin 🎤 * * Max 🎹 * * * -********************''') +********************""" - event_info = ('Concert', ['\U0001F3B8', '\U0001F3A4', '\U0001F3B9'], ['John', 'Benjamin', 'Max'],[30, 4, 2021]) - failure_msg = 'Expected a leaflet for Concert with a partial date, three artists and three icons.' + event_info = ( + "Concert", + ["\U0001f3b8", "\U0001f3a4", "\U0001f3b9"], + ["John", "Benjamin", "Max"], + [30, 4, 2021], + ) + failure_msg = "Expected a leaflet for Concert with a partial date, three artists and three icons." self.assertEqual(print_leaflet(*event_info), handbill, msg=failure_msg) @pytest.mark.task(taskno=4) def test_print_leaflet_teather_empty_date_and_missing_icon(self): - handbill = ('''******************** + handbill = """******************** * * * 'Macbeth' * * * @@ -60,15 +80,15 @@ def test_print_leaflet_teather_empty_date_and_missing_icon(self): * Fleance 🌘 * * Seyton * * * -********************''') +********************""" - event_info = ('macbeth',['\U0001F318'],['Fleance', 'Seyton']) - failure_msg = 'Expected a leaflet for Macbeth with two artists and one icon but without date.' - self.assertEqual(print_leaflet(*event_info), handbill,msg=failure_msg) + event_info = ("macbeth", ["\U0001f318"], ["Fleance", "Seyton"]) + failure_msg = "Expected a leaflet for Macbeth with two artists and one icon but without date." + self.assertEqual(print_leaflet(*event_info), handbill, msg=failure_msg) @pytest.mark.task(taskno=4) def test_print_leaflet_webinar(self): - handbill = ('''******************** + handbill = """******************** * * * 'Webinar' * * * @@ -78,8 +98,13 @@ def test_print_leaflet_webinar(self): * Chris 💻 * * Leo 🎯 * * * -********************''') +********************""" - event_info = ('webinar',['\U0001F4DA', '\U0001F4BB', '\U0001F3AF'],['Vince', 'Chris', 'Leo'],[29, 1, 2020]) - failure_msg = 'Expected a leaflet for Webinar with a complete date, with three artists and icons.' + event_info = ( + "webinar", + ["\U0001f4da", "\U0001f4bb", "\U0001f3af"], + ["Vince", "Chris", "Leo"], + [29, 1, 2020], + ) + failure_msg = "Expected a leaflet for Webinar with a complete date, with three artists and icons." self.assertEqual(print_leaflet(*event_info), handbill, msg=failure_msg) diff --git a/exercises/concept/restaurant-rozalynn/none_test.py b/exercises/concept/restaurant-rozalynn/none_test.py index 9f985d05221..2ed3a04a2db 100644 --- a/exercises/concept/restaurant-rozalynn/none_test.py +++ b/exercises/concept/restaurant-rozalynn/none_test.py @@ -6,123 +6,284 @@ find_all_available_seats, current_empty_seat_capacity, accommodate_waiting_guests, - empty_seats) + empty_seats, +) class RestaurantRozalynnTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_new_seating_chart_1(self): - failure_message='The New Seating chart does not match with the expected.' - self.assertDictEqual(new_seating_chart(3), {1: None, 2: None, 3: None}, msg=failure_message) + failure_message = "The New Seating chart does not match with the expected." + self.assertDictEqual( + new_seating_chart(3), {1: None, 2: None, 3: None}, msg=failure_message + ) @pytest.mark.task(taskno=1) def test_new_seating_chart_2(self): - expected_results = {1: None, 2: None, 3: None, 4: None, 5: None, 6: None, 7: None, 8: None, 9: None, 10: None, - 11: None, 12: None, 13: None, 14: None, 15: None, 16: None, 17: None, 18: None, 19: None, - 20: None, 21: None, 22: None} - failure_msg = 'The New Seating chart does not match with the expected.' + expected_results = { + 1: None, + 2: None, + 3: None, + 4: None, + 5: None, + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: None, + 19: None, + 20: None, + 21: None, + 22: None, + } + failure_msg = "The New Seating chart does not match with the expected." self.assertDictEqual(new_seating_chart(), expected_results, msg=failure_msg) @pytest.mark.task(taskno=2) def test_arrange_reservations_1(self): - guests = ['Walter', 'Frank', 'Jenny', 'Carol', 'Alice', 'George'] - expected_results = {1: 'Frank', 2: 'Jenny', 3: 'Carol', 4: 'Alice', 5: 'George', - 6: None, 7: None, 8: None, 9: None, 10: None, - 11: None, 12: None, 13: None, 14: None, 15: None, - 16: None, 17: None, 18: None, 19: None, 20: None, 21: None, 22: None} - failure_msg = 'The reservation dict is incorrect' - - self.assertDictEqual(arrange_reservations(guests), expected_results, msg=failure_msg) + guests = ["Walter", "Frank", "Jenny", "Carol", "Alice", "George"] + expected_results = { + 1: "Frank", + 2: "Jenny", + 3: "Carol", + 4: "Alice", + 5: "George", + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: None, + 19: None, + 20: None, + 21: None, + 22: None, + } + failure_msg = "The reservation dict is incorrect" + + self.assertDictEqual( + arrange_reservations(guests), expected_results, msg=failure_msg + ) @pytest.mark.task(taskno=2) def test_arrange_reservations_2(self): - expected_result = {1: None, 2: None, 3: None, 4: None, 5: None, 6: None, 7: None, 8: None, 9: None, - 10: None, 11: None, 12: None, 13: None, 14: None, 15: None, 16: None, 17: None, - 18: None,19: None, 20: None, 21: None, 22: None} - - failure_msg = 'The reservation dict is incorrect' + expected_result = { + 1: None, + 2: None, + 3: None, + 4: None, + 5: None, + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: None, + 19: None, + 20: None, + 21: None, + 22: None, + } + + failure_msg = "The reservation dict is incorrect" # pylint: disable= no-value-for-parameter self.assertDictEqual(arrange_reservations(), expected_result, failure_msg) @pytest.mark.task(taskno=3) def test_find_all_available_seats_1(self): - seats={1: None, 2: 'Frank', 3: 'Jenny', 4: None, 5: 'Alice', 6: 'George', 7: None, 8: 'Carol', - 9: None, 10: None, 11: None, 12: 'Walter'} + seats = { + 1: None, + 2: "Frank", + 3: "Jenny", + 4: None, + 5: "Alice", + 6: "George", + 7: None, + 8: "Carol", + 9: None, + 10: None, + 11: None, + 12: "Walter", + } expected_results = [1, 4, 7, 9, 10, 11] - failure_msg = 'The Available Seat list is incorrect' + failure_msg = "The Available Seat list is incorrect" - self.assertListEqual(find_all_available_seats(seats), expected_results, msg=failure_msg) + self.assertListEqual( + find_all_available_seats(seats), expected_results, msg=failure_msg + ) @pytest.mark.task(taskno=3) def test_find_all_available_seats_2(self): - seats={1: None, 2: None, 3: None, 4: None, 5: 'Alice', 6: None, 7: None, - 8: None, 9: None, 10: None, 11: None, 12: None} + seats = { + 1: None, + 2: None, + 3: None, + 4: None, + 5: "Alice", + 6: None, + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + } expected_results = [1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12] - failure_msg = 'The Available Seat list is incorrect' + failure_msg = "The Available Seat list is incorrect" - self.assertListEqual(find_all_available_seats(seats), expected_results, failure_msg) + self.assertListEqual( + find_all_available_seats(seats), expected_results, failure_msg + ) @pytest.mark.task(taskno=4) def test_current_empty_seat_capacity_1(self): - failure_msg = 'the index of the seat which is empty is invalid.' + failure_msg = "the index of the seat which is empty is invalid." - self.assertIs(current_empty_seat_capacity({1: 'Occupied', 2: None, 3: 'Occupied'}), 1, msg=failure_msg) + self.assertIs( + current_empty_seat_capacity({1: "Occupied", 2: None, 3: "Occupied"}), + 1, + msg=failure_msg, + ) @pytest.mark.task(taskno=4) def test_current_empty_seat_capacity_2(self): - seats = {1: 'Occupied', 2: 'Occupied', 3: None, 4: 'Occupied', 5: None} - failure_msg = 'the index of the seat which is empty is invalid.' + seats = {1: "Occupied", 2: "Occupied", 3: None, 4: "Occupied", 5: None} + failure_msg = "the index of the seat which is empty is invalid." self.assertIs(current_empty_seat_capacity(seats), 2, msg=failure_msg) @pytest.mark.task(taskno=5) def test_accommodate_waiting_guests_1(self): - reservations = {1: 'Carol', 2: 'Alice', 3: 'George', 4: None, - 5: None, 6: None, 7: 'Frank',8: 'Walter'} - - guests = ['Mort', 'Suze', 'Phillip', 'Tony'] - - failure_msg = 'The Accommodation of waiting guests are incorrect' - self.assertDictEqual(accommodate_waiting_guests(reservations,guests), reservations, msg=failure_msg) + reservations = { + 1: "Carol", + 2: "Alice", + 3: "George", + 4: None, + 5: None, + 6: None, + 7: "Frank", + 8: "Walter", + } + + guests = ["Mort", "Suze", "Phillip", "Tony"] + + failure_msg = "The Accommodation of waiting guests are incorrect" + self.assertDictEqual( + accommodate_waiting_guests(reservations, guests), + reservations, + msg=failure_msg, + ) @pytest.mark.task(taskno=5) def test_accommodate_waiting_guests_2(self): - reservations = {1: None, 2: None, 3: None, 4: 'Carol', 5: 'Alice', 6: 'George', 7: None, 8: None, - 9: None, 10: None, 11: None, 12: None, 13: None, 14: None, 15: None, 16: None, - 17: None, 18: 'Frank', 19: 'Jenny', 20: None, 21: None, 22: 'Walter'} - - guests = ['Mort', 'Suze', 'Phillip', 'Tony'] - - expected_results = {1: 'Mort', 2: 'Suze', 3: 'Phillip', 4: 'Carol', 5: 'Alice', 6: 'George', - 7: 'Tony', 8: None, 9: None, 10: None, 11: None, 12: None, 13: None, 14: None, - 15: None, 16: None, 17: None, 18: 'Frank', 19: 'Jenny', 20: None, 21: None, 22: 'Walter'} - - failure_msg = 'The Accommodation of waiting guests are incorrect' - - self.assertDictEqual(accommodate_waiting_guests(reservations, guests), expected_results, msg=failure_msg) + reservations = { + 1: None, + 2: None, + 3: None, + 4: "Carol", + 5: "Alice", + 6: "George", + 7: None, + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: "Frank", + 19: "Jenny", + 20: None, + 21: None, + 22: "Walter", + } + + guests = ["Mort", "Suze", "Phillip", "Tony"] + + expected_results = { + 1: "Mort", + 2: "Suze", + 3: "Phillip", + 4: "Carol", + 5: "Alice", + 6: "George", + 7: "Tony", + 8: None, + 9: None, + 10: None, + 11: None, + 12: None, + 13: None, + 14: None, + 15: None, + 16: None, + 17: None, + 18: "Frank", + 19: "Jenny", + 20: None, + 21: None, + 22: "Walter", + } + + failure_msg = "The Accommodation of waiting guests are incorrect" + + self.assertDictEqual( + accommodate_waiting_guests(reservations, guests), + expected_results, + msg=failure_msg, + ) @pytest.mark.task(taskno=6) def test_empty_seats_1(self): - seats = {1: 'Alice', 2: None, 3: 'Bob', 4: 'George', 5: 'Gloria'} + seats = {1: "Alice", 2: None, 3: "Bob", 4: "George", 5: "Gloria"} seat_numbers = [5, 3, 1] - expected_results = {1: None, 2: None, 3: None, 4: 'George', 5: None} + expected_results = {1: None, 2: None, 3: None, 4: "George", 5: None} - failure_msg = 'Seats are not emptied properly' - self.assertDictEqual(empty_seats(seats, seat_numbers), expected_results, msg=failure_msg) + failure_msg = "Seats are not emptied properly" + self.assertDictEqual( + empty_seats(seats, seat_numbers), expected_results, msg=failure_msg + ) @pytest.mark.task(taskno=6) def test_empty_seats_2(self): - seats = {1: 'Alice', 2: None, 3: 'Bob', 4: 'George', 5: 'Gloria'} + seats = {1: "Alice", 2: None, 3: "Bob", 4: "George", 5: "Gloria"} seat_numbers = [] - expected_results = {1: 'Alice', 2: None, 3: 'Bob', 4: 'George', 5: 'Gloria'} - failure_msg = 'Seats are not emptied properly' + expected_results = {1: "Alice", 2: None, 3: "Bob", 4: "George", 5: "Gloria"} + failure_msg = "Seats are not emptied properly" - self.assertDictEqual(empty_seats(seats, seat_numbers), expected_results, msg=failure_msg) + self.assertDictEqual( + empty_seats(seats, seat_numbers), expected_results, msg=failure_msg + ) diff --git a/exercises/concept/tisbury-treasure-hunt/tuples_test.py b/exercises/concept/tisbury-treasure-hunt/tuples_test.py index 6bd8a50c56b..6201ebdb3fb 100644 --- a/exercises/concept/tisbury-treasure-hunt/tuples_test.py +++ b/exercises/concept/tisbury-treasure-hunt/tuples_test.py @@ -1,146 +1,270 @@ import unittest import pytest -from tuples import (get_coordinate, - convert_coordinate, - compare_records, - create_record, - clean_up) +from tuples import ( + get_coordinate, + convert_coordinate, + compare_records, + create_record, + clean_up, +) class TisburyTreasureTest(unittest.TestCase): @pytest.mark.task(taskno=1) def test_get_coordinate(self): - input_data = [('Scrimshawed Whale Tooth', '2A'), - ('Brass Spyglass', '4B'), - ('Robot Parrot', '1C'), - ('Glass Starfish', '6D'), - ('Vintage Pirate Hat', '7E'), - ('Pirate Flag', '7F'), - ('Crystal Crab', '6A'), - ('Model Ship in Large Bottle', '8A'), - ('Angry Monkey Figurine', '5B'), - ('Carved Wooden Elephant', '8C'), - ('Amethyst Octopus', '1F'), - ('Antique Glass Fishnet Float', '3D'), - ('Silver Seahorse', '4E')] - - result_data = ['2A', '4B', '1C', '6D', '7E', '7F', '6A', '8A', '5B', '8C', '1F', '3D', '4E'] - - for variant, (item, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', item=item, expected=expected): + input_data = [ + ("Scrimshawed Whale Tooth", "2A"), + ("Brass Spyglass", "4B"), + ("Robot Parrot", "1C"), + ("Glass Starfish", "6D"), + ("Vintage Pirate Hat", "7E"), + ("Pirate Flag", "7F"), + ("Crystal Crab", "6A"), + ("Model Ship in Large Bottle", "8A"), + ("Angry Monkey Figurine", "5B"), + ("Carved Wooden Elephant", "8C"), + ("Amethyst Octopus", "1F"), + ("Antique Glass Fishnet Float", "3D"), + ("Silver Seahorse", "4E"), + ] + + result_data = [ + "2A", + "4B", + "1C", + "6D", + "7E", + "7F", + "6A", + "8A", + "5B", + "8C", + "1F", + "3D", + "4E", + ] + + for variant, (item, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", item=item, expected=expected): actual_result = get_coordinate(item) - error_message = (f'Called get_coordinate({item}). ' - f'The function returned "{actual_result}", but ' - f'the tests expected "{expected}" as the coordinates.') + error_message = ( + f"Called get_coordinate({item}). " + f'The function returned "{actual_result}", but ' + f'the tests expected "{expected}" as the coordinates.' + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=2) def test_convert_coordinate(self): - input_data = ['2A', '4B', '1C', '6D', '7E', '7F', - '6A', '8A', '5B', '8C', '1F', '3D', '4E'] - result_data = [('2', 'A'), - ('4', 'B'), - ('1', 'C'), - ('6', 'D'), - ('7', 'E'), - ('7', 'F'), - ('6', 'A'), - ('8', 'A'), - ('5', 'B'), - ('8', 'C'), - ('1', 'F'), - ('3', 'D'), - ('4', 'E')] - - for variant, (item, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', item=item, expected=expected): + input_data = [ + "2A", + "4B", + "1C", + "6D", + "7E", + "7F", + "6A", + "8A", + "5B", + "8C", + "1F", + "3D", + "4E", + ] + result_data = [ + ("2", "A"), + ("4", "B"), + ("1", "C"), + ("6", "D"), + ("7", "E"), + ("7", "F"), + ("6", "A"), + ("8", "A"), + ("5", "B"), + ("8", "C"), + ("1", "F"), + ("3", "D"), + ("4", "E"), + ] + + for variant, (item, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", item=item, expected=expected): actual_result = convert_coordinate(item) - error_message = (f'Called convert_coordinate({item}). ' - f'The function returned {actual_result}, but the ' - f'tests expected {expected} as the converted coordinate.') + error_message = ( + f"Called convert_coordinate({item}). " + f"The function returned {actual_result}, but the " + f"tests expected {expected} as the converted coordinate." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=3) def test_compare_records(self): input_data = [ - (('Scrimshawed Whale Tooth', '2A'), ('Deserted Docks', ('2', 'A'), 'Blue')), - (('Brass Spyglass', '4B'), ('Abandoned Lighthouse', ('4', 'B'), 'Blue')), - (('Robot Parrot', '1C'), ('Seaside Cottages', ('1', 'C'), 'Blue')), - (('Glass Starfish', '6D'), ('Tangled Seaweed Patch', ('6', 'D'), 'Orange')), - (('Vintage Pirate Hat', '7E'), ('Quiet Inlet (Island of Mystery)', ('7', 'E'), 'Orange')), - (('Amethyst Octopus', '1F'), ('Seaside Cottages', ('1', 'C'), 'Blue')), - (('Angry Monkey Figurine', '5B'), ('Aqua Lagoon (Island of Mystery)', ('1', 'F'), 'Yellow')), - (('Antique Glass Fishnet Float', '3D'), ('Deserted Docks', ('2', 'A'), 'Blue')), - (('Brass Spyglass', '4B'), ('Spiky Rocks', ('3', 'D'), 'Yellow')), - (('Carved Wooden Elephant', '8C'), ('Abandoned Lighthouse', ('4', 'B'), 'Blue')) + (("Scrimshawed Whale Tooth", "2A"), ("Deserted Docks", ("2", "A"), "Blue")), + (("Brass Spyglass", "4B"), ("Abandoned Lighthouse", ("4", "B"), "Blue")), + (("Robot Parrot", "1C"), ("Seaside Cottages", ("1", "C"), "Blue")), + (("Glass Starfish", "6D"), ("Tangled Seaweed Patch", ("6", "D"), "Orange")), + ( + ("Vintage Pirate Hat", "7E"), + ("Quiet Inlet (Island of Mystery)", ("7", "E"), "Orange"), + ), + (("Amethyst Octopus", "1F"), ("Seaside Cottages", ("1", "C"), "Blue")), + ( + ("Angry Monkey Figurine", "5B"), + ("Aqua Lagoon (Island of Mystery)", ("1", "F"), "Yellow"), + ), + ( + ("Antique Glass Fishnet Float", "3D"), + ("Deserted Docks", ("2", "A"), "Blue"), + ), + (("Brass Spyglass", "4B"), ("Spiky Rocks", ("3", "D"), "Yellow")), + ( + ("Carved Wooden Elephant", "8C"), + ("Abandoned Lighthouse", ("4", "B"), "Blue"), + ), ] result_data = [True, True, True, True, True, False, False, False, False, False] - for variant, (item, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', item=item, expected=expected): + for variant, (item, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", item=item, expected=expected): actual_result = compare_records(item[0], item[1]) - error_message = (f'Called compare_records({item[0]}, {item[1]}). ' - f'The function returned {actual_result}, but the ' - f'tests expected {expected}.') + error_message = ( + f"Called compare_records({item[0]}, {item[1]}). " + f"The function returned {actual_result}, but the " + f"tests expected {expected}." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=4) def test_create_record(self): input_data = [ - (('Angry Monkey Figurine', '5B'), ('Stormy Breakwater', ('5', 'B'), 'Purple')), - (('Carved Wooden Elephant', '8C'), ('Foggy Seacave', ('8', 'C'), 'Purple')), - (('Amethyst Octopus', '1F'), ('Aqua Lagoon (Island of Mystery)', ('1', 'F'), 'Yellow')), - (('Antique Glass Fishnet Float', '3D'), ('Spiky Rocks', ('3', 'D'), 'Yellow')), - (('Silver Seahorse', '4E'), ('Hidden Spring (Island of Mystery)', ('4', 'E'), 'Yellow')), - (('Amethyst Octopus', '1F'), ('Seaside Cottages', ('1', 'C'), 'Blue')), - (('Angry Monkey Figurine', '5B'), ('Aqua Lagoon (Island of Mystery)', ('1', 'F'), 'Yellow')), - (('Antique Glass Fishnet Float', '3D'), ('Deserted Docks', ('2', 'A'), 'Blue')), - (('Brass Spyglass', '4B'), ('Spiky Rocks', ('3', 'D'), 'Yellow')), - (('Carved Wooden Elephant', '8C'), ('Abandoned Lighthouse', ('4', 'B'), 'Blue')) + ( + ("Angry Monkey Figurine", "5B"), + ("Stormy Breakwater", ("5", "B"), "Purple"), + ), + (("Carved Wooden Elephant", "8C"), ("Foggy Seacave", ("8", "C"), "Purple")), + ( + ("Amethyst Octopus", "1F"), + ("Aqua Lagoon (Island of Mystery)", ("1", "F"), "Yellow"), + ), + ( + ("Antique Glass Fishnet Float", "3D"), + ("Spiky Rocks", ("3", "D"), "Yellow"), + ), + ( + ("Silver Seahorse", "4E"), + ("Hidden Spring (Island of Mystery)", ("4", "E"), "Yellow"), + ), + (("Amethyst Octopus", "1F"), ("Seaside Cottages", ("1", "C"), "Blue")), + ( + ("Angry Monkey Figurine", "5B"), + ("Aqua Lagoon (Island of Mystery)", ("1", "F"), "Yellow"), + ), + ( + ("Antique Glass Fishnet Float", "3D"), + ("Deserted Docks", ("2", "A"), "Blue"), + ), + (("Brass Spyglass", "4B"), ("Spiky Rocks", ("3", "D"), "Yellow")), + ( + ("Carved Wooden Elephant", "8C"), + ("Abandoned Lighthouse", ("4", "B"), "Blue"), + ), ] result_data = [ - ('Angry Monkey Figurine', '5B', 'Stormy Breakwater', ('5', 'B'), 'Purple'), - ('Carved Wooden Elephant', '8C', 'Foggy Seacave', ('8', 'C'), 'Purple'), - ('Amethyst Octopus', '1F', 'Aqua Lagoon (Island of Mystery)', ('1', 'F'), 'Yellow'), - ('Antique Glass Fishnet Float', '3D', 'Spiky Rocks', ('3', 'D'), 'Yellow'), - ('Silver Seahorse', '4E', 'Hidden Spring (Island of Mystery)', ('4', 'E'), 'Yellow'), - 'not a match', - 'not a match', - 'not a match', - 'not a match', - 'not a match' + ("Angry Monkey Figurine", "5B", "Stormy Breakwater", ("5", "B"), "Purple"), + ("Carved Wooden Elephant", "8C", "Foggy Seacave", ("8", "C"), "Purple"), + ( + "Amethyst Octopus", + "1F", + "Aqua Lagoon (Island of Mystery)", + ("1", "F"), + "Yellow", + ), + ("Antique Glass Fishnet Float", "3D", "Spiky Rocks", ("3", "D"), "Yellow"), + ( + "Silver Seahorse", + "4E", + "Hidden Spring (Island of Mystery)", + ("4", "E"), + "Yellow", + ), + "not a match", + "not a match", + "not a match", + "not a match", + "not a match", ] - for variant, (item, expected) in enumerate(zip(input_data, result_data), start=1): - with self.subTest(f'variation #{variant}', item=item, expected=expected): + for variant, (item, expected) in enumerate( + zip(input_data, result_data), start=1 + ): + with self.subTest(f"variation #{variant}", item=item, expected=expected): actual_result = create_record(item[0], item[1]) - error_message = (f'Called create_record({item[0]},{item[1]}). ' - f'The function returned ' - f'{actual_result}, but the tests expected ' - f'{expected} for the record.') + error_message = ( + f"Called create_record({item[0]},{item[1]}). " + f"The function returned " + f"{actual_result}, but the tests expected " + f"{expected} for the record." + ) self.assertEqual(actual_result, expected, msg=error_message) @pytest.mark.task(taskno=5) def test_clean_up(self): input_data = ( - ('Scrimshawed Whale Tooth', '2A', 'Deserted Docks', ('2', 'A'), 'Blue'), - ('Brass Spyglass', '4B', 'Abandoned Lighthouse', ('4', 'B'), 'Blue'), - ('Robot Parrot', '1C', 'Seaside Cottages', ('1', 'C'), 'Blue'), - ('Glass Starfish', '6D', 'Tangled Seaweed Patch', ('6', 'D'), 'Orange'), - ('Vintage Pirate Hat', '7E', 'Quiet Inlet (Island of Mystery)', ('7', 'E'), 'Orange'), - ('Pirate Flag', '7F', 'Windswept Hilltop (Island of Mystery)', ('7', 'F'), 'Orange'), - ('Crystal Crab', '6A', 'Old Schooner', ('6', 'A'), 'Purple'), - ('Model Ship in Large Bottle', '8A', 'Harbor Managers Office', ('8', 'A'), 'Purple'), - ('Angry Monkey Figurine', '5B', 'Stormy Breakwater', ('5', 'B'), 'Purple'), - ('Carved Wooden Elephant', '8C', 'Foggy Seacave', ('8', 'C'), 'Purple'), - ('Amethyst Octopus', '1F', 'Aqua Lagoon (Island of Mystery)', ('1', 'F'), 'Yellow'), - ('Antique Glass Fishnet Float', '3D', 'Spiky Rocks', ('3', 'D'), 'Yellow'), - ('Silver Seahorse', '4E', 'Hidden Spring (Island of Mystery)', ('4', 'E'), 'Yellow') + ("Scrimshawed Whale Tooth", "2A", "Deserted Docks", ("2", "A"), "Blue"), + ("Brass Spyglass", "4B", "Abandoned Lighthouse", ("4", "B"), "Blue"), + ("Robot Parrot", "1C", "Seaside Cottages", ("1", "C"), "Blue"), + ("Glass Starfish", "6D", "Tangled Seaweed Patch", ("6", "D"), "Orange"), + ( + "Vintage Pirate Hat", + "7E", + "Quiet Inlet (Island of Mystery)", + ("7", "E"), + "Orange", + ), + ( + "Pirate Flag", + "7F", + "Windswept Hilltop (Island of Mystery)", + ("7", "F"), + "Orange", + ), + ("Crystal Crab", "6A", "Old Schooner", ("6", "A"), "Purple"), + ( + "Model Ship in Large Bottle", + "8A", + "Harbor Managers Office", + ("8", "A"), + "Purple", + ), + ("Angry Monkey Figurine", "5B", "Stormy Breakwater", ("5", "B"), "Purple"), + ("Carved Wooden Elephant", "8C", "Foggy Seacave", ("8", "C"), "Purple"), + ( + "Amethyst Octopus", + "1F", + "Aqua Lagoon (Island of Mystery)", + ("1", "F"), + "Yellow", + ), + ("Antique Glass Fishnet Float", "3D", "Spiky Rocks", ("3", "D"), "Yellow"), + ( + "Silver Seahorse", + "4E", + "Hidden Spring (Island of Mystery)", + ("4", "E"), + "Yellow", + ), ) result_data = """('Scrimshawed Whale Tooth', 'Deserted Docks', ('2', 'A'), 'Blue')\n\ diff --git a/exercises/practice/accumulate/accumulate_test.py b/exercises/practice/accumulate/accumulate_test.py index a49be036d08..08372a6bc7f 100644 --- a/exercises/practice/accumulate/accumulate_test.py +++ b/exercises/practice/accumulate/accumulate_test.py @@ -9,31 +9,33 @@ def test_empty_sequence(self): def test_pow(self): self.assertEqual( - accumulate([1, 2, 3, 4, 5], lambda x: x * x), [1, 4, 9, 16, 25]) + accumulate([1, 2, 3, 4, 5], lambda x: x * x), [1, 4, 9, 16, 25] + ) def test_divmod(self): self.assertEqual( - accumulate([10, 17, 23], lambda x: divmod(x, 7)), - [(1, 3), (2, 3), (3, 2)]) + accumulate([10, 17, 23], lambda x: divmod(x, 7)), [(1, 3), (2, 3), (3, 2)] + ) def test_composition(self): inp = [10, 17, 23] self.assertEqual( accumulate( - accumulate(inp, lambda x: divmod(x, 7)), - lambda x: 7 * x[0] + x[1]), inp) + accumulate(inp, lambda x: divmod(x, 7)), lambda x: 7 * x[0] + x[1] + ), + inp, + ) def test_capitalize(self): - self.assertEqual( - accumulate(['hello', 'world'], str.upper), ['HELLO', 'WORLD']) + self.assertEqual(accumulate(["hello", "world"], str.upper), ["HELLO", "WORLD"]) def test_recursive(self): - inp = ['a', 'b', 'c'] - out = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3'], ['c1', 'c2', 'c3']] + inp = ["a", "b", "c"] + out = [["a1", "a2", "a3"], ["b1", "b2", "b3"], ["c1", "c2", "c3"]] self.assertEqual( - accumulate( - inp, lambda x: accumulate(list('123'), lambda y: x + y)), out) + accumulate(inp, lambda x: accumulate(list("123"), lambda y: x + y)), out + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/acronym/.articles/performance/code/Benchmark.py b/exercises/practice/acronym/.articles/performance/code/Benchmark.py index 44ae8db7b24..bc163537e36 100644 --- a/exercises/practice/acronym/.articles/performance/code/Benchmark.py +++ b/exercises/practice/acronym/.articles/performance/code/Benchmark.py @@ -20,17 +20,17 @@ # ------------ FUNCTIONS TO TIME ------------- # def abbreviate_list_comprehension(to_abbreviate): phrase = to_abbreviate.replace("_", " ").replace("-", " ").upper().split() - return ''.join([word[0] for word in phrase]) + return "".join([word[0] for word in phrase]) def abbreviate_genex(to_abbreviate): phrase = to_abbreviate.replace("_", " ").replace("-", " ").upper().split() letters = (word[0] for word in phrase) - return ''.join(letters) + return "".join(letters) def abbreviate_loop(to_abbreviate): - phrase = to_abbreviate.replace('-', ' ').replace("_", " ").upper().split() + phrase = to_abbreviate.replace("-", " ").replace("_", " ").upper().split() acronym = "" for word in phrase: @@ -42,7 +42,7 @@ def abbreviate_loop(to_abbreviate): def abbreviate_map(to_abbreviate): phrase = to_abbreviate.replace("_", " ").replace("-", " ").upper().split() - return ''.join(map(lambda word: word[0], phrase)) + return "".join(map(lambda word: word[0], phrase)) def abbreviate_reduce(to_abbreviate): @@ -53,12 +53,13 @@ def abbreviate_reduce(to_abbreviate): def abbreviate_regex_join(phrase): removed = re.findall(r"[a-zA-Z']+", phrase) - return ''.join(word[0] for word in removed).upper() + return "".join(word[0] for word in removed).upper() def abbreviate_finditer_join(to_abbreviate): - return ''.join(word[0][0] for word in - re.finditer(r"[a-zA-Z']+", to_abbreviate)).upper() + return "".join( + word[0][0] for word in re.finditer(r"[a-zA-Z']+", to_abbreviate) + ).upper() def abbreviate_regex_sub(to_abbreviate): @@ -67,7 +68,7 @@ def abbreviate_regex_sub(to_abbreviate): def abbreviate_regex_findall(to_abbreviate): - return ''.join(re.findall(r"(? self.balance: - raise ValueError('amount must be less than balance') + raise ValueError("amount must be less than balance") self.balance -= amount def close(self): if not self.is_open: - raise ValueError('account not open') + raise ValueError("account not open") self.is_open = False diff --git a/exercises/practice/beer-song/.meta/example.py b/exercises/practice/beer-song/.meta/example.py index 4dfa8ea0296..da434c5a0ed 100644 --- a/exercises/practice/beer-song/.meta/example.py +++ b/exercises/practice/beer-song/.meta/example.py @@ -3,35 +3,35 @@ def recite(start, take=1): for idx in range(start, start - take, -1): results.extend(verse(idx)) if idx > start - take + 1: - results.append('') + results.append("") return results def verse(number): return [ - f'{_bottles(number).capitalize()} of beer on the wall, {_bottles(number)} of beer.', - f'{_action(number)}{_next_bottle(number)}' + f"{_bottles(number).capitalize()} of beer on the wall, {_bottles(number)} of beer.", + f"{_action(number)}{_next_bottle(number)}", ] def _action(current_verse): if current_verse == 0: - return 'Go to the store and buy some more, ' + return "Go to the store and buy some more, " else: return f'Take {"one" if current_verse > 1 else "it"} down and pass it around, ' def _next_bottle(current_verse): - return f'{_bottles(_next_verse(current_verse))} of beer on the wall.' + return f"{_bottles(_next_verse(current_verse))} of beer on the wall." def _bottles(number): if number == 0: - return 'no more bottles' + return "no more bottles" if number == 1: - return '1 bottle' + return "1 bottle" else: - return f'{number} bottles' + return f"{number} bottles" def _next_verse(current_verse): diff --git a/exercises/practice/binary-search-tree/.meta/example.py b/exercises/practice/binary-search-tree/.meta/example.py index fede54dd61c..ddcd494bca4 100644 --- a/exercises/practice/binary-search-tree/.meta/example.py +++ b/exercises/practice/binary-search-tree/.meta/example.py @@ -5,7 +5,7 @@ def __init__(self, data, left=None, right=None): self.right = right def __str__(self): - return f'TreeNode(data={self.data}, left={self.left}, right={self.right})' + return f"TreeNode(data={self.data}, left={self.left}, right={self.right})" class BinarySearchTree: diff --git a/exercises/practice/binary-search-tree/binary_search_tree.py b/exercises/practice/binary-search-tree/binary_search_tree.py index afca5d44ec2..59d731f64bb 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree.py +++ b/exercises/practice/binary-search-tree/binary_search_tree.py @@ -5,7 +5,7 @@ def __init__(self, data, left=None, right=None): self.right = None def __str__(self): - return f'TreeNode(data={self.data}, left={self.left}, right={self.right})' + return f"TreeNode(data={self.data}, left={self.left}, right={self.right})" class BinarySearchTree: diff --git a/exercises/practice/binary-search/.meta/example.py b/exercises/practice/binary-search/.meta/example.py index 0bd7be2cbb9..c5fd05879ee 100644 --- a/exercises/practice/binary-search/.meta/example.py +++ b/exercises/practice/binary-search/.meta/example.py @@ -9,4 +9,4 @@ def find(search_list, value): low = middle + 1 else: return middle - raise ValueError('value not in array') + raise ValueError("value not in array") diff --git a/exercises/practice/binary/.meta/example.py b/exercises/practice/binary/.meta/example.py index 364669062a5..77fd60814ec 100644 --- a/exercises/practice/binary/.meta/example.py +++ b/exercises/practice/binary/.meta/example.py @@ -1,5 +1,4 @@ def parse_binary(digits): - if set(digits) - set('01'): - raise ValueError('Invalid binary literal: ' + digits) - return sum(int(digit) * 2 ** idx - for (idx, digit) in enumerate(reversed(digits))) + if set(digits) - set("01"): + raise ValueError("Invalid binary literal: " + digits) + return sum(int(digit) * 2**idx for (idx, digit) in enumerate(reversed(digits))) diff --git a/exercises/practice/binary/binary_test.py b/exercises/practice/binary/binary_test.py index de7fa2dfd88..a8205a6ca1d 100644 --- a/exercises/practice/binary/binary_test.py +++ b/exercises/practice/binary/binary_test.py @@ -4,6 +4,7 @@ If the argument to parse_binary isn't a valid binary number the function should raise a ValueError with a meaningful error message. """ + import unittest from binary import parse_binary @@ -55,5 +56,6 @@ def test_invalid_binary_text_with_numbers(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "Invalid binary literal: nope10") -if __name__ == '__main__': + +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/bob/.articles/performance/code/Benchmark.py b/exercises/practice/bob/.articles/performance/code/Benchmark.py index 3e5a011fcbc..845b592e1a1 100644 --- a/exercises/practice/bob/.articles/performance/code/Benchmark.py +++ b/exercises/practice/bob/.articles/performance/code/Benchmark.py @@ -2,8 +2,10 @@ loops = 1_000_000 -val = timeit.timeit("""response("I really don't have anything to say.")""", - """ +val = ( + timeit.timeit( + """response("I really don't have anything to say.")""", + """ def response(hey_bob): hey_bob = hey_bob.rstrip() if not hey_bob: @@ -18,13 +20,19 @@ def response(hey_bob): return 'Sure.' return 'Whatever.' -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"if statements: {val}") -val = timeit.timeit("""response("I really don't have anything to say.")""", - """ +val = ( + timeit.timeit( + """response("I really don't have anything to say.")""", + """ def response(hey_bob): hey_bob = hey_bob.rstrip() if not hey_bob: @@ -39,12 +47,18 @@ def response(hey_bob): return 'Sure.' return 'Whatever.' -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"if statements nested: {val}") -val = timeit.timeit("""response("I really don't have anything to say.")""", - """ +val = ( + timeit.timeit( + """response("I really don't have anything to say.")""", + """ ANSWERS = ['Whatever.', 'Sure.', 'Whoa, chill out!', "Calm down, I know what I'm doing!"] @@ -59,6 +73,10 @@ def response(hey_bob): return ANSWERS[is_shout + is_question] -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"answer list: {val}") diff --git a/exercises/practice/bob/.meta/example.py b/exercises/practice/bob/.meta/example.py index 630ccccc613..5f9b0274a2d 100644 --- a/exercises/practice/bob/.meta/example.py +++ b/exercises/practice/bob/.meta/example.py @@ -2,20 +2,20 @@ def response(hey_bob): hey_bob = hey_bob.strip() if _is_silence(hey_bob): - return 'Fine. Be that way!' + return "Fine. Be that way!" if _is_shouting(hey_bob): if _is_question(hey_bob): return "Calm down, I know what I'm doing!" else: - return 'Whoa, chill out!' + return "Whoa, chill out!" elif _is_question(hey_bob): - return 'Sure.' + return "Sure." else: - return 'Whatever.' + return "Whatever." def _is_silence(hey_bob): - return hey_bob == '' + return hey_bob == "" def _is_shouting(hey_bob): @@ -23,4 +23,4 @@ def _is_shouting(hey_bob): def _is_question(hey_bob): - return hey_bob.endswith('?') + return hey_bob.endswith("?") diff --git a/exercises/practice/bottle-song/.meta/example.py b/exercises/practice/bottle-song/.meta/example.py index 18e1167da3d..ede22ad52b9 100644 --- a/exercises/practice/bottle-song/.meta/example.py +++ b/exercises/practice/bottle-song/.meta/example.py @@ -1,11 +1,24 @@ -NUMBERS = {10: "ten", 9: "nine", 8: "eight", 7: "seven", 6: "six", 5: "five", 4: "four", 3: "three", 2: "two", 1: "one", 0: "no"} +NUMBERS = { + 10: "ten", + 9: "nine", + 8: "eight", + 7: "seven", + 6: "six", + 5: "five", + 4: "four", + 3: "three", + 2: "two", + 1: "one", + 0: "no", +} + def recite(start, take=1): results = [] for idx in range(start, start - take, -1): results.extend(verse(idx)) if idx > start - take + 1: - results.append('') + results.append("") return results @@ -13,22 +26,25 @@ def verse(number): return [ *main_verse(number), "And if one green bottle should accidentally fall,", - last_verse(number) - ] + last_verse(number), + ] + def main_verse(number): if number == 1: return [ - f'One green bottle hanging on the wall,', - f'One green bottle hanging on the wall,', + f"One green bottle hanging on the wall,", + f"One green bottle hanging on the wall,", ] else: return [ - f'{NUMBERS[number].capitalize()} green bottles hanging on the wall,', - f'{NUMBERS[number].capitalize()} green bottles hanging on the wall,',] + f"{NUMBERS[number].capitalize()} green bottles hanging on the wall,", + f"{NUMBERS[number].capitalize()} green bottles hanging on the wall,", + ] + def last_verse(number): - if number -1 == 1: + if number - 1 == 1: return f"There'll be one green bottle hanging on the wall." else: return f"There'll be {NUMBERS[number-1]} green bottles hanging on the wall." diff --git a/exercises/practice/bowling/.meta/example.py b/exercises/practice/bowling/.meta/example.py index 7afb0d63f8d..f58eb6c85f5 100644 --- a/exercises/practice/bowling/.meta/example.py +++ b/exercises/practice/bowling/.meta/example.py @@ -59,26 +59,31 @@ def next_throws(self, frame_idx): def roll_bonus(self, pins): tenth_frame = self.frames[-1] if tenth_frame.is_open(): - raise IndexError('cannot throw bonus with an open tenth frame') + raise IndexError("cannot throw bonus with an open tenth frame") self.bonus_throws.append(pins) # Check against invalid fill balls, e.g. [3, 10] - if (len(self.bonus_throws) == 2 and self.bonus_throws[0] != 10 and - sum(self.bonus_throws) > 10): - raise ValueError('invalid fill balls') + if ( + len(self.bonus_throws) == 2 + and self.bonus_throws[0] != 10 + and sum(self.bonus_throws) > 10 + ): + raise ValueError("invalid fill balls") # Check if there are more bonuses than it should be if tenth_frame.is_strike() and len(self.bonus_throws) > 2: raise IndexError( - 'wrong number of fill balls when the tenth frame is a strike') + "wrong number of fill balls when the tenth frame is a strike" + ) elif tenth_frame.is_spare() and len(self.bonus_throws) > 1: raise IndexError( - 'wrong number of fill balls when the tenth frame is a spare') + "wrong number of fill balls when the tenth frame is a spare" + ) def roll(self, pins): if not 0 <= pins <= 10: - raise ValueError('invalid pins') + raise ValueError("invalid pins") elif self.current_frame_idx == MAX_FRAME: self.roll_bonus(pins) else: @@ -88,12 +93,11 @@ def roll(self, pins): def score(self): if self.current_frame_idx < MAX_FRAME: - raise IndexError('frame less than 10') + raise IndexError("frame less than 10") if self.frames[-1].is_spare() and len(self.bonus_throws) != 1: - raise IndexError( - 'one bonus must be rolled when the tenth frame is spare') + raise IndexError("one bonus must be rolled when the tenth frame is spare") if self.frames[-1].is_strike() and len(self.bonus_throws) != 2: raise IndexError( - 'two bonuses must be rolled when the tenth frame is strike') - return sum(frame.score(self.next_throws(frame.idx)) - for frame in self.frames) + "two bonuses must be rolled when the tenth frame is strike" + ) + return sum(frame.score(self.next_throws(frame.idx)) for frame in self.frames) diff --git a/exercises/practice/change/.meta/example.py b/exercises/practice/change/.meta/example.py index b62fa0cc10c..03c562643eb 100644 --- a/exercises/practice/change/.meta/example.py +++ b/exercises/practice/change/.meta/example.py @@ -20,6 +20,6 @@ def find_fewest_coins(coins, target): last_coin_value = target array = [] while last_coin[last_coin_value] != -1: - array.append(last_coin_value-last_coin[last_coin_value]) + array.append(last_coin_value - last_coin[last_coin_value]) last_coin_value = last_coin[last_coin_value] return array diff --git a/exercises/practice/circular-buffer/.meta/example.py b/exercises/practice/circular-buffer/.meta/example.py index 538cc7bc5e2..3d6e7ab7e98 100644 --- a/exercises/practice/circular-buffer/.meta/example.py +++ b/exercises/practice/circular-buffer/.meta/example.py @@ -4,6 +4,7 @@ class BufferFullException(BufferError): message: explanation of the error. """ + def __init__(self, message): self.message = message @@ -14,6 +15,7 @@ class BufferEmptyException(BufferError): message: explanation of the error. """ + def __init__(self, message): self.message = message @@ -37,7 +39,7 @@ def clear(self): def write(self, data): if all(self.buffer): - raise BufferFullException('Circular buffer is full') + raise BufferFullException("Circular buffer is full") self._update_buffer(data) self.write_point = (self.write_point + 1) % len(self.buffer) @@ -49,7 +51,7 @@ def overwrite(self, data): def read(self): if not any(self.buffer): - raise BufferEmptyException('Circular buffer is empty') + raise BufferEmptyException("Circular buffer is empty") data = chr(self.buffer[self.read_point]) self.buffer[self.read_point] = 0 self.read_point = (self.read_point + 1) % len(self.buffer) diff --git a/exercises/practice/circular-buffer/circular_buffer.py b/exercises/practice/circular-buffer/circular_buffer.py index 87583f62cfd..ad2fb4a67c0 100644 --- a/exercises/practice/circular-buffer/circular_buffer.py +++ b/exercises/practice/circular-buffer/circular_buffer.py @@ -4,6 +4,7 @@ class BufferFullException(BufferError): message: explanation of the error. """ + def __init__(self, message): pass @@ -14,6 +15,7 @@ class BufferEmptyException(BufferError): message: explanation of the error. """ + def __init__(self, message): pass diff --git a/exercises/practice/clock/.meta/example.py b/exercises/practice/clock/.meta/example.py index 47d52681622..25ddfc1af18 100644 --- a/exercises/practice/clock/.meta/example.py +++ b/exercises/practice/clock/.meta/example.py @@ -7,10 +7,10 @@ def __init__(self, hour, minute): self.cleanup() def __repr__(self): - return f'Clock({self.hour}, {self.minute})' + return f"Clock({self.hour}, {self.minute})" def __str__(self): - return '{:02d}:{:02d}'.format(self.hour, self.minute) + return "{:02d}:{:02d}".format(self.hour, self.minute) def __eq__(self, other): return repr(self) == repr(other) diff --git a/exercises/practice/collatz-conjecture/.articles/performance/code/Benchmark.py b/exercises/practice/collatz-conjecture/.articles/performance/code/Benchmark.py index aea0162e59f..cd4b5f7b154 100644 --- a/exercises/practice/collatz-conjecture/.articles/performance/code/Benchmark.py +++ b/exercises/practice/collatz-conjecture/.articles/performance/code/Benchmark.py @@ -1,5 +1,6 @@ import timeit + def steps_if(number): if number <= 0: raise ValueError("Only positive integers are allowed") @@ -12,6 +13,7 @@ def steps_if(number): counter += 1 return counter + def steps_recursion(number): if number <= 0: raise ValueError("Only positive integers are allowed") @@ -20,6 +22,7 @@ def steps_recursion(number): number = number / 2 if number % 2 == 0 else number * 3 + 1 return 1 + steps_recursion(number) + def steps_ternary(number): if number <= 0: raise ValueError("Only positive integers are allowed") diff --git a/exercises/practice/collatz-conjecture/.meta/example.py b/exercises/practice/collatz-conjecture/.meta/example.py index 843fe43e677..2ddcc546a7e 100644 --- a/exercises/practice/collatz-conjecture/.meta/example.py +++ b/exercises/practice/collatz-conjecture/.meta/example.py @@ -1,6 +1,6 @@ def steps(number): if number <= 0: - raise ValueError('Only positive integers are allowed') + raise ValueError("Only positive integers are allowed") step_count = 0 while number > 1: diff --git a/exercises/practice/complex-numbers/.meta/example.py b/exercises/practice/complex-numbers/.meta/example.py index b833c38fc97..aceb0a3c8fa 100644 --- a/exercises/practice/complex-numbers/.meta/example.py +++ b/exercises/practice/complex-numbers/.meta/example.py @@ -1,5 +1,6 @@ import math + class ComplexNumber: def __init__(self, real=0, imaginary=0): self.real = real @@ -70,7 +71,9 @@ def __truediv__(self, other): denominator = denominator_all.real numerator = self * conjugation - return ComplexNumber((numerator.real / denominator), (numerator.imaginary / denominator)) + return ComplexNumber( + (numerator.real / denominator), (numerator.imaginary / denominator) + ) def __rtruediv__(self, other): if not isinstance(other, ComplexNumber): @@ -81,7 +84,9 @@ def __rtruediv__(self, other): denominator = float(denominator_all.real) numerator = other * conjugation - return ComplexNumber((numerator.real / denominator), (numerator.imaginary / denominator)) + return ComplexNumber( + (numerator.real / denominator), (numerator.imaginary / denominator) + ) def __abs__(self): square_sum = self.real * self.real + self.imaginary * self.imaginary diff --git a/exercises/practice/connect/.meta/example.py b/exercises/practice/connect/.meta/example.py index 0cb00334831..6ee65d31c91 100644 --- a/exercises/practice/connect/.meta/example.py +++ b/exercises/practice/connect/.meta/example.py @@ -1,9 +1,8 @@ - class ConnectGame: DIRECTIONS = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, -1), (-1, 1)] - WHITE = 'O' - BLACK = 'X' + WHITE = "O" + BLACK = "X" def __init__(self, lines): self.board = ConnectGame.make_board(lines) @@ -21,7 +20,7 @@ def valid(self, width, height): @staticmethod def make_board(lines): - return [''.join(cur_line.split()) for cur_line in lines.splitlines()] + return ["".join(cur_line.split()) for cur_line in lines.splitlines()] def player_reach_dest(self, player, width, height): if player == self.BLACK: @@ -43,7 +42,12 @@ def walk_board(self, player, width, height, visited=None): return True for vector in self.DIRECTIONS: - if self.walk_board(player, width + vector[0], height + vector[1], visited + [(width, height)]): + if self.walk_board( + player, + width + vector[0], + height + vector[1], + visited + [(width, height)], + ): return True return None @@ -63,4 +67,4 @@ def get_winner(self): return self.BLACK if self.check_player_is_winner(self.WHITE): return self.WHITE - return '' + return "" diff --git a/exercises/practice/connect/connect.py b/exercises/practice/connect/connect.py index 688dd688ae7..f10f9a4ded3 100644 --- a/exercises/practice/connect/connect.py +++ b/exercises/practice/connect/connect.py @@ -1,4 +1,3 @@ - class ConnectGame: def __init__(self, board): pass diff --git a/exercises/practice/crypto-square/.meta/example.py b/exercises/practice/crypto-square/.meta/example.py index 8cfc7642f0b..8d752be61cb 100644 --- a/exercises/practice/crypto-square/.meta/example.py +++ b/exercises/practice/crypto-square/.meta/example.py @@ -6,15 +6,12 @@ def cipher_text(plain_text): plain_text = _cleanse(plain_text) square_size = int(ceil(sqrt(len(plain_text)))) square = _chunks_of(plain_text, square_size) - return ' '.join([''.join(column) - for column in zip_longest(*square, fillvalue=' ')]) + return " ".join(["".join(column) for column in zip_longest(*square, fillvalue=" ")]) def _cleanse(text): - """Lowercase a string and remove punctuation and whitespace - """ - return ''.join([character for character in text - if character.isalnum()]).lower() + """Lowercase a string and remove punctuation and whitespace""" + return "".join([character for character in text if character.isalnum()]).lower() def _chunks_of(text, num): diff --git a/exercises/practice/darts/.meta/example.py b/exercises/practice/darts/.meta/example.py index eed150cea8d..7086b8dd654 100644 --- a/exercises/practice/darts/.meta/example.py +++ b/exercises/practice/darts/.meta/example.py @@ -1,5 +1,6 @@ from math import sqrt + # X, and Y variable names against [pylint]: C0104, but is the same as the stub, advise not to change this. def score(x, y): dart_location = sqrt(x * x + y * y) diff --git a/exercises/practice/diamond/.meta/example.py b/exercises/practice/diamond/.meta/example.py index bd992476405..ad9014f94a6 100644 --- a/exercises/practice/diamond/.meta/example.py +++ b/exercises/practice/diamond/.meta/example.py @@ -8,8 +8,8 @@ def rows(letter): def make_half(lines, columns): diamond_half = [] for number in range(lines): - row = [' '] * columns + row = [" "] * columns row[lines - 1 - number] = chr(number + 65) row[lines - 1 + number] = chr(number + 65) - diamond_half.append(''.join(row)) + diamond_half.append("".join(row)) return diamond_half diff --git a/exercises/practice/diffie-hellman/.meta/example.py b/exercises/practice/diffie-hellman/.meta/example.py index 45a547bcb75..d4937e1f7ec 100644 --- a/exercises/practice/diffie-hellman/.meta/example.py +++ b/exercises/practice/diffie-hellman/.meta/example.py @@ -2,7 +2,7 @@ def private_key(p): - return random.randint(2, p-1) + return random.randint(2, p - 1) def public_key(p, g, private): diff --git a/exercises/practice/dnd-character/.meta/example.py b/exercises/practice/dnd-character/.meta/example.py index fad3dfe172d..2d10e4cd2c5 100644 --- a/exercises/practice/dnd-character/.meta/example.py +++ b/exercises/practice/dnd-character/.meta/example.py @@ -18,4 +18,4 @@ def ability(self): def modifier(value): - return math.floor((value-10)/2) + return math.floor((value - 10) / 2) diff --git a/exercises/practice/dnd-character/dnd_character.py b/exercises/practice/dnd-character/dnd_character.py index 1d310dde81e..acfe6aef067 100644 --- a/exercises/practice/dnd-character/dnd_character.py +++ b/exercises/practice/dnd-character/dnd_character.py @@ -2,5 +2,6 @@ class Character: def __init__(self): pass + def modifier(value): pass diff --git a/exercises/practice/dot-dsl/.meta/example.py b/exercises/practice/dot-dsl/.meta/example.py index 9229cc41080..8c855ff00e1 100644 --- a/exercises/practice/dot-dsl/.meta/example.py +++ b/exercises/practice/dot-dsl/.meta/example.py @@ -17,9 +17,11 @@ def __init__(self, src, dst, attrs): self.attrs = attrs def __eq__(self, other): - return (self.src == other.src and - self.dst == other.dst and - self.attrs == other.attrs) + return ( + self.src == other.src + and self.dst == other.dst + and self.attrs == other.attrs + ) class Graph: @@ -32,24 +34,24 @@ def __init__(self, data=None): data = [] if not isinstance(data, list): - raise TypeError('Graph data malformed') + raise TypeError("Graph data malformed") for item in data: if len(item) < 3: - raise TypeError('Graph item incomplete') + raise TypeError("Graph item incomplete") type_ = item[0] if type_ == ATTR: if len(item) != 3: - raise ValueError('Attribute is malformed') + raise ValueError("Attribute is malformed") self.attrs[item[1]] = item[2] elif type_ == NODE: if len(item) != 3: - raise ValueError('Node is malformed') + raise ValueError("Node is malformed") self.nodes.append(Node(item[1], item[2])) elif type_ == EDGE: if len(item) != 4: - raise ValueError('Edge is malformed') + raise ValueError("Edge is malformed") self.edges.append(Edge(item[1], item[2], item[3])) else: - raise ValueError('Unknown item') + raise ValueError("Unknown item") diff --git a/exercises/practice/dot-dsl/dot_dsl.py b/exercises/practice/dot-dsl/dot_dsl.py index e22a618bd60..e333e450b6a 100644 --- a/exercises/practice/dot-dsl/dot_dsl.py +++ b/exercises/practice/dot-dsl/dot_dsl.py @@ -17,9 +17,11 @@ def __init__(self, src, dst, attrs): self.attrs = attrs def __eq__(self, other): - return (self.src == other.src and - self.dst == other.dst and - self.attrs == other.attrs) + return ( + self.src == other.src + and self.dst == other.dst + and self.attrs == other.attrs + ) class Graph: diff --git a/exercises/practice/dot-dsl/dot_dsl_test.py b/exercises/practice/dot-dsl/dot_dsl_test.py index 96f502644d0..8fd7e385353 100644 --- a/exercises/practice/dot-dsl/dot_dsl_test.py +++ b/exercises/practice/dot-dsl/dot_dsl_test.py @@ -12,63 +12,59 @@ def test_empty_graph(self): self.assertEqual(g.attrs, {}) def test_graph_with_one_node(self): - g = Graph([ - (NODE, "a", {}) - ]) + g = Graph([(NODE, "a", {})]) self.assertEqual(g.nodes, [Node("a", {})]) self.assertEqual(g.edges, []) self.assertEqual(g.attrs, {}) def test_graph_with_one_node_with_keywords(self): - g = Graph([ - (NODE, "a", {"color": "green"}) - ]) + g = Graph([(NODE, "a", {"color": "green"})]) self.assertEqual(g.nodes, [Node("a", {"color": "green"})]) self.assertEqual(g.edges, []) self.assertEqual(g.attrs, {}) def test_graph_with_one_edge(self): - g = Graph([ - (EDGE, "a", "b", {}) - ]) + g = Graph([(EDGE, "a", "b", {})]) self.assertEqual(g.nodes, []) self.assertEqual(g.edges, [Edge("a", "b", {})]) self.assertEqual(g.attrs, {}) def test_graph_with_one_attribute(self): - g = Graph([ - (ATTR, "foo", "1") - ]) + g = Graph([(ATTR, "foo", "1")]) self.assertEqual(g.nodes, []) self.assertEqual(g.edges, []) self.assertEqual(g.attrs, {"foo": "1"}) def test_graph_with_attributes(self): - g = Graph([ - (ATTR, "foo", "1"), - (ATTR, "title", "Testing Attrs"), - (NODE, "a", {"color": "green"}), - (NODE, "c", {}), - (NODE, "b", {"label": "Beta!"}), - (EDGE, "b", "c", {}), - (EDGE, "a", "b", {"color": "blue"}), - (ATTR, "bar", "true") - ]) - - self.assertEqual(g.nodes, [Node("a", {"color": "green"}), - Node("c", {}), - Node("b", {"label": "Beta!"})]) - self.assertEqual(g.edges, [Edge("b", "c", {}), - Edge("a", "b", {"color": "blue"})]) - self.assertEqual(g.attrs, { - "foo": "1", - "title": "Testing Attrs", - "bar": "true" - }) + g = Graph( + [ + (ATTR, "foo", "1"), + (ATTR, "title", "Testing Attrs"), + (NODE, "a", {"color": "green"}), + (NODE, "c", {}), + (NODE, "b", {"label": "Beta!"}), + (EDGE, "b", "c", {}), + (EDGE, "a", "b", {"color": "blue"}), + (ATTR, "bar", "true"), + ] + ) + + self.assertEqual( + g.nodes, + [ + Node("a", {"color": "green"}), + Node("c", {}), + Node("b", {"label": "Beta!"}), + ], + ) + self.assertEqual( + g.edges, [Edge("b", "c", {}), Edge("a", "b", {"color": "blue"})] + ) + self.assertEqual(g.attrs, {"foo": "1", "title": "Testing Attrs", "bar": "true"}) def test_malformed_graph(self): with self.assertRaises(TypeError) as err: @@ -87,27 +83,23 @@ def test_malformed_graph_item(self): self.assertEqual(type(err.exception), TypeError) self.assertEqual(err.exception.args[0], "Graph item incomplete") - with self.assertRaises(TypeError) as err: - Graph([(ATTR, )]) + Graph([(ATTR,)]) self.assertEqual(type(err.exception), TypeError) self.assertEqual(err.exception.args[0], "Graph item incomplete") - def test_malformed_attr(self): with self.assertRaises(ValueError) as err: Graph([(ATTR, 1, 2, 3)]) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "Attribute is malformed") - def test_malformed_node(self): with self.assertRaises(ValueError) as err: Graph([(NODE, 1, 2, 3)]) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "Node is malformed") - def test_malformed_EDGE(self): with self.assertRaises(ValueError) as err: Graph([(EDGE, 1, 2)]) diff --git a/exercises/practice/error-handling/.meta/example.py b/exercises/practice/error-handling/.meta/example.py index 1dba190d4f6..f4b7fd9a2fe 100644 --- a/exercises/practice/error-handling/.meta/example.py +++ b/exercises/practice/error-handling/.meta/example.py @@ -1,5 +1,5 @@ def handle_error_by_throwing_exception(): - raise Exception('Meaningful message describing the source of the error') + raise Exception("Meaningful message describing the source of the error") def handle_error_by_returning_none(input_data): diff --git a/exercises/practice/error-handling/error_handling_test.py b/exercises/practice/error-handling/error_handling_test.py index fc926074f3c..9a0c67fcada 100644 --- a/exercises/practice/error-handling/error_handling_test.py +++ b/exercises/practice/error-handling/error_handling_test.py @@ -10,46 +10,59 @@ def test_throw_exception(self): er.handle_error_by_throwing_exception() def test_return_none(self): - self.assertEqual(er.handle_error_by_returning_none('1'), 1, - 'Result of valid input should not be None') - self.assertIsNone(er.handle_error_by_returning_none('a'), - 'Result of invalid input should be None') + self.assertEqual( + er.handle_error_by_returning_none("1"), + 1, + "Result of valid input should not be None", + ) + self.assertIsNone( + er.handle_error_by_returning_none("a"), + "Result of invalid input should be None", + ) def test_return_tuple(self): - successful_result, result = er.handle_error_by_returning_tuple('1') - self.assertIs(successful_result, True, - 'Valid input should be successful') - self.assertEqual(result, 1, 'Result of valid input should not be None') + successful_result, result = er.handle_error_by_returning_tuple("1") + self.assertIs(successful_result, True, "Valid input should be successful") + self.assertEqual(result, 1, "Result of valid input should not be None") - failure_result, result = er.handle_error_by_returning_tuple('a') - self.assertIs(failure_result, False, - 'Invalid input should not be successful') + failure_result, result = er.handle_error_by_returning_tuple("a") + self.assertIs(failure_result, False, "Invalid input should not be successful") def test_filelike_objects_are_closed_on_exception(self): filelike_object = FileLike(fail_something=True) with self.assertRaisesWithMessage(Exception): er.filelike_objects_are_closed_on_exception(filelike_object) - self.assertIs(filelike_object.is_open, False, - 'filelike_object should be closed') - self.assertIs(filelike_object.was_open, True, - 'filelike_object should have been opened') - self.assertIs(filelike_object.did_something, True, - 'filelike_object should call do_something()') + self.assertIs( + filelike_object.is_open, False, "filelike_object should be closed" + ) + self.assertIs( + filelike_object.was_open, True, "filelike_object should have been opened" + ) + self.assertIs( + filelike_object.did_something, + True, + "filelike_object should call do_something()", + ) def test_filelike_objects_are_closed_without_exception(self): filelike_object = FileLike(fail_something=False) er.filelike_objects_are_closed_on_exception(filelike_object) - self.assertIs(filelike_object.is_open, False, - 'filelike_object should be closed') - self.assertIs(filelike_object.was_open, True, - 'filelike_object should have been opened') - self.assertIs(filelike_object.did_something, True, - 'filelike_object should call do_something()') + self.assertIs( + filelike_object.is_open, False, "filelike_object should be closed" + ) + self.assertIs( + filelike_object.was_open, True, "filelike_object should have been opened" + ) + self.assertIs( + filelike_object.did_something, + True, + "filelike_object should call do_something()", + ) # Utility functions def assertRaisesWithMessage(self, exception): return self.assertRaisesRegex(exception, r".+") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/error-handling/test_utils.py b/exercises/practice/error-handling/test_utils.py index d9a091e0b2a..4e336174d72 100644 --- a/exercises/practice/error-handling/test_utils.py +++ b/exercises/practice/error-handling/test_utils.py @@ -23,4 +23,4 @@ def __exit__(self, *args): def do_something(self): self.did_something = True if self.fail_something: - raise Exception("Failed while doing something") \ No newline at end of file + raise Exception("Failed while doing something") diff --git a/exercises/practice/food-chain/.meta/example.py b/exercises/practice/food-chain/.meta/example.py index 075f83fafa2..6c2e486f747 100644 --- a/exercises/practice/food-chain/.meta/example.py +++ b/exercises/practice/food-chain/.meta/example.py @@ -1,62 +1,64 @@ def get_song(): - animals = ['fly', 'spider', 'bird', 'cat', 'dog', 'goat', 'cow', 'horse'] - - phrases = [' wriggled and jiggled and tickled inside her.', - 'How absurd to swallow a bird!', - 'Imagine that, to swallow a cat!', - 'What a hog, to swallow a dog!', - 'Just opened her throat and swallowed a goat!', - "I don't know how she swallowed a cow!", - "She's dead, of course!"] - - old_lady = 'I know an old lady who swallowed a ' - swallowed = 'She swallowed the to catch the ' + animals = ["fly", "spider", "bird", "cat", "dog", "goat", "cow", "horse"] + + phrases = [ + " wriggled and jiggled and tickled inside her.", + "How absurd to swallow a bird!", + "Imagine that, to swallow a cat!", + "What a hog, to swallow a dog!", + "Just opened her throat and swallowed a goat!", + "I don't know how she swallowed a cow!", + "She's dead, of course!", + ] + + old_lady = "I know an old lady who swallowed a " + swallowed = "She swallowed the to catch the " die = "I don't know why she swallowed the fly. Perhaps she'll die." - song = '' - verse = '' - chain = '' + song = "" + verse = "" + chain = "" for number, animal in enumerate(animals): - verse = old_lady + animal + '.\n' + verse = old_lady + animal + ".\n" if number == 7: verse += phrases[6] else: if number == 0: - chain = swallowed + animal + '.\n' + chain = swallowed + animal + ".\n" elif number == 1: - verse += 'It' + phrases[0] + '\n' - chain = chain.replace('', animal) + verse += "It" + phrases[0] + "\n" + chain = chain.replace("", animal) verse += chain - chain = swallowed + animal + ' that' + phrases[0] + '\n' + chain + chain = swallowed + animal + " that" + phrases[0] + "\n" + chain else: - verse += phrases[number-1] + '\n' - chain = chain.replace('', animal) + verse += phrases[number - 1] + "\n" + chain = chain.replace("", animal) verse += chain - chain = swallowed + animal + '.\n' + chain + chain = swallowed + animal + ".\n" + chain - verse += die + '\n' + verse += die + "\n" - verse += '\n' + verse += "\n" song += verse return song def verses(letter): - return letter.replace('die.', 'die.slice').split('slice') + return letter.replace("die.", "die.slice").split("slice") def recite(start_verse, end_verse): - generated = [verse.strip().split('\n') for verse in verses(get_song())] + generated = [verse.strip().split("\n") for verse in verses(get_song())] if start_verse == end_verse: return generated[start_verse - 1] else: result = [] for idx in range(start_verse - 1, end_verse): - result += generated[idx] + [''] + result += generated[idx] + [""] # Pop out the last empty string result.pop() diff --git a/exercises/practice/forth/.meta/example.py b/exercises/practice/forth/.meta/example.py index 5e499acf53d..8b9fce78fda 100644 --- a/exercises/practice/forth/.meta/example.py +++ b/exercises/practice/forth/.meta/example.py @@ -1,7 +1,8 @@ class StackUnderflowError(Exception): """Exception raised when Stack is not full. - message: explanation of the error. + message: explanation of the error. """ + def __init__(self, message): self.message = message @@ -18,17 +19,15 @@ def evaluate(input_data): if not input_data: return [] defines = {} - while input_data[0][:1] == ':': + while input_data[0][:1] == ":": values = input_data.pop(0).split() values.pop() values.pop(0) key = values.pop(0).lower() if is_integer(key): - raise ValueError('illegal operation') + raise ValueError("illegal operation") defines[key] = [ - idx - for vivaldi in values - for idx in defines.get(vivaldi, [vivaldi]) + idx for vivaldi in values for idx in defines.get(vivaldi, [vivaldi]) ] stack = [] input_data = input_data[-1].split() @@ -39,28 +38,30 @@ def evaluate(input_data): stack.append(int(word)) elif word in defines: input_data = defines[word] + input_data - elif word == '+': + elif word == "+": stack.append(stack.pop() + stack.pop()) - elif word == '-': + elif word == "-": stack.append(-stack.pop() + stack.pop()) - elif word == '*': + elif word == "*": stack.append(stack.pop() * stack.pop()) - elif word == '/': + elif word == "/": divisor = stack.pop() if divisor == 0: - raise ZeroDivisionError('divide by zero') + raise ZeroDivisionError("divide by zero") stack.append(int(stack.pop() / divisor)) - elif word == 'dup': + elif word == "dup": stack.append(stack[-1]) - elif word == 'drop': + elif word == "drop": stack.pop() - elif word == 'swap': + elif word == "swap": stack.append(stack[-2]) del stack[-3] - elif word == 'over': + elif word == "over": stack.append(stack[-2]) else: - raise ValueError('undefined operation') + raise ValueError("undefined operation") except IndexError as error: - raise StackUnderflowError('Insufficient number of items in stack') from error + raise StackUnderflowError( + "Insufficient number of items in stack" + ) from error return stack diff --git a/exercises/practice/go-counting/.meta/example.py b/exercises/practice/go-counting/.meta/example.py index c6ccd512110..486a699ee5c 100644 --- a/exercises/practice/go-counting/.meta/example.py +++ b/exercises/practice/go-counting/.meta/example.py @@ -1,7 +1,6 @@ - -BLACK = 'B' -WHITE = 'W' -NONE = '' +BLACK = "B" +WHITE = "W" +NONE = "" STONES = [BLACK, WHITE] DIRECTIONS = [(0, 1), (0, -1), (1, 0), (-1, 0)] @@ -15,7 +14,14 @@ def __init__(self, board): def valid(self, width, height): return self.width > width >= 0 and self.height > height >= 0 - def walk(self, width, height, visited_territory=None, visited_coords=None, visited_stones=None): + def walk( + self, + width, + height, + visited_territory=None, + visited_coords=None, + visited_stones=None, + ): # Pylint gives W0102 warning if list used as default argument, because list is mutable. visited_territory = [] if visited_territory is None else visited_territory visited_coords = [] if visited_coords is None else visited_coords @@ -28,10 +34,13 @@ def walk(self, width, height, visited_territory=None, visited_coords=None, visit return (visited_territory, visited_stones + [stone]) else: # s is empty for direction in DIRECTIONS: - visited = self.walk(width + direction[0], height + direction[1], - visited_territory + [(width, height)], - visited_coords + [(width, height)], - visited_stones) + visited = self.walk( + width + direction[0], + height + direction[1], + visited_territory + [(width, height)], + visited_coords + [(width, height)], + visited_stones, + ) visited_territory = visited[0] visited_stones = visited[1] @@ -39,7 +48,7 @@ def walk(self, width, height, visited_territory=None, visited_coords=None, visit def territory(self, x, y): if not self.valid(x, y): - raise ValueError('Invalid coordinate') + raise ValueError("Invalid coordinate") if self.board[y][x] in STONES: return (NONE, set()) @@ -52,7 +61,7 @@ def territory(self, x, y): def territories(self): owners = STONES + [NONE] - result = {owner:set() for owner in owners} + result = {owner: set() for owner in owners} visited = set() for row in range(self.height): for column in range(self.width): diff --git a/exercises/practice/go-counting/go_counting.py b/exercises/practice/go-counting/go_counting.py index d1c689e704a..a3ed7fa8eee 100644 --- a/exercises/practice/go-counting/go_counting.py +++ b/exercises/practice/go-counting/go_counting.py @@ -1,4 +1,3 @@ - class Board: """Count territories of each player in a Go game diff --git a/exercises/practice/grade-school/.meta/example.py b/exercises/practice/grade-school/.meta/example.py index fc974919e7e..42756875b34 100644 --- a/exercises/practice/grade-school/.meta/example.py +++ b/exercises/practice/grade-school/.meta/example.py @@ -19,7 +19,6 @@ def add_student(self, name, grade): else: self.add.append(False) - def roster(self, grade=0): grades_roster = defaultdict(list) @@ -29,7 +28,9 @@ def roster(self, grade=0): if grade: return sorted(grades_roster[grade]) else: - working_list = (sorted(grades_roster[key]) for key in sorted(grades_roster.keys())) + working_list = ( + sorted(grades_roster[key]) for key in sorted(grades_roster.keys()) + ) return [element for item in working_list for element in item] def grade(self, grade_number): diff --git a/exercises/practice/grains/.articles/performance/code/Benchmark.py b/exercises/practice/grains/.articles/performance/code/Benchmark.py index 8fef0fad053..5ae5b270674 100644 --- a/exercises/practice/grains/.articles/performance/code/Benchmark.py +++ b/exercises/practice/grains/.articles/performance/code/Benchmark.py @@ -2,8 +2,10 @@ loops = 1_000_000 -val = timeit.timeit("""square(64)""", - """ +val = ( + timeit.timeit( + """square(64)""", + """ def square(number): if number < 1 or number > 64: raise ValueError("square must be between 1 and 64") @@ -12,13 +14,19 @@ def square(number): def total(): return (1 << 64) - 1 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"bit shifting square 64: {val}") -val = timeit.timeit("""total()""", - """ +val = ( + timeit.timeit( + """total()""", + """ def square(number): if number < 1 or number > 64: raise ValueError("square must be between 1 and 64") @@ -27,12 +35,18 @@ def square(number): def total(): return (1 << 64) - 1 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"bit shifting total 64: {val}") -val = timeit.timeit("""square(64)""", - """ +val = ( + timeit.timeit( + """square(64)""", + """ def square(number): if number < 1 or number > 64: raise ValueError("square must be between 1 and 64") @@ -42,13 +56,19 @@ def square(number): def total(): return 2**64 - 1 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"exponentiation square 64: {val}") -val = timeit.timeit("""total()""", - """ +val = ( + timeit.timeit( + """total()""", + """ def square(number): if number < 1 or number > 64: raise ValueError("square must be between 1 and 64") @@ -58,12 +78,18 @@ def square(number): def total(): return 2**64 - 1 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"exponentiation total 64: {val}") -val = timeit.timeit("""square(64)""", - """ +val = ( + timeit.timeit( + """square(64)""", + """ def square(number): if number < 1 or number > 64: raise ValueError("square must be between 1 and 64") @@ -73,13 +99,19 @@ def square(number): def total(): return pow(2, 64) - 1 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"pow square 64: {val}") -val = timeit.timeit("""total()""", - """ +val = ( + timeit.timeit( + """total()""", + """ def square(number): if number < 1 or number > 64: raise ValueError("square must be between 1 and 64") @@ -89,6 +121,10 @@ def square(number): def total(): return pow(2, 64) - 1 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"pow total 64: {val}") diff --git a/exercises/practice/grains/.meta/example.py b/exercises/practice/grains/.meta/example.py index 8610d32b52f..7b5aaa4ba8e 100644 --- a/exercises/practice/grains/.meta/example.py +++ b/exercises/practice/grains/.meta/example.py @@ -1,13 +1,13 @@ def square(number): if number == 0: - raise ValueError('square must be between 1 and 64') + raise ValueError("square must be between 1 and 64") elif number < 0: - raise ValueError('square must be between 1 and 64') + raise ValueError("square must be between 1 and 64") elif number > 64: - raise ValueError('square must be between 1 and 64') + raise ValueError("square must be between 1 and 64") return 2 ** (number - 1) def total(): - return (2 ** 64) - 1 + return (2**64) - 1 diff --git a/exercises/practice/grep/.meta/example.py b/exercises/practice/grep/.meta/example.py index e0ffbfe2db1..f2ee5348e1e 100644 --- a/exercises/practice/grep/.meta/example.py +++ b/exercises/practice/grep/.meta/example.py @@ -1,24 +1,24 @@ def matches(line, pattern, flags): - if '-i' in flags: # case-insensitive + if "-i" in flags: # case-insensitive line = line.lower() pattern = pattern.lower() - if '-x' in flags: # match entire lines + if "-x" in flags: # match entire lines if len(pattern) != len(line.rstrip()): - return '-v' in flags + return "-v" in flags - if '-v' in flags: # invert matching + if "-v" in flags: # invert matching return pattern not in line return pattern in line def format_files(matched_lines): - result = '' + result = "" for file_name, _, _ in matched_lines: if file_name not in result: - result += file_name + '\n' + result += file_name + "\n" return result @@ -27,31 +27,31 @@ def format_lines(matched_lines, flags, files): result = [] for file_name, line_number, line in matched_lines: - line_result = '' + line_result = "" if len(files) > 1: - line_result += file_name + ':' + line_result += file_name + ":" - if '-n' in flags: - line_result += str(line_number) + ':' + if "-n" in flags: + line_result += str(line_number) + ":" line_result += line result.append(line_result) - return ''.join(result) + return "".join(result) def grep(pattern, flags, files): matched_lines = [] for file_name in files: - with open(file_name, encoding='utf-8') as f: + with open(file_name, encoding="utf-8") as f: for line_number, line in enumerate(f.readlines(), start=1): if matches(line, pattern, flags): matched_lines.append((file_name, line_number, line)) - if '-l' in flags: + if "-l" in flags: return format_files(matched_lines) return format_lines(matched_lines, flags, files) diff --git a/exercises/practice/hamming/.meta/example.py b/exercises/practice/hamming/.meta/example.py index d6a3848eff3..943c580faae 100644 --- a/exercises/practice/hamming/.meta/example.py +++ b/exercises/practice/hamming/.meta/example.py @@ -1,5 +1,5 @@ def distance(strand_a, strand_b): if len(strand_a) != len(strand_b): - raise ValueError('Strands must be of equal length.') + raise ValueError("Strands must be of equal length.") return sum(a_part != b_part for a_part, b_part in zip(strand_a, strand_b)) diff --git a/exercises/practice/hangman/.meta/example.py b/exercises/practice/hangman/.meta/example.py index b0316860956..89fdd3a09c8 100644 --- a/exercises/practice/hangman/.meta/example.py +++ b/exercises/practice/hangman/.meta/example.py @@ -1,6 +1,6 @@ -STATUS_WIN = 'win' -STATUS_LOSE = 'lose' -STATUS_ONGOING = 'ongoing' +STATUS_WIN = "win" +STATUS_LOSE = "lose" +STATUS_ONGOING = "ongoing" class Hangman: @@ -8,24 +8,24 @@ def __init__(self, word): self.remaining_guesses = 9 self.status = STATUS_ONGOING self.word = word - self.masked_word = '' + self.masked_word = "" self.guesses = [] for _ in self.word: - self.masked_word += '_' + self.masked_word += "_" def guess(self, char): if self.status != STATUS_ONGOING: - raise ValueError('The game has already ended.') + raise ValueError("The game has already ended.") self.update_remaining_guesses(char) self.update_masked_word() self.update_status() def update_masked_word(self): - self.masked_word = '' + self.masked_word = "" for idx in self.word: if idx not in self.guesses: - self.masked_word += '_' + self.masked_word += "_" else: self.masked_word += idx diff --git a/exercises/practice/hangman/hangman.py b/exercises/practice/hangman/hangman.py index 5f0db276c06..9385d240b32 100644 --- a/exercises/practice/hangman/hangman.py +++ b/exercises/practice/hangman/hangman.py @@ -1,8 +1,8 @@ # Game status categories # Change the values as you see fit -STATUS_WIN = 'win' -STATUS_LOSE = 'lose' -STATUS_ONGOING = 'ongoing' +STATUS_WIN = "win" +STATUS_LOSE = "lose" +STATUS_ONGOING = "ongoing" class Hangman: diff --git a/exercises/practice/hangman/hangman_test.py b/exercises/practice/hangman/hangman_test.py index 5733e9a80f8..28afeddac05 100644 --- a/exercises/practice/hangman/hangman_test.py +++ b/exercises/practice/hangman/hangman_test.py @@ -6,92 +6,93 @@ # Tests adapted from csharp//hangman/HangmanTest.cs + class HangmanTests(unittest.TestCase): def test_initially_9_failures_are_allowed(self): - game = Hangman('foo') + game = Hangman("foo") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 9) def test_initially_no_letters_are_guessed(self): - game = Hangman('foo') + 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') + game = Hangman("foo") for i in range(10): - game.guess('x') + game.guess("x") self.assertEqual(game.get_status(), hangman.STATUS_LOSE) with self.assertRaises(ValueError) as err: - game.guess('x') + game.guess("x") self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "The game has already ended.") def test_feeding_a_correct_letter_removes_underscores(self): - game = Hangman('foobar') + game = Hangman("foobar") - game.guess('b') + game.guess("b") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 9) - self.assertEqual(game.get_masked_word(), '___b__') + self.assertEqual(game.get_masked_word(), "___b__") - game.guess('o') + game.guess("o") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 9) - self.assertEqual(game.get_masked_word(), '_oob__') + self.assertEqual(game.get_masked_word(), "_oob__") def test_feeding_a_correct_letter_twice_counts_as_a_failure(self): - game = Hangman('foobar') + game = Hangman("foobar") - game.guess('b') + game.guess("b") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 9) - self.assertEqual(game.get_masked_word(), '___b__') + self.assertEqual(game.get_masked_word(), "___b__") - game.guess('b') + game.guess("b") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 8) - self.assertEqual(game.get_masked_word(), '___b__') + self.assertEqual(game.get_masked_word(), "___b__") def test_getting_all_the_letters_right_makes_for_a_win(self): - game = Hangman('hello') + game = Hangman("hello") - game.guess('b') + game.guess("b") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 8) - self.assertEqual(game.get_masked_word(), '_____') + self.assertEqual(game.get_masked_word(), "_____") - game.guess('e') + game.guess("e") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 8) - self.assertEqual(game.get_masked_word(), '_e___') + self.assertEqual(game.get_masked_word(), "_e___") - game.guess('l') + game.guess("l") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 8) - self.assertEqual(game.get_masked_word(), '_ell_') + self.assertEqual(game.get_masked_word(), "_ell_") - game.guess('o') + game.guess("o") self.assertEqual(game.get_status(), hangman.STATUS_ONGOING) self.assertEqual(game.remaining_guesses, 8) - self.assertEqual(game.get_masked_word(), '_ello') + self.assertEqual(game.get_masked_word(), "_ello") - game.guess('h') + game.guess("h") self.assertEqual(game.get_status(), hangman.STATUS_WIN) - self.assertEqual(game.get_masked_word(), 'hello') + self.assertEqual(game.get_masked_word(), "hello") with self.assertRaises(ValueError) as err: - game.guess('x') + game.guess("x") self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "The game has already ended.") def test_winning_on_last_guess_still_counts_as_a_win(self): - game = Hangman('aaa') - for ch in 'bcdefghij': + game = Hangman("aaa") + for ch in "bcdefghij": game.guess(ch) - game.guess('a') + game.guess("a") self.assertEqual(game.remaining_guesses, 0) self.assertEqual(game.get_status(), hangman.STATUS_WIN) - self.assertEqual(game.get_masked_word(), 'aaa') + self.assertEqual(game.get_masked_word(), "aaa") diff --git a/exercises/practice/hello-world/.meta/example.py b/exercises/practice/hello-world/.meta/example.py index d695ea11589..dea05ae20e8 100644 --- a/exercises/practice/hello-world/.meta/example.py +++ b/exercises/practice/hello-world/.meta/example.py @@ -1,2 +1,2 @@ def hello(): - return 'Hello, World!' + return "Hello, World!" diff --git a/exercises/practice/hello-world/hello_world.py b/exercises/practice/hello-world/hello_world.py index adaa6c2c997..dcc91b52349 100644 --- a/exercises/practice/hello-world/hello_world.py +++ b/exercises/practice/hello-world/hello_world.py @@ -1,2 +1,2 @@ def hello(): - return 'Goodbye, Mars!' + return "Goodbye, Mars!" diff --git a/exercises/practice/hexadecimal/.meta/example.py b/exercises/practice/hexadecimal/.meta/example.py index 672321a8929..3941ca2f44e 100644 --- a/exercises/practice/hexadecimal/.meta/example.py +++ b/exercises/practice/hexadecimal/.meta/example.py @@ -3,8 +3,10 @@ def hexa(hex_string): hex_string = hex_string.lower() - if set(hex_string) - set('0123456789abcdef'): - raise ValueError('Invalid hexadecimal string') - digits = [ord(letter) - ord('a') + 10 if letter in 'abcdef' else ord(letter) - ord('0') - for letter in hex_string] + if set(hex_string) - set("0123456789abcdef"): + raise ValueError("Invalid hexadecimal string") + digits = [ + ord(letter) - ord("a") + 10 if letter in "abcdef" else ord(letter) - ord("0") + for letter in hex_string + ] return reduce(lambda var_1, var_2: var_1 * 16 + var_2, digits, 0) diff --git a/exercises/practice/hexadecimal/hexadecimal_test.py b/exercises/practice/hexadecimal/hexadecimal_test.py index 228c4b45627..7ce0387de87 100644 --- a/exercises/practice/hexadecimal/hexadecimal_test.py +++ b/exercises/practice/hexadecimal/hexadecimal_test.py @@ -8,40 +8,40 @@ class HexadecimalTest(unittest.TestCase): def test_valid_hexa1(self): - self.assertEqual(hexa('1'), 1) + self.assertEqual(hexa("1"), 1) def test_valid_hexa2(self): - self.assertEqual(hexa('c'), 12) + self.assertEqual(hexa("c"), 12) def test_valid_hexa3(self): - self.assertEqual(hexa('10'), 16) + self.assertEqual(hexa("10"), 16) def test_valid_hexa4(self): - self.assertEqual(hexa('af'), 175) + self.assertEqual(hexa("af"), 175) def test_valid_hexa5(self): - self.assertEqual(hexa('100'), 256) + self.assertEqual(hexa("100"), 256) def test_valid_hexa6(self): - self.assertEqual(hexa('19ACE'), 105166) + self.assertEqual(hexa("19ACE"), 105166) def test_valid_hexa7(self): - self.assertEqual(hexa('000000'), 0) + self.assertEqual(hexa("000000"), 0) def test_valid_hexa8(self): - self.assertEqual(hexa('ffff00'), 16776960) + self.assertEqual(hexa("ffff00"), 16776960) def test_valid_hexa9(self): - self.assertEqual(hexa('00fff0'), 65520) + self.assertEqual(hexa("00fff0"), 65520) def test_invalid_hexa(self): with self.assertRaisesWithMessage(ValueError): - hexa('carrot') + hexa("carrot") # Utility functions def assertRaisesWithMessage(self, exception): return self.assertRaisesRegex(exception, r".+") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/house/.meta/example.py b/exercises/practice/house/.meta/example.py index 30e289b9195..188d4d644f8 100644 --- a/exercises/practice/house/.meta/example.py +++ b/exercises/practice/house/.meta/example.py @@ -1,23 +1,26 @@ -PARTS = [('lay in', 'the house that Jack built.'), - ('ate', 'the malt'), - ('killed', 'the rat'), - ('worried', 'the cat'), - ('tossed', 'the dog'), - ('milked', 'the cow with the crumpled horn'), - ('kissed', 'the maiden all forlorn'), - ('married', 'the man all tattered and torn'), - ('woke', 'the priest all shaven and shorn'), - ('kept', 'the rooster that crowed in the morn'), - ('belonged to', 'the farmer sowing his corn'), - ('', 'the horse and the hound and the horn')] +PARTS = [ + ("lay in", "the house that Jack built."), + ("ate", "the malt"), + ("killed", "the rat"), + ("worried", "the cat"), + ("tossed", "the dog"), + ("milked", "the cow with the crumpled horn"), + ("kissed", "the maiden all forlorn"), + ("married", "the man all tattered and torn"), + ("woke", "the priest all shaven and shorn"), + ("kept", "the rooster that crowed in the morn"), + ("belonged to", "the farmer sowing his corn"), + ("", "the horse and the hound and the horn"), +] def verse(verse_num): - verse = [f'This is {PARTS[verse_num][1]}'] - verse.extend(['that {0} {1}'.format(*PARTS[idx]) - for idx in range(verse_num - 1, -1, -1)]) - return ' '.join(verse) + verse = [f"This is {PARTS[verse_num][1]}"] + verse.extend( + ["that {0} {1}".format(*PARTS[idx]) for idx in range(verse_num - 1, -1, -1)] + ) + return " ".join(verse) def recite(start_verse, end_verse): - return [verse(verse_num) for verse_num in range(start_verse-1, end_verse)] + return [verse(verse_num) for verse_num in range(start_verse - 1, end_verse)] diff --git a/exercises/practice/isbn-verifier/.meta/example.py b/exercises/practice/isbn-verifier/.meta/example.py index f2f14f3947f..8e5441155d2 100644 --- a/exercises/practice/isbn-verifier/.meta/example.py +++ b/exercises/practice/isbn-verifier/.meta/example.py @@ -1,7 +1,7 @@ def is_valid(isbn): - chars = list(isbn.replace('-', '')) - if chars and chars[-1] == 'X': - chars[-1] = '10' + chars = list(isbn.replace("-", "")) + if chars and chars[-1] == "X": + chars[-1] = "10" if not len(chars) == 10 or not all(char.isdigit() for char in chars): return False indices = list(range(10, 0, -1)) diff --git a/exercises/practice/isogram/.articles/performance/code/Benchmark.py b/exercises/practice/isogram/.articles/performance/code/Benchmark.py index 47790fdc4af..3318f4afef8 100644 --- a/exercises/practice/isogram/.articles/performance/code/Benchmark.py +++ b/exercises/practice/isogram/.articles/performance/code/Benchmark.py @@ -2,52 +2,78 @@ loops = 1_000_000 -val = timeit.timeit("""is_isogram("Emily Jung-Schwartzkopf")""", - """ +val = ( + timeit.timeit( + """is_isogram("Emily Jung-Schwartzkopf")""", + """ def is_isogram(phrase): scrubbed = [ltr.lower() for ltr in phrase if ltr.isalpha()] return len(set(scrubbed)) == len(scrubbed) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"scrubbed comprehension: {val}") -val = timeit.timeit("""is_isogram("Emily Jung-Schwartzkopf")""", - """ +val = ( + timeit.timeit( + """is_isogram("Emily Jung-Schwartzkopf")""", + """ def is_isogram(phrase): scrubbed = phrase.replace('-', '').replace(' ', '').lower() return len(scrubbed) == len(set(scrubbed)) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"scrubbed replace: {val}") -val = timeit.timeit("""is_isogram("Emily Jung-Schwartzkopf")""", - """ +val = ( + timeit.timeit( + """is_isogram("Emily Jung-Schwartzkopf")""", + """ import re def is_isogram(phrase): scrubbed = re.compile('[^a-zA-Z]').sub('', phrase).lower() return len(set(scrubbed)) == len(scrubbed) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"scrubbed regex: {val}") -val = timeit.timeit("""is_isogram("Emily Jung-Schwartzkopf")""", - """ +val = ( + timeit.timeit( + """is_isogram("Emily Jung-Schwartzkopf")""", + """ import re def is_isogram(phrase): scrubbed = "".join(re.findall("[a-zA-Z]", phrase)).lower() return len(set(scrubbed)) == len(scrubbed) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"findall regex: {val}") -val = timeit.timeit("""is_isogram("Emily Jung-Schwartzkopf")""", - """ +val = ( + timeit.timeit( + """is_isogram("Emily Jung-Schwartzkopf")""", + """ A_LCASE = 97 Z_LCASE = 122 A_UCASE = 65 @@ -71,6 +97,10 @@ def is_isogram(phrase): letter_flags |= 1 << (letter - A_UCASE) return True -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"bitfield: {val}") diff --git a/exercises/practice/killer-sudoku-helper/.meta/example.py b/exercises/practice/killer-sudoku-helper/.meta/example.py index ac3a7f87962..54900b5df03 100644 --- a/exercises/practice/killer-sudoku-helper/.meta/example.py +++ b/exercises/practice/killer-sudoku-helper/.meta/example.py @@ -1,10 +1,13 @@ import itertools + def combinations(target, size, exclude): result = [] - possible = [index for index in - range(1, int((target ** 2 /size) ** 0.6)) - if index not in exclude] + possible = [ + index + for index in range(1, int((target**2 / size) ** 0.6)) + if index not in exclude + ] if size == 1: return [[target]] diff --git a/exercises/practice/kindergarten-garden/.meta/example.py b/exercises/practice/kindergarten-garden/.meta/example.py index 262c6ad6e22..30c9aa531be 100644 --- a/exercises/practice/kindergarten-garden/.meta/example.py +++ b/exercises/practice/kindergarten-garden/.meta/example.py @@ -1,20 +1,20 @@ class Garden: STUDENTS = [ - 'Alice', - 'Bob', - 'Charlie', - 'David', - 'Eve', - 'Fred', - 'Ginny', - 'Harriet', - 'Ileana', - 'Joseph', - 'Kincaid', - 'Larry', + "Alice", + "Bob", + "Charlie", + "David", + "Eve", + "Fred", + "Ginny", + "Harriet", + "Ileana", + "Joseph", + "Kincaid", + "Larry", ] - PLANTS = {'C': 'Clover', 'G': 'Grass', 'R': 'Radishes', 'V': 'Violets'} + PLANTS = {"C": "Clover", "G": "Grass", "R": "Radishes", "V": "Violets"} def __init__(self, diagram, students=None): students = sorted(students or self.STUDENTS) @@ -24,12 +24,8 @@ def __init__(self, diagram, students=None): start = idx * 2 stop = start + 2 self.cups.setdefault(student, []) - self.cups[student].extend( - self.PLANTS[plant] for plant in front[start:stop] - ) - self.cups[student].extend( - self.PLANTS[plant] for plant in back[start:stop] - ) + self.cups[student].extend(self.PLANTS[plant] for plant in front[start:stop]) + self.cups[student].extend(self.PLANTS[plant] for plant in back[start:stop]) def plants(self, student): return self.cups.get(student, []) diff --git a/exercises/practice/knapsack/.meta/example.py b/exercises/practice/knapsack/.meta/example.py index 548dd5a2b92..017d160f706 100644 --- a/exercises/practice/knapsack/.meta/example.py +++ b/exercises/practice/knapsack/.meta/example.py @@ -1,12 +1,10 @@ def maximum_value(maximum_weight, items): - totals = [[0 for _ in range(len(items) + 1)] - for _ in range(maximum_weight + 1)] + totals = [[0 for _ in range(len(items) + 1)] for _ in range(maximum_weight + 1)] for weight in range(1, maximum_weight + 1): for index, item in enumerate(items, 1): - if item['weight'] <= weight: - value = item['value'] + \ - totals[weight - item['weight']][index - 1] + if item["weight"] <= weight: + value = item["value"] + totals[weight - item["weight"]][index - 1] value_without_item = totals[weight][index - 1] totals[weight][index] = max(value, value_without_item) diff --git a/exercises/practice/largest-series-product/.meta/example.py b/exercises/practice/largest-series-product/.meta/example.py index 0599e7417e6..049e35d7b51 100644 --- a/exercises/practice/largest-series-product/.meta/example.py +++ b/exercises/practice/largest-series-product/.meta/example.py @@ -5,16 +5,15 @@ def slices(series, size): if not size <= len(series): - raise ValueError('span must be smaller than string length') + raise ValueError("span must be smaller than string length") elif not 0 < size: - raise ValueError('span must not be negative') + raise ValueError("span must not be negative") elif not all(item.isdigit() for item in series): - raise ValueError('digits input must only contain digits') + raise ValueError("digits input must only contain digits") numbers = [int(digit) for digit in series] - return [numbers[idx:idx + size] - for idx in range(len(numbers) - size + 1)] + return [numbers[idx : idx + size] for idx in range(len(numbers) - size + 1)] def largest_product(series, size): diff --git a/exercises/practice/leap/.articles/performance/code/Benchmark.py b/exercises/practice/leap/.articles/performance/code/Benchmark.py index d2a204b3616..a70dec69ef4 100644 --- a/exercises/practice/leap/.articles/performance/code/Benchmark.py +++ b/exercises/practice/leap/.articles/performance/code/Benchmark.py @@ -17,24 +17,32 @@ setups = {} -setups["if-statements"] = """ +setups[ + "if-statements" +] = """ def leap_year(year): return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) """ -setups["ternary"] = """ +setups[ + "ternary" +] = """ def leap_year(year): return not year % 400 if not year % 100 else not year % 4 """ -setups["datetime-add"] = """ +setups[ + "datetime-add" +] = """ from datetime import datetime, timedelta def leap_year(year): return (datetime(year, 2, 28) + timedelta(days=1)).day == 29 """ -setups["calendar-isleap"] = """ +setups[ + "calendar-isleap" +] = """ from calendar import isleap def leap_year(year): @@ -45,47 +53,53 @@ def leap_year(year): # Conducting ghe timings for descriptor in row_headers: val = timeit.timeit("""leap_year(1900)""", setups[descriptor], number=loops) / loops - year = '1900' + year = "1900" print(f"{descriptor} {year}: {val}") df.loc[descriptor, year] = val val = timeit.timeit("""leap_year(2000)""", setups[descriptor], number=loops) / loops - year = '2000' + year = "2000" print(f"{descriptor} {year}: {val}") df.loc[descriptor, year] = val val = timeit.timeit("""leap_year(2019)""", setups[descriptor], number=loops) / loops - year = '2019' + year = "2019" print(f"{descriptor} {year}: {val}") df.loc[descriptor, year] = val val = timeit.timeit("""leap_year(2020)""", setups[descriptor], number=loops) / loops - year = '2020' + year = "2020" print(f"{descriptor} {year}: {val}") df.loc[descriptor, year] = val # Settng up chart details and colors -mpl.rcParams['axes.labelsize'] = 18 -bar_colors = ["#AFAD6A", "#B1C9FD", "#CDC6FD", - "#FABD19", "#3B76F2", "#7467D1", - "#FA9A19", "#85832F", "#1A54CE","#4536B0"] +mpl.rcParams["axes.labelsize"] = 18 +bar_colors = [ + "#AFAD6A", + "#B1C9FD", + "#CDC6FD", + "#FABD19", + "#3B76F2", + "#7467D1", + "#FA9A19", + "#85832F", + "#1A54CE", + "#4536B0", +] my_cmap = ListedColormap(sns.color_palette(bar_colors, as_cmap=True)) # bar plot of actual run times -ax = df.plot.bar(figsize=(10, 7), - ylabel="time (s)", - fontsize=14, - width=0.8, - rot=0, - colormap=my_cmap) +ax = df.plot.bar( + figsize=(10, 7), ylabel="time (s)", fontsize=14, width=0.8, rot=0, colormap=my_cmap +) # Saving the graph for later use -plt.savefig('../timeit_bar_plot.svg') +plt.savefig("../timeit_bar_plot.svg") # The next bit will be useful for `introduction.md` # pd.options.display.float_format = '{:,.2e}'.format -print('\nDataframe in Markdown format:\n') +print("\nDataframe in Markdown format:\n") print(df.to_markdown(floatfmt=".1e")) diff --git a/exercises/practice/ledger/.meta/example.py b/exercises/practice/ledger/.meta/example.py index 46e8e3c9f6f..85aac97d1a8 100644 --- a/exercises/practice/ledger/.meta/example.py +++ b/exercises/practice/ledger/.meta/example.py @@ -1,39 +1,39 @@ # -*- coding: utf-8 -*- from datetime import datetime -ROW_FMT = '{{:<{1}}} | {{:<{2}}} | {{:{0}{3}}}' +ROW_FMT = "{{:<{1}}} | {{:<{2}}} | {{:{0}{3}}}" def truncate(s, length=25): if len(s) <= length: return s - return s[:length - 3] + '...' + return s[: length - 3] + "..." class LCInfo: def __init__(self, locale, currency, columns): self.columns = columns - if locale == 'en_US': - headers = ['Date', 'Description', 'Change'] - self.datefmt = '{0.month:02}/{0.day:02}/{0.year:04}' - self.cur_fmt = '{}{}{}{}' - self.lead_neg = '(' - self.trail_neg = ')' - self.thousands = ',' - self.decimal = '.' - elif locale == 'nl_NL': - headers = ['Datum', 'Omschrijving', 'Verandering'] - self.datefmt = '{0.day:02}-{0.month:02}-{0.year:04}' - self.cur_fmt = '{1} {0}{2}{3}' - self.lead_neg = '-' - self.trail_neg = ' ' - self.thousands = '.' - self.decimal = ',' - fmt = ROW_FMT.format('<', *columns) + if locale == "en_US": + headers = ["Date", "Description", "Change"] + self.datefmt = "{0.month:02}/{0.day:02}/{0.year:04}" + self.cur_fmt = "{}{}{}{}" + self.lead_neg = "(" + self.trail_neg = ")" + self.thousands = "," + self.decimal = "." + elif locale == "nl_NL": + headers = ["Datum", "Omschrijving", "Verandering"] + self.datefmt = "{0.day:02}-{0.month:02}-{0.year:04}" + self.cur_fmt = "{1} {0}{2}{3}" + self.lead_neg = "-" + self.trail_neg = " " + self.thousands = "." + self.decimal = "," + fmt = ROW_FMT.format("<", *columns) self.headers = fmt.format(*headers) self.cur_symbol = { - 'USD': '$', - 'EUR': '€', + "USD": "$", + "EUR": "€", }.get(currency) def number(self, n): @@ -42,23 +42,23 @@ def number(self, n): while n_int > 0: n_int, idx = divmod(n_int, 1000) n_int_parts.insert(0, str(idx)) - return '{}{}{:02}'.format( - self.thousands.join(n_int_parts) or '0', + return "{}{}{:02}".format( + self.thousands.join(n_int_parts) or "0", self.decimal, n_float, ) def currency(self, change): return self.cur_fmt.format( - self.lead_neg if change < 0 else '', + self.lead_neg if change < 0 else "", self.cur_symbol, self.number(change), - self.trail_neg if change < 0 else ' ', + self.trail_neg if change < 0 else " ", ) def entry(self, entry): date, change, desc = entry - fmt = ROW_FMT.format('>', *self.columns) + fmt = ROW_FMT.format(">", *self.columns) return fmt.format( self.datefmt.format(date), truncate(desc), @@ -68,15 +68,11 @@ def entry(self, entry): def table(self, entries): lines = [self.headers] lines.extend(map(self.entry, sorted(entries))) - return '\n'.join(lines) + return "\n".join(lines) def create_entry(date, description, change): - return ( - datetime.strptime(date, '%Y-%m-%d'), - change, - description - ) + return (datetime.strptime(date, "%Y-%m-%d"), change, description) def format_entries(currency, locale, entries): diff --git a/exercises/practice/ledger/ledger.py b/exercises/practice/ledger/ledger.py index c0dcf94f738..e7504fff04c 100644 --- a/exercises/practice/ledger/ledger.py +++ b/exercises/practice/ledger/ledger.py @@ -11,27 +11,27 @@ def __init__(self): def create_entry(date, description, change): entry = LedgerEntry() - entry.date = datetime.strptime(date, '%Y-%m-%d') + entry.date = datetime.strptime(date, "%Y-%m-%d") entry.description = description entry.change = change return entry def format_entries(currency, locale, entries): - if locale == 'en_US': + if locale == "en_US": # Generate Header Row - table = 'Date' + table = "Date" for _ in range(7): - table += ' ' - table += '| Description' + table += " " + table += "| Description" for _ in range(15): - table += ' ' - table += '| Change' + table += " " + table += "| Change" for _ in range(7): - table += ' ' + table += " " while len(entries) > 0: - table += '\n' + table += "\n" # Find next entry in order min_entry_index = -1 @@ -44,16 +44,13 @@ def format_entries(currency, locale, entries): if entry.date < min_entry.date: min_entry_index = i continue - if ( - entry.date == min_entry.date and - entry.change < min_entry.change - ): + if entry.date == min_entry.date and entry.change < min_entry.change: min_entry_index = i continue if ( - entry.date == min_entry.date and - entry.change == min_entry.change and - entry.description < min_entry.description + entry.date == min_entry.date + and entry.change == min_entry.change + and entry.description < min_entry.description ): min_entry_index = i continue @@ -64,117 +61,117 @@ def format_entries(currency, locale, entries): month = entry.date.month month = str(month) if len(month) < 2: - month = '0' + month + month = "0" + month date_str = month - date_str += '/' + date_str += "/" day = entry.date.day day = str(day) if len(day) < 2: - day = '0' + day + day = "0" + day date_str += day - date_str += '/' + date_str += "/" year = entry.date.year year = str(year) while len(year) < 4: - year = '0' + year + year = "0" + year date_str += year table += date_str - table += ' | ' + table += " | " # Write entry description to table # Truncate if necessary if len(entry.description) > 25: for i in range(22): table += entry.description[i] - table += '...' + table += "..." else: for i in range(25): if len(entry.description) > i: table += entry.description[i] else: - table += ' ' - table += ' | ' + table += " " + table += " | " # Write entry change to table - if currency == 'USD': - change_str = '' + if currency == "USD": + change_str = "" if entry.change < 0: - change_str = '(' - change_str += '$' + change_str = "(" + change_str += "$" change_dollar = abs(int(entry.change / 100.0)) dollar_parts = [] while change_dollar > 0: dollar_parts.insert(0, str(change_dollar % 1000)) change_dollar = change_dollar // 1000 if len(dollar_parts) == 0: - change_str += '0' + change_str += "0" else: while True: change_str += dollar_parts[0] dollar_parts.pop(0) if len(dollar_parts) == 0: break - change_str += ',' - change_str += '.' + change_str += "," + change_str += "." change_cents = abs(entry.change) % 100 change_cents = str(change_cents) if len(change_cents) < 2: - change_cents = '0' + change_cents + change_cents = "0" + change_cents change_str += change_cents if entry.change < 0: - change_str += ')' + change_str += ")" else: - change_str += ' ' + change_str += " " while len(change_str) < 13: - change_str = ' ' + change_str + change_str = " " + change_str table += change_str - elif currency == 'EUR': - change_str = '' + elif currency == "EUR": + change_str = "" if entry.change < 0: - change_str = '(' - change_str += u'€' + change_str = "(" + change_str += "€" change_euro = abs(int(entry.change / 100.0)) euro_parts = [] while change_euro > 0: euro_parts.insert(0, str(change_euro % 1000)) change_euro = change_euro // 1000 if len(euro_parts) == 0: - change_str += '0' + change_str += "0" else: while True: change_str += euro_parts[0] euro_parts.pop(0) if len(euro_parts) == 0: break - change_str += ',' - change_str += '.' + change_str += "," + change_str += "." change_cents = abs(entry.change) % 100 change_cents = str(change_cents) if len(change_cents) < 2: - change_cents = '0' + change_cents + change_cents = "0" + change_cents change_str += change_cents if entry.change < 0: - change_str += ')' + change_str += ")" else: - change_str += ' ' + change_str += " " while len(change_str) < 13: - change_str = ' ' + change_str + change_str = " " + change_str table += change_str return table - elif locale == 'nl_NL': + elif locale == "nl_NL": # Generate Header Row - table = 'Datum' + table = "Datum" for _ in range(6): - table += ' ' - table += '| Omschrijving' + table += " " + table += "| Omschrijving" for _ in range(14): - table += ' ' - table += '| Verandering' + table += " " + table += "| Verandering" for _ in range(2): - table += ' ' + table += " " while len(entries) > 0: - table += '\n' + table += "\n" # Find next entry in order min_entry_index = -1 @@ -187,16 +184,13 @@ def format_entries(currency, locale, entries): if entry.date < min_entry.date: min_entry_index = i continue - if ( - entry.date == min_entry.date and - entry.change < min_entry.change - ): + if entry.date == min_entry.date and entry.change < min_entry.change: min_entry_index = i continue if ( - entry.date == min_entry.date and - entry.change == min_entry.change and - entry.description < min_entry.description + entry.date == min_entry.date + and entry.change == min_entry.change + and entry.description < min_entry.description ): min_entry_index = i continue @@ -207,93 +201,92 @@ def format_entries(currency, locale, entries): day = entry.date.day day = str(day) if len(day) < 2: - day = '0' + day + day = "0" + day date_str = day - date_str += '-' + date_str += "-" month = entry.date.month month = str(month) if len(month) < 2: - month = '0' + month + month = "0" + month date_str += month - date_str += '-' + date_str += "-" year = entry.date.year year = str(year) while len(year) < 4: - year = '0' + year + year = "0" + year date_str += year table += date_str - table += ' | ' + table += " | " # Write entry description to table # Truncate if necessary if len(entry.description) > 25: for i in range(22): table += entry.description[i] - table += '...' + table += "..." else: for i in range(25): if len(entry.description) > i: table += entry.description[i] else: - table += ' ' - table += ' | ' + table += " " + table += " | " # Write entry change to table - if currency == 'USD': - change_str = '$ ' + if currency == "USD": + change_str = "$ " if entry.change < 0: - change_str += '-' + change_str += "-" change_dollar = abs(int(entry.change / 100.0)) dollar_parts = [] while change_dollar > 0: dollar_parts.insert(0, str(change_dollar % 1000)) change_dollar = change_dollar // 1000 if len(dollar_parts) == 0: - change_str += '0' + change_str += "0" else: while True: change_str += dollar_parts[0] dollar_parts.pop(0) if len(dollar_parts) == 0: break - change_str += '.' - change_str += ',' + change_str += "." + change_str += "," change_cents = abs(entry.change) % 100 change_cents = str(change_cents) if len(change_cents) < 2: - change_cents = '0' + change_cents + change_cents = "0" + change_cents change_str += change_cents - change_str += ' ' + change_str += " " while len(change_str) < 13: - change_str = ' ' + change_str + change_str = " " + change_str table += change_str - elif currency == 'EUR': - change_str = u'€ ' + elif currency == "EUR": + change_str = "€ " if entry.change < 0: - change_str += '-' + change_str += "-" change_euro = abs(int(entry.change / 100.0)) euro_parts = [] while change_euro > 0: euro_parts.insert(0, str(change_euro % 1000)) change_euro = change_euro // 1000 if len(euro_parts) == 0: - change_str += '0' + change_str += "0" else: while True: change_str += euro_parts[0] euro_parts.pop(0) if len(euro_parts) == 0: break - change_str += '.' - change_str += ',' + change_str += "." + change_str += "," change_cents = abs(entry.change) % 100 change_cents = str(change_cents) if len(change_cents) < 2: - change_cents = '0' + change_cents + change_cents = "0" + change_cents change_str += change_cents - change_str += ' ' + change_str += " " while len(change_str) < 13: - change_str = ' ' + change_str + change_str = " " + change_str table += change_str return table - diff --git a/exercises/practice/luhn/.articles/performance/code/Benchmark.py b/exercises/practice/luhn/.articles/performance/code/Benchmark.py index 27372f52824..7171169d9d7 100644 --- a/exercises/practice/luhn/.articles/performance/code/Benchmark.py +++ b/exercises/practice/luhn/.articles/performance/code/Benchmark.py @@ -2,8 +2,10 @@ loops = 1_000_000 -val = timeit.timeit("""Luhn("9999999999 9999999999 9999999999 9999999999").valid()""", - """ +val = ( + timeit.timeit( + """Luhn("9999999999 9999999999 9999999999 9999999999").valid()""", + """ class Luhn: def __init__(self, card_num): @@ -31,12 +33,18 @@ def luhny_bin(num): return False return pos > 1 and not total % 10 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"reversed for: {val}") -val = timeit.timeit("""Luhn("9999999999 9999999999 9999999999 9999999999").valid()""", - """ +val = ( + timeit.timeit( + """Luhn("9999999999 9999999999 9999999999 9999999999").valid()""", + """ class Luhn: def __init__(self, card_num): @@ -63,12 +71,18 @@ def luhny_bin(num): pos += 1 return pos > 1 and not total % 10 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"replace reverse enumerate: {val}") -val = timeit.timeit("""Luhn("9999999999 9999999999 9999999999 9999999999").valid()""", - """ +val = ( + timeit.timeit( + """Luhn("9999999999 9999999999 9999999999 9999999999").valid()""", + """ class Luhn: def __init__(self, card_num): self.isValid = Luhn.luhny_bin(0, 0, list(card_num[::-1])) @@ -95,6 +109,10 @@ def luhny_bin(pos, sum, chars): return Luhn.luhny_bin(pos, sum, tail) return False -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"recursion: {val}") diff --git a/exercises/practice/luhn/.meta/example.py b/exercises/practice/luhn/.meta/example.py index 32a4dbc48b9..1380d8c930d 100644 --- a/exercises/practice/luhn/.meta/example.py +++ b/exercises/practice/luhn/.meta/example.py @@ -2,7 +2,7 @@ class Luhn: def __init__(self, card_num): self.card_num = card_num self.checksum = -1 - digits = card_num.replace(' ', '') + digits = card_num.replace(" ", "") length = len(digits) if digits.isdigit() and length > 1: self.checksum = 0 diff --git a/exercises/practice/markdown/.meta/example.py b/exercises/practice/markdown/.meta/example.py index 1c9d04cf9e6..d332de9173d 100644 --- a/exercises/practice/markdown/.meta/example.py +++ b/exercises/practice/markdown/.meta/example.py @@ -2,49 +2,55 @@ def parse(markdown): - lines = markdown.split('\n') - html = '' + lines = markdown.split("\n") + html = "" in_list = False in_list_append = False for line in lines: result = parse_line(line, in_list, in_list_append) - html += result['line'] - in_list = result['in_list'] - in_list_append = result['in_list_append'] + html += result["line"] + in_list = result["in_list"] + in_list_append = result["in_list_append"] if in_list: - html += '' + html += "" return html def wrap(line, tag): - return '<{tag}>{line}'.format(line=line, tag=tag) + return "<{tag}>{line}".format(line=line, tag=tag) def check_headers(line): - pattern = '# (.*)' + pattern = "# (.*)" for index in range(6): if re.match(pattern, line): - return wrap(line[(index + 2):], 'h' + str(index + 1)) - pattern = '#' + pattern + return wrap(line[(index + 2) :], "h" + str(index + 1)) + pattern = "#" + pattern return line def check_bold(line): - bold_pattern = '(.*)__(.*)__(.*)' + bold_pattern = "(.*)__(.*)__(.*)" bold_match = re.match(bold_pattern, line) if bold_match: - return bold_match.group(1) + wrap(bold_match.group(2), 'strong')\ + return ( + bold_match.group(1) + + wrap(bold_match.group(2), "strong") + bold_match.group(3) + ) else: return None def check_italic(line): - italic_pattern = '(.*)_(.*)_(.*)' + italic_pattern = "(.*)_(.*)_(.*)" italic_match = re.match(italic_pattern, line) if italic_match: - return italic_match.group(1) + wrap(italic_match.group(2), 'em')\ + return ( + italic_match.group(1) + + wrap(italic_match.group(2), "em") + italic_match.group(3) + ) else: return None @@ -52,25 +58,24 @@ def check_italic(line): def parse_line(line, in_list, in_list_append): result = check_headers(line) - list_match = re.match(r'\* (.*)', result) + list_match = re.match(r"\* (.*)", result) if list_match: if not in_list: - result = '
    ' + wrap(list_match.group(1), 'li') + result = "
      " + wrap(list_match.group(1), "li") in_list = True else: - result = wrap(list_match.group(1), 'li') + result = wrap(list_match.group(1), "li") else: if in_list: in_list_append = True in_list = False - if not re.match(')(.*)()(.*)', - r'\1\2

      \3

      \4\5', result) + result = re.sub("(.*)(
    • )(.*)(
    • )(.*)", r"\1\2

      \3

      \4\5", result) while check_bold(result): result = check_bold(result) @@ -78,11 +83,7 @@ def parse_line(line, in_list, in_list_append): result = check_italic(result) if in_list_append: - result = '
    ' + result + result = "
" + result in_list_append = False - return { - 'line': result, - 'in_list': in_list, - 'in_list_append': in_list_append - } + return {"line": result, "in_list": in_list, "in_list_append": in_list_append} diff --git a/exercises/practice/markdown/markdown.py b/exercises/practice/markdown/markdown.py index 3c4bd2fa86a..763b0eb4da6 100644 --- a/exercises/practice/markdown/markdown.py +++ b/exercises/practice/markdown/markdown.py @@ -2,76 +2,84 @@ def parse(markdown): - lines = markdown.split('\n') - res = '' + lines = markdown.split("\n") + res = "" in_list = False in_list_append = False for i in lines: - if re.match('###### (.*)', i) is not None: - i = '
' + i[7:] + '
' - elif re.match('##### (.*)', i) is not None: - i = '
' + i[6:] + '
' - elif re.match('#### (.*)', i) is not None: - i = '

' + i[5:] + '

' - elif re.match('### (.*)', i) is not None: - i = '

' + i[4:] + '

' - elif re.match('## (.*)', i) is not None: - i = '

' + i[3:] + '

' - elif re.match('# (.*)', i) is not None: - i = '

' + i[2:] + '

' - m = re.match(r'\* (.*)', i) + if re.match("###### (.*)", i) is not None: + i = "
" + i[7:] + "
" + elif re.match("##### (.*)", i) is not None: + i = "
" + i[6:] + "
" + elif re.match("#### (.*)", i) is not None: + i = "

" + i[5:] + "

" + elif re.match("### (.*)", i) is not None: + i = "

" + i[4:] + "

" + elif re.match("## (.*)", i) is not None: + i = "

" + i[3:] + "

" + elif re.match("# (.*)", i) is not None: + i = "

" + i[2:] + "

" + m = re.match(r"\* (.*)", i) if m: if not in_list: in_list = True is_bold = False is_italic = False curr = m.group(1) - m1 = re.match('(.*)__(.*)__(.*)', curr) + m1 = re.match("(.*)__(.*)__(.*)", curr) if m1: - curr = m1.group(1) + '' + \ - m1.group(2) + '' + m1.group(3) + curr = ( + m1.group(1) + + "" + + m1.group(2) + + "" + + m1.group(3) + ) is_bold = True - m1 = re.match('(.*)_(.*)_(.*)', curr) + m1 = re.match("(.*)_(.*)_(.*)", curr) if m1: - curr = m1.group(1) + '' + m1.group(2) + \ - '' + m1.group(3) + curr = m1.group(1) + "" + m1.group(2) + "" + m1.group(3) is_italic = True - i = '
  • ' + curr + '
  • ' + i = "
    • " + curr + "
    • " else: is_bold = False is_italic = False curr = m.group(1) - m1 = re.match('(.*)__(.*)__(.*)', curr) + m1 = re.match("(.*)__(.*)__(.*)", curr) if m1: is_bold = True - m1 = re.match('(.*)_(.*)_(.*)', curr) + m1 = re.match("(.*)_(.*)_(.*)", curr) if m1: is_italic = True if is_bold: - curr = m1.group(1) + '' + \ - m1.group(2) + '' + m1.group(3) + curr = ( + m1.group(1) + + "" + + m1.group(2) + + "" + + m1.group(3) + ) if is_italic: - curr = m1.group(1) + '' + m1.group(2) + \ - '' + m1.group(3) - i = '
    • ' + curr + '
    • ' + curr = m1.group(1) + "" + m1.group(2) + "" + m1.group(3) + i = "
    • " + curr + "
    • " else: if in_list: in_list_append = True in_list = False - m = re.match('' - m = re.match('(.*)__(.*)__(.*)', i) + i = "

      " + i + "

      " + m = re.match("(.*)__(.*)__(.*)", i) if m: - i = m.group(1) + '' + m.group(2) + '' + m.group(3) - m = re.match('(.*)_(.*)_(.*)', i) + i = m.group(1) + "" + m.group(2) + "" + m.group(3) + m = re.match("(.*)_(.*)_(.*)", i) if m: - i = m.group(1) + '' + m.group(2) + '' + m.group(3) + i = m.group(1) + "" + m.group(2) + "" + m.group(3) if in_list_append: - i = '
    ' + i + i = "
" + i in_list_append = False res += i if in_list: - res += '' + res += "" return res diff --git a/exercises/practice/matching-brackets/.articles/performance/code/Benchmark.py b/exercises/practice/matching-brackets/.articles/performance/code/Benchmark.py index 1ca6ff0025a..2a9be659315 100644 --- a/exercises/practice/matching-brackets/.articles/performance/code/Benchmark.py +++ b/exercises/practice/matching-brackets/.articles/performance/code/Benchmark.py @@ -7,8 +7,9 @@ # ------------ FUNCTIONS TO TIME ------------- # + def stack_match1(input_string): - bracket_map = {"]" : "[", "}": "{", ")":"("} + bracket_map = {"]": "[", "}": "{", ")": "("} tracking = [] for element in input_string: @@ -21,9 +22,9 @@ def stack_match1(input_string): def stack_match2(input_string): - opening = {'[', '{', '('} - closing = {']', '}', ')'} - pairs = {('[', ']'), ('{', '}'), ('(', ')')} + opening = {"[", "{", "("} + closing = {"]", "}", ")"} + pairs = {("[", "]"), ("{", "}"), ("(", ")")} stack = list() for char in input_string: @@ -35,10 +36,9 @@ def stack_match2(input_string): return stack == [] - def stack_match3(input_string): - BRACKETS = {'(': ')', '[': ']', '{': '}'} - END_BRACKETS = {')', ']', '}'} + BRACKETS = {"(": ")", "[": "]", "{": "}"} + END_BRACKETS = {")", "]", "}"} stack = [] @@ -55,19 +55,19 @@ def is_valid(char): def stack_match4(input_string): - stack = [] - r = {')': '(', ']': '[', '}': '{'} - for c in input_string: - if c in '[{(': - stack.append(c) - if c in ']})': - if not stack: - return False - if stack[-1] == r[c]: - stack.pop() - else: - return False - return not stack + stack = [] + r = {")": "(", "]": "[", "}": "{"} + for c in input_string: + if c in "[{(": + stack.append(c) + if c in "]})": + if not stack: + return False + if stack[-1] == r[c]: + stack.pop() + else: + return False + return not stack from collections import deque @@ -94,41 +94,53 @@ def stack_match5(text: str) -> bool: def repeated_substitution1(text): text = "".join(x for x in text if x in "()[]{}") while "()" in text or "[]" in text or "{}" in text: - text = text.replace("()","").replace("[]", "").replace("{}","") + text = text.replace("()", "").replace("[]", "").replace("{}", "") return not text def repeated_substitution2(input_string): symbols = "".join(c for c in input_string if c in "{}[]()") - while (pair := next((pair for pair in ("{}", "[]", "()") if pair in symbols), False)): + while pair := next((pair for pair in ("{}", "[]", "()") if pair in symbols), False): symbols = symbols.replace(pair, "") return not symbols import re + def repeated_substitution3(str_: str) -> bool: - str_ = re.sub(r'[^{}\[\]()]', '', str_) - while str_ != (str_ := re.sub(r'{\}|\[]|\(\)', '', str_)): + str_ = re.sub(r"[^{}\[\]()]", "", str_) + while str_ != (str_ := re.sub(r"{\}|\[]|\(\)", "", str_)): pass return not bool(str_) def repeated_substitution4(input_string): replaced = re.sub(r"[^\[\(\{\}\)\]]|\{\}|\(\)|\[\]", "", input_string) - return not input_string if input_string == replaced else repeated_substitution4(replaced) + return ( + not input_string + if input_string == replaced + else repeated_substitution4(replaced) + ) + ## ---------END FUNCTIONS TO BE TIMED-------------------- ## ## -------- Timing Code Starts Here ---------------------## + def get_file(url): resp = requests.get(url) return resp.text + short = "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)" -mars_moons = get_file("https://raw.githubusercontent.com/colinleach/PTYS516/main/term_paper/term_paper.tex") -galaxy_cnn = get_file("https://raw.githubusercontent.com/colinleach/proj502/main/project_report/report.tex") +mars_moons = get_file( + "https://raw.githubusercontent.com/colinleach/PTYS516/main/term_paper/term_paper.tex" +) +galaxy_cnn = get_file( + "https://raw.githubusercontent.com/colinleach/proj502/main/project_report/report.tex" +) # Input Data Setup @@ -138,47 +150,58 @@ def get_file(url): assert all([stack_match1(txt) for txt in inputs]) # #Set up columns and rows for Pandas Data Frame -col_headers = ['short', 'mars_moons', 'galaxy_cnn'] +col_headers = ["short", "mars_moons", "galaxy_cnn"] row_headers = [ "stack_match1", "stack_match2", "stack_match3", "stack_match4", "stack_match5", - "repeated_substitution1", "repeated_substitution2", "repeated_substitution3", - "repeated_substitution4" - ] + "repeated_substitution4", +] # Empty dataframe will be filled in one cell at a time later df = pd.DataFrame(np.nan, index=row_headers, columns=col_headers) # Function List to Call When Timing -functions = [stack_match1, stack_match2, stack_match3, stack_match4, stack_match5, - repeated_substitution1, repeated_substitution2, repeated_substitution3, repeated_substitution4] +functions = [ + stack_match1, + stack_match2, + stack_match3, + stack_match4, + stack_match5, + repeated_substitution1, + repeated_substitution2, + repeated_substitution3, + repeated_substitution4, +] # Run timings using timeit.autorange(). Run Each Set 3 Times. for function, title in zip(functions, row_headers): - timings = [[ - timeit.Timer(lambda: function(data), globals=globals()).autorange()[1] / - timeit.Timer(lambda: function(data), globals=globals()).autorange()[0] - for data in inputs] for rounds in range(3)] + timings = [ + [ + timeit.Timer(lambda: function(data), globals=globals()).autorange()[1] + / timeit.Timer(lambda: function(data), globals=globals()).autorange()[0] + for data in inputs + ] + for rounds in range(3) + ] # Only the fastest Cycle counts. timing_result = min(timings) - print(f'{title}', f'Timings : {timing_result}') + print(f"{title}", f"Timings : {timing_result}") # Insert results into the dataframe - df.loc[title, col_headers[0]:col_headers[-1]] = timing_result + df.loc[title, col_headers[0] : col_headers[-1]] = timing_result # Save the data to avoid constantly regenerating it -df.to_feather('run_times.feather') +df.to_feather("run_times.feather") print("\nDataframe saved to './run_times.feather'") # The next bit is useful for `introduction.md` -pd.options.display.float_format = '{:,.2e}'.format -print('\nDataframe in Markdown format:\n') +pd.options.display.float_format = "{:,.2e}".format +print("\nDataframe in Markdown format:\n") print(df.to_markdown(floatfmt=".2e")) - diff --git a/exercises/practice/matching-brackets/.meta/example.py b/exercises/practice/matching-brackets/.meta/example.py index b37f13207ee..e219e9d8aac 100644 --- a/exercises/practice/matching-brackets/.meta/example.py +++ b/exercises/practice/matching-brackets/.meta/example.py @@ -1,5 +1,5 @@ def is_paired(input_string): - counterparts = {')': '(', '}': '{', ']': '['} + counterparts = {")": "(", "}": "{", "]": "["} stack = [] for char in input_string: diff --git a/exercises/practice/matrix/.meta/example.py b/exercises/practice/matrix/.meta/example.py index 3c89844bee8..f3b3619e04d 100644 --- a/exercises/practice/matrix/.meta/example.py +++ b/exercises/practice/matrix/.meta/example.py @@ -1,7 +1,8 @@ class Matrix: def __init__(self, matrix_string): - self.rows = [[int(number) for number in row.split()] - for row in matrix_string.split('\n')] + self.rows = [ + [int(number) for number in row.split()] for row in matrix_string.split("\n") + ] self.columns = [list(tup) for tup in zip(*self.rows)] def row(self, index): diff --git a/exercises/practice/meetup/.meta/example.py b/exercises/practice/meetup/.meta/example.py index d547107488c..43766ca7d2e 100644 --- a/exercises/practice/meetup/.meta/example.py +++ b/exercises/practice/meetup/.meta/example.py @@ -2,25 +2,27 @@ def meetup(year, month, week, day_of_week): - candidates = [date - for date in Calendar().itermonthdates(year, month) - if date.month == month - if date.strftime('%A') == day_of_week] + candidates = [ + date + for date in Calendar().itermonthdates(year, month) + if date.month == month + if date.strftime("%A") == day_of_week + ] return _choice(week)(candidates) def _choice(week): - if week == 'teenth': - return lambda dates: next(date for date in dates if - 13 <= date.day <= 19) + if week == "teenth": + return lambda dates: next(date for date in dates if 13 <= date.day <= 19) - ordinals = ('first', 'second', 'third', 'fourth', 'fifth', 'sixth') - day = -1 if (week == 'last') else (ordinals.index(week)) + ordinals = ("first", "second", "third", "fourth", "fifth", "sixth") + day = -1 if (week == "last") else (ordinals.index(week)) def _func(dates): if day < len(dates): return dates[day] - raise MeetupDayException('That day does not exist.') + raise MeetupDayException("That day does not exist.") + return _func @@ -30,5 +32,6 @@ class MeetupDayException(ValueError): message: explanation of the error. """ + def __init__(self, message): self.message = message diff --git a/exercises/practice/meetup/meetup.py b/exercises/practice/meetup/meetup.py index 10f6bcaacf1..3aaf8077a8c 100644 --- a/exercises/practice/meetup/meetup.py +++ b/exercises/practice/meetup/meetup.py @@ -5,6 +5,7 @@ class MeetupDayException(ValueError): message: explanation of the error. """ + def __init__(self): pass diff --git a/exercises/practice/minesweeper/.meta/example.py b/exercises/practice/minesweeper/.meta/example.py index 4ebbc8413b8..33c3228eac6 100644 --- a/exercises/practice/minesweeper/.meta/example.py +++ b/exercises/practice/minesweeper/.meta/example.py @@ -8,33 +8,33 @@ def annotate(minefield): for index1 in range(col_len): for index2 in range(row_len): - if board[index1][index2] != ' ': + if board[index1][index2] != " ": continue low = max(index2 - 1, 0) high = min(index2 + 2, row_len + 2) - counts = minefield[index1][low:high].count('*') + counts = minefield[index1][low:high].count("*") if index1 > 0: - counts += minefield[index1 - 1][low:high].count('*') + counts += minefield[index1 - 1][low:high].count("*") if index1 < col_len - 1: - counts += minefield[index1 + 1][low:high].count('*') + counts += minefield[index1 + 1][low:high].count("*") if counts == 0: continue board[index1][index2] = str(counts) - return [''.join(row) for row in board] + return ["".join(row) for row in board] def verify_board(minefield): # Rows with different lengths row_len = len(minefield[0]) if not all(len(row) == row_len for row in minefield): - raise ValueError('The board is invalid with current input.') + raise ValueError("The board is invalid with current input.") # Unknown character in board character_set = set() for row in minefield: character_set.update(row) - if character_set - set(' *'): - raise ValueError('The board is invalid with current input.') + if character_set - set(" *"): + raise ValueError("The board is invalid with current input.") diff --git a/exercises/practice/nth-prime/.meta/example.py b/exercises/practice/nth-prime/.meta/example.py index 73517c4b30b..1f6c10df6ad 100644 --- a/exercises/practice/nth-prime/.meta/example.py +++ b/exercises/practice/nth-prime/.meta/example.py @@ -4,7 +4,7 @@ def prime(number): if number < 1: - raise ValueError('there is no zeroth prime') + raise ValueError("there is no zeroth prime") known = [] candidates = prime_candidates() diff --git a/exercises/practice/ocr-numbers/.meta/example.py b/exercises/practice/ocr-numbers/.meta/example.py index bc926487ef4..7996a51c548 100644 --- a/exercises/practice/ocr-numbers/.meta/example.py +++ b/exercises/practice/ocr-numbers/.meta/example.py @@ -3,41 +3,46 @@ def split_ocr(ocr): - return [[ocr[idx][NUM_COLS * jam:NUM_COLS * (jam + 1)] for idx in range(NUM_ROWS)] - for jam in range(len(ocr[0]) // NUM_COLS)] + return [ + [ocr[idx][NUM_COLS * jam : NUM_COLS * (jam + 1)] for idx in range(NUM_ROWS)] + for jam in range(len(ocr[0]) // NUM_COLS) + ] -ALL = [' _ _ _ _ _ _ _ _ ', - ' | _| _||_||_ |_ ||_||_|| |', - ' ||_ _| | _||_| ||_| _||_|', - ' '] +ALL = [ + " _ _ _ _ _ _ _ _ ", + " | _| _||_||_ |_ ||_||_|| |", + " ||_ _| | _||_| ||_| _||_|", + " ", +] OCR_LIST = split_ocr(ALL) OCR_LIST = [OCR_LIST[-1]] + OCR_LIST[:9] def convert(input_grid): - split_indices = (list(range(0, len(input_grid), NUM_ROWS)) + - [len(input_grid)]) + split_indices = list(range(0, len(input_grid), NUM_ROWS)) + [len(input_grid)] - lines = [input_grid[start:end] - for start, end in zip(split_indices[:-1], split_indices[1:])] + lines = [ + input_grid[start:end] + for start, end in zip(split_indices[:-1], split_indices[1:]) + ] - return ','.join(convert_one_line(line) for line in lines) + return ",".join(convert_one_line(line) for line in lines) def convert_one_line(input_grid): if len(input_grid) != NUM_ROWS: - raise ValueError('Number of input lines is not a multiple of four') + raise ValueError("Number of input lines is not a multiple of four") if len(input_grid[0]) % NUM_COLS: - raise ValueError('Number of input columns is not a multiple of three') + raise ValueError("Number of input columns is not a multiple of three") numbers = split_ocr(input_grid) - digits = '' + digits = "" for num in numbers: try: digits += str(OCR_LIST.index(num)) except ValueError: - digits += '?' + digits += "?" return digits diff --git a/exercises/practice/ocr-numbers/ocr_numbers.py b/exercises/practice/ocr-numbers/ocr_numbers.py index 5e20881f165..5d753d548dc 100644 --- a/exercises/practice/ocr-numbers/ocr_numbers.py +++ b/exercises/practice/ocr-numbers/ocr_numbers.py @@ -1,3 +1,2 @@ def convert(input_grid): pass - diff --git a/exercises/practice/octal/.meta/example.py b/exercises/practice/octal/.meta/example.py index 86000ee4d34..9da7b560dbc 100644 --- a/exercises/practice/octal/.meta/example.py +++ b/exercises/practice/octal/.meta/example.py @@ -1,11 +1,10 @@ def parse_octal(digits): digits = _validate_octal(digits) - return sum(int(digit) * 8 ** idx - for (idx, digit) in enumerate(reversed(digits))) + return sum(int(digit) * 8**idx for (idx, digit) in enumerate(reversed(digits))) def _validate_octal(digits): for digit in digits: - if not '0' <= digit < '8': + if not "0" <= digit < "8": raise ValueError("Invalid octal digit: " + digit) return digits diff --git a/exercises/practice/octal/octal_test.py b/exercises/practice/octal/octal_test.py index 1f3a5ba5561..073a9f901a7 100644 --- a/exercises/practice/octal/octal_test.py +++ b/exercises/practice/octal/octal_test.py @@ -4,6 +4,7 @@ If the string supplied to parse_octal cannot be parsed as an octal number your program should raise a ValueError with a meaningful error message. """ + import unittest from octal import parse_octal @@ -48,5 +49,5 @@ def assertRaisesWithMessage(self, exception): return self.assertRaisesRegex(exception, r".+") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/paasio/paasio_test.py b/exercises/practice/paasio/paasio_test.py index c5c7ff73176..445b8bb6e79 100644 --- a/exercises/practice/paasio/paasio_test.py +++ b/exercises/practice/paasio/paasio_test.py @@ -199,13 +199,25 @@ def test_meteredsocket_stats_read_only(self): self.assertEqual(282, socket.send_bytes) self.assertEqual(258, socket.recv_ops) self.assertEqual(259, socket.recv_bytes) - with self.assertRaises(AttributeError, msg="property 'send_ops' of 'MeteredSocket' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'send_ops' of 'MeteredSocket' object has no setter", + ): socket.send_ops = 0 - with self.assertRaises(AttributeError, msg="property 'send_bytes' of 'MeteredSocket' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'send_bytes' of 'MeteredSocket' object has no setter", + ): socket.send_bytes = 0 - with self.assertRaises(AttributeError, msg="property 'recv_ops' of 'MeteredSocket' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'recv_ops' of 'MeteredSocket' object has no setter", + ): socket.recv_ops = 0 - with self.assertRaises(AttributeError, msg="property 'recv_bytes' of 'MeteredSocket' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'recv_bytes' of 'MeteredSocket' object has no setter", + ): socket.recv_bytes = 0 self.assertEqual(278, socket.send_ops) self.assertEqual(282, socket.send_bytes) @@ -426,13 +438,25 @@ def test_meteredfile_stats_read_only(self, super_mock): file.write(b"bytes") self.assertEqual(78, file.write_ops) self.assertEqual(82, file.write_bytes) - with self.assertRaises(AttributeError, msg="property 'write_ops' of 'MeteredFile' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'write_ops' of 'MeteredFile' object has no setter", + ): file.write_ops = 0 - with self.assertRaises(AttributeError, msg="property 'write_bytes' of 'MeteredFile' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'write_bytes' of 'MeteredFile' object has no setter", + ): file.write_bytes = 0 - with self.assertRaises(AttributeError, msg="property 'read_ops' of 'MeteredFile' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'read_ops' of 'MeteredFile' object has no setter", + ): file.read_ops = 0 - with self.assertRaises(AttributeError, msg="property 'read_bytes' of 'MeteredFile' object has no setter"): + with self.assertRaises( + AttributeError, + msg="property 'read_bytes' of 'MeteredFile' object has no setter", + ): file.read_bytes = 0 self.assertEqual(78, file.write_ops) self.assertEqual(82, file.write_bytes) diff --git a/exercises/practice/palindrome-products/.articles/performance/code/Benchmark.py b/exercises/practice/palindrome-products/.articles/performance/code/Benchmark.py index 9bfbbf35b31..1232776640d 100644 --- a/exercises/practice/palindrome-products/.articles/performance/code/Benchmark.py +++ b/exercises/practice/palindrome-products/.articles/performance/code/Benchmark.py @@ -10,8 +10,8 @@ def largest(min_factor, max_factor): raise ValueError("min must be <= max") result = 0 answer = [] - for number_a in range(min_factor, max_factor+1): - for number_b in range(min_factor, max_factor+1): + for number_a in range(min_factor, max_factor + 1): + for number_b in range(min_factor, max_factor + 1): if number_a * number_b >= result: test_value = str(number_a * number_b) if test_value == test_value[::-1]: @@ -29,8 +29,8 @@ def smallest(min_factor, max_factor): raise ValueError("min must be <= max") result = 0 answer = [] - for number_a in range(min_factor, max_factor+1): - for number_b in range(min_factor, max_factor+1): + for number_a in range(min_factor, max_factor + 1): + for number_b in range(min_factor, max_factor + 1): if number_a * number_b <= result or result == 0: test_value = str(number_a * number_b) if test_value == test_value[::-1]: @@ -42,17 +42,18 @@ def smallest(min_factor, max_factor): result = None return (result, answer) + def largest_optimized(min_factor, max_factor): if min_factor > max_factor: raise ValueError("min must be <= max") result = 0 answer = [] - for number_a in range(max_factor, min_factor - 1,-1): + for number_a in range(max_factor, min_factor - 1, -1): was_bigger = False for number_b in range(max_factor, number_a - 1, -1): if number_a * number_b >= result: was_bigger = True - test_value = str(number_a * number_b) + test_value = str(number_a * number_b) if test_value == test_value[::-1]: if number_a * number_b > result: answer = [] @@ -70,9 +71,9 @@ def smallest_optimized(min_factor, max_factor): raise ValueError("min must be <= max") result = 0 answer = [] - for number_a in range(min_factor, max_factor+1): + for number_a in range(min_factor, max_factor + 1): was_smaller = False - for number_b in range(min_factor, max_factor+1): + for number_b in range(min_factor, max_factor + 1): if number_a * number_b <= result or result == 0: was_smaller = True test_value = str(number_a * number_b) @@ -105,7 +106,6 @@ def smallest_optimized(min_factor, max_factor): print("smallest_optimized, min=1, max=1000 :", timeit.default_timer() - starttime) - starttime = timeit.default_timer() largest(100, 100000) print("largest, min=100, max=100000 :", timeit.default_timer() - starttime) diff --git a/exercises/practice/palindrome-products/.meta/example.py b/exercises/practice/palindrome-products/.meta/example.py index f656ff18522..b832ad4b709 100644 --- a/exercises/practice/palindrome-products/.meta/example.py +++ b/exercises/practice/palindrome-products/.meta/example.py @@ -3,22 +3,27 @@ def largest(min_factor, max_factor): - return get_extreme_palindrome_with_factors(max_factor, min_factor, 'largest') + return get_extreme_palindrome_with_factors(max_factor, min_factor, "largest") def smallest(max_factor, min_factor): - return get_extreme_palindrome_with_factors(max_factor, min_factor, 'smallest') + return get_extreme_palindrome_with_factors(max_factor, min_factor, "smallest") def get_extreme_palindrome_with_factors(max_factor, min_factor, extreme): - palindromes_found = palindromes(max_factor, min_factor, reverse=(extreme == 'largest')) + palindromes_found = palindromes( + max_factor, min_factor, reverse=(extreme == "largest") + ) factor_pairs = None for palindrome in palindromes_found: - factor_pairs = ((factor, palindrome // factor) - for factor in range(min_factor, max_factor + 1) - if palindrome % factor == 0) - factor_pairs = list(pair for pair in factor_pairs - if min_factor <= pair[1] <= max_factor) + factor_pairs = ( + (factor, palindrome // factor) + for factor in range(min_factor, max_factor + 1) + if palindrome % factor == 0 + ) + factor_pairs = list( + pair for pair in factor_pairs if min_factor <= pair[1] <= max_factor + ) if len(factor_pairs) > 0: break @@ -32,7 +37,7 @@ def reverse_num(number): reversed_nums = 0 while number > 0: reversed_nums *= 10 - reversed_nums += (number % 10) + reversed_nums += number % 10 number //= 10 return reversed_nums @@ -49,10 +54,10 @@ def palindromes(max_factor, min_factor, reverse=False): most of the palindromes just to find the one it needs. """ if max_factor < min_factor: - raise ValueError('min must be <= max') + raise ValueError("min must be <= max") - minimum = min_factor ** 2 - maximum = max_factor ** 2 + minimum = min_factor**2 + maximum = max_factor**2 def gen_palindromes_of_length(digit_count, reverse=reverse): """Generates all palindromes with `nd` number of digits that are @@ -60,19 +65,23 @@ def gen_palindromes_of_length(digit_count, reverse=reverse): Again, if `reverse` is True, the palindromes are generated in reverse order. """ - even_nd = (digit_count % 2 == 0) + even_nd = digit_count % 2 == 0 - min_left_half = max(10 ** (int(ceil(digit_count / 2)) - 1), - minimum // (10 ** (digit_count // 2))) - max_left_half = min((10 ** int(ceil(digit_count / 2))) - 1, - maximum // (10 ** (digit_count // 2))) + min_left_half = max( + 10 ** (int(ceil(digit_count / 2)) - 1), + minimum // (10 ** (digit_count // 2)), + ) + max_left_half = min( + (10 ** int(ceil(digit_count / 2))) - 1, + maximum // (10 ** (digit_count // 2)), + ) current_left_half = min_left_half if not reverse else max_left_half def make_palindrome(left_half, even_nd=False): - right_half = (reverse_num(left_half) - if even_nd - else reverse_num(left_half // 10)) + right_half = ( + reverse_num(left_half) if even_nd else reverse_num(left_half // 10) + ) return (left_half * (10 ** (digit_count // 2))) + right_half if not reverse: @@ -101,8 +110,8 @@ def make_palindrome(left_half, even_nd=False): min_nd = num_digits(minimum) max_nd = num_digits(maximum) - lengths = (range(min_nd, max_nd + 1) - if not reverse - else range(max_nd, min_nd - 1, -1)) + lengths = ( + range(min_nd, max_nd + 1) if not reverse else range(max_nd, min_nd - 1, -1) + ) return chain(*map(gen_palindromes_of_length, lengths)) diff --git a/exercises/practice/pangram/.articles/performance/code/Benchmark.py b/exercises/practice/pangram/.articles/performance/code/Benchmark.py index 1b423744479..621ba035797 100644 --- a/exercises/practice/pangram/.articles/performance/code/Benchmark.py +++ b/exercises/practice/pangram/.articles/performance/code/Benchmark.py @@ -2,18 +2,26 @@ loops = 1_000_000 -val = timeit.timeit("""is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", - """ +val = ( + timeit.timeit( + """is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", + """ from string import ascii_lowercase def is_pangram(sentence): return all(letter in sentence.lower() for letter in ascii_lowercase) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"all: {val}") -val = timeit.timeit("""is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", - """ +val = ( + timeit.timeit( + """is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", + """ from string import ascii_lowercase ALPHABET = set(ascii_lowercase) @@ -21,21 +29,33 @@ def is_pangram(sentence): def is_pangram(sentence): return ALPHABET.issubset(sentence.lower()) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"set: {val}") -val = timeit.timeit("""is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", - """ +val = ( + timeit.timeit( + """is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", + """ def is_pangram(sentence): return len([ltr for ltr in set(sentence.lower()) if ltr.isalpha()]) == 26 -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"len: {val}") -val = timeit.timeit("""is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", - """ +val = ( + timeit.timeit( + """is_pangram("Victor jagt zwölf_(12) Boxkämpfer quer über den großen Sylter Deich.")""", + """ A_LCASE = 97; A_UCASE = 65; ALL_26_BITS_SET = 67108863; @@ -49,6 +69,10 @@ def is_pangram(sentence): letter_flags |= 1 << (ord(letter) - A_UCASE) return letter_flags == ALL_26_BITS_SET -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"bit: {val}") diff --git a/exercises/practice/perfect-numbers/.meta/example.py b/exercises/practice/perfect-numbers/.meta/example.py index 3a3494817f4..fff76c259d9 100644 --- a/exercises/practice/perfect-numbers/.meta/example.py +++ b/exercises/practice/perfect-numbers/.meta/example.py @@ -1,5 +1,6 @@ import math + def divisor_generator(number): """Returns an unordered list of divisors for n (1 < number). @@ -15,20 +16,20 @@ def divisor_generator(number): def classify(number): - """ A perfect number equals the sum of its positive divisors. + """A perfect number equals the sum of its positive divisors. :param number: int a positive integer :return: str the classification of the input integer """ if number <= 0: - raise ValueError('Classification is only possible for positive integers.') + raise ValueError("Classification is only possible for positive integers.") aliquot_sum = sum(divisor_generator(number)) + (1 if number > 1 else 0) if aliquot_sum < number: - return 'deficient' + return "deficient" elif aliquot_sum == number: - return 'perfect' + return "perfect" else: - return 'abundant' + return "abundant" diff --git a/exercises/practice/perfect-numbers/perfect_numbers.py b/exercises/practice/perfect-numbers/perfect_numbers.py index eb093dd6c98..1b289ed0c8d 100644 --- a/exercises/practice/perfect-numbers/perfect_numbers.py +++ b/exercises/practice/perfect-numbers/perfect_numbers.py @@ -1,5 +1,5 @@ def classify(number): - """ A perfect number equals the sum of its positive divisors. + """A perfect number equals the sum of its positive divisors. :param number: int a positive integer :return: str the classification of the input integer diff --git a/exercises/practice/phone-number/.meta/example.py b/exercises/practice/phone-number/.meta/example.py index d23102a01ed..58b59f39be4 100644 --- a/exercises/practice/phone-number/.meta/example.py +++ b/exercises/practice/phone-number/.meta/example.py @@ -10,44 +10,44 @@ def __init__(self, number): self.subscriber_number = self.number[-4:] def pretty(self): - return f'({self.area_code})-{self.exchange_code}-{self.subscriber_number}' + return f"({self.area_code})-{self.exchange_code}-{self.subscriber_number}" def _clean(self, number): - preprocess = re.sub(r'[() +-.]', '', number) + preprocess = re.sub(r"[() +-.]", "", number) if any(item for item in preprocess if item.isalpha()): - raise ValueError('letters not permitted') + raise ValueError("letters not permitted") if any(item for item in preprocess if item in punctuation): - raise ValueError('punctuations not permitted') + raise ValueError("punctuations not permitted") return self._normalize(preprocess) def _normalize(self, number): if len(number) < 10: - raise ValueError('must not be fewer than 10 digits') + raise ValueError("must not be fewer than 10 digits") if len(number) > 11: - raise ValueError('must not be greater than 11 digits') - - if len(number) == 10 or len(number) == 11 and number.startswith('1'): - if number[-10] == '0': - raise ValueError('area code cannot start with zero') - elif number[-10] == '1': - raise ValueError('area code cannot start with one') - elif number[-7] == '0': - raise ValueError('exchange code cannot start with zero') - elif number[-7] == '1': - raise ValueError('exchange code cannot start with one') + raise ValueError("must not be greater than 11 digits") + + if len(number) == 10 or len(number) == 11 and number.startswith("1"): + if number[-10] == "0": + raise ValueError("area code cannot start with zero") + elif number[-10] == "1": + raise ValueError("area code cannot start with one") + elif number[-7] == "0": + raise ValueError("exchange code cannot start with zero") + elif number[-7] == "1": + raise ValueError("exchange code cannot start with one") else: - valid = number[-10] in '23456789' and number[-7] in '23456789' + valid = number[-10] in "23456789" and number[-7] in "23456789" else: valid = False - if number[0] in '023456789': - raise ValueError('11 digits must start with 1') + if number[0] in "023456789": + raise ValueError("11 digits must start with 1") if valid: return number[-10:] - return None # [Pylint]: R1710; + return None # [Pylint]: R1710; diff --git a/exercises/practice/pig-latin/.meta/example.py b/exercises/practice/pig-latin/.meta/example.py index f4b5ca575fb..a0b548e8b98 100644 --- a/exercises/practice/pig-latin/.meta/example.py +++ b/exercises/practice/pig-latin/.meta/example.py @@ -1,8 +1,8 @@ import re -re_cons = re.compile('^([^aeiou]?qu|[^aeiouy]+|y(?=[aeiou]))([a-z]*)') -re_vowel = re.compile('^([aeiou]|y[^aeiou]|xr)[a-z]*') +re_cons = re.compile("^([^aeiou]?qu|[^aeiouy]+|y(?=[aeiou]))([a-z]*)") +re_vowel = re.compile("^([aeiou]|y[^aeiou]|xr)[a-z]*") def split_initial_consonant_sound(word): @@ -17,8 +17,8 @@ def translate(text): words = [] for word in text.split(): if starts_with_vowel_sound(word): - words.append(word + 'ay') + words.append(word + "ay") else: head, tail = split_initial_consonant_sound(word) - words.append(tail + head + 'ay') - return ' '.join(words) + words.append(tail + head + "ay") + return " ".join(words) diff --git a/exercises/practice/point-mutations/point_mutations_test.py b/exercises/practice/point-mutations/point_mutations_test.py index 1977888bc32..d2a88e7496c 100644 --- a/exercises/practice/point-mutations/point_mutations_test.py +++ b/exercises/practice/point-mutations/point_mutations_test.py @@ -5,32 +5,34 @@ class PointMutationsTest(unittest.TestCase): def test_no_difference_between_empty_strands(self): - self.assertEqual(hamming_distance('', ''), 0) + self.assertEqual(hamming_distance("", ""), 0) def test_no_difference_between_identical_strands(self): - self.assertEqual(hamming_distance('GGACTGA', 'GGACTGA'), 0) + self.assertEqual(hamming_distance("GGACTGA", "GGACTGA"), 0) def test_complete_hamming_distance_in_small_strand(self): - self.assertEqual(hamming_distance('ACT', 'GGA'), 3) + self.assertEqual(hamming_distance("ACT", "GGA"), 3) def test_hamming_distance_in_off_by_one_strand(self): self.assertEqual( - hamming_distance('GGACGGATTCTGACCTGGACTAATTTTGGGG', - 'AGGACGGATTCTGACCTGGACTAATTTTGGGG'), 19) + hamming_distance( + "GGACGGATTCTGACCTGGACTAATTTTGGGG", "AGGACGGATTCTGACCTGGACTAATTTTGGGG" + ), + 19, + ) def test_small_hamming_distance_in_middle_somewhere(self): - self.assertEqual(hamming_distance('GGACG', 'GGTCG'), 1) + self.assertEqual(hamming_distance("GGACG", "GGTCG"), 1) def test_larger_distance(self): - self.assertEqual(hamming_distance('ACCAGGG', 'ACTATGG'), 2) + self.assertEqual(hamming_distance("ACCAGGG", "ACTATGG"), 2) def test_ignores_extra_length_on_other_strand_when_longer(self): - self.assertEqual(hamming_distance('AAACTAGGGG', 'AGGCTAGCGGTAGGAC'), 3) + self.assertEqual(hamming_distance("AAACTAGGGG", "AGGCTAGCGGTAGGAC"), 3) def test_ignores_extra_length_on_original_strand_when_longer(self): - self.assertEqual( - hamming_distance('GACTACGGACAGGGTAGGGAAT', 'GACATCGCACACC'), 5) + self.assertEqual(hamming_distance("GACTACGGACAGGGTAGGGAAT", "GACATCGCACACC"), 5) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/poker/.meta/example.py b/exercises/practice/poker/.meta/example.py index e650f143cd0..aa73166e32b 100644 --- a/exercises/practice/poker/.meta/example.py +++ b/exercises/practice/poker/.meta/example.py @@ -15,8 +15,8 @@ def allmax(iterable, key=None): def hand_rank(hand): - hand = hand.replace('10', 'T').split() - card_ranks = ['..23456789TJQKA'.index(idx) for idx, _ in hand] + hand = hand.replace("10", "T").split() + card_ranks = ["..23456789TJQKA".index(idx) for idx, _ in hand] groups = [(card_ranks.count(idx), idx) for idx in set(card_ranks)] groups.sort(reverse=True) counts, ranks = zip(*groups) @@ -24,13 +24,39 @@ def hand_rank(hand): ranks = (5, 4, 3, 2, 1) straight = (len(counts) == 5) and (max(ranks) - min(ranks) == 4) flush = len({idx for _, idx in hand}) == 1 - return (9 if counts == (5,) else - 8 if straight and flush else - 7 if counts == (4, 1) else - 6 if counts == (3, 2) else - 5 if flush else - 4 if straight else - 3 if counts == (3, 1, 1) else - 2 if counts == (2, 2, 1) else - 1 if counts == (2, 1, 1, 1) else - 0, ranks) + return ( + ( + 9 + if counts == (5,) + else ( + 8 + if straight and flush + else ( + 7 + if counts == (4, 1) + else ( + 6 + if counts == (3, 2) + else ( + 5 + if flush + else ( + 4 + if straight + else ( + 3 + if counts == (3, 1, 1) + else ( + 2 + if counts == (2, 2, 1) + else 1 if counts == (2, 1, 1, 1) else 0 + ) + ) + ) + ) + ) + ) + ) + ), + ranks, + ) diff --git a/exercises/practice/pov/.meta/example.py b/exercises/practice/pov/.meta/example.py index 9747d985e38..839ed593bf3 100644 --- a/exercises/practice/pov/.meta/example.py +++ b/exercises/practice/pov/.meta/example.py @@ -57,9 +57,7 @@ def from_pov(self, from_node): for child in tree.children: stack.append(child.add(tree.remove(child.label))) - raise ValueError('Tree could not be reoriented') - - + raise ValueError("Tree could not be reoriented") def path_to(self, from_node, to_node): reordered = self.from_pov(from_node) @@ -70,7 +68,7 @@ def path_to(self, from_node, to_node): try: tree = stack.pop() except IndexError as error: - raise ValueError('No path found') from error + raise ValueError("No path found") from error if to_node in tree: path.append(tree.label) stack = tree.children diff --git a/exercises/practice/protein-translation/.meta/example.py b/exercises/practice/protein-translation/.meta/example.py index e8c2ac29b5d..b17f4c36bd1 100644 --- a/exercises/practice/protein-translation/.meta/example.py +++ b/exercises/practice/protein-translation/.meta/example.py @@ -1,25 +1,38 @@ -CODONS = {'AUG': 'Methionine', 'UUU': 'Phenylalanine', - 'UUC': 'Phenylalanine', 'UUA': 'Leucine', 'UUG': 'Leucine', - 'UCU': 'Serine', 'UCC': 'Serine', 'UCA': 'Serine', - 'UCG': 'Serine', 'UAU': 'Tyrosine', 'UAC': 'Tyrosine', - 'UGU': 'Cysteine', 'UGC': 'Cysteine', 'UGG': 'Tryptophan', - 'UAA': 'STOP', 'UAG': 'STOP', 'UGA': 'STOP'} +CODONS = { + "AUG": "Methionine", + "UUU": "Phenylalanine", + "UUC": "Phenylalanine", + "UUA": "Leucine", + "UUG": "Leucine", + "UCU": "Serine", + "UCC": "Serine", + "UCA": "Serine", + "UCG": "Serine", + "UAU": "Tyrosine", + "UAC": "Tyrosine", + "UGU": "Cysteine", + "UGC": "Cysteine", + "UGG": "Tryptophan", + "UAA": "STOP", + "UAG": "STOP", + "UGA": "STOP", +} def of_codon(codon): if codon not in CODONS: - raise ValueError(f'Invalid codon: {codon}') + raise ValueError(f"Invalid codon: {codon}") return CODONS[codon] def proteins(strand): protein_list = [] for codon in map(of_codon, _chunkstring(strand, 3)): - if codon == 'STOP': + if codon == "STOP": break protein_list.append(codon) return protein_list def _chunkstring(string, number): - return (string[idx:number + idx] for idx in range(0, len(string), number)) + return (string[idx : number + idx] for idx in range(0, len(string), number)) diff --git a/exercises/practice/proverb/.meta/example.py b/exercises/practice/proverb/.meta/example.py index 8e6f30f5510..b03281309bb 100644 --- a/exercises/practice/proverb/.meta/example.py +++ b/exercises/practice/proverb/.meta/example.py @@ -2,10 +2,12 @@ def proverb(*rhyme_items, qualifier): print(rhyme_items) if not rhyme_items: return [] - phrases = [f'For want of a {element_1} the {element_2} was lost.' - for element_1, element_2 in zip(rhyme_items, rhyme_items[1:])] + phrases = [ + f"For want of a {element_1} the {element_2} was lost." + for element_1, element_2 in zip(rhyme_items, rhyme_items[1:]) + ] if qualifier: - phrases.append(f'And all for the want of a {qualifier} {rhyme_items[0]}.') + phrases.append(f"And all for the want of a {qualifier} {rhyme_items[0]}.") else: - phrases.append(f'And all for the want of a {rhyme_items[0]}.') + phrases.append(f"And all for the want of a {rhyme_items[0]}.") return phrases diff --git a/exercises/practice/pythagorean-triplet/.articles/performance/code/Benchmark.py b/exercises/practice/pythagorean-triplet/.articles/performance/code/Benchmark.py index a00e3fc68dd..c1d12966518 100644 --- a/exercises/practice/pythagorean-triplet/.articles/performance/code/Benchmark.py +++ b/exercises/practice/pythagorean-triplet/.articles/performance/code/Benchmark.py @@ -13,7 +13,7 @@ # create a dictionary with all the solution codes code = { - 'cubic': """ + "cubic": """ def triplets_with_sum(number): triplets = [] for a in range(1, number + 1): @@ -23,8 +23,7 @@ def triplets_with_sum(number): triplets.append([a, b, c]) return triplets """, - - 'quad_loose': """ + "quad_loose": """ def triplets_with_sum(number): triplets = [] for a in range(1, number + 1): @@ -34,8 +33,7 @@ def triplets_with_sum(number): triplets.append([a, b, c]) return triplets """, - - 'quad_tight': """ + "quad_tight": """ def triplets_with_sum(number): result = [] for c in range(5, number - 1): @@ -46,8 +44,7 @@ def triplets_with_sum(number): result.append([a, b, c]) return result """, - - 'linear_loop': """ + "linear_loop": """ from math import sqrt def triplets_with_sum(number): @@ -59,8 +56,7 @@ def triplets_with_sum(number): triplets.append([int((N - c - D) / 2), int((N - c + D) / 2), c]) return triplets """, - - 'linear_comp': """ + "linear_comp": """ def triplets_with_sum(number): def calculate_medium(small): return (number ** 2 - 2 * number * small) / (2 * (number - small)) @@ -71,17 +67,17 @@ def calculate_medium(small): return [[small, medium, (medium ** 2 + small ** 2) ** 0.5] for medium, small in two_sides] -""" +""", } # Workaround for needing to do fewer runs with slow code run_params = { - 'cubic': (5, n_values[:5]), - 'quad_loose': (0, n_values[:-1]), - 'quad_tight': (0, n_values[:-1]), - 'linear_loop': (1000, n_values), - 'linear_comp': (1000, n_values) + "cubic": (5, n_values[:5]), + "quad_loose": (0, n_values[:-1]), + "quad_tight": (0, n_values[:-1]), + "linear_loop": (1000, n_values), + "linear_comp": (1000, n_values), } # Run the timing tests - SLOW! @@ -90,7 +86,7 @@ def calculate_medium(small): loops = run_params[descriptor][0] for n in run_params[descriptor][1]: # ugly hack for the quadratic runs - if descriptor.startswith('quad'): + if descriptor.startswith("quad"): loops = 10 if n <= 10_000 else 3 # including a string comprehension in the timed part of the run would @@ -104,21 +100,21 @@ def calculate_medium(small): # Save the data to avoid constantly regenerating it -df.to_feather('run_times.feather') +df.to_feather("run_times.feather") print("\nDataframe saved to './run_times.feather'") # The next bit will be useful for `introduction.md` -pd.options.display.float_format = '{:,.2e}'.format -print('\nDataframe in Markdown format:\n') +pd.options.display.float_format = "{:,.2e}".format +print("\nDataframe in Markdown format:\n") print(df.to_markdown(floatfmt=".1e")) # To plot and fit the slopes, the df needs to be log10-transformed and transposed -pd.options.display.float_format = '{:,.2g}'.format +pd.options.display.float_format = "{:,.2g}".format log_n_values = np.log10(n_values) df[df == 0.0] = np.nan transposed = np.log10(df).T transposed = transposed.set_axis(log_n_values, axis=0) -transposed.to_feather('transposed_logs.feather') +transposed.to_feather("transposed_logs.feather") print("\nDataframe saved to './transposed_logs.feather'") diff --git a/exercises/practice/pythagorean-triplet/.articles/performance/code/create_plots.py b/exercises/practice/pythagorean-triplet/.articles/performance/code/create_plots.py index 59fa8896e10..292cf0b34fc 100644 --- a/exercises/practice/pythagorean-triplet/.articles/performance/code/create_plots.py +++ b/exercises/practice/pythagorean-triplet/.articles/performance/code/create_plots.py @@ -6,14 +6,14 @@ # These dataframes are slow to create, so they should be saved in Feather format try: - df = pd.read_feather('./run_times.feather') + df = pd.read_feather("./run_times.feather") except FileNotFoundError: print("File './run_times.feather' not found!") print("Please run './Benchmark.py' to create it.") exit(1) try: - transposed = pd.read_feather('./transposed_logs.feather') + transposed = pd.read_feather("./transposed_logs.feather") except FileNotFoundError: print("File './transposed_logs.feather' not found!") print("Please run './Benchmark.py' to create it.") @@ -21,22 +21,21 @@ # Ready to start creating plots -mpl.rcParams['axes.labelsize'] = 18 +mpl.rcParams["axes.labelsize"] = 18 # bar plot of actual run times -ax = df.plot.bar(figsize=(10, 7), - logy=True, - ylabel="time (s)", - fontsize=14, - width=0.8, - rot=0) -plt.savefig('../timeit_bar_plot.svg') +ax = df.plot.bar( + figsize=(10, 7), logy=True, ylabel="time (s)", fontsize=14, width=0.8, rot=0 +) +plt.savefig("../timeit_bar_plot.svg") # log-log plot of times vs n, to see slopes -transposed.plot(figsize=(8, 6), - marker='.', - markersize=10, - ylabel="$log_{10}(time)$ (s)", - xlabel="$log_{10}(n)$", - fontsize=14) -plt.savefig('../slopes.svg') +transposed.plot( + figsize=(8, 6), + marker=".", + markersize=10, + ylabel="$log_{10}(time)$ (s)", + xlabel="$log_{10}(n)$", + fontsize=14, +) +plt.savefig("../slopes.svg") diff --git a/exercises/practice/pythagorean-triplet/.articles/performance/code/fit_gradients.py b/exercises/practice/pythagorean-triplet/.articles/performance/code/fit_gradients.py index 22ace93f819..9a2fff1e051 100644 --- a/exercises/practice/pythagorean-triplet/.articles/performance/code/fit_gradients.py +++ b/exercises/practice/pythagorean-triplet/.articles/performance/code/fit_gradients.py @@ -6,7 +6,7 @@ # These dataframes are slow to create, so they should be saved in Feather format try: - transposed = pd.read_feather('./transposed_logs.feather') + transposed = pd.read_feather("./transposed_logs.feather") except FileNotFoundError: print("File './transposed_logs.feather' not found!") print("Please run './Benchmark.py' to create it.") @@ -20,6 +20,7 @@ # Do a least-squares fit to get the slopes, working around missing values # Apparently, it does need to be this complicated + def find_slope(name): log_times = transposed[name] missing = np.isnan(log_times) @@ -32,7 +33,6 @@ def find_slope(name): # Print the slope results slopes = [(name, find_slope(name)) for name in row_headers] -print('\nSlopes of log-log plots:') +print("\nSlopes of log-log plots:") for name, slope in slopes: - print(f'{name:>14} : {slope:.2f}') - + print(f"{name:>14} : {slope:.2f}") diff --git a/exercises/practice/pythagorean-triplet/.meta/example.py b/exercises/practice/pythagorean-triplet/.meta/example.py index 40b91444b26..7da39073703 100644 --- a/exercises/practice/pythagorean-triplet/.meta/example.py +++ b/exercises/practice/pythagorean-triplet/.meta/example.py @@ -36,8 +36,8 @@ def primitive_triplets(limit): for more information """ for member_1, member_2 in euclidian_coprimes(limit): - calc_1 = member_1 ** 2 - calc_2 = member_2 ** 2 + calc_1 = member_1**2 + calc_2 = member_2**2 alpha = calc_1 - calc_2 beta = 2 * member_1 * member_2 @@ -51,7 +51,7 @@ def primitive_triplets(limit): def triplets_with_sum(number): return [ - triplet for triplet - in triplets_in_range(1, number // 2) + triplet + for triplet in triplets_in_range(1, number // 2) if sum(triplet) == number - ] + ] diff --git a/exercises/practice/queen-attack/.meta/example.py b/exercises/practice/queen-attack/.meta/example.py index e9ae242ff2b..0edcb202f5f 100644 --- a/exercises/practice/queen-attack/.meta/example.py +++ b/exercises/practice/queen-attack/.meta/example.py @@ -1,13 +1,13 @@ class Queen: def __init__(self, row, column): if row < 0: - raise ValueError('row not positive') + raise ValueError("row not positive") if not 0 <= row <= 7: - raise ValueError('row not on board') + raise ValueError("row not on board") if column < 0: - raise ValueError('column not positive') + raise ValueError("column not positive") if not 0 <= column <= 7: - raise ValueError('column not on board') + raise ValueError("column not on board") self.row = row self.column = column @@ -15,7 +15,7 @@ def can_attack(self, another_queen): idx = abs(self.row - another_queen.row) edx = abs(self.column - another_queen.column) if idx == edx == 0: - raise ValueError('Invalid queen position: both queens in the same square') + raise ValueError("Invalid queen position: both queens in the same square") elif idx == edx or idx == 0 or edx == 0: return True else: diff --git a/exercises/practice/rail-fence-cipher/.meta/example.py b/exercises/practice/rail-fence-cipher/.meta/example.py index a27bd2670a8..6066faaae1f 100644 --- a/exercises/practice/rail-fence-cipher/.meta/example.py +++ b/exercises/practice/rail-fence-cipher/.meta/example.py @@ -8,10 +8,10 @@ def fence_pattern(rails, size): def encode(msg, rails): fence = fence_pattern(rails, len(msg)) - return ''.join(msg[idx] for _, idx in sorted(fence)) + return "".join(msg[idx] for _, idx in sorted(fence)) def decode(msg, rails): fence = fence_pattern(rails, len(msg)) fence_msg = zip(msg, sorted(fence)) - return ''.join(char for char, _ in sorted(fence_msg, key=lambda item: item[1][1])) + return "".join(char for char, _ in sorted(fence_msg, key=lambda item: item[1][1])) diff --git a/exercises/practice/raindrops/.articles/performance/code/Benchmark.py b/exercises/practice/raindrops/.articles/performance/code/Benchmark.py index b30a091e60c..91d3e28b73b 100644 --- a/exercises/practice/raindrops/.articles/performance/code/Benchmark.py +++ b/exercises/practice/raindrops/.articles/performance/code/Benchmark.py @@ -17,31 +17,35 @@ # ------------ FUNCTIONS TO TIME ------------- # + def convert_if_statements(num): - sounds = '' + sounds = "" - if num % 3 == 0: sounds += 'Pling' - if num % 5 == 0: sounds += 'Plang' - if num % 7 == 0: sounds += 'Plong' + if num % 3 == 0: + sounds += "Pling" + if num % 5 == 0: + sounds += "Plang" + if num % 7 == 0: + sounds += "Plong" return sounds if sounds else str(num) def convert_truthy_falsy(number): - threes = '' if number % 3 else 'Pling' # Empty string if there is a remainder - fives = '' if number % 5 else 'Plang' - sevens = '' if number % 7 else 'Plong' + threes = "" if number % 3 else "Pling" # Empty string if there is a remainder + fives = "" if number % 5 else "Plang" + sevens = "" if number % 7 else "Plong" - return f'{threes}{fives}{sevens}' or str(number) + return f"{threes}{fives}{sevens}" or str(number) def convert_loop(number): - sounds = '' + sounds = "" drops = ("i", 3), ("a", 5), ("o", 7) for vowel, factor in drops: if number % factor == 0: - sounds += f'Pl{vowel}ng' + sounds += f"Pl{vowel}ng" return sounds or str(number) @@ -49,53 +53,53 @@ def convert_loop(number): def convert_sequence_join(number): drops = ["Pling", "Plang", "Plong"] factors = [3, 5, 7] - sounds = ''.join(drops[index] for - index, factor in - enumerate(factors) if (number % factor == 0)) + sounds = "".join( + drops[index] for index, factor in enumerate(factors) if (number % factor == 0) + ) return sounds or str(number) def convert_dict(number): - sounds = {3: 'Pling', - 5: 'Plang', - 7: 'Plong'} + sounds = {3: "Pling", 5: "Plang", 7: "Plong"} - results = ''.join(sounds[divisor] for - divisor in sounds.keys() - if number % divisor == 0) + results = "".join( + sounds[divisor] for divisor in sounds.keys() if number % divisor == 0 + ) return results or str(number) def convert_dict_recommended(number): - sounds = {3: 'Pling', - 5: 'Plang', - 7: 'Plong'} + sounds = {3: "Pling", 5: "Plang", 7: "Plong"} - results = ''.join(sound for - divisor, sound in sounds.items() - if number % divisor == 0) + results = "".join( + sound for divisor, sound in sounds.items() if number % divisor == 0 + ) return results or str(number) from itertools import compress + def convert_itertools(number): - sounds = ('Pling', 'Plang', 'Plong') + sounds = ("Pling", "Plang", "Plong") mask = ((number % factor) == 0 for factor in (3, 5, 7)) - return ''.join(compress(sounds, mask)) or str(number) + return "".join(compress(sounds, mask)) or str(number) from functools import reduce + def convert_functools(number): - sounds = ('Pling', 'Plang', 'Plong') + sounds = ("Pling", "Plang", "Plong") factors = ((number % factor) == 0 for factor in (3, 5, 7)) - result = reduce(lambda sound, item: sound + (item[0] * item[1]), zip(sounds, factors), '') + result = reduce( + lambda sound, item: sound + (item[0] * item[1]), zip(sounds, factors), "" + ) return result or str(number) @@ -104,19 +108,19 @@ def convert_pattern_matching(number): match [(number % factor) == 0 for factor in (3, 5, 7)]: case [True, True, True]: - return 'PlingPlangPlong' + return "PlingPlangPlong" case [True, True, False]: - return 'PlingPlang' + return "PlingPlang" case [False, True, True]: - return 'PlangPlong' + return "PlangPlong" case [True, False, True]: - return 'PlingPlong' + return "PlingPlong" case [True, False, False]: - return 'Pling' + return "Pling" case [False, False, True]: - return 'Plong' + return "Plong" case [False, True, False]: - return 'Plang' + return "Plang" case _: return str(number) @@ -127,56 +131,105 @@ def convert_pattern_matching(number): # Input Data Setup -inputs = [1,5,7,6,8,9,10,14,15,21,27, 35, 49, 52, 70, 105, 144, 182, - 189, 195, 198, 203, 204, 210, 228, 231, 252, 315, 318, 329, - 340, 349, 379, 399, 409, 415, 497, 500, 525, 625, 735, 813, - 1575, 3125, 3250] +inputs = [ + 1, + 5, + 7, + 6, + 8, + 9, + 10, + 14, + 15, + 21, + 27, + 35, + 49, + 52, + 70, + 105, + 144, + 182, + 189, + 195, + 198, + 203, + 204, + 210, + 228, + 231, + 252, + 315, + 318, + 329, + 340, + 349, + 379, + 399, + 409, + 415, + 497, + 500, + 525, + 625, + 735, + 813, + 1575, + 3125, + 3250, +] # #Set up columns and rows for Pandas Data Frame -col_headers = [f'Number: {number}'for number in inputs] -row_headers = ["if statements", - "ternary with truthy/falsy", - "loop with tuple", - "sequence with join", - "dictionary with join", - "dictionary recommended" - "itertools with join", - "functools reduce", - "structural pattern matching"] +col_headers = [f"Number: {number}" for number in inputs] +row_headers = [ + "if statements", + "ternary with truthy/falsy", + "loop with tuple", + "sequence with join", + "dictionary with join", + "dictionary recommended" "itertools with join", + "functools reduce", + "structural pattern matching", +] # # empty dataframe will be filled in one cell at a time later df = pd.DataFrame(np.nan, index=row_headers, columns=col_headers) # #Function List to Call When Timing -functions = [convert_if_statements, - convert_truthy_falsy, - convert_loop, - convert_sequence_join, - convert_dict, - convert_dict_recommended, - convert_itertools, - convert_functools, - convert_pattern_matching] +functions = [ + convert_if_statements, + convert_truthy_falsy, + convert_loop, + convert_sequence_join, + convert_dict, + convert_dict_recommended, + convert_itertools, + convert_functools, + convert_pattern_matching, +] # Run timings using timeit.autorange(). Run Each Set 3 Times. for function, title in zip(functions, row_headers): - timings = [[ - timeit.Timer(lambda: function(data), globals=globals()).autorange()[1] / - timeit.Timer(lambda: function(data), globals=globals()).autorange()[0] - for data in inputs] for rounds in range(3)] + timings = [ + [ + timeit.Timer(lambda: function(data), globals=globals()).autorange()[1] + / timeit.Timer(lambda: function(data), globals=globals()).autorange()[0] + for data in inputs + ] + for rounds in range(3) + ] # Only the fastest Cycle counts. timing_result = min(timings) # timing_result = [round(min(timeit.repeat(lambda: function(data), repeat=3, number=1000000, globals=globals())), 6) for data in words_II] - print(f'{title}', f'Timings : {timing_result}') + print(f"{title}", f"Timings : {timing_result}") # Insert results into the dataframe - df.loc[title, 'Number: 1':'Number: 3250'] = timing_result + df.loc[title, "Number: 1":"Number: 3250"] = timing_result # The next bit is useful for `introduction.md` -pd.options.display.float_format = '{:,.2e}'.format -print('\nDataframe in Markdown format:\n') +pd.options.display.float_format = "{:,.2e}".format +print("\nDataframe in Markdown format:\n") print(df.to_markdown(floatfmt=".2e")) - diff --git a/exercises/practice/raindrops/.meta/example.py b/exercises/practice/raindrops/.meta/example.py index 97eeadc332b..4160ced6ea8 100644 --- a/exercises/practice/raindrops/.meta/example.py +++ b/exercises/practice/raindrops/.meta/example.py @@ -3,13 +3,13 @@ def convert(number): Converts a number to a string according to the raindrop sounds. """ - result = '' + result = "" if number % 3 == 0: - result += 'Pling' + result += "Pling" if number % 5 == 0: - result += 'Plang' + result += "Plang" if number % 7 == 0: - result += 'Plong' + result += "Plong" if not result: result = str(number) diff --git a/exercises/practice/rational-numbers/.meta/example.py b/exercises/practice/rational-numbers/.meta/example.py index d8a0b87be88..df44b540f82 100644 --- a/exercises/practice/rational-numbers/.meta/example.py +++ b/exercises/practice/rational-numbers/.meta/example.py @@ -17,7 +17,7 @@ def __eq__(self, other): return self.numer == other.numer and self.denom == other.denom def __repr__(self): - return f'{self.numer}/{self.denom}' + return f"{self.numer}/{self.denom}" def __add__(self, other): numer = (self.numer * other.denom) + (other.numer * self.denom) diff --git a/exercises/practice/rational-numbers/rational_numbers.py b/exercises/practice/rational-numbers/rational_numbers.py index d553c30b1b2..b18cbdf3ec8 100644 --- a/exercises/practice/rational-numbers/rational_numbers.py +++ b/exercises/practice/rational-numbers/rational_numbers.py @@ -7,7 +7,7 @@ def __eq__(self, other): return self.numer == other.numer and self.denom == other.denom def __repr__(self): - return f'{self.numer}/{self.denom}' + return f"{self.numer}/{self.denom}" def __add__(self, other): pass diff --git a/exercises/practice/react/react.py b/exercises/practice/react/react.py index ab6be311d97..03ff02e7891 100644 --- a/exercises/practice/react/react.py +++ b/exercises/practice/react/react.py @@ -12,4 +12,3 @@ def add_callback(self, callback): def remove_callback(self, callback): pass - \ No newline at end of file diff --git a/exercises/practice/rectangles/.meta/example.py b/exercises/practice/rectangles/.meta/example.py index fe665729d35..0b7b5fcee18 100644 --- a/exercises/practice/rectangles/.meta/example.py +++ b/exercises/practice/rectangles/.meta/example.py @@ -8,7 +8,7 @@ def __init__(self, idx, jdx): self.jdx = jdx def __str__(self): - return '[' + str(self.idx) + ', ' + str(self.jdx) + ']' + return "[" + str(self.idx) + ", " + str(self.jdx) + "]" # return corner on the same line @@ -29,9 +29,12 @@ def same_col(index, list_obj): def search_corners(list_obj): - return [Corners(item, element) for item in range(len(list_obj)) - for element in range(len(list_obj[item])) - if list_obj[item][element] == '+'] + return [ + Corners(item, element) + for item in range(len(list_obj)) + for element in range(len(list_obj[item])) + if list_obj[item][element] == "+" + ] # validate that 4 points form a rectangle by @@ -58,16 +61,18 @@ def possible_rect(quartet): # validate path between two corners def path(corner1, corner2, item): if corner1.idx == corner2.idx: - for jdx in range(min(corner1.jdx + 1, corner2.jdx + 1), - max(corner1.jdx, corner2.jdx)): - if item[corner1.idx][jdx] != '-' and item[corner1.idx][jdx] != '+': + for jdx in range( + min(corner1.jdx + 1, corner2.jdx + 1), max(corner1.jdx, corner2.jdx) + ): + if item[corner1.idx][jdx] != "-" and item[corner1.idx][jdx] != "+": return False return True elif corner1.jdx == corner2.jdx: - for idx in range(min(corner1.idx + 1, corner2.idx + 1), - max(corner1.idx, corner2.idx)): - if item[idx][corner1.jdx] != '|' and item[idx][corner1.jdx] != '+': + for idx in range( + min(corner1.idx + 1, corner2.idx + 1), max(corner1.idx, corner2.idx) + ): + if item[idx][corner1.jdx] != "|" and item[idx][corner1.jdx] != "+": return False return True return None @@ -78,17 +83,19 @@ def validate_rect(rectangle, item): # validate connection at every corner # with neighbours on the same line and col for idx, _ in enumerate(rectangle): - line = same_line(rectangle[idx].idx, rectangle[0:idx] + rectangle[idx + 1:]) - column = same_col(rectangle[idx].jdx, rectangle[0:idx] + rectangle[idx + 1:]) + line = same_line(rectangle[idx].idx, rectangle[0:idx] + rectangle[idx + 1 :]) + column = same_col(rectangle[idx].jdx, rectangle[0:idx] + rectangle[idx + 1 :]) - if not path(rectangle[idx], line, item) or not path(rectangle[idx], column, item): + if not path(rectangle[idx], line, item) or not path( + rectangle[idx], column, item + ): return False return True # count number of rectangles inside ASCII in input lines -def rectangles(strings=''): +def rectangles(strings=""): rectangle_total = 0 # test empty str if not strings: diff --git a/exercises/practice/resistor-color-duo/.meta/example.py b/exercises/practice/resistor-color-duo/.meta/example.py index 0f128593925..6b714699532 100644 --- a/exercises/practice/resistor-color-duo/.meta/example.py +++ b/exercises/practice/resistor-color-duo/.meta/example.py @@ -1,14 +1,14 @@ COLORS = [ - 'black', - 'brown', - 'red', - 'orange', - 'yellow', - 'green', - 'blue', - 'violet', - 'grey', - 'white' + "black", + "brown", + "red", + "orange", + "yellow", + "green", + "blue", + "violet", + "grey", + "white", ] diff --git a/exercises/practice/resistor-color-expert/.meta/example.py b/exercises/practice/resistor-color-expert/.meta/example.py index 0fd6e42fcd9..e86b77735cc 100644 --- a/exercises/practice/resistor-color-expert/.meta/example.py +++ b/exercises/practice/resistor-color-expert/.meta/example.py @@ -1,49 +1,53 @@ COLORS = [ - 'black', - 'brown', - 'red', - 'orange', - 'yellow', - 'green', - 'blue', - 'violet', - 'grey', - 'white' + "black", + "brown", + "red", + "orange", + "yellow", + "green", + "blue", + "violet", + "grey", + "white", ] COLORS_TOLERANCE = { - 'brown': 1, - 'red': 2, - 'green': 0.5, - 'blue': 0.25, - 'violet': 0.1, - 'grey': 0.05, - 'gold': 5, - 'silver': 10 + "brown": 1, + "red": 2, + "green": 0.5, + "blue": 0.25, + "violet": 0.1, + "grey": 0.05, + "gold": 5, + "silver": 10, } def resistor_label(colors): if len(colors) == 1: - return f'0 ohms' + return f"0 ohms" elif len(colors) == 4: value = 10 * COLORS.index(colors[0]) + COLORS.index(colors[1]) value *= 10 ** COLORS.index(colors[2]) value, unit = color_code(value) value = int(value) if value.is_integer() else value - return f'{value} {unit} ±{COLORS_TOLERANCE[colors[3]]}%' + return f"{value} {unit} ±{COLORS_TOLERANCE[colors[3]]}%" else: - value = 100 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) + value = ( + 100 * COLORS.index(colors[0]) + + 10 * COLORS.index(colors[1]) + + COLORS.index(colors[2]) + ) value *= 10 ** COLORS.index(colors[3]) value, unit = color_code(value) value = int(value) if value.is_integer() else value - return f'{value} {unit} ±{COLORS_TOLERANCE[colors[4]]}%' + return f"{value} {unit} ±{COLORS_TOLERANCE[colors[4]]}%" def color_code(color): if color < 1000: - return color / 1, 'ohms' + return color / 1, "ohms" elif color < 1000000: - return color / 1000, 'kiloohms' + return color / 1000, "kiloohms" else: - return color / 1000000, 'megaohms' \ No newline at end of file + return color / 1000000, "megaohms" diff --git a/exercises/practice/resistor-color-expert/resistor_color_expert_test.py b/exercises/practice/resistor-color-expert/resistor_color_expert_test.py index 47e7fc63440..08e613da9d7 100644 --- a/exercises/practice/resistor-color-expert/resistor_color_expert_test.py +++ b/exercises/practice/resistor-color-expert/resistor_color_expert_test.py @@ -9,13 +9,19 @@ class ResistorColorExpertTest(unittest.TestCase): def test_orange_orange_black_and_red(self): - self.assertEqual(resistor_label(["orange", "orange", "black", "red"]), "33 ohms ±2%") + self.assertEqual( + resistor_label(["orange", "orange", "black", "red"]), "33 ohms ±2%" + ) def test_blue_grey_brown_and_violet(self): - self.assertEqual(resistor_label(["blue", "grey", "brown", "violet"]), "680 ohms ±0.1%") + self.assertEqual( + resistor_label(["blue", "grey", "brown", "violet"]), "680 ohms ±0.1%" + ) def test_red_black_red_and_green(self): - self.assertEqual(resistor_label(["red", "black", "red", "green"]), "2 kiloohms ±0.5%") + self.assertEqual( + resistor_label(["red", "black", "red", "green"]), "2 kiloohms ±0.5%" + ) def test_green_brown_orange_and_grey(self): self.assertEqual( @@ -27,17 +33,20 @@ def test_one_black_band(self): def test_orange_orange_yellow_black_and_brown(self): self.assertEqual( - resistor_label(["orange", "orange", "yellow", "black", "brown"]), "334 ohms ±1%" + resistor_label(["orange", "orange", "yellow", "black", "brown"]), + "334 ohms ±1%", ) def test_red_green_yellow_yellow_and_brown(self): self.assertEqual( - resistor_label(["red", "green", "yellow", "yellow", "brown"]), "2.54 megaohms ±1%" + resistor_label(["red", "green", "yellow", "yellow", "brown"]), + "2.54 megaohms ±1%", ) def test_blue_grey_white_brown_and_brown(self): self.assertEqual( - resistor_label(["blue", "grey", "white", "brown", "brown"]), "6.89 kiloohms ±1%" + resistor_label(["blue", "grey", "white", "brown", "brown"]), + "6.89 kiloohms ±1%", ) def test_violet_orange_red_and_grey(self): @@ -47,12 +56,14 @@ def test_violet_orange_red_and_grey(self): def test_brown_red_orange_green_and_blue(self): self.assertEqual( - resistor_label(["brown", "red", "orange", "green", "blue"]), "12.3 megaohms ±0.25%" + resistor_label(["brown", "red", "orange", "green", "blue"]), + "12.3 megaohms ±0.25%", ) def test_brown_black_brown_yellow_and_violet(self): self.assertEqual( - resistor_label(["brown", "black", "brown", "yellow", "violet"]), "1.01 megaohms ±0.1%" + resistor_label(["brown", "black", "brown", "yellow", "violet"]), + "1.01 megaohms ±0.1%", ) def test_brown_black_red_and_red(self): diff --git a/exercises/practice/resistor-color-trio/.meta/example.py b/exercises/practice/resistor-color-trio/.meta/example.py index 69554592d06..3860e04123c 100644 --- a/exercises/practice/resistor-color-trio/.meta/example.py +++ b/exercises/practice/resistor-color-trio/.meta/example.py @@ -1,14 +1,14 @@ COLORS = [ - 'black', - 'brown', - 'red', - 'orange', - 'yellow', - 'green', - 'blue', - 'violet', - 'grey', - 'white' + "black", + "brown", + "red", + "orange", + "yellow", + "green", + "blue", + "violet", + "grey", + "white", ] @@ -17,16 +17,16 @@ def label(colors): value *= 10 ** COLORS.index(colors[2]) label = str(value) - if len(label) < 4 : - unit = 'ohms' + if len(label) < 4: + unit = "ohms" elif len(label) < 7: - label = str(value//1000) - unit = 'kiloohms' - elif len(label) <= 8 : - label = str(value//1000000) - unit = 'megaohms' + label = str(value // 1000) + unit = "kiloohms" + elif len(label) <= 8: + label = str(value // 1000000) + unit = "megaohms" elif len(label) >= 9: - label = str(value//1000000000) - unit = 'gigaohms' + label = str(value // 1000000000) + unit = "gigaohms" - return f'{value if value < 1000 else label} {unit}' + return f"{value if value < 1000 else label} {unit}" diff --git a/exercises/practice/resistor-color/.meta/example.py b/exercises/practice/resistor-color/.meta/example.py index 83c67f4f19a..3eb8897e62f 100644 --- a/exercises/practice/resistor-color/.meta/example.py +++ b/exercises/practice/resistor-color/.meta/example.py @@ -1,14 +1,14 @@ COLORS = [ - 'black', - 'brown', - 'red', - 'orange', - 'yellow', - 'green', - 'blue', - 'violet', - 'grey', - 'white' + "black", + "brown", + "red", + "orange", + "yellow", + "green", + "blue", + "violet", + "grey", + "white", ] diff --git a/exercises/practice/rest-api/.meta/example.py b/exercises/practice/rest-api/.meta/example.py index 46556efcedc..1cc2a89bb82 100644 --- a/exercises/practice/rest-api/.meta/example.py +++ b/exercises/practice/rest-api/.meta/example.py @@ -3,12 +3,12 @@ class RestAPI: def __init__(self, database=None): - self.database = database or {'users': []} + self.database = database or {"users": []} def update(self): - for user in self.database['users']: - owed_by = user['owed_by'] - owes = user['owes'] + for user in self.database["users"]: + owed_by = user["owed_by"] + owes = user["owes"] for debtor in list(owed_by.keys()): if debtor in owes: diff = 0 @@ -22,65 +22,62 @@ def update(self): owes[debtor] = diff elif diff < 0: owed_by[debtor] = -diff - user['balance'] = sum(owed_by.values()) - sum(owes.values()) + user["balance"] = sum(owed_by.values()) - sum(owes.values()) def get(self, url, payload=None): if payload is not None: payload = json.loads(payload) - if url == '/users': + if url == "/users": if payload is None: return json.dumps(self.database) else: - return json.dumps({ - 'users': [ - user for user in self.database['users'] - if user['name'] in payload['users'] - ] - }) + return json.dumps( + { + "users": [ + user + for user in self.database["users"] + if user["name"] in payload["users"] + ] + } + ) return None def post(self, url, payload=None): result = None if payload is not None: payload = json.loads(payload) - if url == '/add': + if url == "/add": if payload is not None: - name = payload['user'] - users = self.database['users'] + name = payload["user"] + users = self.database["users"] user = None for idx in users: - if idx['name'] == name: + if idx["name"] == name: user = idx break if user is None: - new_user = { - 'name': name, - 'owes': {}, - 'owed_by': {}, - 'balance': 0 - } + new_user = {"name": name, "owes": {}, "owed_by": {}, "balance": 0} users.append(new_user) self.update() result = json.dumps(new_user) - elif url == '/iou': + elif url == "/iou": if payload is not None: - lender_name = payload['lender'] - borrower_name = payload['borrower'] - amount = payload['amount'] + lender_name = payload["lender"] + borrower_name = payload["borrower"] + amount = payload["amount"] lender = borrower = None - for user in self.database['users']: - if user['name'] == lender_name: + for user in self.database["users"]: + if user["name"] == lender_name: lender = user - elif user['name'] == borrower_name: + elif user["name"] == borrower_name: borrower = user if lender is not None and borrower is not None: - lender['owed_by'].setdefault(borrower_name, 0) - lender['owed_by'][borrower_name] += amount - borrower['owes'].setdefault(lender_name, 0) - borrower['owes'][lender_name] += amount + lender["owed_by"].setdefault(borrower_name, 0) + lender["owed_by"][borrower_name] += amount + borrower["owes"].setdefault(lender_name, 0) + borrower["owes"][lender_name] += amount self.update() result = self.get( - '/users', - json.dumps({'users': [lender_name, borrower_name]}) + "/users", json.dumps({"users": [lender_name, borrower_name]}) ) return result diff --git a/exercises/practice/reverse-string/.meta/example.py b/exercises/practice/reverse-string/.meta/example.py index c8b38d5798b..3d6b8fb8c48 100644 --- a/exercises/practice/reverse-string/.meta/example.py +++ b/exercises/practice/reverse-string/.meta/example.py @@ -1,2 +1,2 @@ -def reverse(text=''): +def reverse(text=""): return text[::-1] diff --git a/exercises/practice/rna-transcription/.articles/performance/code/Benchmark.py b/exercises/practice/rna-transcription/.articles/performance/code/Benchmark.py index 3980aa1748a..6d9ba8fbebf 100644 --- a/exercises/practice/rna-transcription/.articles/performance/code/Benchmark.py +++ b/exercises/practice/rna-transcription/.articles/performance/code/Benchmark.py @@ -2,24 +2,36 @@ loops = 1_000_000 -val = timeit.timeit("""to_rna("ACGTGGTCTTAA")""", - """ +val = ( + timeit.timeit( + """to_rna("ACGTGGTCTTAA")""", + """ LOOKUP = str.maketrans("GCTA","CGAU") def to_rna(dna_strand): return dna_strand.translate(LOOKUP) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"translate maketrans: {val}") -val = timeit.timeit("""to_rna("ACGTGGTCTTAA")""", - """ +val = ( + timeit.timeit( + """to_rna("ACGTGGTCTTAA")""", + """ LOOKUP = {"G": "C", "C": "G", "T": "A", "A": "U"} def to_rna(dna_strand): return ''.join(LOOKUP[chr] for chr in dna_strand) -""", number=loops) / loops +""", + number=loops, + ) + / loops +) print(f"dictionary join: {val}") diff --git a/exercises/practice/rna-transcription/.meta/example.py b/exercises/practice/rna-transcription/.meta/example.py index 61db942ea3b..ed94e045ce4 100644 --- a/exercises/practice/rna-transcription/.meta/example.py +++ b/exercises/practice/rna-transcription/.meta/example.py @@ -1,4 +1,5 @@ DNA_TO_RNA = str.maketrans("AGCT", "UCGA") + def to_rna(dna_strand): return dna_strand.translate(DNA_TO_RNA) diff --git a/exercises/practice/robot-name/.meta/example.py b/exercises/practice/robot-name/.meta/example.py index 405142718ae..858702f688e 100644 --- a/exercises/practice/robot-name/.meta/example.py +++ b/exercises/practice/robot-name/.meta/example.py @@ -1,22 +1,18 @@ import random -ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + class Robot: def __init__(self): self._name = None self._past_names = set() def prefix(self): - return ''.join([ - random.choice(ALPHABET) - for _ in range(0, 2) - ]) + return "".join([random.choice(ALPHABET) for _ in range(0, 2)]) def suffix(self): - return ''.join([ - str(random.choice(range(0, 10))) - for _ in range(0, 3) - ]) + return "".join([str(random.choice(range(0, 10))) for _ in range(0, 3)]) def get_name(self): if not self._name: diff --git a/exercises/practice/robot-name/robot_name_test.py b/exercises/practice/robot-name/robot_name_test.py index 1062ad2f20c..b107bae8f35 100644 --- a/exercises/practice/robot-name/robot_name_test.py +++ b/exercises/practice/robot-name/robot_name_test.py @@ -10,7 +10,7 @@ class RobotNameTest(unittest.TestCase): if not hasattr(unittest.TestCase, "assertRegex"): assertRegex = unittest.TestCase.assertRegexpMatches - name_re = r'^[A-Z]{2}\d{3}$' + name_re = r"^[A-Z]{2}\d{3}$" def test_has_name(self): self.assertRegex(Robot().name, self.name_re) @@ -21,10 +21,7 @@ def test_name_sticks(self): self.assertEqual(robot.name, robot.name) def test_different_robots_have_different_names(self): - self.assertNotEqual( - Robot().name, - Robot().name - ) + self.assertNotEqual(Robot().name, Robot().name) def test_reset_name(self): # Set a seed @@ -47,5 +44,5 @@ def test_reset_name(self): self.assertRegex(name2, self.name_re) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/robot-simulator/.meta/example.py b/exercises/practice/robot-simulator/.meta/example.py index 20caf3bedcb..f34748f07c1 100644 --- a/exercises/practice/robot-simulator/.meta/example.py +++ b/exercises/practice/robot-simulator/.meta/example.py @@ -37,9 +37,7 @@ def turn_right(self): self.compass.right() def move(self, commands): - instructions = {'A': self.advance, - 'R': self.turn_right, - 'L': self.turn_left} + instructions = {"A": self.advance, "R": self.turn_right, "L": self.turn_left} for cmd in commands: if cmd in instructions: instructions[cmd]() diff --git a/exercises/practice/roman-numerals/.meta/example.py b/exercises/practice/roman-numerals/.meta/example.py index c6e56ec03ba..a9fbd19e649 100644 --- a/exercises/practice/roman-numerals/.meta/example.py +++ b/exercises/practice/roman-numerals/.meta/example.py @@ -1,16 +1,22 @@ NUMERAL_MAPPINGS = ( - (1000, 'M'), (900, 'CM'), - (500, 'D'), (400, 'CD'), - (100, 'C'), (90, 'XC'), - (50, 'L'), (40, 'XL'), - (10, 'X'), (9, 'IX'), - (5, 'V'), (4, 'IV'), - (1, 'I') + (1000, "M"), + (900, "CM"), + (500, "D"), + (400, "CD"), + (100, "C"), + (90, "XC"), + (50, "L"), + (40, "XL"), + (10, "X"), + (9, "IX"), + (5, "V"), + (4, "IV"), + (1, "I"), ) def roman(number): - result = '' + result = "" for arabic_num, roman_num in NUMERAL_MAPPINGS: while number >= arabic_num: result += roman_num diff --git a/exercises/practice/roman-numerals/roman_numerals.py b/exercises/practice/roman-numerals/roman_numerals.py index 96f266dc4aa..f52e854e18a 100644 --- a/exercises/practice/roman-numerals/roman_numerals.py +++ b/exercises/practice/roman-numerals/roman_numerals.py @@ -1,3 +1,2 @@ def roman(number): pass - diff --git a/exercises/practice/rotational-cipher/.articles/performance/code/Benchmark.py b/exercises/practice/rotational-cipher/.articles/performance/code/Benchmark.py index 2919024a1f2..7fe2d1d2a42 100644 --- a/exercises/practice/rotational-cipher/.articles/performance/code/Benchmark.py +++ b/exercises/practice/rotational-cipher/.articles/performance/code/Benchmark.py @@ -7,9 +7,12 @@ AlPHABET = "abcdefghijklmnopqrstuvwxyz" -COMBINATIONS = itertools.combinations_with_replacement(f"{AlPHABET[:13]}{AlPHABET[:13].upper()} 12,", 2) +COMBINATIONS = itertools.combinations_with_replacement( + f"{AlPHABET[:13]}{AlPHABET[:13].upper()} 12,", 2 +) TEST_TEST = "".join([element for sublist in COMBINATIONS for element in sublist]) + def rotate_ascii(text, key): result = "" for letter in text: @@ -38,7 +41,9 @@ def rotate_alphabet(text, key): def rotate_translate(text, key): translator = AlPHABET[key:] + AlPHABET[:key] - return text.translate(str.maketrans(AlPHABET + AlPHABET.upper(), translator + translator.upper())) + return text.translate( + str.maketrans(AlPHABET + AlPHABET.upper(), translator + translator.upper()) + ) def rotate_recursion(text, key): @@ -47,14 +52,17 @@ def rotate_recursion(text, key): first_letter, rest = text[0], text[1:] if first_letter.isalpha(): if first_letter.isupper(): - return AlPHABET[(AlPHABET.index(first_letter.lower()) + key) % 26].upper() + rotate_recursion(rest, key) + return AlPHABET[ + (AlPHABET.index(first_letter.lower()) + key) % 26 + ].upper() + rotate_recursion(rest, key) else: - return AlPHABET[(AlPHABET.index(first_letter) + key) % 26] + rotate_recursion(rest, key) + return AlPHABET[ + (AlPHABET.index(first_letter) + key) % 26 + ] + rotate_recursion(rest, key) else: return first_letter + rotate_recursion(rest, key) - start_time = timeit.default_timer() rotate_ascii(TEST_TEST, 25) print("rotate ascii long :", timeit.default_timer() - start_time) @@ -72,7 +80,6 @@ def rotate_recursion(text, key): print("rotate recursion long :", timeit.default_timer() - start_time) - start_time = timeit.default_timer() rotate_ascii("abcABC -12", 11) print("rotate ascii short :", timeit.default_timer() - start_time) diff --git a/exercises/practice/rotational-cipher/.meta/example.py b/exercises/practice/rotational-cipher/.meta/example.py index 33263275421..20d4926d23d 100644 --- a/exercises/practice/rotational-cipher/.meta/example.py +++ b/exercises/practice/rotational-cipher/.meta/example.py @@ -5,7 +5,7 @@ def rotate(message, key): - coded_message = '' + coded_message = "" for char in message: if char in ascii_lowercase: char = ascii_lowercase[(ascii_lowercase.index(char) + key) % ALPHA_LEN] diff --git a/exercises/practice/run-length-encoding/.meta/example.py b/exercises/practice/run-length-encoding/.meta/example.py index 309c8a3b1d2..33e60209c6d 100644 --- a/exercises/practice/run-length-encoding/.meta/example.py +++ b/exercises/practice/run-length-encoding/.meta/example.py @@ -3,11 +3,12 @@ def decode(string): - return sub(r'(\d+)(\D)', lambda main: main.group(2) * int(main.group(1)), string) + return sub(r"(\d+)(\D)", lambda main: main.group(2) * int(main.group(1)), string) def encode(string): def single_helper(key, group): size = len(list(group)) return key if size == 1 else str(size) + key - return ''.join(single_helper(key, group) for key, group in groupby(string)) + + return "".join(single_helper(key, group) for key, group in groupby(string)) diff --git a/exercises/practice/saddle-points/.meta/example.py b/exercises/practice/saddle-points/.meta/example.py index ff11e68a516..86a7cd37027 100644 --- a/exercises/practice/saddle-points/.meta/example.py +++ b/exercises/practice/saddle-points/.meta/example.py @@ -3,14 +3,16 @@ def saddle_points(matrix): return [] if any(len(row) != len(matrix[0]) for row in matrix): - raise ValueError('irregular matrix') + raise ValueError("irregular matrix") mmax = [max(row) for row in matrix] mmin = [min(col) for col in zip(*matrix)] - points = [{'row': index + 1, 'column': col_index + 1} - for index, _ in enumerate(matrix) - for col_index, _ in enumerate(matrix[0]) - if mmax[index] == mmin[col_index]] + points = [ + {"row": index + 1, "column": col_index + 1} + for index, _ in enumerate(matrix) + for col_index, _ in enumerate(matrix[0]) + if mmax[index] == mmin[col_index] + ] return points or [] diff --git a/exercises/practice/satellite/.meta/example.py b/exercises/practice/satellite/.meta/example.py index 310a89aeed1..fef73ef9ae7 100644 --- a/exercises/practice/satellite/.meta/example.py +++ b/exercises/practice/satellite/.meta/example.py @@ -1,16 +1,16 @@ def tree_from_traversals(preorder, inorder): if len(preorder) != len(inorder): - raise ValueError('traversals must have the same length') + raise ValueError("traversals must have the same length") if set(preorder) != set(inorder): - raise ValueError('traversals must have the same elements') + raise ValueError("traversals must have the same elements") if len(set(preorder)) != len(preorder) != len(set(inorder)): - raise ValueError('traversals must contain unique items') + raise ValueError("traversals must contain unique items") if not preorder: return {} value = preorder.pop(0) index = inorder.index(value) - left_inorder, right_inorder = inorder[:index], inorder[index+1:] + left_inorder, right_inorder = inorder[:index], inorder[index + 1 :] left_preorder = [idx for idx in preorder if idx in left_inorder] right_preorder = [idx for idx in preorder if idx in right_inorder] @@ -18,4 +18,4 @@ def tree_from_traversals(preorder, inorder): left = tree_from_traversals(left_preorder, left_inorder) right = tree_from_traversals(right_preorder, right_inorder) - return {'v': value, 'l': left, 'r': right} + return {"v": value, "l": left, "r": right} diff --git a/exercises/practice/say/.meta/example.py b/exercises/practice/say/.meta/example.py index 95d6d44770f..7a409f4e155 100644 --- a/exercises/practice/say/.meta/example.py +++ b/exercises/practice/say/.meta/example.py @@ -1,11 +1,41 @@ def say(number): - small = dict(enumerate(( - 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', - 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', - 'sixteen', 'seventeen', 'eighteen', 'nineteen'))) + small = dict( + enumerate( + ( + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten", + "eleven", + "twelve", + "thirteen", + "fourteen", + "fifteen", + "sixteen", + "seventeen", + "eighteen", + "nineteen", + ) + ) + ) - tens = {20: 'twenty', 30: 'thirty', 40: 'forty', 50: 'fifty', - 60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety'} + tens = { + 20: "twenty", + 30: "thirty", + 40: "forty", + 50: "fifty", + 60: "sixty", + 70: "seventy", + 80: "eighty", + 90: "ninety", + } kilo = 1e3 mega = 1e6 @@ -13,9 +43,9 @@ def say(number): tera = 1e12 if number < 0: - raise ValueError('input out of range') + raise ValueError("input out of range") if number >= tera: - raise ValueError('input out of range') + raise ValueError("input out of range") if number < 20: return small[number] @@ -23,23 +53,23 @@ def say(number): if number < 100: if number % 10 == 0: return tens[number] - return tens[number // 10 * 10] + '-' + small[number % 10] + return tens[number // 10 * 10] + "-" + small[number % 10] if number < kilo: if number % 100 == 0: - return small[number // 100] + ' hundred' - return small[number // 100] + ' hundred ' + say(number % 100) + return small[number // 100] + " hundred" + return small[number // 100] + " hundred " + say(number % 100) if number < mega: if number % kilo == 0: - return say(number // kilo) + ' thousand' - return say(number // kilo) + ' thousand ' + say(number % kilo) + return say(number // kilo) + " thousand" + return say(number // kilo) + " thousand " + say(number % kilo) if number < giga: if number % mega == 0: - return say(number // mega) + ' million' - return say(number // mega) + ' million ' + say(number % mega) + return say(number // mega) + " million" + return say(number // mega) + " million " + say(number % mega) if number % giga == 0: - return say(number // giga) + ' billion' - return say(number // giga) + ' billion ' + say(number % giga) \ No newline at end of file + return say(number // giga) + " billion" + return say(number // giga) + " billion " + say(number % giga) diff --git a/exercises/practice/scale-generator/.meta/example.py b/exercises/practice/scale-generator/.meta/example.py index 19c0c816c82..249a125df60 100644 --- a/exercises/practice/scale-generator/.meta/example.py +++ b/exercises/practice/scale-generator/.meta/example.py @@ -1,13 +1,30 @@ class Scale: - ASCENDING_INTERVALS = ['m', 'M', 'A'] - CHROMATIC_SCALE = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'] - FLAT_CHROMATIC_SCALE = ['A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab'] - FLAT_KEYS = ['F', 'Bb', 'Eb', 'Ab', 'Db', 'Gb', 'd', 'g', 'c', 'f', 'bb', 'eb'] + ASCENDING_INTERVALS = ["m", "M", "A"] + CHROMATIC_SCALE = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"] + FLAT_CHROMATIC_SCALE = [ + "A", + "Bb", + "B", + "C", + "Db", + "D", + "Eb", + "E", + "F", + "Gb", + "G", + "Ab", + ] + FLAT_KEYS = ["F", "Bb", "Eb", "Ab", "Db", "Gb", "d", "g", "c", "f", "bb", "eb"] def __init__(self, tonic, intervals=None): self.tonic = tonic.capitalize() self.intervals = intervals - self.chromatic_scale = (self.FLAT_CHROMATIC_SCALE if tonic in self.FLAT_KEYS else self.CHROMATIC_SCALE) + self.chromatic_scale = ( + self.FLAT_CHROMATIC_SCALE + if tonic in self.FLAT_KEYS + else self.CHROMATIC_SCALE + ) def chromatic(self): return self._reorder_chromatic_scale() @@ -27,4 +44,4 @@ def interval(self, intervals): def _reorder_chromatic_scale(self): index = self.chromatic_scale.index(self.tonic) - return self.chromatic_scale[index:] + self.chromatic_scale[:index] + return self.chromatic_scale[index:] + self.chromatic_scale[:index] diff --git a/exercises/practice/scrabble-score/.meta/example.py b/exercises/practice/scrabble-score/.meta/example.py index 8ab7d58df09..e78f18984fb 100644 --- a/exercises/practice/scrabble-score/.meta/example.py +++ b/exercises/practice/scrabble-score/.meta/example.py @@ -1,10 +1,30 @@ POINTS = { - 'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, - 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, - 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, - 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, - 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, - 'z': 10 + "a": 1, + "b": 3, + "c": 3, + "d": 2, + "e": 1, + "f": 4, + "g": 2, + "h": 4, + "i": 1, + "j": 8, + "k": 5, + "l": 1, + "m": 3, + "n": 1, + "o": 1, + "p": 3, + "q": 10, + "r": 1, + "s": 1, + "t": 1, + "u": 1, + "v": 4, + "w": 4, + "x": 8, + "y": 4, + "z": 10, } diff --git a/exercises/practice/secret-handshake/.meta/example.py b/exercises/practice/secret-handshake/.meta/example.py index 14e681d9350..7728b5cfaea 100644 --- a/exercises/practice/secret-handshake/.meta/example.py +++ b/exercises/practice/secret-handshake/.meta/example.py @@ -1,7 +1,7 @@ -GESTURES = ['jump', 'close your eyes', 'double blink', 'wink'] +GESTURES = ["jump", "close your eyes", "double blink", "wink"] def commands(binary_str): - reverse, *bits = [digit == '1' for digit in binary_str] + reverse, *bits = [digit == "1" for digit in binary_str] actions = [gesture for gesture, bit in zip(GESTURES, bits) if bit] return actions if reverse else actions[::-1] diff --git a/exercises/practice/series/.meta/example.py b/exercises/practice/series/.meta/example.py index 447819fc505..04db528b0a4 100644 --- a/exercises/practice/series/.meta/example.py +++ b/exercises/practice/series/.meta/example.py @@ -1,11 +1,11 @@ def slices(series, length): if not series: - raise ValueError('series cannot be empty') + raise ValueError("series cannot be empty") elif length == 0: - raise ValueError('slice length cannot be zero') + raise ValueError("slice length cannot be zero") elif length < 0: - raise ValueError('slice length cannot be negative') + raise ValueError("slice length cannot be negative") elif len(series) < length: - raise ValueError('slice length cannot be greater than series length') + raise ValueError("slice length cannot be greater than series length") - return [series[idx:idx + length] for idx in range(len(series) - length + 1)] + return [series[idx : idx + length] for idx in range(len(series) - length + 1)] diff --git a/exercises/practice/sgf-parsing/.meta/example.py b/exercises/practice/sgf-parsing/.meta/example.py index 2b14e371530..dbaacde79d1 100644 --- a/exercises/practice/sgf-parsing/.meta/example.py +++ b/exercises/practice/sgf-parsing/.meta/example.py @@ -1,4 +1,5 @@ """Parse an SGF tree.""" + from __future__ import annotations import collections @@ -27,7 +28,7 @@ def parse_property_vals(sgf: str, idx: int) -> tuple[int, list[str]]: while sgf[idx] != "]": # \ has special SGF handling. if sgf[idx] == "\\": - if sgf[idx:idx + 2] == "\\\n": + if sgf[idx : idx + 2] == "\\\n": # Newlines are removed if they come immediately after a \, # otherwise they remain as newlines. pass @@ -70,7 +71,7 @@ def parse_node(sgf: str) -> SgfTree: raise ValueError("propery key is empty") prop_key = sgf[prop_key_start:idx] if not prop_key.isupper(): - raise ValueError('property must be in uppercase') + raise ValueError("property must be in uppercase") idx, prop_vals = parse_property_vals(sgf, idx) properties[prop_key].extend(prop_vals) @@ -101,15 +102,15 @@ def parse_node(sgf: str) -> SgfTree: idx += 1 if idx > prop_key_start and not properties: - raise ValueError('properties without delimiter') + raise ValueError("properties without delimiter") return SgfTree(children=children, properties=dict(properties)) def parse(sgf: str) -> SgfTree: """Parse an SGF tree.""" if not sgf.startswith("(") and not sgf.endswith(")"): - raise ValueError('tree missing') + raise ValueError("tree missing") if not sgf.startswith("(;"): - raise ValueError('tree with no nodes') + raise ValueError("tree with no nodes") inside = sgf[1:-1] return parse_node(inside) diff --git a/exercises/practice/sieve/.articles/performance/code/Benchmark.py b/exercises/practice/sieve/.articles/performance/code/Benchmark.py index 7027fc0ef9f..535c58bf862 100644 --- a/exercises/practice/sieve/.articles/performance/code/Benchmark.py +++ b/exercises/practice/sieve/.articles/performance/code/Benchmark.py @@ -6,6 +6,7 @@ # ------------ FUNCTIONS TO TIME ------------- # + def nested_loops_1(number): not_prime = [] prime = [] @@ -33,8 +34,11 @@ def nested_loops_2(limit): def set_ops_1(number): numbers = set(item for item in range(2, number + 1)) - not_prime = set(not_prime for item in range(2, number + 1) - for not_prime in range(item ** 2, number + 1, item)) + not_prime = set( + not_prime + for item in range(2, number + 1) + for not_prime in range(item**2, number + 1, item) + ) # sorting adds .2ms, but the tests won't pass with an unsorted list return sorted(list((numbers - not_prime))) @@ -60,15 +64,25 @@ def set_ops_3(limit: int) -> list[int]: def generator_comprehension(number): # slowest - primes = (item for item in range(2, number + 1) if item not in - (not_prime for item in range(2, number + 1) for - not_prime in range(item * item, number + 1, item))) + primes = ( + item + for item in range(2, number + 1) + if item + not in ( + not_prime + for item in range(2, number + 1) + for not_prime in range(item * item, number + 1, item) + ) + ) return list(primes) def list_comprehension(limit): - return [x for x in range(2, limit + 1) - if all(x % y != 0 for y in range(2, x))] if limit >= 2 else [] + return ( + [x for x in range(2, limit + 1) if all(x % y != 0 for y in range(2, x))] + if limit >= 2 + else [] + ) ## ---------END FUNCTIONS TO BE TIMED-------------------- ## @@ -80,47 +94,55 @@ def list_comprehension(limit): inputs = [10, 30, 100, 300, 1_000, 3_000, 10_000, 30_000, 100_000] # #Set up columns and rows for Pandas Data Frame -col_headers = [f'Number: {number}' for number in inputs] -row_headers = ["nested_loops_1", - "nested_loops_2", - "set_ops_1", - "set_ops_2", - "set_ops_3", - "generator_comprehension", - "list_comprehension"] +col_headers = [f"Number: {number}" for number in inputs] +row_headers = [ + "nested_loops_1", + "nested_loops_2", + "set_ops_1", + "set_ops_2", + "set_ops_3", + "generator_comprehension", + "list_comprehension", +] # Empty dataframe will be filled in one cell at a time later df = pd.DataFrame(np.nan, index=row_headers, columns=col_headers) # Function List to Call When Timing -functions = [nested_loops_1, - nested_loops_2, - set_ops_1, - set_ops_2, - set_ops_3, - generator_comprehension, - list_comprehension] +functions = [ + nested_loops_1, + nested_loops_2, + set_ops_1, + set_ops_2, + set_ops_3, + generator_comprehension, + list_comprehension, +] # Run timings using timeit.autorange(). Run Each Set 3 Times. for function, title in zip(functions, row_headers): - timings = [[ - timeit.Timer(lambda: function(data), globals=globals()).autorange()[1] / - timeit.Timer(lambda: function(data), globals=globals()).autorange()[0] - for data in inputs] for rounds in range(3)] + timings = [ + [ + timeit.Timer(lambda: function(data), globals=globals()).autorange()[1] + / timeit.Timer(lambda: function(data), globals=globals()).autorange()[0] + for data in inputs + ] + for rounds in range(3) + ] # Only the fastest Cycle counts. timing_result = min(timings) - print(f'{title}', f'Timings : {timing_result}') + print(f"{title}", f"Timings : {timing_result}") # Insert results into the dataframe - df.loc[title, 'Number: 10':'Number: 100000'] = timing_result + df.loc[title, "Number: 10":"Number: 100000"] = timing_result # Save the data to avoid constantly regenerating it -df.to_feather('run_times.feather') +df.to_feather("run_times.feather") print("\nDataframe saved to './run_times.feather'") # # The next bit is useful for `introduction.md` -pd.options.display.float_format = '{:,.2e}'.format -print('\nDataframe in Markdown format:\n') +pd.options.display.float_format = "{:,.2e}".format +print("\nDataframe in Markdown format:\n") print(df.to_markdown(floatfmt=".2e")) diff --git a/exercises/practice/sieve/.articles/performance/code/create_plots.py b/exercises/practice/sieve/.articles/performance/code/create_plots.py index 43f256ab28f..44236fae9a3 100644 --- a/exercises/practice/sieve/.articles/performance/code/create_plots.py +++ b/exercises/practice/sieve/.articles/performance/code/create_plots.py @@ -6,14 +6,14 @@ # These dataframes are slow to create, so they should be saved in Feather format try: - df = pd.read_feather('./run_times.feather') + df = pd.read_feather("./run_times.feather") except FileNotFoundError: print("File './run_times.feather' not found!") print("Please run './Benchmark.py' to create it.") exit(1) try: - transposed = pd.read_feather('./transposed_logs.feather') + transposed = pd.read_feather("./transposed_logs.feather") except FileNotFoundError: print("File './transposed_logs.feather' not found!") print("Please run './Benchmark.py' to create it.") @@ -21,23 +21,22 @@ # Ready to start creating plots -mpl.rcParams['axes.labelsize'] = 18 +mpl.rcParams["axes.labelsize"] = 18 # bar plot of actual run times -ax = df.plot.bar(figsize=(10, 7), - logy=True, - ylabel="time (s)", - fontsize=14, - width=0.8, - rot=-30) +ax = df.plot.bar( + figsize=(10, 7), logy=True, ylabel="time (s)", fontsize=14, width=0.8, rot=-30 +) plt.tight_layout() -plt.savefig('../timeit_bar_plot.svg') +plt.savefig("../timeit_bar_plot.svg") # log-log plot of times vs n, to see slopes -transposed.plot(figsize=(8, 6), - marker='.', - markersize=10, - ylabel="$log_{10}(time)$ (s)", - xlabel="$log_{10}(n)$", - fontsize=14) -plt.savefig('../slopes.svg') +transposed.plot( + figsize=(8, 6), + marker=".", + markersize=10, + ylabel="$log_{10}(time)$ (s)", + xlabel="$log_{10}(n)$", + fontsize=14, +) +plt.savefig("../slopes.svg") diff --git a/exercises/practice/sieve/.articles/performance/code/fit_gradients.py b/exercises/practice/sieve/.articles/performance/code/fit_gradients.py index f90d8010a36..2c7c8654b1c 100644 --- a/exercises/practice/sieve/.articles/performance/code/fit_gradients.py +++ b/exercises/practice/sieve/.articles/performance/code/fit_gradients.py @@ -6,7 +6,7 @@ # These dataframes are slow to create, so they should be saved in Feather format try: - df = pd.read_feather('./run_times.feather') + df = pd.read_feather("./run_times.feather") except FileNotFoundError: print("File './run_times.feather' not found!") print("Please run './Benchmark.py' to create it.") @@ -16,28 +16,31 @@ inputs = [10, 30, 100, 300, 1_000, 3_000, 10_000, 30_000, 100_000] -pd.options.display.float_format = '{:,.2g}'.format +pd.options.display.float_format = "{:,.2g}".format log_n_values = np.log10(inputs) df[df == 0.0] = np.nan transposed = np.log10(df).T transposed = transposed.set_axis(log_n_values, axis=0) -transposed.to_feather('transposed_logs.feather') +transposed.to_feather("transposed_logs.feather") print("\nDataframe saved to './transposed_logs.feather'") n_values = (10, 30, 100, 300, 1_000, 3_000, 10_000, 30_000, 100_000) log_n_values = np.log10(n_values) -row_headers = ["nested_loops_1", - "nested_loops_2", - "set_ops_1", - "set_ops_2", - "set_ops_3", - "generator_comprehension", - "list_comprehension"] +row_headers = [ + "nested_loops_1", + "nested_loops_2", + "set_ops_1", + "set_ops_2", + "set_ops_3", + "generator_comprehension", + "list_comprehension", +] # Do a least-squares fit to get the slopes, working around missing values # Apparently, it does need to be this complicated + def find_slope(name): log_times = transposed[name] missing = np.isnan(log_times) @@ -50,7 +53,6 @@ def find_slope(name): # Print the slope results slopes = [(name, find_slope(name)) for name in row_headers] -print('\nSlopes of log-log plots:') +print("\nSlopes of log-log plots:") for name, slope in slopes: - print(f'{name:>14} : {slope:.2f}') - + print(f"{name:>14} : {slope:.2f}") diff --git a/exercises/practice/sieve/.meta/example.py b/exercises/practice/sieve/.meta/example.py index 0e8ae8ad35c..e43d2c299f4 100644 --- a/exercises/practice/sieve/.meta/example.py +++ b/exercises/practice/sieve/.meta/example.py @@ -1,7 +1,7 @@ def primes(limit): prime = [True] * (limit + 1) prime[0] = prime[1] = False - for idx in range(2, int(limit ** 0.5) + 1): + for idx in range(2, int(limit**0.5) + 1): if prime[idx]: for edx in range(idx * idx, limit + 1, idx): prime[edx] = False diff --git a/exercises/practice/simple-cipher/.meta/example.py b/exercises/practice/simple-cipher/.meta/example.py index 61abf58d2a4..eb7e924e01f 100644 --- a/exercises/practice/simple-cipher/.meta/example.py +++ b/exercises/practice/simple-cipher/.meta/example.py @@ -9,17 +9,17 @@ class Cipher: def __init__(self, key=None): if key is None: random.seed(time()) - key = ''.join(random.choice(ascii_lowercase) for _ in range(100)) + key = "".join(random.choice(ascii_lowercase) for _ in range(100)) self.key = key def encode(self, text): - return ''.join( - chr(((ord(character) - 2 * ord('a') + ord(key)) % 26) + ord('a')) + return "".join( + chr(((ord(character) - 2 * ord("a") + ord(key)) % 26) + ord("a")) for character, key in zip(text, cycle(self.key)) ) def decode(self, text): - return ''.join( - chr(((ord(character) - ord(key) + 26) % 26) + ord('a')) + return "".join( + chr(((ord(character) - ord(key) + 26) % 26) + ord("a")) for character, key in zip(text, cycle(self.key)) ) diff --git a/exercises/practice/simple-linked-list/.meta/example.py b/exercises/practice/simple-linked-list/.meta/example.py index f87b155e79e..41d3ccbf2aa 100644 --- a/exercises/practice/simple-linked-list/.meta/example.py +++ b/exercises/practice/simple-linked-list/.meta/example.py @@ -44,7 +44,7 @@ def __len__(self): def head(self): if self._head is None: - raise EmptyListException('The list is empty.') + raise EmptyListException("The list is empty.") return self._head def push(self, value): @@ -55,7 +55,7 @@ def push(self, value): def pop(self): if self._head is None: - raise EmptyListException('The list is empty.') + raise EmptyListException("The list is empty.") self._len -= 1 ret = self._head.value() self._head = self._head.next() diff --git a/exercises/practice/simple-linked-list/simple_linked_list_test.py b/exercises/practice/simple-linked-list/simple_linked_list_test.py index 91025e0e945..8cbb7be2cb6 100644 --- a/exercises/practice/simple-linked-list/simple_linked_list_test.py +++ b/exercises/practice/simple-linked-list/simple_linked_list_test.py @@ -5,6 +5,7 @@ # No canonical data available for this exercise + class SimpleLinkedListTest(unittest.TestCase): def test_empty_list_has_len_zero(self): sut = LinkedList() diff --git a/exercises/practice/spiral-matrix/.meta/example.py b/exercises/practice/spiral-matrix/.meta/example.py index cc25fb3c208..0dc69ab8943 100644 --- a/exercises/practice/spiral-matrix/.meta/example.py +++ b/exercises/practice/spiral-matrix/.meta/example.py @@ -1,5 +1,5 @@ def spiral_matrix(size): - matrix = [[0]*size for row in range(size)] + matrix = [[0] * size for row in range(size)] idx = 0 jdx = -1 element = 1 @@ -7,8 +7,8 @@ def spiral_matrix(size): digital = [0, 1, 0, -1] disco = [1, 0, -1, 0] - for edx in range(2*size - 1): - for _ in range((2*size - edx) // 2): + for edx in range(2 * size - 1): + for _ in range((2 * size - edx) // 2): idx += digital[edx % 4] jdx += disco[edx % 4] matrix[idx][jdx] = element diff --git a/exercises/practice/square-root/.meta/example.py b/exercises/practice/square-root/.meta/example.py index 94cd0fdc711..56c7ff401e2 100644 --- a/exercises/practice/square-root/.meta/example.py +++ b/exercises/practice/square-root/.meta/example.py @@ -1,5 +1,5 @@ def square_root(number): n = 0 - while n ** 2 != number: + while n**2 != number: n += 1 return n diff --git a/exercises/practice/strain/.meta/example.py b/exercises/practice/strain/.meta/example.py index 6c4b3f8152b..c4960684ba1 100644 --- a/exercises/practice/strain/.meta/example.py +++ b/exercises/practice/strain/.meta/example.py @@ -1,5 +1,6 @@ def keep(sequence, predicate): return [element for element in sequence if predicate(element)] + def discard(sequence, predicate): return [element for element in sequence if not predicate(element)] diff --git a/exercises/practice/strain/strain_test.py b/exercises/practice/strain/strain_test.py index 9341ddb6ba1..73e3110b30c 100644 --- a/exercises/practice/strain/strain_test.py +++ b/exercises/practice/strain/strain_test.py @@ -22,25 +22,24 @@ def test_keep_everything(self): self.assertEqual(keep(inp, lambda x: x % 2 == 0), inp) def test_discard_endswith(self): - inp = ['dough', 'cash', 'plough', 'though', 'through', 'enough'] - out = ['cash'] - self.assertEqual(discard(inp, lambda x: str.endswith(x, 'ough')), out) + inp = ["dough", "cash", "plough", "though", "through", "enough"] + out = ["cash"] + self.assertEqual(discard(inp, lambda x: str.endswith(x, "ough")), out) def test_keep_z(self): - inp = ['zebra', 'arizona', 'apple', 'google', 'mozilla'] - out = ['zebra', 'arizona', 'mozilla'] - self.assertEqual(keep(inp, lambda x: 'z' in x), out) + inp = ["zebra", "arizona", "apple", "google", "mozilla"] + out = ["zebra", "arizona", "mozilla"] + self.assertEqual(keep(inp, lambda x: "z" in x), out) def test_keep_discard(self): - inp = ['1,2,3', 'one', 'almost!', 'love'] + inp = ["1,2,3", "one", "almost!", "love"] self.assertEqual(discard(keep(inp, str.isalpha), str.isalpha), []) def test_keep_plus_discard(self): - inp = ['1,2,3', 'one', 'almost!', 'love'] - out = ['one', 'love', '1,2,3', 'almost!'] - self.assertEqual( - keep(inp, str.isalpha) + discard(inp, str.isalpha), out) + inp = ["1,2,3", "one", "almost!", "love"] + out = ["one", "love", "1,2,3", "almost!"] + self.assertEqual(keep(inp, str.isalpha) + discard(inp, str.isalpha), out) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/sum-of-multiples/.meta/example.py b/exercises/practice/sum-of-multiples/.meta/example.py index 55e16822740..fa6424124aa 100644 --- a/exercises/practice/sum-of-multiples/.meta/example.py +++ b/exercises/practice/sum-of-multiples/.meta/example.py @@ -1,5 +1,6 @@ def sum_of_multiples(limit, multiples): - return sum(value for value in range(limit) - if any(value % multiple == 0 - for multiple in multiples - if multiple > 0)) + return sum( + value + for value in range(limit) + if any(value % multiple == 0 for multiple in multiples if multiple > 0) + ) diff --git a/exercises/practice/tournament/.meta/example.py b/exercises/practice/tournament/.meta/example.py index e711468e21c..322886bae2b 100644 --- a/exercises/practice/tournament/.meta/example.py +++ b/exercises/practice/tournament/.meta/example.py @@ -12,7 +12,7 @@ def invert_result(result): def parse_game(game_line): - game = game_line.split(';') + game = game_line.split(";") if len(game) == 3 and game[2] in RESULTS: result = RESULTS[game[2]] return (game[0], result), (game[1], invert_result(result)) @@ -24,13 +24,13 @@ def calculate_points(stats): def format_table(results): - table = ['Team | MP | W | D | L | P'] + table = ["Team | MP | W | D | L | P"] for team, games in sorted( - results.items(), key=lambda group: (-calculate_points(group[1]), group[0])): - team_fmt = '{0:30} | {1:2} | {3:2} | {4:2} | {5:2} | {2:2}' - table.append( - team_fmt.format(team, sum(games), calculate_points(games), *games)) + results.items(), key=lambda group: (-calculate_points(group[1]), group[0]) + ): + team_fmt = "{0:30} | {1:2} | {3:2} | {4:2} | {5:2} | {2:2}" + table.append(team_fmt.format(team, sum(games), calculate_points(games), *games)) return table diff --git a/exercises/practice/transpose/.meta/example.py b/exercises/practice/transpose/.meta/example.py index cbb8e5f96e4..fb35092f7f0 100644 --- a/exercises/practice/transpose/.meta/example.py +++ b/exercises/practice/transpose/.meta/example.py @@ -1,6 +1,6 @@ def transpose(lines): - rows = [row.replace(' ', '_') for row in lines.splitlines()] + rows = [row.replace(" ", "_") for row in lines.splitlines()] rows = [row.ljust(len(max(rows, key=len))) for row in rows] - rows = [''.join(row) for row in zip(*rows)] - rows = [row.rstrip().replace('_', ' ') for row in rows] - return '\n'.join(rows) + rows = ["".join(row) for row in zip(*rows)] + rows = [row.rstrip().replace("_", " ") for row in rows] + return "\n".join(rows) diff --git a/exercises/practice/tree-building/.meta/example.py b/exercises/practice/tree-building/.meta/example.py index e3929ea031c..2c39609da26 100644 --- a/exercises/practice/tree-building/.meta/example.py +++ b/exercises/practice/tree-building/.meta/example.py @@ -15,7 +15,7 @@ def __init__(self, node_id): def validate_record(record): if record.equal_id() and record.record_id != 0: - raise ValueError('Only root should have equal record and parent id.') + raise ValueError("Only root should have equal record and parent id.") if not record.equal_id() and record.parent_id >= record.record_id: raise ValueError("Node parent_id should be smaller than it's record_id.") @@ -36,7 +36,7 @@ def BuildTree(records): for index, record_id in enumerate(ordered_id): if index != record_id: - raise ValueError('Record id is invalid or out of order.') + raise ValueError("Record id is invalid or out of order.") if record_id == root_id: root = node_dict[record_id] diff --git a/exercises/practice/tree-building/tree_building.py b/exercises/practice/tree-building/tree_building.py index 75082a66b05..aae5ba38dcc 100644 --- a/exercises/practice/tree-building/tree_building.py +++ b/exercises/practice/tree-building/tree_building.py @@ -16,9 +16,9 @@ def BuildTree(records): ordered_id = [i.record_id for i in records] if records: if ordered_id[-1] != len(ordered_id) - 1: - raise ValueError('broken tree') + raise ValueError("broken tree") if ordered_id[0] != 0: - raise ValueError('invalid') + raise ValueError("invalid") trees = [] parent = {} for i in range(len(ordered_id)): @@ -26,12 +26,12 @@ def BuildTree(records): if ordered_id[i] == j.record_id: if j.record_id == 0: if j.parent_id != 0: - raise ValueError('error!') + raise ValueError("error!") if j.record_id < j.parent_id: - raise ValueError('something went wrong!') + raise ValueError("something went wrong!") if j.record_id == j.parent_id: if j.record_id != 0: - raise ValueError('error!') + raise ValueError("error!") trees.append(Node(ordered_id[i])) for i in range(len(ordered_id)): for j in trees: diff --git a/exercises/practice/tree-building/tree_building_test.py b/exercises/practice/tree-building/tree_building_test.py index 426ed2b95b3..b85d524f5fb 100644 --- a/exercises/practice/tree-building/tree_building_test.py +++ b/exercises/practice/tree-building/tree_building_test.py @@ -5,10 +5,10 @@ class TreeBuildingTest(unittest.TestCase): """ - Record(record_id, parent_id): records given to be processed - Node(node_id): Node in tree - BuildTree(records): records as argument and returns tree - BuildTree should raise ValueError if given records are invalid + Record(record_id, parent_id): records given to be processed + Node(node_id): Node in tree + BuildTree(records): records as argument and returns tree + BuildTree should raise ValueError if given records are invalid """ def test_empty_list_input(self): @@ -17,19 +17,13 @@ def test_empty_list_input(self): self.assertIsNone(root) def test_one_node(self): - records = [ - Record(0, 0) - ] + records = [Record(0, 0)] root = BuildTree(records) self.assert_node_is_leaf(root, node_id=0) def test_three_nodes_in_order(self): - records = [ - Record(0, 0), - Record(1, 0), - Record(2, 0) - ] + records = [Record(0, 0), Record(1, 0), Record(2, 0)] root = BuildTree(records) self.assert_node_is_branch(root, node_id=0, children_count=2) @@ -37,11 +31,7 @@ def test_three_nodes_in_order(self): self.assert_node_is_leaf(root.children[1], node_id=2) def test_three_nodes_in_reverse_order(self): - records = [ - Record(2, 0), - Record(1, 0), - Record(0, 0) - ] + records = [Record(2, 0), Record(1, 0), Record(0, 0)] root = BuildTree(records) self.assert_node_is_branch(root, node_id=0, children_count=2) @@ -49,12 +39,7 @@ def test_three_nodes_in_reverse_order(self): self.assert_node_is_leaf(root.children[1], node_id=2) def test_more_than_two_children(self): - records = [ - Record(0, 0), - Record(1, 0), - Record(2, 0), - Record(3, 0) - ] + records = [Record(0, 0), Record(1, 0), Record(2, 0), Record(3, 0)] root = BuildTree(records) self.assert_node_is_branch(root, node_id=0, children_count=3) @@ -70,7 +55,7 @@ def test_binary_tree(self): Record(2, 0), Record(4, 1), Record(5, 2), - Record(1, 0) + Record(1, 0), ] root = BuildTree(records) @@ -103,21 +88,18 @@ def test_unbalanced_tree(self): self.assert_node_is_leaf(root.children[1].children[0], 6) def test_root_node_has_parent(self): - records = [ - Record(0, 1), - Record(1, 0) - ] + records = [Record(0, 1), Record(1, 0)] # Root parent_id should be equal to record_id(0) with self.assertRaises(ValueError) as err: BuildTree(records) self.assertEqual(type(err.exception), ValueError) - self.assertEqual(err.exception.args[0], "Node parent_id should be smaller than it's record_id.") + self.assertEqual( + err.exception.args[0], + "Node parent_id should be smaller than it's record_id.", + ) def test_no_root_node(self): - records = [ - Record(1, 0), - Record(2, 0) - ] + records = [Record(1, 0), Record(2, 0)] # Record with record_id 0 (root) is missing with self.assertRaises(ValueError) as err: BuildTree(records) @@ -125,12 +107,7 @@ def test_no_root_node(self): self.assertEqual(err.exception.args[0], "Record id is invalid or out of order.") def test_non_continuous(self): - records = [ - Record(2, 0), - Record(4, 2), - Record(1, 0), - Record(0, 0) - ] + records = [Record(2, 0), Record(4, 2), Record(1, 0), Record(0, 0)] # Record with record_id 3 is missing with self.assertRaises(ValueError) as err: BuildTree(records) @@ -145,13 +122,15 @@ def test_cycle_directly(self): Record(4, 1), Record(1, 0), Record(0, 0), - Record(6, 3) + Record(6, 3), ] # Cycle caused by Record 2 with parent_id pointing to itself with self.assertRaises(ValueError) as err: BuildTree(records) self.assertEqual(type(err.exception), ValueError) - self.assertEqual(err.exception.args[0], "Only root should have equal record and parent id.") + self.assertEqual( + err.exception.args[0], "Only root should have equal record and parent id." + ) def test_cycle_indirectly(self): records = [ @@ -161,25 +140,27 @@ def test_cycle_indirectly(self): Record(4, 1), Record(1, 0), Record(0, 0), - Record(6, 3) + Record(6, 3), ] # Cycle caused by Record 2 with parent_id(6) greater than record_id(2) with self.assertRaises(ValueError) as err: BuildTree(records) self.assertEqual(type(err.exception), ValueError) - self.assertEqual(err.exception.args[0], "Node parent_id should be smaller than it's record_id.") + self.assertEqual( + err.exception.args[0], + "Node parent_id should be smaller than it's record_id.", + ) def test_higher_id_parent_of_lower_id(self): - records = [ - Record(0, 0), - Record(2, 0), - Record(1, 2) - ] + records = [Record(0, 0), Record(2, 0), Record(1, 2)] # Record 1 have parent_id(2) greater than record_id(1) with self.assertRaises(ValueError) as err: BuildTree(records) self.assertEqual(type(err.exception), ValueError) - self.assertEqual(err.exception.args[0], "Node parent_id should be smaller than it's record_id.") + self.assertEqual( + err.exception.args[0], + "Node parent_id should be smaller than it's record_id.", + ) def assert_node_is_branch(self, node, node_id, children_count): self.assertEqual(node.node_id, node_id) diff --git a/exercises/practice/trinary/.meta/example.py b/exercises/practice/trinary/.meta/example.py index 48074c008fd..c497c8ed401 100644 --- a/exercises/practice/trinary/.meta/example.py +++ b/exercises/practice/trinary/.meta/example.py @@ -2,6 +2,6 @@ def trinary(string): - if set(string) - set('012'): + if set(string) - set("012"): return 0 return reduce(lambda idx, edx: idx * 3 + int(edx), string, 0) diff --git a/exercises/practice/trinary/trinary_test.py b/exercises/practice/trinary/trinary_test.py index 3e9a46438aa..37480a49309 100644 --- a/exercises/practice/trinary/trinary_test.py +++ b/exercises/practice/trinary/trinary_test.py @@ -5,26 +5,26 @@ class TrinaryTest(unittest.TestCase): def test_valid_trinary1(self): - self.assertEqual(trinary('0'), 0) + self.assertEqual(trinary("0"), 0) def test_valid_trinary2(self): - self.assertEqual(trinary('1'), 1) + self.assertEqual(trinary("1"), 1) def test_valid_trinary3(self): - self.assertEqual(trinary('10'), 3) + self.assertEqual(trinary("10"), 3) def test_valid_trinary4(self): - self.assertEqual(trinary('102101'), 307) + self.assertEqual(trinary("102101"), 307) def test_valid_trinary5(self): - self.assertEqual(trinary('22222'), 242) + self.assertEqual(trinary("22222"), 242) def test_valid_trinary6(self): - self.assertEqual(trinary('10000'), 81) + self.assertEqual(trinary("10000"), 81) def test_invalid_trinary(self): - self.assertEqual(trinary('13201'), 0) + self.assertEqual(trinary("13201"), 0) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/exercises/practice/twelve-days/.meta/example.py b/exercises/practice/twelve-days/.meta/example.py index 6b24c65b1a3..e7a2054e319 100644 --- a/exercises/practice/twelve-days/.meta/example.py +++ b/exercises/practice/twelve-days/.meta/example.py @@ -1,28 +1,43 @@ -GIFTS = ['twelve Drummers Drumming', - 'eleven Pipers Piping', - 'ten Lords-a-Leaping', - 'nine Ladies Dancing', - 'eight Maids-a-Milking', - 'seven Swans-a-Swimming', - 'six Geese-a-Laying', - 'five Gold Rings', - 'four Calling Birds', - 'three French Hens', - 'two Turtle Doves', - 'a Partridge in a Pear Tree'] +GIFTS = [ + "twelve Drummers Drumming", + "eleven Pipers Piping", + "ten Lords-a-Leaping", + "nine Ladies Dancing", + "eight Maids-a-Milking", + "seven Swans-a-Swimming", + "six Geese-a-Laying", + "five Gold Rings", + "four Calling Birds", + "three French Hens", + "two Turtle Doves", + "a Partridge in a Pear Tree", +] -ORDINAL = [None, 'first', 'second', 'third', 'fourth', 'fifth', 'sixth', - 'seventh', 'eighth', 'ninth', 'tenth', 'eleventh', 'twelfth'] +ORDINAL = [ + None, + "first", + "second", + "third", + "fourth", + "fifth", + "sixth", + "seventh", + "eighth", + "ninth", + "tenth", + "eleventh", + "twelfth", +] def verse(day_number): gifts = GIFTS[-day_number:] if len(gifts) > 1: - gifts[:-1] = [', '.join(gifts[:-1])] + gifts[:-1] = [", ".join(gifts[:-1])] - gifts = ', and '.join(gifts) - return f'On the {ORDINAL[day_number]} day of Christmas my true love gave to me: {gifts}.' + gifts = ", and ".join(gifts) + return f"On the {ORDINAL[day_number]} day of Christmas my true love gave to me: {gifts}." def recite(start, end): diff --git a/exercises/practice/two-bucket/.meta/example.py b/exercises/practice/two-bucket/.meta/example.py index 83077eb1656..6fa8ececd1a 100644 --- a/exercises/practice/two-bucket/.meta/example.py +++ b/exercises/practice/two-bucket/.meta/example.py @@ -1,13 +1,13 @@ -''' - This solution implements a breadth-first search of the graph - of possible valid states for the two buckets until it reaches a state - in which one of the two buckets contains the goal amount -''' +""" +This solution implements a breadth-first search of the graph +of possible valid states for the two buckets until it reaches a state +in which one of the two buckets contains the goal amount +""" def measure(bucket_one, bucket_two, goal, start_bucket): sizes = [bucket_one, bucket_two] - goal_index = 0 if start_bucket == 'one' else 1 + goal_index = 0 if start_bucket == "one" else 1 def empty(buckets, idx): return [0, buckets[1]] if idx == 0 else [buckets[0], 0] @@ -22,7 +22,7 @@ def consolidate(buckets, idx): return [target, source] if idx == 0 else [source, target] def bucket_str(buckets): - return f'{buckets[0]},{buckets[1]}' + return f"{buckets[0]},{buckets[1]}" invalid = [0, 0] invalid[1 - goal_index] = sizes[1 - goal_index] @@ -44,10 +44,10 @@ def bucket_str(buckets): to_visit.append((fill(buckets, idx), number_count)) to_visit.append((consolidate(buckets, idx), number_count)) if not any(to_visit): - raise ValueError('No more moves!') + raise ValueError("No more moves!") buckets, count = to_visit.pop(0) goal_index = buckets.index(goal) - goal_bucket = ['one', 'two'][goal_index] + goal_bucket = ["one", "two"][goal_index] other_bucket = buckets[1 - goal_index] return (count, goal_bucket, other_bucket) diff --git a/exercises/practice/two-fer/.meta/example.py b/exercises/practice/two-fer/.meta/example.py index 425d236d252..95d3c99cffa 100644 --- a/exercises/practice/two-fer/.meta/example.py +++ b/exercises/practice/two-fer/.meta/example.py @@ -1,2 +1,2 @@ -def two_fer(name='you'): - return f'One for {name}, one for me.' +def two_fer(name="you"): + return f"One for {name}, one for me." diff --git a/exercises/practice/variable-length-quantity/.meta/example.py b/exercises/practice/variable-length-quantity/.meta/example.py index ed5a393b65c..0f6a2f43b78 100644 --- a/exercises/practice/variable-length-quantity/.meta/example.py +++ b/exercises/practice/variable-length-quantity/.meta/example.py @@ -1,5 +1,5 @@ EIGHT_BIT_MASK = 0x80 -SEVEN_BIT_MASK = 0x7f +SEVEN_BIT_MASK = 0x7F def encode_single(number): @@ -23,12 +23,12 @@ def decode(byte_string): for idx, byte in enumerate(byte_string): number <<= 7 - number += (byte & SEVEN_BIT_MASK) + number += byte & SEVEN_BIT_MASK if byte & EIGHT_BIT_MASK == 0: values.append(number) number = 0 elif idx == len(byte_string) - 1: - raise ValueError('incomplete sequence') + raise ValueError("incomplete sequence") return values diff --git a/exercises/practice/word-search/.meta/example.py b/exercises/practice/word-search/.meta/example.py index fe2b9b6652b..e30c2c14bde 100644 --- a/exercises/practice/word-search/.meta/example.py +++ b/exercises/practice/word-search/.meta/example.py @@ -7,7 +7,7 @@ def __init__(self, x, y): self.y = y def __repr__(self): - return f'Point({self.x}:{self.y})' + return f"Point({self.x}:{self.y})" def __add__(self, other): return Point(self.x + other.x, self.y + other.y) @@ -22,8 +22,16 @@ 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)) +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: @@ -48,8 +56,9 @@ def find(self, word, position, direction): return position, current - direction def search(self, word): - positions = (Point(idx, edx) - for idx in range(self.width) for edx in range(self.height)) + positions = ( + Point(idx, edx) for idx in range(self.width) for edx in range(self.height) + ) for position in positions: for direction in DIRECTIONS: result = self.find(word, position, direction) diff --git a/exercises/practice/wordy/.meta/example.py b/exercises/practice/wordy/.meta/example.py index 2488153e827..45491080c77 100644 --- a/exercises/practice/wordy/.meta/example.py +++ b/exercises/practice/wordy/.meta/example.py @@ -2,15 +2,15 @@ from operator import floordiv as div -VALID_OPERATIONS = {'plus': add, 'minus': sub, 'multiplied by': mul, 'divided by': div} +VALID_OPERATIONS = {"plus": add, "minus": sub, "multiplied by": mul, "divided by": div} def answer(question): if not bool(question[8:-1].strip().lower().split()): - raise ValueError('syntax error') + raise ValueError("syntax error") - elif not question.startswith('What is '): - raise ValueError('unknown operation') + elif not question.startswith("What is "): + raise ValueError("unknown operation") else: words = question[8:-1].strip().lower().split() @@ -19,7 +19,7 @@ def answer(question): try: main_value = int(words.pop()) except ValueError as error: - raise ValueError('syntax error') from error + raise ValueError("syntax error") from error while words: operation = [words.pop()] @@ -30,20 +30,20 @@ def answer(question): break except ValueError as error: if next_to_evaluate == operation[-1]: - raise ValueError('syntax error') from error + raise ValueError("syntax error") from error else: operation.append(next_to_evaluate) else: - if operation[-1] not in VALID_OPERATIONS and not operation[-1].isdigit() : - raise ValueError('unknown operation') + if operation[-1] not in VALID_OPERATIONS and not operation[-1].isdigit(): + raise ValueError("unknown operation") else: - raise ValueError('syntax error') + raise ValueError("syntax error") - operation = ' '.join(operation) + operation = " ".join(operation) try: main_value = VALID_OPERATIONS[operation](main_value, second_value) except KeyError as error: - raise ValueError('syntax error') from error + raise ValueError("syntax error") from error return main_value diff --git a/exercises/practice/yacht/.meta/example.py b/exercises/practice/yacht/.meta/example.py index dedcb7ac81e..a290caf971e 100644 --- a/exercises/practice/yacht/.meta/example.py +++ b/exercises/practice/yacht/.meta/example.py @@ -62,4 +62,4 @@ def score(dice, category): try: return functions[category](dice) except IndexError as error: - raise ValueError('No such category.') from error + raise ValueError("No such category.") from error diff --git a/exercises/practice/zebra-puzzle/.meta/example.py b/exercises/practice/zebra-puzzle/.meta/example.py index a6ea8f93792..f9385124b9e 100644 --- a/exercises/practice/zebra-puzzle/.meta/example.py +++ b/exercises/practice/zebra-puzzle/.meta/example.py @@ -25,25 +25,36 @@ def solution(): # - J08K <3 (1:05 AM, nov 29th, 2021) result = next( - [{ - english_man: 'Englishman', - spaniard: 'Spaniard', - ukrainian: 'Ukrainian', - japanese: 'Japanese', - norwegian: 'Norwegian' - }[idx] for idx in (water, zebra)] + [ + { + english_man: "Englishman", + spaniard: "Spaniard", + ukrainian: "Ukrainian", + japanese: "Japanese", + norwegian: "Norwegian", + }[idx] + for idx in (water, zebra) + ] for (red, green, ivory, yellow, blue) in orderings if just_right_of(green, ivory) for (english_man, spaniard, ukrainian, japanese, norwegian) in orderings - if english_man is red if norwegian is first if next_to(norwegian, blue) - for (coffee, tea, milk, orange_juice, water) in orderings if coffee is green - if ukrainian is tea if milk is middle - for (old_gold, kools, chesterfields, lucky_strike, parliaments - ) in orderings if kools is yellow if lucky_strike is orange_juice + if english_man is red + if norwegian is first + if next_to(norwegian, blue) + for (coffee, tea, milk, orange_juice, water) in orderings + if coffee is green + if ukrainian is tea + if milk is middle + for (old_gold, kools, chesterfields, lucky_strike, parliaments) in orderings + if kools is yellow + if lucky_strike is orange_juice if japanese is parliaments - for (dog, snails, fox, horse, zebra) in orderings if spaniard is dog - if old_gold is snails if next_to(chesterfields, fox) - if next_to(kools, horse)) + for (dog, snails, fox, horse, zebra) in orderings + if spaniard is dog + if old_gold is snails + if next_to(chesterfields, fox) + if next_to(kools, horse) + ) return result diff --git a/exercises/practice/zipper/.meta/example.py b/exercises/practice/zipper/.meta/example.py index 570771ddbb5..8fdeb2e5286 100644 --- a/exercises/practice/zipper/.meta/example.py +++ b/exercises/practice/zipper/.meta/example.py @@ -8,28 +8,28 @@ def __init__(self, tree, ancestors): self.ancestors = ancestors def value(self): - return self.tree['value'] + return self.tree["value"] def set_value(self, value): - self.tree['value'] = value + self.tree["value"] = value return self def left(self): - if self.tree['left'] is None: + if self.tree["left"] is None: return None - return Zipper(self.tree['left'], self.ancestors + [self.tree]) + return Zipper(self.tree["left"], self.ancestors + [self.tree]) def set_left(self, tree): - self.tree['left'] = tree + self.tree["left"] = tree return self def right(self): - if self.tree['right'] is None: + if self.tree["right"] is None: return None - return Zipper(self.tree['right'], self.ancestors + [self.tree]) + return Zipper(self.tree["right"], self.ancestors + [self.tree]) def set_right(self, tree): - self.tree['right'] = tree + self.tree["right"] = tree return self def up(self):