arc-agi 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. arc_agi-0.0.1/LICENSE +1 -0
  2. arc_agi-0.0.1/PKG-INFO +12 -0
  3. arc_agi-0.0.1/README.md +1 -0
  4. arc_agi-0.0.1/arc/__init__.py +1 -0
  5. arc_agi-0.0.1/arc/core/.pdm-build/.gitignore +1 -0
  6. arc_agi-0.0.1/arc/core/.pdm-build/pyproject.toml +42 -0
  7. arc_agi-0.0.1/arc/core/.python-version +1 -0
  8. arc_agi-0.0.1/arc/core/README.md +0 -0
  9. arc_agi-0.0.1/arc/core/__init__.py +7 -0
  10. arc_agi-0.0.1/arc/core/contants.py +29 -0
  11. arc_agi-0.0.1/arc/core/datasets.py +69 -0
  12. arc_agi-0.0.1/arc/core/grid.py +118 -0
  13. arc_agi-0.0.1/arc/core/pair.py +75 -0
  14. arc_agi-0.0.1/arc/core/pyproject.toml +33 -0
  15. arc_agi-0.0.1/arc/core/task.py +148 -0
  16. arc_agi-0.0.1/arc/core/utils.py +187 -0
  17. arc_agi-0.0.1/arc/lambda/.pdm-build/.gitignore +1 -0
  18. arc_agi-0.0.1/arc/lambda/.pdm-build/arc_lambda-0.1.0.dist-info/METADATA +8 -0
  19. arc_agi-0.0.1/arc/lambda/.pdm-build/arc_lambda-0.1.0.dist-info/WHEEL +4 -0
  20. arc_agi-0.0.1/arc/lambda/.pdm-build/arc_lambda-0.1.0.dist-info/entry_points.txt +4 -0
  21. arc_agi-0.0.1/arc/lambda/.pdm-build/arc_lambda.pth +1 -0
  22. arc_agi-0.0.1/arc/lambda/.python-version +1 -0
  23. arc_agi-0.0.1/arc/lambda/README.md +0 -0
  24. arc_agi-0.0.1/arc/lambda/__init__.py +0 -0
  25. arc_agi-0.0.1/arc/lambda/pyproject.toml +30 -0
  26. arc_agi-0.0.1/arc/llm/.pdm-build/.gitignore +1 -0
  27. arc_agi-0.0.1/arc/llm/.pdm-build/arc_llm-0.1.0.dist-info/METADATA +8 -0
  28. arc_agi-0.0.1/arc/llm/.pdm-build/arc_llm-0.1.0.dist-info/WHEEL +4 -0
  29. arc_agi-0.0.1/arc/llm/.pdm-build/arc_llm-0.1.0.dist-info/entry_points.txt +4 -0
  30. arc_agi-0.0.1/arc/llm/.pdm-build/arc_llm.pth +1 -0
  31. arc_agi-0.0.1/arc/llm/.python-version +1 -0
  32. arc_agi-0.0.1/arc/llm/README.md +0 -0
  33. arc_agi-0.0.1/arc/llm/__init__.py +0 -0
  34. arc_agi-0.0.1/arc/llm/pyproject.toml +31 -0
  35. arc_agi-0.0.1/arc/llm/something.py +2 -0
  36. arc_agi-0.0.1/arc/torch/.pdm-build/.gitignore +1 -0
  37. arc_agi-0.0.1/arc/torch/.pdm-build/arc_torch-0.1.0.dist-info/METADATA +9 -0
  38. arc_agi-0.0.1/arc/torch/.pdm-build/arc_torch-0.1.0.dist-info/WHEEL +4 -0
  39. arc_agi-0.0.1/arc/torch/.pdm-build/arc_torch-0.1.0.dist-info/entry_points.txt +4 -0
  40. arc_agi-0.0.1/arc/torch/.pdm-build/arc_torch.pth +1 -0
  41. arc_agi-0.0.1/arc/torch/.python-version +1 -0
  42. arc_agi-0.0.1/arc/torch/README.md +0 -0
  43. arc_agi-0.0.1/arc/torch/__init__.py +0 -0
  44. arc_agi-0.0.1/arc/torch/pyproject.toml +32 -0
  45. arc_agi-0.0.1/pyproject.toml +54 -0
arc_agi-0.0.1/LICENSE ADDED
@@ -0,0 +1 @@
1
+ test
arc_agi-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.1
2
+ Name: arc-agi
3
+ Version: 0.0.1
4
+ Summary: Work in progress...
5
+ License: test
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: ipykernel>=6.29.5
8
+ Requires-Dist: numpy>=2.2.4
9
+ Requires-Dist: requests>=2.32.3
10
+ Description-Content-Type: text/markdown
11
+
12
+ WIP
@@ -0,0 +1 @@
1
+ WIP
@@ -0,0 +1 @@
1
+
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "arc-core"
3
+ version = "0.1.0"
4
+ description = "Core package of ARC-RTK"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Jumyung Park", email = "parkjumyungpublic@gmail.com" },
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "numpy>=2.2.4",
12
+ "requests>=2.32.3",
13
+ ]
14
+
15
+ [dependency-groups]
16
+ lint = [
17
+ "ruff>=0.11.2",
18
+ ]
19
+ dev = [
20
+ "ipykernel>=6.29.5",
21
+ ]
22
+
23
+ [tool.uv.sources]
24
+
25
+ [tool.ruff]
26
+ extend-include = [
27
+ "*.ipynb",
28
+ ]
29
+
30
+ [tool.ruff.lint]
31
+ select = [
32
+ "D",
33
+ ]
34
+
35
+ [tool.ruff.lint.pydocstyle]
36
+ convention = "google"
37
+
38
+ [build-system]
39
+ requires = [
40
+ "pdm-backend",
41
+ ]
42
+ build-backend = "pdm.backend"
@@ -0,0 +1 @@
1
+ 3.13
File without changes
@@ -0,0 +1,7 @@
1
+ from .grid import Grid
2
+ from .pair import Pair
3
+ from .task import Task
4
+ from .datasets import ARC1, ARC2
5
+ from .contants import COLOR, PALETTE
6
+
7
+ __all__ = ["Grid", "Pair", "Task", "ARC1", "ARC2", "COLOR", "PALETTE"]
@@ -0,0 +1,29 @@
1
+ from enum import Enum
2
+ from typing import Dict
3
+
4
+
5
+ class COLOR(Enum):
6
+ ZERO = 0 # Background
7
+ ONE = 1
8
+ TWO = 2
9
+ THREE = 3
10
+ FOUR = 4
11
+ FIVE = 5
12
+ SIX = 6
13
+ SEVEN = 7
14
+ EIGHT = 8
15
+ NINE = 9
16
+
17
+
18
+ PALETTE: Dict[COLOR, str] = {
19
+ COLOR.ZERO: "\033[48;5;0m \033[0m",
20
+ COLOR.ONE: "\033[48;5;20m \033[0m",
21
+ COLOR.TWO: "\033[48;5;124m \033[0m",
22
+ COLOR.THREE: "\033[48;5;10m \033[0m",
23
+ COLOR.FOUR: "\033[48;5;11m \033[0m",
24
+ COLOR.FIVE: "\033[48;5;7m \033[0m",
25
+ COLOR.SIX: "\033[48;5;5m \033[0m",
26
+ COLOR.SEVEN: "\033[48;5;208m \033[0m",
27
+ COLOR.EIGHT: "\033[48;5;14m \033[0m",
28
+ COLOR.NINE: "\033[48;5;1m \033[0m",
29
+ }
@@ -0,0 +1,69 @@
1
+ from typing import Union, List, Dict
2
+ from pathlib import Path
3
+ from .utils import download_from_github
4
+ from .task import Task
5
+
6
+
7
+ class ARC1:
8
+ def __init__(
9
+ self, dataset_path: Union[str, Path], train: bool = True, download: bool = True
10
+ ):
11
+ self._tasks: List[Task] = list()
12
+ self._tasks_map: Dict[str, int] = dict()
13
+ self._dataset_path = (
14
+ dataset_path if isinstance(dataset_path, Path) else Path(dataset_path)
15
+ )
16
+ self._train = train
17
+
18
+ if download:
19
+ self.download()
20
+
21
+ self.load()
22
+
23
+ def load(self):
24
+ if not self._dataset_path.exists():
25
+ raise FileNotFoundError(
26
+ f"Dataset path '{self._dataset_path}' does not exist. "
27
+ )
28
+ if not self._dataset_path.is_dir():
29
+ raise NotADirectoryError(
30
+ f"Dataset path '{self._dataset_path}' is not a directory. "
31
+ )
32
+
33
+ for file_path in self._dataset_path.glob("*.json"):
34
+ task = Task.from_json(file_path)
35
+ self._tasks.append(task)
36
+
37
+ def download(self):
38
+ download_from_github(
39
+ "fchollet",
40
+ "ARC-AGI",
41
+ f"data/{'training' if self._train else 'evaluation'}",
42
+ "master",
43
+ self._dataset_path,
44
+ )
45
+
46
+ def __contains__(self, task_id: str) -> bool:
47
+ return any(task.task_id == task_id for task in self._tasks)
48
+
49
+ def get(self, task_id: str) -> Task:
50
+ if task_id not in self:
51
+ raise KeyError(f"Task with task id: {task_id} is not in this dataset. ")
52
+ return next((task for task in self._tasks if task.task_id == task_id), None)
53
+
54
+ def __getitem__(self, i: int) -> Task:
55
+ return self._tasks[i]
56
+
57
+ def __len__(self) -> int:
58
+ return len(self._tasks)
59
+
60
+
61
+ class ARC2(ARC1):
62
+ def download(self):
63
+ download_from_github(
64
+ "arcprize",
65
+ "ARC-AGI-2",
66
+ f"data/{'training' if self._train else 'evaluation'}",
67
+ "main",
68
+ self._dataset_path,
69
+ )
@@ -0,0 +1,118 @@
1
+ from typing import Union, List, Self
2
+ import numpy as np
3
+ from pathlib import Path
4
+ from .contants import PALETTE, COLOR
5
+ import json
6
+
7
+
8
+ class Grid:
9
+ PALETTE = PALETTE
10
+
11
+ @classmethod
12
+ def show_palette(cls):
13
+ """Prints the color palette."""
14
+ print(
15
+ " | ".join(
16
+ f"{color}={symbol.value}" for symbol, color in cls.PALETTE.items()
17
+ )
18
+ )
19
+
20
+ def __init__(self, array: Union[List[List[int]], np.ndarray, None] = None) -> None:
21
+ """
22
+ Initializes the `Grid` with a 2D array of integers.
23
+
24
+ Args:
25
+ array (Union[List[List[int]], np.ndarray, None]): A 2D list of int or numpy ndarray representing the grid.
26
+ If None, a default 1x1 `Grid` of `COLOR.ZERO` is used.
27
+
28
+ Raises:
29
+ ValueError: If the input array is not a 2D list or numpy ndarray of integers.
30
+ ValueError: If any element in the array is not a value of `COLOR` (values of `COLOR` is 0~9 integers by default if `COLOR` is not modified. )
31
+
32
+ Returns:
33
+ None
34
+
35
+ """
36
+ if not array:
37
+ array = [[0]]
38
+
39
+ if not isinstance(array, (np.ndarray, list)):
40
+ raise ValueError("Input array must be a 2D list or numpy ndarray.")
41
+
42
+ if not all(item in COLOR for row in array for item in row):
43
+ raise ValueError("Array elements must be values of `COLOR`")
44
+
45
+ self._array = array if isinstance(array, np.ndarray) else np.array(array)
46
+
47
+ @classmethod
48
+ def from_json(cls, file_path: Union[str, Path]) -> Self:
49
+ """
50
+ Creates a `Grid` instance from a JSON file at a given path.
51
+
52
+ Args:
53
+ file_path (Union[str, Path]): File path of the JSON file to be loaded.
54
+
55
+ Raises:
56
+ ValueError: If the string format is incorrect or if any element is not a valid `COLOR` value.
57
+
58
+ Returns:
59
+ Grid: A `Grid` instance created from the JSON file.
60
+ """
61
+ try:
62
+ with open(file_path) as f:
63
+ array = json.load(f)
64
+ except json.JSONDecodeError:
65
+ raise ValueError("Invalid JSON format.")
66
+
67
+ return cls(array)
68
+
69
+ @classmethod
70
+ def from_npy(cls, filePath: Union[str, Path]) -> Self:
71
+ return cls(np.load(filePath))
72
+
73
+ def save_as_json(self, path: Union[str, Path]) -> None:
74
+ with open(path, "w") as f:
75
+ json.dump(self.to_list(), f)
76
+
77
+ def save_as_npy(self, path: str | Path) -> None:
78
+ np.save(path, self.to_numpy())
79
+
80
+ def to_list(self) -> List[List[int]]:
81
+ return self._array.tolist()
82
+
83
+ def to_numpy(self) -> np.ndarray:
84
+ return self._array
85
+
86
+ @property
87
+ def shape(self) -> Tuple[int, int]:
88
+ return self.to_numpy().shape
89
+
90
+ def __repr__(self) -> str:
91
+ return (
92
+ "\n".join(
93
+ "".join(self.PALETTE[COLOR(value)] for value in row)
94
+ for row in self.to_numpy()
95
+ )
96
+ + "\n"
97
+ )
98
+
99
+ def __eq__(self, other: object) -> bool:
100
+ if not isinstance(other, Grid):
101
+ raise ValueError(
102
+ "Cannot compare with non-`Grid` object. "
103
+ "If the object is 2d list or numpy array, try converting it to `Grid` and then compare. "
104
+ )
105
+ return bool((self.to_numpy() == other.to_numpy()).all())
106
+
107
+ def __sub__(self, other: object) -> int:
108
+ """Number of different pixels"""
109
+ if not isinstance(other, Grid):
110
+ raise NotImplementedError(
111
+ "Cannot compare with non-`Grid` object. "
112
+ "If the object is 2d list or numpy array, try converting it to `Grid` and then compare. "
113
+ )
114
+ if self.shape != other.shape:
115
+ raise ValueError(
116
+ f"Connot compare `Grid`s of different shape. {self.shape} != {other.shape}"
117
+ )
118
+ return np.sum(self.to_numpy() != other.to_numpy())
@@ -0,0 +1,75 @@
1
+ from typing import Union, List
2
+ import warnings
3
+ from .grid import Grid
4
+ from .utils import Layout
5
+
6
+
7
+ class Pair:
8
+ def __init__(
9
+ self,
10
+ input: Union[Grid, List[List[int]]],
11
+ output: Union[Grid, List[List[int]]],
12
+ censor: bool = False,
13
+ ) -> None:
14
+ self._input = input if isinstance(input, Grid) else Grid(input)
15
+ self._output = output if isinstance(output, Grid) else Grid(output)
16
+ self._is_censored = censor
17
+
18
+ @property
19
+ def input(self):
20
+ return self._input
21
+
22
+ @input.setter
23
+ def input(self, grid: Union[Grid, List[List[int]]]):
24
+ self._input = grid if isinstance(grid, Grid) else Grid(grid)
25
+ return self._input
26
+
27
+ @property
28
+ def output(self):
29
+ if self._is_censored:
30
+ warnings.warn(
31
+ "Access to `output` is censored. Call `.uncensor()` to gain access. ",
32
+ UserWarning,
33
+ )
34
+ return None
35
+ return self._output
36
+
37
+ @output.setter
38
+ def output(self, grid: Union[Grid, List[List[int]]]):
39
+ if self._is_censored:
40
+ warnings.warn(
41
+ "Access to `output` is censored. Call `.uncensor()` to gain access. ",
42
+ UserWarning,
43
+ )
44
+ return None
45
+ self._output = grid if isinstance(grid, Grid) else Grid(grid)
46
+ return self._output
47
+
48
+ def censor(self):
49
+ self._is_censored = True
50
+
51
+ def uncensor(self):
52
+ self._is_censored = False
53
+
54
+ def __repr__(self):
55
+ return repr(
56
+ Layout(
57
+ Layout(
58
+ "INPUT",
59
+ self.input,
60
+ direction="vertical",
61
+ align="center",
62
+ ),
63
+ "->",
64
+ Layout(
65
+ "OUTPUT",
66
+ self.output if self.output else "*CENSORED*",
67
+ direction="vertical",
68
+ align="center",
69
+ ),
70
+ align="center",
71
+ )
72
+ )
73
+
74
+ def to_dict(self):
75
+ return {"input": self.input.to_list(), "output": self.output.to_list()}
@@ -0,0 +1,33 @@
1
+ [project]
2
+ name = "arc-core"
3
+ version = "0.1.0"
4
+ description = "Core package of ARC-RTK"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Jumyung Park", email = "parkjumyungpublic@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "numpy>=2.2.4",
12
+ "requests>=2.32.3",
13
+ ]
14
+
15
+ [dependency-groups]
16
+ lint = ["ruff>=0.11.2"]
17
+ dev = [
18
+ "ipykernel>=6.29.5"
19
+ ]
20
+
21
+ [tool.uv.sources]
22
+
23
+
24
+ [build-system]
25
+ requires = ["pdm-backend"]
26
+ build-backend = "pdm.backend"
27
+
28
+ [tool.ruff]
29
+ extend-include = ["*.ipynb"]
30
+
31
+ [tool.ruff.lint]
32
+ select = ["D"]
33
+ pydocstyle = { convention = "google" }
@@ -0,0 +1,148 @@
1
+ from typing import Union, List, Tuple, Optional, Dict, Literal
2
+ from pathlib import Path
3
+ import json
4
+
5
+ from .grid import Grid
6
+ from .pair import Pair
7
+ from .utils import Layout
8
+
9
+
10
+ class Task:
11
+ def __init__(
12
+ self,
13
+ train: Union[
14
+ List[Pair],
15
+ List[Tuple[List[List[int]], List[List[int]]]],
16
+ List[Tuple[Grid, Grid]],
17
+ ],
18
+ test: Union[
19
+ List[Pair],
20
+ List[Tuple[List[List[int]], List[List[int]]]],
21
+ List[Tuple[Grid, Grid]],
22
+ ],
23
+ task_id: Optional[str] = None,
24
+ ):
25
+ self.train = [pair if isinstance(pair, Pair) else Pair(*pair) for pair in train]
26
+ self.test = [pair if isinstance(pair, Pair) else Pair(*pair) for pair in test]
27
+ self.task_id = task_id
28
+
29
+ @classmethod
30
+ def from_dict(
31
+ cls,
32
+ task_dict: Dict[
33
+ Literal["train", "test"],
34
+ List[Dict[Literal["input", "output"], List[List[int]]]],
35
+ ],
36
+ task_id: Optional[str] = None,
37
+ ):
38
+ train = [Pair(pair["input"], pair["output"]) for pair in task_dict["train"]]
39
+ test = [Pair(pair["input"], pair["output"]) for pair in task_dict["test"]]
40
+
41
+ return cls(train, test, task_id)
42
+
43
+ def to_dict(self):
44
+ return {
45
+ "train": [pair.to_dict() for pair in self.train],
46
+ "test": [pair.to_dict() for pair in self.test],
47
+ }
48
+
49
+ @classmethod
50
+ def from_json(cls, file_path: Union[str, Path]):
51
+ file_path = file_path if isinstance(file_path, Path) else Path(file_path)
52
+ task_id = file_path.stem
53
+
54
+ task = None
55
+ try:
56
+ with file_path.open() as f:
57
+ task = json.load(f)
58
+ # TODO: validate schema
59
+ except Exception as e:
60
+ raise RuntimeError(
61
+ f"Failed to load and parse task json file at '{file_path}: {e}"
62
+ )
63
+
64
+ return cls.from_dict(task, task_id)
65
+
66
+ @property
67
+ def inputs(self):
68
+ return [pair.input for pair in self.train + self.test]
69
+
70
+ @property
71
+ def outputs(self):
72
+ return [pair.output for pair in self.train + self.test]
73
+
74
+ def __repr__(self):
75
+ train = Layout(
76
+ *[
77
+ Layout(
78
+ Layout(
79
+ f"INPUT {i}",
80
+ pair.input,
81
+ direction="vertical",
82
+ align="center",
83
+ ),
84
+ " -> ",
85
+ Layout(
86
+ f"OUTPUT {i}",
87
+ pair.output if pair.output else "*CENSORED*",
88
+ direction="vertical",
89
+ align="center",
90
+ ),
91
+ )
92
+ for i, pair in enumerate(self.train)
93
+ ],
94
+ direction="vertical",
95
+ )
96
+ test = Layout(
97
+ *[
98
+ Layout(
99
+ Layout(
100
+ f"INPUT {i}",
101
+ pair.input,
102
+ direction="vertical",
103
+ align="center",
104
+ ),
105
+ " -> ",
106
+ Layout(
107
+ f"OUTPUT {i}",
108
+ pair.output if pair.output else "*CENSORED*",
109
+ direction="vertical",
110
+ align="center",
111
+ ),
112
+ )
113
+ for i, pair in enumerate(self.test)
114
+ ],
115
+ direction="vertical",
116
+ )
117
+ width = max(train.width, test.width)
118
+ return repr(
119
+ Layout(
120
+ f"< Task{' ' + self.task_id if self.task_id else ''} >".center(
121
+ width, "="
122
+ ),
123
+ " Train ".center(width, "-"),
124
+ train,
125
+ " Test ".center(width, "-"),
126
+ test,
127
+ direction="vertical",
128
+ )
129
+ )
130
+
131
+ def __str__(self):
132
+ return str(repr(self))
133
+
134
+ def censor_outputs(self):
135
+ for pair in self.train + self.test:
136
+ pair.censor()
137
+
138
+ def uncensor_outputs(self):
139
+ for pair in self.train + self.test:
140
+ pair.uncensor()
141
+
142
+ def censor_test_outputs(self):
143
+ for pair in self.test:
144
+ pair.censor()
145
+
146
+ def uncensor_test_outputs(self):
147
+ for pair in self.test:
148
+ pair.uncensor()
@@ -0,0 +1,187 @@
1
+ import re
2
+ from typing import List, Literal, Any
3
+ import os
4
+ import requests
5
+ import zipfile
6
+ import io
7
+
8
+
9
+ ANSI_ESCAPE_PATTERN = re.compile(r"\x1b\[[0-9;]*m")
10
+
11
+
12
+ def strip_ansi(text: str) -> str:
13
+ """Removes ANSI escape codes from the string for correct width calculation."""
14
+ return ANSI_ESCAPE_PATTERN.sub("", text)
15
+
16
+
17
+ def ansi_width(text: str) -> int:
18
+ """Returns the width of text after removing ANSI escape sequences."""
19
+ return len(strip_ansi(text))
20
+
21
+
22
+ def align_lines(
23
+ lines: List[str],
24
+ target_width: int,
25
+ align: Literal["start", "center", "end"],
26
+ ) -> List[str]:
27
+ """Aligns lines while preserving ANSI codes."""
28
+ if align == "start":
29
+ return [
30
+ line + " " * (max(target_width - ansi_width(line), 0)) for line in lines
31
+ ]
32
+ elif align == "center":
33
+ return [
34
+ " " * (max(target_width - ansi_width(line), 0) // 2)
35
+ + line
36
+ + " " * ((max(target_width - ansi_width(line), 0) + 1) // 2)
37
+ for line in lines
38
+ ]
39
+ elif align == "end":
40
+ return [" " * max(target_width - ansi_width(line), 0) + line for line in lines]
41
+
42
+
43
+ class Layout:
44
+ def __init__(
45
+ self,
46
+ *elements: Any,
47
+ direction: Literal["horizontal", "vertical"] = "horizontal",
48
+ align: Literal["start", "center", "end"] = "start",
49
+ show_divider: bool = False,
50
+ min_width: int = 0,
51
+ ):
52
+ self.elements = elements
53
+ self.direction = direction
54
+ self.align = align
55
+ self.show_divider = show_divider
56
+ self.min_width = min_width
57
+
58
+ @property
59
+ def width(self):
60
+ return max(ansi_width(line) for line in repr(self).splitlines())
61
+
62
+ @property
63
+ def height(self):
64
+ return len(repr(self).splitlines())
65
+
66
+ def __repr__(self) -> str:
67
+ elements = [
68
+ (element if isinstance(element, str) else repr(element)).splitlines()
69
+ for element in self.elements
70
+ ]
71
+
72
+ if self.direction == "horizontal":
73
+ max_height = max(len(element) for element in elements)
74
+ normalized_elements = [
75
+ element + [""] * (max_height - len(element)) for element in elements
76
+ ]
77
+ widths = [max(ansi_width(line) for line in element) for element in elements]
78
+ aligned_elements = [
79
+ align_lines(element, width, self.align)
80
+ for element, width in zip(normalized_elements, widths)
81
+ ]
82
+ divider = " | " if self.show_divider else ""
83
+ return "\n".join(
84
+ align_lines(
85
+ [
86
+ divider.join(
87
+ aligned_elements[col][row]
88
+ for col in range(len(aligned_elements))
89
+ )
90
+ for row in range(max_height)
91
+ ],
92
+ self.min_width,
93
+ self.align,
94
+ )
95
+ )
96
+
97
+ elif self.direction == "vertical":
98
+ max_width = max(
99
+ max(ansi_width(line) for line in element) for element in elements
100
+ )
101
+ aligned_elements = [
102
+ align_lines(element, max_width, self.align) for element in elements
103
+ ]
104
+ divider = "\n" + "-" * max_width if self.show_divider else ""
105
+ return f"{divider}\n".join(
106
+ "\n".join(element) for element in aligned_elements
107
+ )
108
+
109
+ def __str__(self) -> str:
110
+ elements = [str(element).splitlines() for element in self.elements]
111
+
112
+ if self.direction == "horizontal":
113
+ max_height = max(len(element) for element in elements)
114
+ normalized_elements = [
115
+ element + [""] * (max_height - len(element)) for element in elements
116
+ ]
117
+ widths = [max(ansi_width(line) for line in element) for element in elements]
118
+ aligned_elements = [
119
+ align_lines(element, width, self.align)
120
+ for element, width in zip(normalized_elements, widths)
121
+ ]
122
+ divider = " | " if self.show_divider else ""
123
+ return "\n".join(
124
+ divider.join(
125
+ aligned_elements[col][row] for col in range(len(aligned_elements))
126
+ )
127
+ for row in range(max_height)
128
+ )
129
+
130
+ elif self.direction == "vertical":
131
+ max_width = max(
132
+ max(ansi_width(line) for line in element) for element in elements
133
+ )
134
+ aligned_elements = [
135
+ align_lines(element, max_width, self.align) for element in elements
136
+ ]
137
+ divider = "\n" + "-" * max_width if self.show_divider else ""
138
+ return f"{divider}\n".join(
139
+ "\n".join(element) for element in aligned_elements
140
+ )
141
+
142
+
143
+ def download_from_github(
144
+ repo_owner, repo_name, path, branch="main", destination="./downloaded"
145
+ ):
146
+ """
147
+ Downloads and extracts a specific path from a GitHub repository.
148
+
149
+ :param repo_owner: GitHub username or organization.
150
+ :param repo_name: Repository name.
151
+ :param path: Path to the folder inside the repo to extract.
152
+ :param branch: Repo branch (default: "main").
153
+ :param destination: Local destination folder for saving files.
154
+ """
155
+ url = f"https://github.com/{repo_owner}/{repo_name}/archive/refs/heads/{branch}.zip"
156
+ print(f"Downloading from {url}")
157
+ response = requests.get(url, stream=True)
158
+
159
+ if response.status_code == 200:
160
+ with zipfile.ZipFile(io.BytesIO(response.content)) as zip_file:
161
+ repo_folder = f"{repo_name}-{branch}/"
162
+ target_folder = f"{repo_folder}{path}/"
163
+
164
+ extracted_files = 0
165
+
166
+ for file in zip_file.namelist():
167
+ if file.startswith(target_folder) and not file.endswith("/"):
168
+ relative_path = file[len(target_folder) :]
169
+ save_path = os.path.join(destination, relative_path)
170
+
171
+ os.makedirs(os.path.dirname(save_path), exist_ok=True)
172
+ with zip_file.open(file) as source, open(save_path, "wb") as target:
173
+ target.write(source.read())
174
+
175
+ extracted_files += 1
176
+
177
+ if extracted_files > 0:
178
+ print(
179
+ f"✅ Successfully downloaded '{path}' from {repo_owner}/{repo_name} into '{destination}'."
180
+ )
181
+ else:
182
+ print(
183
+ f"⚠️ No files extracted. Check if the path '{path}' exists in the repository."
184
+ )
185
+
186
+ else:
187
+ print(f"❌ Failed to download: HTTP {response.status_code}")
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.1
2
+ Name: arc-lambda
3
+ Version: 0.1.0
4
+ Summary: ARC-RTK for lamdba-calculus(functional programming) approach
5
+ Author-Email: Jumyung Park <parkjumyungpublic@gmail.com>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: pdm-backend (2.4.3)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+
3
+ [gui_scripts]
4
+
@@ -0,0 +1 @@
1
+ /Users/jumyung/dev/arc-research-template/libs/arc/lambda
@@ -0,0 +1 @@
1
+ 3.13
File without changes
File without changes
@@ -0,0 +1,30 @@
1
+ [project]
2
+ name = "arc-lambda"
3
+ version = "0.1.0"
4
+ description = "ARC-RTK for lamdba-calculus(functional programming) approach"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Jumyung Park", email = "parkjumyungpublic@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = []
11
+
12
+ [dependency-groups]
13
+ lint = ["ruff>=0.11.2"]
14
+ dev = [
15
+ "ipykernel>=6.29.5"
16
+ ]
17
+
18
+ [tool.uv.sources]
19
+ arc-core = { path = "../core" }
20
+
21
+ [build-system]
22
+ requires = ["pdm-backend"]
23
+ build-backend = "pdm.backend"
24
+
25
+ [tool.ruff]
26
+ extend-include = ["*.ipynb"]
27
+
28
+ [tool.ruff.lint]
29
+ select = ["D"]
30
+ pydocstyle = { convention = "google" }
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.1
2
+ Name: arc-llm
3
+ Version: 0.1.0
4
+ Summary: ARC-RTK for LLM(Large Language Model) approach
5
+ Author-Email: Jumyung Park <parkjumyungpublic@gmail.com>
6
+ Requires-Python: >=3.13
7
+ Description-Content-Type: text/markdown
8
+
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: pdm-backend (2.4.3)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+
3
+ [gui_scripts]
4
+
@@ -0,0 +1 @@
1
+ /Users/jumyung/dev/arc-research-template/libs/arc/llm
@@ -0,0 +1 @@
1
+ 3.13
File without changes
File without changes
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "arc-llm"
3
+ version = "0.1.0"
4
+ description = "ARC-RTK for LLM(Large Language Model) approach"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Jumyung Park", email = "parkjumyungpublic@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = []
11
+
12
+
13
+ [dependency-groups]
14
+ lint = ["ruff>=0.11.2"]
15
+ dev = [
16
+ "ipykernel>=6.29.5"
17
+ ]
18
+
19
+ [tool.uv.sources]
20
+ arc-core = { path = "../core" }
21
+
22
+ [build-system]
23
+ requires = ["pdm-backend"]
24
+ build-backend = "pdm.backend"
25
+
26
+ [tool.ruff]
27
+ extend-include = ["*.ipynb"]
28
+
29
+ [tool.ruff.lint]
30
+ select = ["D"]
31
+ pydocstyle = { convention = "google" }
@@ -0,0 +1,2 @@
1
+ class Test:
2
+ x = 1
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: arc-torch
3
+ Version: 0.1.0
4
+ Summary: Extended ARC-RTK for PyTorch integration.
5
+ Author-Email: Jumyung Park <parkjumyungpublic@gmail.com>
6
+ Requires-Python: >=3.13
7
+ Requires-Dist: torch>=2.6.0
8
+ Description-Content-Type: text/markdown
9
+
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: pdm-backend (2.4.3)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+
3
+ [gui_scripts]
4
+
@@ -0,0 +1 @@
1
+ /Users/jumyung/dev/arc-research-template/libs/arc/torch
@@ -0,0 +1 @@
1
+ 3.13
File without changes
File without changes
@@ -0,0 +1,32 @@
1
+ [project]
2
+ name = "arc-torch"
3
+ version = "0.1.0"
4
+ description = "Extended ARC-RTK for PyTorch integration. "
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Jumyung Park", email = "parkjumyungpublic@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "torch>=2.6.0",
12
+ ]
13
+
14
+ [dependency-groups]
15
+ lint = ["ruff>=0.11.2"]
16
+ dev = [
17
+ "ipykernel>=6.29.5"
18
+ ]
19
+
20
+ [tool.uv.sources]
21
+ arc-core = { path = "../core" }
22
+
23
+ [build-system]
24
+ requires = ["pdm-backend"]
25
+ build-backend = "pdm.backend"
26
+
27
+ [tool.ruff]
28
+ extend-include = ["*.ipynb"]
29
+
30
+ [tool.ruff.lint]
31
+ select = ["D"]
32
+ pydocstyle = { convention = "google" }
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = [
3
+ "pdm-backend",
4
+ ]
5
+ build-backend = "pdm.backend"
6
+
7
+ [project]
8
+ name = "arc-agi"
9
+ version = "0.0.1"
10
+ description = "Work in progress..."
11
+ readme = "README.md"
12
+ requires-python = ">=3.13"
13
+ dependencies = [
14
+ "ipykernel>=6.29.5",
15
+ "numpy>=2.2.4",
16
+ "requests>=2.32.3",
17
+ ]
18
+
19
+ [project.license]
20
+ file = "LICENSE"
21
+
22
+ [tool.pdm.extras]
23
+ core = [
24
+ "arc.core",
25
+ ]
26
+ lambda = [
27
+ "arc.lamdba",
28
+ ]
29
+ llm = [
30
+ "arc.llm",
31
+ ]
32
+ torch = [
33
+ "arc.torch",
34
+ ]
35
+ all = [
36
+ "arc.core",
37
+ "arc.lambda",
38
+ "arc.llm",
39
+ "arc.torch",
40
+ ]
41
+
42
+ [tool.uv.workspace]
43
+ members = [
44
+ "arc/core",
45
+ "arc/lambda",
46
+ "arc/llm",
47
+ "arc/torch",
48
+ ]
49
+
50
+ [[tool.uv.index]]
51
+ name = "testpypi"
52
+ url = "https://test.pypi.org/simple/"
53
+ publish-utl = "https://test.pypi.org/legacy/"
54
+ explicit = true