From af443c94b2fd7e6b964ff4dc198a17504a889df1 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Sun, 3 Dec 2023 14:34:08 +0100 Subject: [PATCH] Grid.from_data() --- src/tools/grid.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/tools/grid.py b/src/tools/grid.py index 2f93cdf..41475db 100644 --- a/src/tools/grid.py +++ b/src/tools/grid.py @@ -1,11 +1,15 @@ from __future__ import annotations + +import re from collections import deque +from collections.abc import Callable + from .aoc_ocr import convert_array_6 from .coordinate import Coordinate, DistanceAlgorithm, Shape from enum import Enum from heapq import heappop, heappush from math import inf -from typing import Any, Dict, List +from typing import Any, Dict, List, Iterable, Mapping OFF = False ON = True @@ -620,6 +624,57 @@ class Grid: return ret + @classmethod + def from_data( + cls, + data: Iterable[Iterable], + default: Any = False, + translate: Mapping[str, Any] = None, + gen_3d: bool = False, + ) -> Grid: + """ + Every entry in data will be treated as row, every entry in data[entry] will be a separate column. + gen_3d = True will just add z=0 to every Coordinate + translate is used on every data[entry] and if present as key, its value will be used instead + a value in translate can be a function with the following signature: def translate(value: Any) -> Any + a key in translate is either a string of len 1 or it will be treated as regexp + if multiple regexp match, the first encountered wins + if there is a key that matches the entry it wins over any mathing regexp + """ + grid = cls(default=default) + + regex_in_translate = False + if translate is not None: + for k in translate: + if len(k) > 1: + regex_in_translate = True + + for y, row in enumerate(data): + for x, col in enumerate(row): + if translate is not None and col in translate: + if isinstance(col, Callable): + col = translate[col](col) + else: + col = translate[col] + elif regex_in_translate: + for k, v in translate.items(): + if len(k) == 1: + continue + + if re.search(k, col): + if isinstance(v, Callable): + col = translate[k](col) + else: + col = v + break + + if gen_3d: + grid.set(Coordinate(x, y, 0), col) + else: + grid.set(Coordinate(x, y), col) + + return grid + def __eq__(self, other: Grid) -> bool: if not isinstance(other, Grid): return False