Skip to content

Commit

Permalink
feat(Reverse String): From LeetCode (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
percebus authored Jan 4, 2025
1 parent 7cdf70a commit 0125e0b
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 0 deletions.
20 changes: 20 additions & 0 deletions features/problems/leetcode/easy/Reverse String.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Feature: Reverse String

# SRC: https://leetcode.com/problems/reverse-string/

# Constraints
# - 1 <= s.length <= 105
# - s[i] is a printable ascii character.


Scenario Outline: _
Given an array of <chars>
When I call reverseString
Then the void function returns None
And the same array is procedurally <reversed> by reference
# And it used 0(1) extra memory # TODO how to test?

Examples:
| chars | reversed |
| h,e,l,l,o | o,l,l,e,h |
| H,a,n,n,a,h | h,a,n,n,a,H |
2 changes: 2 additions & 0 deletions src/problems/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from src.problems.interviews.shortest_common_prefixes import __main__ as shortest_common_prefixes
from src.problems.leetcode.easy.longest_common_prefix import __main__ as longest_common_prefix
from src.problems.leetcode.easy.palindrome_number import __main__ as palindrome_number
from src.problems.leetcode.easy.reverse_string import __main__ as reverse_string
from src.problems.leetcode.easy.roman_to_integer import __main__ as roman_to_integer
from src.problems.leetcode.easy.two_sum import __main__ as two_sum
from src.problems.leetcode.easy.valid_parentheses import __main__ as valid_parentheses
Expand All @@ -26,6 +27,7 @@
shortest_common_prefixes,
longest_common_prefix,
palindrome_number,
reverse_string,
roman_to_integer,
two_sum,
valid_parentheses,
Expand Down
26 changes: 26 additions & 0 deletions src/problems/leetcode/easy/reverse_string/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 344. Reverse String

Write a function that reverses a string. The input string is given as an array of characters `s`.

You must do this by modifying the input array in-place with `O(1)` extra memory.

## Examples

### Example 1

- Input: s = ["h","e","l","l","o"]
- Output: ["o","l","l","e","h"]

### Example 2

- Input: s = ["H","a","n","n","a","h"]
- Output: ["h","a","n","n","a","H"]

### Constraints

- `1 <= s.length <= 105`
- `s[i]` is a printable ascii character.

## SRC

[344. Reverse String](https://leetcode.com/problems/reverse-string/description/)
5 changes: 5 additions & 0 deletions src/problems/leetcode/easy/reverse_string/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .v1 import Solution, solution

reverse_string = solution.reverseString

__all__ = ["Solution", "solution", "reverse_string"]
31 changes: 31 additions & 0 deletions src/problems/leetcode/easy/reverse_string/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from typing import Optional

from hamcrest import assert_that, equal_to

from src.problems.leetcode.easy.reverse_string import reverse_string


def test(chars: list[str], expected: Optional[list[str]] = None) -> None:
reverse_string(chars)
actual_string: str = "".join(chars)
expected_string: str = "".join(expected or [])
assert_that(actual_string, equal_to(expected_string))
print("✅", end="")


def run() -> None:
# Example 1:
# Input: s = ['h','e','l','l','o']
# Output: ['o','l','l','e','h']
test(["h", "e", "l", "l", "o"], expected=["o", "l", "l", "e", "h"])

# Example 2:
# Input: s = ['H', 'a', 'n', 'n', 'a', 'h']
# Output: ['h', 'a', 'n', 'n', 'a', 'H']
test(["H", "a", "n", "n", "a", "h"], expected=["h", "a", "n", "n", "a", "H"])

print("\n")


if __name__ == "__main__":
run()
25 changes: 25 additions & 0 deletions src/problems/leetcode/easy/reverse_string/protocol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from typing import Protocol, runtime_checkable

"""
SRC: https://leetcode.com/problems/reverse-string/
Write a function that reverses a string.
The input string is given as an array of characters s.
You must do this by modifying the input array in-place with O(1) extra memory.
"""


@runtime_checkable # NOTE: Allows for isinstance check.
class SolutionProtocol(Protocol):
def reverseString(self, s: list[str]) -> None:
"""
SolutionProtocol.reverseString
Given an array of characters s, it modifies the same array.
Parameters:
- `s` (`list[str]`): An array of string characters.
Returns: `None`
"""
raise NotImplementedError
24 changes: 24 additions & 0 deletions src/problems/leetcode/easy/reverse_string/v1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from src.problems.leetcode.easy.reverse_string.protocol import SolutionProtocol


class Solution: # (SolutionProtocol)
def reverseString(self, s: list[str]) -> None:
"""
SolutionProtocol.reverseString
Given an array of characters s, it modifies the same array.
Parameters:
- `s` (`list[str]`): An array of string characters.
Returns: `None`
"""

chars = s
# FIXME simplify do 1 trip, instead of 2
inverted = chars[::-1]
for idx, item in enumerate(inverted):
s[idx] = item # type: ignore


solution: SolutionProtocol = Solution()
34 changes: 34 additions & 0 deletions tests/step_defs/problems/leetcode/easy/test__reverse_string.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from hamcrest import assert_that, equal_to, is_
from pytest_bdd import given, parsers, scenarios, then, when

from src.problems.leetcode.easy.reverse_string import reverse_string

scenarios("problems/leetcode/easy/Reverse String.feature")


@given(parsers.parse("an array of {chars}"), converters={"chars": lambda s: s.split(",")}, target_fixture="context")
def given_an_array_of_chars(chars):
return {"chars": chars}


@when("I call reverseString")
def when_I_call_reverseString(context):
chars = context["chars"]
copy = list(chars)
context["result"] = reverse_string(copy)
context["reversed"] = copy


@then("the void function returns None")
def then_it_returns_None(context):
result = context["result"]
assert_that(result, is_(None))


@then(
parsers.parse("the same array is procedurally {expected} by reference"),
converters={"expected": lambda s: s.split(",")},
)
def then_the_string_got_reversed(expected, context):
actual = context["reversed"]
assert_that(expected, equal_to(actual))

0 comments on commit 0125e0b

Please sign in to comment.