From 57bac42a3fba2a5601181b28a4f7862d53fe90a8 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Tue, 10 Oct 2023 09:36:33 +0200
Subject: Pass TestFiniteMakeSetProduct

---
 src/act4e_solutions/sets_product.py | 78 +++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/act4e_solutions/sets_product.py b/src/act4e_solutions/sets_product.py
index bdba104..19a8062 100644
--- a/src/act4e_solutions/sets_product.py
+++ b/src/act4e_solutions/sets_product.py
@@ -1,11 +1,81 @@
-from typing import Any, Sequence, TypeVar
+from functools import reduce
+from collections.abc import Iterable
+from typing import Any, Sequence, TypeVar, List, Iterator, cast
+from math import prod
 
 import act4e_interfaces as I
 
-X = TypeVar("X")
 
+C = TypeVar("C") # Type of components, "factors", are setoids
+E = List[C] # Type of product, i.e. that holds components
 
-class SolFiniteMakeSetProduct(I.FiniteMakeSetProduct):
+class MyFiniteSetProduct(I.FiniteSetProduct[C, E]):
+    _components: E
+    def __init__(self, components: E):
+        self._components = components
+
+    # Set behaviour
+    def size(self) -> int:
+        return prod(map(lambda c: c.size(), self._components))
+
+    def contains(self, x: E) -> bool:
+        if type(x) != type(self._components):
+            return False
+
+        if len(x) != len(self._components):
+            return False
+
+        for (e, s) in zip(x, self._components):
+            if not s.contains(e):
+                return False
+
+        return True
+
+    def elements(self) -> Iterator[E]:
+        def all_combinations(last, new):
+            return [l + [n] for l in last for n in new]
+
+        parts = map(lambda c: list(c.elements()), self._components)
+        elements = reduce(all_combinations, parts, [[]])
+
+        return list(elements)
+
+    def save(self, h: I.IOHelper, x: E) -> I.ConcreteRepr:
+        return cast(I.ConcreteRepr, x)
+        # raise NotImplementedError
+        # return {"elements": [e for e in self.elements()]}
 
+    def load(self, h: I.IOHelper, o: I.ConcreteRepr):
+        return cast(E, o)
+        # raise NotImplementedError
+        # if not isinstance(o, dict):
+        #     raise I.InvalidFormat()
+
+        # if not "elements" in o:
+        #     raise I.InvalidFormat()
+
+        # nsets = len(o["elements"][0])
+        # components = [[] for _ in range(nsets)]
+        # for elements in o["elements"]:
+        #     for c, e in zip(components, elements):
+        #         if not e in c:
+        #             c.append(e)
+
+        # return MyFiniteSetProduct(components)
+
+    # Product behaviour
+    def components(self) -> Sequence[I.FiniteSet[C]]:
+        return self._components
+
+    def pack(self, args: Sequence[C]) -> E:
+        return cast(E, args)
+
+    def unpack(self, args: E) -> Sequence[C]:
+        return cast(Sequence[C], args)
+
+
+X = TypeVar("X")
+
+class SolFiniteMakeSetProduct(I.FiniteMakeSetProduct):
     def product(self, components: Sequence[I.FiniteSet[X]]) -> I.FiniteSetProduct[X, Any]:
-        raise NotImplementedError()  # implement here
+        return MyFiniteSetProduct(components)
-- 
cgit v1.2.1