|
|
|
|
Strumenti |
08-06-2009, 16:24 | #21 |
Bannato
Iscritto dal: Jan 2003
Città:
Messaggi: 4400
|
...qui viene proposta una applet con diversi sistemi di solver...l'algoritmo proposto risolve il caso richiesto dal thread in una manciata di secondi...volevo chiedere all'autore del thread se la difficoltà di risoluzione di questo sudoku sta solo nella scelta di usare una scala di valori decrescente per la prima riga (un brute force incrementando il valore per ogni riquadro arriverà a ricostruire la sequenza 9-8-7... nel maggior tempo possibile) o ci sono altri giochini dietro?...
...ciao Andrea... |
08-06-2009, 16:30 | #22 |
Member
Iscritto dal: Jul 2008
Messaggi: 237
|
Ok, dai, posto la mia: il codice è per lo più una traduzione di un post che ho trovato, ma solo per una questione di eleganza. Infatti ho sempre reputato l'uso di un po' di constraint programming la via più comoda e dunque appoggiarsi a un solver era secondo me naturale
Il codice è come al solito in F# (4.0), ed in questo caso è richiesta la presenza di Microsoft Solver Foundation (l'express edition gratuita basta). Il tempo impiegato sul mio misero T7700 @ 2.4ghz è 500ms e gran parte del tempo è spesa per il caricamento/inizializzazione del solver e non per la ricerca della soluzione. Codice:
open System open System.IO open Microsoft.SolverFoundation.Common open Microsoft.SolverFoundation.Services module Sudoku = type SudokuCell(row, col, value) = let mutable _value = value member x.Row = row member x.Col = col member x.Value with get() = _value and set(v) = _value <- v member x.FloatValue with get() = float _value and set(v:float) = _value <- int v type Block = { KeyRow : int; KeyCol : int; IsIn : Rational } let Solve(src:int array array) = let rational (i:int) = Rational.op_Implicit i let ctx = SolverContext.GetContext() let model = ctx.CreateModel() let line = Set(Domain.IntegerRange(rational 0, rational 9), "line") let board = Array2D.init 9 9 (fun r c -> SudokuCell(r, c, src.[r].[c])) let boardDec = Decision(Domain.IntegerRange(rational 1, rational 9), "board", line, line) boardDec.SetBinding(board |> Seq.cast<SudokuCell>, "FloatValue", "Row", "Col") let presetBoard = Parameter(Domain.IntegerRange(rational 0, rational 9), "presetBoard", line, line) presetBoard.SetBinding(board |> Seq.cast<SudokuCell>, "Value", "Row", "Col") model.AddDecision boardDec model.AddParameter presetBoard model.AddConstraint(null, Model.ForEach(line, fun i -> Model.ForEachWhere(line, (fun j -> Term.op_Equality(boardDec.[i,j],presetBoard.[i, j])), fun j -> Term.op_GreaterThan(presetBoard.[i, j], 0 |> rational |> Term.op_Implicit)))) |> ignore model.AddConstraint(null, Model.ForEach(line, fun j -> Model.AllDifferent (Model.ForEach(line, fun i -> boardDec.[i,j])))) |> ignore model.AddConstraint(null, Model.ForEach(line, fun i -> Model.AllDifferent (Model.ForEach(line, fun j -> boardDec.[i,j])))) |> ignore let isInBlock i j row col = if i * 3 <= row && row <= i * 3 + 2 && j * 3 <= col && col <= j * 3 + 2 then rational 1 else rational 0 for i in 0..2 do for j in 0..2 do let boardBlock = Parameter(Domain.IntegerNonnegative, "boardBlock", line, line) model.AddParameters boardBlock boardBlock.SetBinding(board |> Seq.cast<SudokuCell> |> Seq.map(fun c -> { KeyRow = c.Row; KeyCol = c.Col; IsIn = isInBlock i j c.Row c.Col }), "IsIn", "KeyRow", "KeyCol") model.AddConstraint(null, Model.AllDifferent(Model.ForEach(line, fun keyi -> Model.ForEachWhere(line, (fun keyj -> boardDec.[keyi, keyj]), fun keyj -> boardBlock.[keyi,keyj])))) |> ignore let solution = ctx.Solve() if solution.Quality = SolverQuality.Feasible then ctx.PropagateDecisions() Some [| for i in 0..8 -> [| for j in 0..8 -> board.[i,j].Value |] |] else None let main() = let puzzle = "sudoku.csv" |> File.ReadAllLines |> Array.Parallel.map(fun ln -> ln.Split([|','|], StringSplitOptions.RemoveEmptyEntries) |> Array.Parallel.map(int)) let sw = System.Diagnostics.Stopwatch.StartNew() match Sudoku.Solve puzzle with | Some b -> sw.Stop() let lines = b |> Array.Parallel.map(fun r -> (r |> Array.fold(fun acc b -> sprintf "%s,%i" acc b) String.Empty).Substring 1) File.WriteAllLines("solved.csv", lines) lines |> Seq.iter(fun ln -> printfn "%s" ln) printfn "Parsed and solved in %ims" sw.ElapsedMilliseconds | None -> printfn "failed" Console.ReadKey() |> ignore do main();; Ultima modifica di !k-0t1c! : 08-06-2009 alle 18:22. |
08-06-2009, 16:43 | #24 | |
Bannato
Iscritto dal: Jan 2003
Città:
Messaggi: 4400
|
Quote:
...ciao Andrea... |
|
08-06-2009, 18:24 | #25 |
Member
Iscritto dal: Jul 2008
Messaggi: 237
|
http://tbn3.google.com/images?q=tbn:...y-facepalm.jpg
Mi ero dimenticato una riga, quella che impone che i valori iniziali diversi da 0 ed i valori finali nelle stesse posizioni coincidano...Fixed, il tempo è salito di qualche millisecondo ma siamo sempre li |
08-06-2009, 18:40 | #26 | |
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Quote:
Un'altro conto è invece fare che ci mette 13 ms a risolverlo Ora provo a metterci il "guessing" spero che non faccia aumentare assurdamente i tempi... |
|
08-06-2009, 20:46 | #27 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:35. |
08-06-2009, 20:57 | #28 | |
Junior Member
Iscritto dal: Jun 2009
Messaggi: 14
|
Quote:
|
|
08-06-2009, 20:57 | #29 | |
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Quote:
Mi interesserebbe capire da dove iniziare per leggerlo più che altro Ma c'è qualche "guideline" per avere dei risultati prestazionali eccellenti come fai sempre oppure serve solamente un'esperienza eccessiva? |
|
08-06-2009, 21:05 | #30 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:35. |
08-06-2009, 21:10 | #31 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:35. |
08-06-2009, 21:38 | #32 |
Junior Member
Iscritto dal: Jun 2009
Messaggi: 14
|
in poco tempo anche. mi sembra difficilissimo il c, io non riesco a farlo neanche in java o in python che conosco un pò meglio.
|
08-06-2009, 22:02 | #33 |
Member
Iscritto dal: Jul 2008
Messaggi: 237
|
Bene bene, festa delle bitmasks
Codice illeggibile, specie senza commenti, ma è comunque comprensibile il principio, complimenti Direi che questo contest è stato risolto interessantemente, il prossimo lo penserò per qualcosa di molto parallelizzabile P.S.: "lieta" <- donna in questo campo? doppi complimenti. Anche se qualcuno potrebbe fare la classica battuta "ecco perché scrive codice così contorto" |
08-06-2009, 22:48 | #34 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:35. |
09-06-2009, 01:34 | #35 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2745
|
@rеpne scasb: Una domanda: gli or + shift servono a segnare in una casella che il numero corrente non può starci? Molto interessante, io nel risolvere i sudoku a mano ho sempre fatto il contrario invece con questo metodo una volta segnata la casella non devi più cancellare il segno che fai. Anche se in effetti facendolo a mano quando i segni diventano tanti diventa un po' un pasticcio...
E un'altra cosa: pensavo che senza il bruteforce non si potesse risolvere qualsiasi schema. Sbaglio? |
09-06-2009, 08:44 | #36 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:36. |
09-06-2009, 09:24 | #37 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Bravissima, repne
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
09-06-2009, 09:52 | #38 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:36. |
09-06-2009, 09:54 | #39 |
Senior Member
Iscritto dal: Oct 2001
Messaggi: 11471
|
|
09-06-2009, 10:10 | #40 |
Senior Member
Iscritto dal: May 2008
Messaggi: 530
|
■
Ultima modifica di rеpne scasb : 18-06-2012 alle 15:36. |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:36.