refactore to new project structure
This commit is contained in:
@@ -43,6 +43,12 @@ func (n *Notes) Remove(field *Field, cell *Cell, note int, trigger string, marks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Notes) Get() []int {
|
||||||
|
copySlice := make([]int, len(n.numbers))
|
||||||
|
copy(copySlice, n.numbers)
|
||||||
|
return copySlice
|
||||||
|
}
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
// CELL STRUCTURE //
|
// CELL STRUCTURE //
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
@@ -98,3 +104,7 @@ func (c *Cell) RemoveNumber(field *Field, trigger string, marks []Mark) {
|
|||||||
|
|
||||||
c.number = 0
|
c.number = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cell) GetNumber() int {
|
||||||
|
return c.number
|
||||||
|
}
|
||||||
|
|||||||
+14
-1
@@ -17,7 +17,7 @@ func (m *Mark) GetColor() color.Color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
// CHANGE STRUCTURE //
|
// CHANGE_ACTION TYPE //
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
|
||||||
type ChangeAction int
|
type ChangeAction int
|
||||||
@@ -33,6 +33,19 @@ const (
|
|||||||
// CHANGE STRUCTURE //
|
// CHANGE STRUCTURE //
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
|
||||||
|
type ExternalChange struct {
|
||||||
|
Cell *Cell
|
||||||
|
Marks []Mark
|
||||||
|
Action ChangeAction
|
||||||
|
Value int
|
||||||
|
From int
|
||||||
|
TriggerdBy string //strategy or manuell
|
||||||
|
}
|
||||||
|
|
||||||
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
// CHANGE STRUCTURE //
|
||||||
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
|
||||||
type Change struct {
|
type Change struct {
|
||||||
Cell *Cell
|
Cell *Cell
|
||||||
marks []Mark
|
marks []Mark
|
||||||
|
|||||||
+7
-7
@@ -145,14 +145,14 @@ func (f *Field) ForEachCell(fn func(cell *Cell)) {
|
|||||||
// MODIFIER //
|
// MODIFIER //
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
|
||||||
func (f *Field) AddChange(cell *Cell, action ChangeAction, value, from int, trigger string, marks []Mark) {
|
func (f *Field) AddChange(eChange *ExternalChange) {
|
||||||
change := Change{
|
change := Change{
|
||||||
Cell: cell,
|
Cell: eChange.Cell,
|
||||||
marks: marks,
|
marks: eChange.Marks,
|
||||||
action: action,
|
action: eChange.Action,
|
||||||
value: value,
|
value: eChange.Value,
|
||||||
from: from,
|
from: eChange.From,
|
||||||
triggerdBy: trigger,
|
triggerdBy: eChange.TriggerdBy,
|
||||||
}
|
}
|
||||||
|
|
||||||
change.do()
|
change.do()
|
||||||
|
|||||||
+6
-6
@@ -8,23 +8,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Parser interface {
|
type Parser interface {
|
||||||
parse(data []byte) error
|
Parse(data []byte) error
|
||||||
getField(i int) *Field
|
GetField(i int) *Field
|
||||||
getAllFields() []Field
|
GetAllFields() []Field
|
||||||
}
|
}
|
||||||
|
|
||||||
type parserHelper struct {
|
type parserHelper struct {
|
||||||
fields []Field
|
fields []Field
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ph *parserHelper) getField(i int) *Field {
|
func (ph *parserHelper) GetField(i int) *Field {
|
||||||
if i < 0 || i >= len(ph.fields) {
|
if i < 0 || i >= len(ph.fields) {
|
||||||
return &Field{}
|
return &Field{}
|
||||||
}
|
}
|
||||||
return &ph.fields[i]
|
return &ph.fields[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ph *parserHelper) getAllFields() []Field {
|
func (ph *parserHelper) GetAllFields() []Field {
|
||||||
if len(ph.fields) == 0 {
|
if len(ph.fields) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ type PuzzleBank struct {
|
|||||||
parserHelper
|
parserHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pb *PuzzleBank) parse(data []byte) error {
|
func (pb *PuzzleBank) Parse(data []byte) error {
|
||||||
|
|
||||||
lines := bytes.Split(data, []byte("\n"))
|
lines := bytes.Split(data, []byte("\n"))
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
|
|||||||
+10
-7
@@ -1,30 +1,33 @@
|
|||||||
package logic
|
package logic
|
||||||
|
|
||||||
import "git.kleiax.de/homepage/libs/sudoku/board"
|
import (
|
||||||
|
"git.kleiax.de/homepage/board"
|
||||||
|
"git.kleiax.de/homepage/logic/strategies"
|
||||||
|
)
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
// SOLVER STRUCTURE //
|
// SOLVER STRUCTURE //
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
|
||||||
type Solver struct {
|
type Solver struct {
|
||||||
strategies []Strategy
|
strategies []strategies.Strategy
|
||||||
conf struct {
|
conf struct {
|
||||||
all bool
|
all bool
|
||||||
repeat bool
|
repeat bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Solver) Add(strategy Strategy) {
|
func (s *Solver) Add(strategy strategies.Strategy) {
|
||||||
s.strategies = append(s.strategies, strategy)
|
s.strategies = append(s.strategies, strategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Solver) initStragies(field *board.Field) {
|
func (s *Solver) InitStragies(field *board.Field) {
|
||||||
for _, strategy := range s.strategies {
|
for _, strategy := range s.strategies {
|
||||||
strategy.Init(field)
|
strategy.Init(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Solver) run(i int) bool {
|
func (s *Solver) Run(i int) bool {
|
||||||
//TODO: clean und Fehlerauffangen
|
//TODO: clean und Fehlerauffangen
|
||||||
s.strategies[i].SearchProgressableCells()
|
s.strategies[i].SearchProgressableCells()
|
||||||
numberOfChanges := s.strategies[i].ApplyAll()
|
numberOfChanges := s.strategies[i].ApplyAll()
|
||||||
@@ -34,10 +37,10 @@ func (s *Solver) run(i int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Solver) search() {
|
func (s *Solver) Search() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Solver) getSolutionPath() []board.Change {
|
func (s *Solver) GetSolutionPath() []board.ExternalChange {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-13
@@ -1,6 +1,6 @@
|
|||||||
package strategies
|
package strategies
|
||||||
|
|
||||||
import "git.kleiax.de/homepage/libs/sudoku/board"
|
import "git.kleiax.de/homepage/board"
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
// LAST_DIGIT STRUCTURE //
|
// LAST_DIGIT STRUCTURE //
|
||||||
@@ -14,18 +14,20 @@ func (ld *LastDigit) SearchProgressableCells() int {
|
|||||||
ld.field.ForEachPart(func(part board.Part) {
|
ld.field.ForEachPart(func(part board.Part) {
|
||||||
missingNumbers := part.GetMissingNumbers()
|
missingNumbers := part.GetMissingNumbers()
|
||||||
if len(missingNumbers) == 1 {
|
if len(missingNumbers) == 1 {
|
||||||
// var emptyCell *Cell
|
var emptyCell *board.Cell
|
||||||
// part.forEachCell(func(cell *Cell) {
|
part.ForEachCell(func(cell *board.Cell) {
|
||||||
// if cell.number == 0 {
|
if cell.GetNumber() == 0 {
|
||||||
// emptyCell = cell
|
emptyCell = cell
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
// change := Change{
|
change := board.ExternalChange{
|
||||||
// cell: emptyCell,
|
Cell: emptyCell,
|
||||||
// action: ActionSetNumber,
|
Action: board.ActionSetNumber,
|
||||||
// value: missingNumbers[0],
|
Value: missingNumbers[0],
|
||||||
// }
|
From: emptyCell.GetNumber(),
|
||||||
// ld.changes = append(ld.changes, change)
|
TriggerdBy: ld.getName(),
|
||||||
|
}
|
||||||
|
ld.changes = append(ld.changes, change)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
//fmt.Printf("LastDigit Changes %d", len(ld.changes))
|
//fmt.Printf("LastDigit Changes %d", len(ld.changes))
|
||||||
|
|||||||
+12
-10
@@ -1,6 +1,6 @@
|
|||||||
package strategies
|
package strategies
|
||||||
|
|
||||||
import "git.kleiax.de/homepage/libs/sudoku/board"
|
import "git.kleiax.de/homepage/board"
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
// NAKED_SINGLE STRUCTURE //
|
// NAKED_SINGLE STRUCTURE //
|
||||||
@@ -13,15 +13,17 @@ type NakedSingle struct {
|
|||||||
func (ns *NakedSingle) SearchProgressableCells() int {
|
func (ns *NakedSingle) SearchProgressableCells() int {
|
||||||
ns.field.ForEachPart(func(part board.Part) {
|
ns.field.ForEachPart(func(part board.Part) {
|
||||||
part.ForEachCell(func(cell *board.Cell) {
|
part.ForEachCell(func(cell *board.Cell) {
|
||||||
// candidates := cell.notes.numbers
|
candidates := cell.Notes.Get()
|
||||||
// if len(candidates) == 1 {
|
if len(candidates) == 1 {
|
||||||
// change := Change{
|
change := board.ExternalChange{
|
||||||
// cell: cell,
|
Cell: cell,
|
||||||
// action: ActionSetNumber,
|
Action: board.ActionSetNumber,
|
||||||
// value: candidates[0],
|
Value: candidates[0],
|
||||||
// }
|
From: cell.GetNumber(),
|
||||||
// ns.changes = append(ns.changes, change)
|
TriggerdBy: ns.getName(),
|
||||||
// }
|
}
|
||||||
|
ns.changes = append(ns.changes, change)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return len(ns.changes)
|
return len(ns.changes)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package strategies
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kleiax.de/homepage/libs/sudoku/board"
|
"git.kleiax.de/homepage/board"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
@@ -14,11 +14,18 @@ type Strategy interface {
|
|||||||
Init(f *board.Field)
|
Init(f *board.Field)
|
||||||
ApplyAll() int
|
ApplyAll() int
|
||||||
ApplyNext() bool
|
ApplyNext() bool
|
||||||
ApplyOne(n int) bool
|
|
||||||
Name() string
|
Name() string
|
||||||
SearchProgressableCells() int
|
SearchProgressableCells() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
// VISUALITION INTERFACE //
|
||||||
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
|
|
||||||
|
type StrategyVisualization interface {
|
||||||
|
pointOut(f *board.Field) []board.Mark
|
||||||
|
}
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
// BASE STRUCTURE //
|
// BASE STRUCTURE //
|
||||||
// ────────────────────────────────────────────────────────────────────────────── //
|
// ────────────────────────────────────────────────────────────────────────────── //
|
||||||
@@ -26,7 +33,7 @@ type Strategy interface {
|
|||||||
type Base struct {
|
type Base struct {
|
||||||
name string
|
name string
|
||||||
field *board.Field
|
field *board.Field
|
||||||
changes []board.Change //eigener Typ muss her
|
changes []board.ExternalChange
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Base) Init(f *board.Field) {
|
func (b *Base) Init(f *board.Field) {
|
||||||
@@ -34,9 +41,9 @@ func (b *Base) Init(f *board.Field) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Base) ApplyAll() int {
|
func (b *Base) ApplyAll() int {
|
||||||
// for _, change := range sb.changes {
|
for _, change := range b.changes {
|
||||||
// //change.do()
|
b.field.AddChange(&change)
|
||||||
// }
|
}
|
||||||
return len(b.changes)
|
return len(b.changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,24 +51,15 @@ func (b *Base) ApplyNext() bool {
|
|||||||
if len(b.changes) < 1 {
|
if len(b.changes) < 1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
//sb.changes[0].do()
|
b.field.AddChange(&b.changes[0])
|
||||||
b.changes = b.changes[1:]
|
b.changes = b.changes[1:]
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Base) ApplyOne(n int) bool {
|
|
||||||
if len(b.changes) <= n || n < 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
//sb.changes[n].do()
|
|
||||||
b.changes = append(b.changes[:n], b.changes[n+1:]...)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Base) getName() string {
|
func (b *Base) getName() string {
|
||||||
return "Unkown"
|
return "Unkown"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Base) Name() string {
|
func (b *Base) Name() string {
|
||||||
return fmt.Sprintf("Die Strategie heißt: %s", b.getName())
|
return fmt.Sprintf("Diese Strategie heißt: %s", b.getName())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,17 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.kleiax.de/homepage/libs/sudoku"
|
"git.kleiax.de/homepage/board"
|
||||||
|
"git.kleiax.de/homepage/logic"
|
||||||
|
"git.kleiax.de/homepage/logic/strategies"
|
||||||
|
"git.kleiax.de/homepage/sudoku"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
solver := sudoku.Solver{}
|
solver := logic.Solver{}
|
||||||
solver.Add(&sudoku.LastDigit{})
|
solver.Add(&strategies.LastDigit{})
|
||||||
solver.Add(&sudoku.NakedSingle{})
|
solver.Add(&strategies.NakedSingle{})
|
||||||
game, err := sudoku.New(&sudoku.PuzzleBank{}, solver, openFile())
|
game, err := sudoku.New(&board.PuzzleBank{}, solver, openFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -31,7 +34,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func openFile() []byte {
|
func openFile() []byte {
|
||||||
file, err := os.Open("libs/sudoku/data/sudoku-exchange-puzzle-bank/easy3.txt")
|
file, err := os.Open("data/sudoku-exchange-puzzle-bank/easy3.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Kann datei nicht öffnen")
|
fmt.Println("Kann datei nicht öffnen")
|
||||||
os.Exit(3)
|
os.Exit(3)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.kleiax.de/homepage/libs/sudoku/board"
|
"git.kleiax.de/homepage/board"
|
||||||
"git.kleiax.de/homepage/libs/sudoku/logic"
|
"git.kleiax.de/homepage/logic"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
@@ -13,16 +13,16 @@ type Game struct {
|
|||||||
solver logic.Solver
|
solver logic.Solver
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(parser Parser, solver Solver, data []byte) (*Game, error) {
|
func New(parser board.Parser, solver logic.Solver, data []byte) (*Game, error) {
|
||||||
err := parser.parse(data)
|
err := parser.Parse(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Game{}, fmt.Errorf("can not create game: %w", err)
|
return &Game{}, fmt.Errorf("can not create game: %w", err)
|
||||||
}
|
}
|
||||||
return &Game{solver: solver, field: parser.getField(0)}, nil
|
return &Game{solver: solver, field: parser.GetField(0)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Solve() error {
|
func (g *Game) Solve() error {
|
||||||
g.solver.initStragies(g.field)
|
g.solver.InitStragies(g.field)
|
||||||
for !g.isFinished() {
|
for !g.isFinished() {
|
||||||
if !g.nextSolveStep() {
|
if !g.nextSolveStep() {
|
||||||
return errors.New("no strategy can solve the puzzle")
|
return errors.New("no strategy can solve the puzzle")
|
||||||
@@ -32,7 +32,7 @@ func (g *Game) Solve() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) nextSolveStep() bool {
|
func (g *Game) nextSolveStep() bool {
|
||||||
return g.solver.run(0)
|
return g.solver.Run(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) prevSolveStep() {
|
func (g *Game) prevSolveStep() {
|
||||||
@@ -40,9 +40,9 @@ func (g *Game) prevSolveStep() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) isFinished() bool {
|
func (g *Game) isFinished() bool {
|
||||||
return g.field.isSolved()
|
return g.field.IsSolved()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) GetField() Field {
|
func (g *Game) GetField() board.Field {
|
||||||
return *g.field
|
return *g.field
|
||||||
}
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
- Parser kann eigenes Package sein nur das Interface und die Helfer funktionen im Board lassen, jeder kann einen Parser für sseine Quelle schreiben. Vielleicht ein Standardparser in Board für gängige Typen oder Hilfsfunktionen
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package sudoku
|
|
||||||
|
|
||||||
// type StrategyVisualization interface {
|
|
||||||
// pointOut(f *Field) []Mark
|
|
||||||
// }
|
|
||||||
Reference in New Issue
Block a user