diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..e0388a8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @CameronImmesoete diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..08b2ec5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,13 @@ +# Copilot Instructions + +> Base instructions: [CameronImmesoete/.github/.github/copilot-instructions.md@1f79bfb](https://github.com/CameronImmesoete/.github/blob/1f79bfb3e9eee277d05ecdd3332220204cb0f38b/.github/copilot-instructions.md) + +## Repository-Specific Guidelines + +This is a Pascal's triangle generator in Python. + +- Algorithmic correctness is the priority (binomial coefficient math) +- Handle edge cases: row 0, negative inputs, very large row numbers +- Integer overflow considerations for large rows +- Output formatting should be consistent and readable +- This is a single-file project; keep it simple and self-contained diff --git a/.github/copilot-review-skill.md b/.github/copilot-review-skill.md new file mode 100644 index 0000000..bcf1b3b --- /dev/null +++ b/.github/copilot-review-skill.md @@ -0,0 +1,17 @@ +# Code Review Standards + +> Base review standards: [CameronImmesoete/.github/.github/copilot-review-skill.md@1f79bfb](https://github.com/CameronImmesoete/.github/blob/1f79bfb3e9eee277d05ecdd3332220204cb0f38b/.github/copilot-review-skill.md) + +## Repository-Specific Review Criteria + +### Algorithm Correctness +- Pascal's triangle values match binomial coefficients +- Each row sum equals 2^n +- Symmetry property: C(n,k) = C(n,n-k) +- Edge values are always 1 + +### Edge Cases +- Row 0 returns [1] +- Negative row numbers rejected with clear error +- Large row numbers: integer overflow handling +- Input validation (non-negative integers only) diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5ace460 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e4854b6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + + - name: Lint + run: uvx ruff check . + + - name: Format check + run: uvx ruff format --check . + + - name: Syntax check + run: python -c "import py_compile; py_compile.compile('pascal.py', doraise=True)" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3244150 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.egg-info/ +dist/ +build/ +*.egg +.eggs/ +*.whl + +# Virtual environments +.venv/ +venv/ +ENV/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ +.project +.settings/ + +# OS +.DS_Store +Thumbs.db +Desktop.ini + +# Testing / Coverage +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +htmlcov/ +.coverage +coverage.xml + +# Secrets +.env +.env.* +*.pem +*.key diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..061b5f7 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,31 @@ +# Agent Guidelines + +## PR Rules +- One PR per branch. One branch per task. +- Never close a PR to open a replacement. Fix in place. +- Never push directly to main. +- Squash merge only. +- Branches auto-delete after merge. +- Branch naming: `user/CameronImmesoete/` + +## CI Requirements +- All CI checks must pass before merge. +- No `[skip ci]` commits unless pure documentation. +- If CI is red on main, fix it before other work. + +## Security +- Never commit secrets, API keys, tokens, or credentials. +- Never add dependencies without justification. +- Never force push to main. +- Run tests before pushing. + +## Code Quality +- Tests required for all new functions. +- Lint must pass (ruff for Python, eslint for TypeScript). +- Type checks must pass (mypy for Python, tsc for TypeScript). +- Prefer simple, readable code over clever abstractions. + +## Shared Workflows +- Python repos can use the reusable CI workflow: `uses: CameronImmesoete/.github/.github/workflows/python-ci.yml@main` + - Note: The doubled `.github` is intentional. The first is the repo name (`CameronImmesoete/.github`), the second is the workflows directory within it (`.github/workflows/`). +- **Pinning policy:** `@main` is temporary during initial setup. Once the shared workflow repo has a stable first release, all callers must pin to a tagged release or specific commit SHA (e.g., `@v1.0.0` or `@abc1234`). Never use `@main` in production workflows. Update callers when the shared workflow changes by bumping the pinned reference. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..100dbad --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,9 @@ +# Contributing + +Solo project maintained by [Cam Immesoete](https://github.com/CameronImmesoete). External contributions are not accepted at this time. + +## Standards + +- All changes go through pull requests (no direct pushes to main) +- Clean, descriptive commit messages +- No secrets, credentials, or API keys in code diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..33354b8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Cam Immesoete + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/pascal.py b/pascal.py index 313aa27..ba3ef0e 100644 --- a/pascal.py +++ b/pascal.py @@ -1,5 +1,6 @@ # Retrying the Pascal problem + def PascalNChooseK(n, k): if n < 0 or k < 0 or k > n: return "Invalid" @@ -8,6 +9,7 @@ def PascalNChooseK(n, k): return halfrow[k] return halfrow[n - k] + def PascalHelper(n): current = [1] last = [1] @@ -20,11 +22,20 @@ def PascalHelper(n): current += [last[len(last) - 1] * 2] return current -if __name__ == '__main__': + +if __name__ == "__main__": print("N Choose K tests:") print("5 choose 2: " + str(PascalNChooseK(5, 2))) print("5 choose 3: " + str(PascalNChooseK(5, 3))) print("5 choose 6: " + str(PascalNChooseK(5, 3))) - print("15 choose 4: " + str(PascalNChooseK(15, 4)) + " # if n > 13, factorial method would blow up") - print("40 choose 30: " + str(PascalNChooseK(40, 30)) + " # if n > 13, factorial method would blow up") - print("0 choose 0: " + str(PascalNChooseK(0, 0))) \ No newline at end of file + print( + "15 choose 4: " + + str(PascalNChooseK(15, 4)) + + " # if n > 13, factorial method would blow up" + ) + print( + "40 choose 30: " + + str(PascalNChooseK(40, 30)) + + " # if n > 13, factorial method would blow up" + ) + print("0 choose 0: " + str(PascalNChooseK(0, 0))) diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..c82cae7 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,8 @@ +# Ruff configuration for Pascal repo +# Preserve existing code style + +indent-width = 2 + +[lint] +# Ignore naming convention rules (PascalCase function names are intentional) +ignore = ["N802", "N803"]