Juni
1 year ago
commit
0f22cd789d
7 changed files with 693 additions and 0 deletions
-
160.dockerignore
-
161.gitignore
-
11Dockerfile
-
32app.py
-
19requirements.txt
-
240solver.py
-
70templates/page.html
@ -0,0 +1,160 @@ |
|||||
|
# Byte-compiled / optimized / DLL files |
||||
|
__pycache__/ |
||||
|
*.py[cod] |
||||
|
*$py.class |
||||
|
|
||||
|
# C extensions |
||||
|
*.so |
||||
|
|
||||
|
# Distribution / packaging |
||||
|
.Python |
||||
|
build/ |
||||
|
develop-eggs/ |
||||
|
dist/ |
||||
|
downloads/ |
||||
|
eggs/ |
||||
|
.eggs/ |
||||
|
lib/ |
||||
|
lib64/ |
||||
|
parts/ |
||||
|
sdist/ |
||||
|
var/ |
||||
|
wheels/ |
||||
|
share/python-wheels/ |
||||
|
*.egg-info/ |
||||
|
.installed.cfg |
||||
|
*.egg |
||||
|
MANIFEST |
||||
|
|
||||
|
# PyInstaller |
||||
|
# Usually these files are written by a python script from a template |
||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it. |
||||
|
*.manifest |
||||
|
*.spec |
||||
|
|
||||
|
# Installer logs |
||||
|
pip-log.txt |
||||
|
pip-delete-this-directory.txt |
||||
|
|
||||
|
# Unit test / coverage reports |
||||
|
htmlcov/ |
||||
|
.tox/ |
||||
|
.nox/ |
||||
|
.coverage |
||||
|
.coverage.* |
||||
|
.cache |
||||
|
nosetests.xml |
||||
|
coverage.xml |
||||
|
*.cover |
||||
|
*.py,cover |
||||
|
.hypothesis/ |
||||
|
.pytest_cache/ |
||||
|
cover/ |
||||
|
|
||||
|
# Translations |
||||
|
*.mo |
||||
|
*.pot |
||||
|
|
||||
|
# Django stuff: |
||||
|
*.log |
||||
|
local_settings.py |
||||
|
db.sqlite3 |
||||
|
db.sqlite3-journal |
||||
|
|
||||
|
# Flask stuff: |
||||
|
instance/ |
||||
|
.webassets-cache |
||||
|
|
||||
|
# Scrapy stuff: |
||||
|
.scrapy |
||||
|
|
||||
|
# Sphinx documentation |
||||
|
docs/_build/ |
||||
|
|
||||
|
# PyBuilder |
||||
|
.pybuilder/ |
||||
|
target/ |
||||
|
|
||||
|
# Jupyter Notebook |
||||
|
.ipynb_checkpoints |
||||
|
|
||||
|
# IPython |
||||
|
profile_default/ |
||||
|
ipython_config.py |
||||
|
|
||||
|
# pyenv |
||||
|
# For a library or package, you might want to ignore these files since the code is |
||||
|
# intended to run in multiple environments; otherwise, check them in: |
||||
|
# .python-version |
||||
|
|
||||
|
# pipenv |
||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. |
||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies |
||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not |
||||
|
# install all needed dependencies. |
||||
|
#Pipfile.lock |
||||
|
|
||||
|
# poetry |
||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. |
||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more |
||||
|
# commonly ignored for libraries. |
||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control |
||||
|
#poetry.lock |
||||
|
|
||||
|
# pdm |
||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. |
||||
|
#pdm.lock |
||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it |
||||
|
# in version control. |
||||
|
# https://pdm.fming.dev/#use-with-ide |
||||
|
.pdm.toml |
||||
|
|
||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm |
||||
|
__pypackages__/ |
||||
|
|
||||
|
# Celery stuff |
||||
|
celerybeat-schedule |
||||
|
celerybeat.pid |
||||
|
|
||||
|
# SageMath parsed files |
||||
|
*.sage.py |
||||
|
|
||||
|
# Environments |
||||
|
.env |
||||
|
.venv |
||||
|
env/ |
||||
|
venv/ |
||||
|
ENV/ |
||||
|
env.bak/ |
||||
|
venv.bak/ |
||||
|
|
||||
|
# Spyder project settings |
||||
|
.spyderproject |
||||
|
.spyproject |
||||
|
|
||||
|
# Rope project settings |
||||
|
.ropeproject |
||||
|
|
||||
|
# mkdocs documentation |
||||
|
/site |
||||
|
|
||||
|
# mypy |
||||
|
.mypy_cache/ |
||||
|
.dmypy.json |
||||
|
dmypy.json |
||||
|
|
||||
|
# Pyre type checker |
||||
|
.pyre/ |
||||
|
|
||||
|
# pytype static type analyzer |
||||
|
.pytype/ |
||||
|
|
||||
|
# Cython debug symbols |
||||
|
cython_debug/ |
||||
|
|
||||
|
# PyCharm |
||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can |
||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore |
||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear |
||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder. |
||||
|
#.idea/ |
@ -0,0 +1,161 @@ |
|||||
|
# Byte-compiled / optimized / DLL files |
||||
|
__pycache__/ |
||||
|
*.py[cod] |
||||
|
*$py.class |
||||
|
|
||||
|
.DS_Store |
||||
|
# C extensions |
||||
|
*.so |
||||
|
|
||||
|
# Distribution / packaging |
||||
|
.Python |
||||
|
build/ |
||||
|
develop-eggs/ |
||||
|
dist/ |
||||
|
downloads/ |
||||
|
eggs/ |
||||
|
.eggs/ |
||||
|
lib/ |
||||
|
lib64/ |
||||
|
parts/ |
||||
|
sdist/ |
||||
|
var/ |
||||
|
wheels/ |
||||
|
share/python-wheels/ |
||||
|
*.egg-info/ |
||||
|
.installed.cfg |
||||
|
*.egg |
||||
|
MANIFEST |
||||
|
|
||||
|
# PyInstaller |
||||
|
# Usually these files are written by a python script from a template |
||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it. |
||||
|
*.manifest |
||||
|
*.spec |
||||
|
|
||||
|
# Installer logs |
||||
|
pip-log.txt |
||||
|
pip-delete-this-directory.txt |
||||
|
|
||||
|
# Unit test / coverage reports |
||||
|
htmlcov/ |
||||
|
.tox/ |
||||
|
.nox/ |
||||
|
.coverage |
||||
|
.coverage.* |
||||
|
.cache |
||||
|
nosetests.xml |
||||
|
coverage.xml |
||||
|
*.cover |
||||
|
*.py,cover |
||||
|
.hypothesis/ |
||||
|
.pytest_cache/ |
||||
|
cover/ |
||||
|
|
||||
|
# Translations |
||||
|
*.mo |
||||
|
*.pot |
||||
|
|
||||
|
# Django stuff: |
||||
|
*.log |
||||
|
local_settings.py |
||||
|
db.sqlite3 |
||||
|
db.sqlite3-journal |
||||
|
|
||||
|
# Flask stuff: |
||||
|
instance/ |
||||
|
.webassets-cache |
||||
|
|
||||
|
# Scrapy stuff: |
||||
|
.scrapy |
||||
|
|
||||
|
# Sphinx documentation |
||||
|
docs/_build/ |
||||
|
|
||||
|
# PyBuilder |
||||
|
.pybuilder/ |
||||
|
target/ |
||||
|
|
||||
|
# Jupyter Notebook |
||||
|
.ipynb_checkpoints |
||||
|
|
||||
|
# IPython |
||||
|
profile_default/ |
||||
|
ipython_config.py |
||||
|
|
||||
|
# pyenv |
||||
|
# For a library or package, you might want to ignore these files since the code is |
||||
|
# intended to run in multiple environments; otherwise, check them in: |
||||
|
# .python-version |
||||
|
|
||||
|
# pipenv |
||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. |
||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies |
||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not |
||||
|
# install all needed dependencies. |
||||
|
#Pipfile.lock |
||||
|
|
||||
|
# poetry |
||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. |
||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more |
||||
|
# commonly ignored for libraries. |
||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control |
||||
|
#poetry.lock |
||||
|
|
||||
|
# pdm |
||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. |
||||
|
#pdm.lock |
||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it |
||||
|
# in version control. |
||||
|
# https://pdm.fming.dev/#use-with-ide |
||||
|
.pdm.toml |
||||
|
|
||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm |
||||
|
__pypackages__/ |
||||
|
|
||||
|
# Celery stuff |
||||
|
celerybeat-schedule |
||||
|
celerybeat.pid |
||||
|
|
||||
|
# SageMath parsed files |
||||
|
*.sage.py |
||||
|
|
||||
|
# Environments |
||||
|
.env |
||||
|
.venv |
||||
|
env/ |
||||
|
venv/ |
||||
|
ENV/ |
||||
|
env.bak/ |
||||
|
venv.bak/ |
||||
|
|
||||
|
# Spyder project settings |
||||
|
.spyderproject |
||||
|
.spyproject |
||||
|
|
||||
|
# Rope project settings |
||||
|
.ropeproject |
||||
|
|
||||
|
# mkdocs documentation |
||||
|
/site |
||||
|
|
||||
|
# mypy |
||||
|
.mypy_cache/ |
||||
|
.dmypy.json |
||||
|
dmypy.json |
||||
|
|
||||
|
# Pyre type checker |
||||
|
.pyre/ |
||||
|
|
||||
|
# pytype static type analyzer |
||||
|
.pytype/ |
||||
|
|
||||
|
# Cython debug symbols |
||||
|
cython_debug/ |
||||
|
|
||||
|
# PyCharm |
||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can |
||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore |
||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear |
||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder. |
||||
|
#.idea/ |
@ -0,0 +1,11 @@ |
|||||
|
FROM python:latest |
||||
|
|
||||
|
WORKDIR /app |
||||
|
COPY ./requirements.txt /app/ |
||||
|
EXPOSE 8000 |
||||
|
|
||||
|
RUN pip install -r requirements.txt |
||||
|
|
||||
|
COPY . /app |
||||
|
|
||||
|
CMD ["gunicorn", "app:app", "-w", "3", "-b", "0.0.0.0:8000"] |
@ -0,0 +1,32 @@ |
|||||
|
from flask import Flask, render_template, request |
||||
|
import solver |
||||
|
|
||||
|
app = Flask(__name__) |
||||
|
|
||||
|
|
||||
|
@app.route("/", methods=["GET", "POST"]) |
||||
|
def index(): |
||||
|
if request.method == "GET": |
||||
|
return render_template("page.html") |
||||
|
else: |
||||
|
try: |
||||
|
M = int(request.form["M"]) |
||||
|
N = int(request.form["N"]) |
||||
|
except ValueError: |
||||
|
return render_template("page.html", invalid=True) |
||||
|
if not (1 <= M <= 40 and 1 <= N <= 40): |
||||
|
return render_template("page.html", invalid=True) |
||||
|
|
||||
|
g = solver.construct(M, N) |
||||
|
if g is None: |
||||
|
return render_template("page.html", nosol=True, M=M, N=N) |
||||
|
else: |
||||
|
image, works = g.plot() |
||||
|
return render_template("page.html", image=image, works=works, M=M, N=N) |
||||
|
|
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
app.run( |
||||
|
host="0.0.0.0", |
||||
|
port=8000 |
||||
|
) |
@ -0,0 +1,19 @@ |
|||||
|
blinker==1.7.0 |
||||
|
click==8.1.7 |
||||
|
contourpy==1.2.0 |
||||
|
cycler==0.12.1 |
||||
|
Flask==3.0.0 |
||||
|
fonttools==4.45.1 |
||||
|
gunicorn==21.2.0 |
||||
|
itsdangerous==2.1.2 |
||||
|
Jinja2==3.1.2 |
||||
|
kiwisolver==1.4.5 |
||||
|
MarkupSafe==2.1.3 |
||||
|
matplotlib==3.8.2 |
||||
|
numpy==1.26.2 |
||||
|
packaging==23.2 |
||||
|
Pillow==10.1.0 |
||||
|
pyparsing==3.1.1 |
||||
|
python-dateutil==2.8.2 |
||||
|
six==1.16.0 |
||||
|
Werkzeug==3.0.1 |
@ -0,0 +1,240 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
|
||||
|
import io |
||||
|
import base64 |
||||
|
|
||||
|
from matplotlib import pyplot as plt |
||||
|
import numpy |
||||
|
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas |
||||
|
from matplotlib.figure import Figure |
||||
|
|
||||
|
|
||||
|
class Grid: |
||||
|
def __init__(self, M, N): |
||||
|
self.N = N |
||||
|
self.M = M |
||||
|
self.grid = [[0 for _ in range(M+N-1)] for _ in range(M+N-1)] |
||||
|
|
||||
|
def check_bounds(self, x, y): |
||||
|
return 1 <= x <= self.M+self.N-1 and\ |
||||
|
1 <= y <= self.M+self.N-1 and\ |
||||
|
self.M+1 <= x+y <= 2*self.M + self.N - 1 |
||||
|
|
||||
|
def get(self, x, y): |
||||
|
if not self.check_bounds(x, y): |
||||
|
return 0 |
||||
|
return self.grid[x-1][y-1] |
||||
|
|
||||
|
def select(self, x, y): |
||||
|
assert self.check_bounds(x, y) |
||||
|
self.grid[x-1][y-1] = 1 |
||||
|
|
||||
|
def grid_parity(self): |
||||
|
for x in range(1, self.M+self.N): |
||||
|
nums = [self.get(x, y) for y in range(1, self.N + self.M)] |
||||
|
if sum(nums) % 2 != 1: |
||||
|
print(f"Found a contradiction at x={x}! {nums}") |
||||
|
return False |
||||
|
for y in range(1, self.M+self.N): |
||||
|
nums = [self.get(x, y) for x in range(1, self.N + self.M)] |
||||
|
if sum(nums) % 2 != 1: |
||||
|
print(f"Found a contradiction at y={y}! {nums}") |
||||
|
return False |
||||
|
for s in range(self.M+1, 2*self.M+self.N): |
||||
|
nums = [self.get(x, s-x) for x in range(1, s)] |
||||
|
if sum(nums) % 2 != 1: |
||||
|
print(f"Found a contradiction at x+y={s}! {nums}") |
||||
|
return False |
||||
|
return True |
||||
|
|
||||
|
def reflect(self): |
||||
|
res = [[0 for _ in range(len(self.grid[i]))] |
||||
|
for i in range(len(self.grid))] |
||||
|
for x in range(self.M+self.N-1): |
||||
|
# reflect across x + y = m + n - 2 |
||||
|
for y in range(self.M+self.N-1): |
||||
|
# sm = 2 * (self.M+self.N-2) - (x+y) |
||||
|
# diff = x - y |
||||
|
res[self.M+self.N-2-x][self.M+self.N-2-y] = self.grid[x][y] |
||||
|
self.grid = res |
||||
|
tmp = self.M |
||||
|
self.M = self.N |
||||
|
self.N = tmp |
||||
|
|
||||
|
def plot(self) -> tuple[str, bool]: |
||||
|
fig = Figure() |
||||
|
ax = fig.add_subplot(1, 1, 1) |
||||
|
ax.set_xticks(numpy.arange(1, self.M+self.N, 1)) |
||||
|
ax.set_yticks(numpy.arange(1, self.M+self.N, 1)) |
||||
|
ax.set_aspect("equal") |
||||
|
|
||||
|
ax.set_xbound(0, self.M+self.N) |
||||
|
ax.set_ybound(0, self.M+self.N) |
||||
|
ax.autoscale(enable=False) |
||||
|
x = [] |
||||
|
y = [] |
||||
|
for i in range(1, self.M+self.N): |
||||
|
for j in range(1, self.M+self.N): |
||||
|
if self.get(i, j): |
||||
|
x.append(i) |
||||
|
y.append(j) |
||||
|
ax.scatter(x, y, color='b') |
||||
|
# plt.title(f"Construction for M={self.M}, N={self.N}") |
||||
|
ax.grid() |
||||
|
|
||||
|
ax.plot([1, self.M], [self.M, 1], color='r') |
||||
|
ax.plot([self.M, self.N+self.M-1], |
||||
|
[self.N+self.M-1, self.M], color='r') |
||||
|
ax.plot([1, 1, self.M], [self.M, self.M + |
||||
|
self.N-1, self.M+self.N-1], color='r') |
||||
|
ax.plot([self.M, self.M+self.N-1, self.M+self.N-1], |
||||
|
[1, 1, self.M], color='r') |
||||
|
pngImage = io.BytesIO() |
||||
|
FigureCanvas(fig).print_png(pngImage) |
||||
|
pngImageB64String = "data:image/png;base64," |
||||
|
pngImageB64String += base64.b64encode( |
||||
|
pngImage.getvalue()).decode('utf8') |
||||
|
return pngImageB64String, self.grid_parity() |
||||
|
|
||||
|
|
||||
|
def one(M, N) -> Grid: |
||||
|
assert (N-M) % 4 == 0 |
||||
|
assert M == 1 or N == 1 |
||||
|
reflect = M == 1 |
||||
|
if reflect: |
||||
|
tmp = M |
||||
|
M = N |
||||
|
N = tmp |
||||
|
g = Grid(M, N) |
||||
|
for k in range(1, M+1): |
||||
|
g.select(k, M+1-k) |
||||
|
|
||||
|
for k in range(1, M//2+1): |
||||
|
g.select((M+1)//2, (M+1)//2+k) |
||||
|
g.select(M, (M+1)//2+k) |
||||
|
|
||||
|
if reflect: |
||||
|
g.reflect() |
||||
|
return g |
||||
|
|
||||
|
|
||||
|
def cong_mod4(M, N) -> Grid: |
||||
|
assert (N-M) % 4 == 0 and N != 1 and M != 1 |
||||
|
reflect = M > N |
||||
|
if reflect: |
||||
|
tmp = M |
||||
|
M = N |
||||
|
N = tmp |
||||
|
g = Grid(M, N) |
||||
|
|
||||
|
if M % 2 == 1: |
||||
|
g.select(M, M) |
||||
|
|
||||
|
# Main Axis points |
||||
|
for k in range(1, N//2+1): |
||||
|
g.select(M, M+2*k-1) |
||||
|
for k in range(1, (M-1)//2+1): |
||||
|
g.select(M, M-2*k) |
||||
|
|
||||
|
for k in range(1, (N-1)//2+1): |
||||
|
g.select(M+2*k, M) |
||||
|
for k in range(1, M//2+1): |
||||
|
g.select(M-2*k+1, M) |
||||
|
|
||||
|
# Points on the diagonal |
||||
|
for k in range(1, M//2 + 1): |
||||
|
g.select(M+2*k-1, M-2*k+1) # going down |
||||
|
for k in range(1, (M-1)//2+1): |
||||
|
g.select(M-2*k, M+2*k) # going up |
||||
|
|
||||
|
for k in range(1, (N-M)//2+1): |
||||
|
g.select( |
||||
|
M+2*(M//2) - 1 + 2*k, |
||||
|
M-2*(M//2) + 2, |
||||
|
) |
||||
|
g.select( |
||||
|
M - 2*((M-1)//2) + 1, |
||||
|
M + 2*((M-1)//2) + 2*k, |
||||
|
) |
||||
|
if reflect: |
||||
|
g.reflect() |
||||
|
return g |
||||
|
|
||||
|
|
||||
|
def mod_0_1(M, N): |
||||
|
assert (M+N) % 4 == 1 and M % 4 in [0, 1] |
||||
|
reflect = (M % 4) == 1 |
||||
|
if reflect: |
||||
|
tmp = M |
||||
|
M = N |
||||
|
N = tmp |
||||
|
g = Grid(M, N) |
||||
|
|
||||
|
g.select(M, M) |
||||
|
# Main Axis Points |
||||
|
for k in range(1, N//2+1): |
||||
|
g.select(M, M+2*k-1) |
||||
|
for k in range(1, (M-1)//2+1): |
||||
|
g.select(M, M-2*k) |
||||
|
|
||||
|
for k in range(1, (N-1)//2+1): |
||||
|
g.select(M+2*k, M) |
||||
|
for k in range(1, M//2+1): |
||||
|
g.select(M-2*k+1, M) |
||||
|
# Step 3 |
||||
|
for k in range(0, M//2): |
||||
|
g.select(M-2*k, 1+2*k) |
||||
|
|
||||
|
# Tail |
||||
|
for k in range(1, (N-1)//2+1): |
||||
|
g.select(2, M+2*k) |
||||
|
g.select(M+2*k-1, 3) |
||||
|
|
||||
|
if reflect: |
||||
|
g.reflect() |
||||
|
return g |
||||
|
|
||||
|
|
||||
|
def mod_2_3(M, N): |
||||
|
assert (M+N) % 4 == 1 and M % 4 in [2, 3] |
||||
|
reflect = (M % 4) == 2 |
||||
|
if reflect: |
||||
|
tmp = M |
||||
|
M = N |
||||
|
N = tmp |
||||
|
g = Grid(M, N) |
||||
|
|
||||
|
for k in range(1, M+1): |
||||
|
g.select(k, M+1-k) |
||||
|
|
||||
|
for k in range((M+1)//2+1, M+1): |
||||
|
g.select((M+1)//2, k) |
||||
|
g.select(M+1, k) |
||||
|
g.select((M+1)//2, M+1) |
||||
|
|
||||
|
for k in range(1, (N-2)//2 + 1): |
||||
|
g.select(M+1, M+2*k) |
||||
|
g.select(M+2*k, M) |
||||
|
|
||||
|
g.select(1, M+1+2*k) |
||||
|
g.select(M+1+2*k, 1) |
||||
|
|
||||
|
if reflect: |
||||
|
g.reflect() |
||||
|
return g |
||||
|
|
||||
|
|
||||
|
def construct(M, N) -> 'Grid | None': |
||||
|
if (M-N) % 4 == 0: |
||||
|
if M != 1 and N != 1: |
||||
|
return cong_mod4(M, N) |
||||
|
else: |
||||
|
return one(M, N) |
||||
|
elif (M+N) % 4 == 1: |
||||
|
if (M % 4) in [0, 1]: |
||||
|
return mod_0_1(M, N) |
||||
|
else: |
||||
|
return mod_2_3(M, N) |
||||
|
else: |
||||
|
assert ((N+M-1)*(N-M)) % 4 == 2 |
||||
|
return None |
@ -0,0 +1,70 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<title>USAMTS 2/5/35 Solution</title> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css"> |
||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous"> |
||||
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js" integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8" crossorigin="anonymous"></script> |
||||
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous" |
||||
|
onload="renderMathInElement(document.body);"></script> |
||||
|
</head> |
||||
|
<body> |
||||
|
<main class="container"> |
||||
|
<strong><h3>Problem</h3></strong> |
||||
|
<p> |
||||
|
Let \(m\) and \(n\) be positive integers. Let \(S\) be the set of all points |
||||
|
\((x, y)\) with integer coordinates such that \(1 \leq x, y \leq m + n − 1\) |
||||
|
and \(m + 1 \leq x + y \leq 2m + n − 1\). Let L be the set of the \(3m + 3n − |
||||
|
3\) lines parallel to one of \(x = 0\), \(y = 0\), or \(x + y = 0\) and passing |
||||
|
through at least one point in \(S\). For which pairs \((m, n)\) does there |
||||
|
exist a subset \(T\) of \(S\) such that every line in \(L\) intersects an odd |
||||
|
number of elements of \(T\)? |
||||
|
</p> |
||||
|
<strong><h3>Proof</h3></strong> |
||||
|
<p> |
||||
|
The answer is just all \((m,n)\) such that \( (m+n-1)(m-n) \) is divisible |
||||
|
by 4. The sum of all the x and y coordinates should clearly be even, but |
||||
|
the sum of all \(x+y \mod 2\) is \( \frac{(m+n-1)(3m+n)}{2} \). For a |
||||
|
construction to even be viable, this quantity clearly needs to be even. |
||||
|
</p> |
||||
|
<strong><h3>Constructor</h3></strong> |
||||
|
{% if invalid %} |
||||
|
<p> Invalid Input! </p> |
||||
|
{% endif %} |
||||
|
{% if nosol %} |
||||
|
<p> No Valid Solution is Possible! </p> |
||||
|
{% endif %} |
||||
|
{% if image %} |
||||
|
<img src="{{ image }}" alt="Solution Image" /> |
||||
|
{% endif %} |
||||
|
{% if works == False %} |
||||
|
<p> Claimed Construction Fails!!!! </p> |
||||
|
{% endif %} |
||||
|
<form method="POST" action="{{url_for ('index')}}"> |
||||
|
<table role="grid"> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td> |
||||
|
<label for="M">Value for M:</label> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input type="number" name="M" min="1" max="40" value="{{M}}" required /> |
||||
|
</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td> |
||||
|
<label for="N">Value for N:</label> |
||||
|
</td> |
||||
|
<td> |
||||
|
<input type="number" name="N" min="1" max="40" value="{{N}}" required /> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
<input type="submit" value="Construct"> |
||||
|
</form> |
||||
|
</main> |
||||
|
</body> |
||||
|
</html> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue