Skip to content

Commit

Permalink
Merge pull request #1 from unmade/github-actions
Browse files Browse the repository at this point in the history
GitHub actions
  • Loading branch information
unmade authored Nov 23, 2019
2 parents ea8f691 + 2edb40e commit d0c6489
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 19 deletions.
77 changes: 77 additions & 0 deletions .github/workflows/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Python package

on:
push:
branches:
- master
tags:
- '[0-2].[0-9]+.[0-9]+*'
pull_request:
branches:
- '**'


jobs:

lint-and-test:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: [3.8]

steps:
- uses: actions/checkout@v1

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}

- name: Cache pip dependencies
uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-pip-
- name: Cache pre-commit dependencies
uses: actions/cache@v1
with:
path: ~/.cache/pre-commit
key: ${{ runner.os }}-${{ matrix.python-version }}-pre-commit-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.python-version }}-pre-commit-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Lint and Test with tox
run: |
tox -v
publish:
if: startsWith(github.event.ref, 'refs/tags')
needs: [lint-and-test]
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1

- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: "3.8"

- name: Build and Publish package
env:
PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }}
PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python -m pip install --upgrade pip
pip install poetry
poetry build
poetry publish -u $PYPI_USERNAME -p $PYPI_PASSWORD
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "dokusan"
version = "0.1.0-alpha"
description = "Sudoku solver with step-by-step guidance"
readme = "README.rst"
authors = ["Aleksei Maslakov <[email protected]>"]
license = "GPL-3.0"
packages = [
Expand Down
49 changes: 30 additions & 19 deletions src/dokusan/techniques.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import operator
from collections import Counter
from dataclasses import dataclass
from typing import Dict, Iterable, Iterator, List, Tuple, Union
from typing import Dict, Iterable, Iterator, List, Optional, Tuple, Union

from dokusan.entities import Cell, Mark, Sudoku

Expand Down Expand Up @@ -70,7 +70,9 @@ def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]
Mark(position=mark.position, candidates=mark.candidates - eliminated)
for mark in self.sudoku.intersection(cell)
if isinstance(mark, Mark) and mark.candidates & eliminated
] + [cell]
] + [
cell # type: ignore
]


class HiddenSingle(Technique):
Expand All @@ -95,7 +97,9 @@ def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]
Mark(position=mark.position, candidates=mark.candidates - eliminated)
for mark in self.sudoku.intersection(cell)
if isinstance(mark, Mark) and mark.candidates & eliminated
] + [cell]
] + [
cell # type: ignore
]


class NakedPair(Technique):
Expand All @@ -112,7 +116,7 @@ def _find(self) -> Iterator[Combination]:
name="Naked Pair", marks=marks, values=list(candidates),
)

def _get_changed_cells(self, combination: Combination) -> List[Mark]:
def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]]:
eliminated = set(combination.values)
return [
Mark(position=mark.position, candidates=mark.candidates - eliminated)
Expand All @@ -137,7 +141,7 @@ def _find(self) -> Iterator[Combination]:
values=list(set.union(*[m.candidates for m in triplet])),
)

def _get_changed_cells(self, combination: Combination) -> List[Mark]:
def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]]:
eliminated = set(combination.values)
return [
Mark(position=mark.position, candidates=mark.candidates - eliminated)
Expand All @@ -159,7 +163,7 @@ def _find(self) -> Iterator[Combination]:
if len(marks) == 2:
yield Combination(name="Omission", marks=marks, values=[candidate])

def _get_changed_cells(self, combination: Combination) -> List[Mark]:
def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]]:
eliminated = set(combination.values)
return [
Mark(position=mark.position, candidates=mark.candidates - eliminated)
Expand Down Expand Up @@ -190,7 +194,7 @@ def _is_xy_wing(self, marks: Iterable[Mark]) -> bool:
return False
return True

def _get_changed_cells(self, combination: Combination) -> List[Mark]:
def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]]:
eliminated = set(combination.values)
return [
Mark(position=m.position, candidates=m.candidates - eliminated)
Expand All @@ -204,10 +208,9 @@ def _find(self) -> Iterator[Combination]:
marks = [mark for mark in self.sudoku.marks() if len(mark.candidates) == 2]
for edges in itertools.combinations(marks, r=3):
if self._is_edges(edges):
rows = {edge.position.row for edge in edges}
cols = {edge.position.column for edge in edges}
rectangle = [self.sudoku[pos] for pos in itertools.product(rows, cols)]
if self._is_rect(rectangle):
rectangle = self._build_rectangle(edges)
# waiting for https://github.com/python/mypy/issues/7316
if rectangle is not None:
yield Combination(
name="Unique Rectangle",
marks=rectangle,
Expand All @@ -219,19 +222,27 @@ def _find(self) -> Iterator[Combination]:
def _is_edges(self, marks: Iterable[Mark]) -> bool:
if len(set.intersection(*[m.candidates for m in marks])) != 2:
return False
combinations = itertools.combinations(marks, 2)
if sum(a.position.square == b.position.square for a, b in combinations) != 1:
combinations = tuple(itertools.combinations(marks, 2))
if sum(a.position.row == b.position.row for a, b in combinations) != 1:
return False
return True

def _is_rect(self, marks: Iterable[Mark]) -> bool:
if any(isinstance(cell, Cell) for cell in marks):
if sum(a.position.column == b.position.column for a, b in combinations) != 1:
return False
if len(set.intersection(*[m.candidates for m in marks])) != 2:
if sum(a.position.square == b.position.square for a, b in combinations) != 1:
return False
return True

def _get_changed_cells(self, combination: Combination) -> List[Mark]:
def _build_rectangle(self, edges: Iterable[Mark]) -> Optional[List[Mark]]:
rows = {edge.position.row for edge in edges}
cols = {edge.position.column for edge in edges}
cells = [self.sudoku[i, j] for i, j in itertools.product(rows, cols)]
rectangle = [mark for mark in cells if isinstance(mark, Mark)]
if len(rectangle) != 4:
return None
if len(set.intersection(*[m.candidates for m in rectangle])) != 2:
return None
return rectangle

def _get_changed_cells(self, combination: Combination) -> List[Union[Cell, Mark]]:
return next(
[Mark(position=edge_a.position, candidates=diff)]
for edge_a, edge_b in itertools.combinations(combination.marks, 2)
Expand Down
7 changes: 7 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
isolated_build = true
skip_missing_interpreters = true
envlist =
lint
{py38}

[tox:.package]
Expand All @@ -17,3 +18,9 @@ deps =
pytest-cov
commands =
{posargs:pytest --cov -vv tests}

[testenv:lint]
deps =
pre-commit
commands =
pre-commit run --all-files {posargs}

0 comments on commit d0c6489

Please sign in to comment.