<commit_before>import unittest
from typing import List

import utils


def calc_max_product(a, b, c, d, e):
    if b == 0:
        return a
    if d == 0:
        if c >= 0:
            return max(a, c)
        else:
            return (a if a else 1) * b * c
    if c >= 0:
        return (a if a else 1) * b * (c if c else 1) * d * (e if e else 1)
    else:
        return max((a if a else 1) * b * c, e, a, c * d * (e if e else 1))


# O(n) time. O(1) space. Logic.
class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return nums[0]

        result = 0
        a = b = c = d = e = 0

        for num in nums:
            if num > 0:
                if e:
                    e *= num
                else:
                    e = num
            elif num < 0:
                if d < 0:
                    c = (c if c else 1) * d * (e if e else 1)
                    d = num
                elif b < 0:
                    c = e
                    d = num
                else:
                    a = e
                    b = num
                e = 0
            else:
                if b == 0:
                    a = e
                    e = 0
                elif d == 0:
                    c = e
                    e = 0
                result = max(result, calc_max_product(a, b, c, d, e))
                a = b = c = d = e = 0

        if b == 0:
            a = e
            e = 0
        elif d == 0:
            c = e
            e = 0
        result = max(result, calc_max_product(a, b, c, d, e))

        return result


class Test(unittest.TestCase):
    def test(self):
        cases = utils.load_test_json(__file__).test_cases

        for case in cases:
            actual = Solution().maxProduct(**case.args._asdict())<commit_msg>152. Maximum Product Subarray<commit_after>import unittest
from typing import List

import utils


# O(n) time. O(1) space. DP.
class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        result = nums[0]
        left_max = 0
        right_max = 0

        for num in nums:
            left_max = left_max * num if left_max else num
            result = max(result, left_max)

        for num in reversed(nums):
            right_max = right_max * num if right_max else num
            result = max(result, right_max)

        return result


class Test(unittest.TestCase):
    def test(self):
        cases = utils.load_test_json(__file__).test_cases

        for case in cases:
            actual = Solution().maxProduct(**case.args._asdict())
{'fraction_non_alphanumeric': 0.09801633605600933, 'fraction_numerical': 0.014780241151302996, 'mean_word_length': 1.1362126245847175, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6235336', 'n_tokens_mistral': 845, 'n_tokens_neox': 773, 'n_words': 282}