Sudoku - python

Sudoku - python

Avtor: Mateja Gorišek

Opis problema

Sudoku je številčna križanka. Igralno polje velikosti 9×9 kvadrantov je dodatno razdeljeno na devet manjših kvadratov velikost 3×3 ( na spodnji sliki so predstavljeni z debelejšimi črtami), vanj pa je vpisanih nekaj števil (od 1 do 9)

(mreza.JPG)


V igralno polje igralec vpisuje števila od 1 do 9 in to tako, da so na koncu izpolnjeni naslednji trije pogoji: (1) v vsakem stolpcu se mora vsako število od 1 do 9 pojaviti natanko enkrat; (2) v vsaki vrstici se mora vsako število od 1 do 9 pojaviti natanko enkrat; (3) v vsakem od devetih malih kvadrantov velikosti 3×3 se mora vsako število od 1 do 9 pojaviti natanko enkrat.

Opis problema

Na zgornji sliki vidimo primer pravilno izpolnjenega polja. Na spodnji sliki pa polje, ki je izpolnjeno napačno (med drugim zato, ker v zadnjem stolpcu ni števila 6, se pa število 2 v njem pojavlja kar dvakrat).

(pravilnaM.JPG) (nepravilnaM.JPG)


Napiši program, ki bo sprejel izpolnjeno polje in izpisal niz PRAVILNA, če je rešitev pravilna, in NAPACNA, če ni pravilna. Če ti je naloga pretežka, lahko poskusiš napisati program, ki bo preverjal le pogoja (1) in (2), ne pa tudi pogoja (3) (z drugimi besedami: preveri naj, le če so prisotna vsa števila od 1 do 9 v vsaki vrstici in v vsakem stolpcu, ni pa se mu treba ukvarjati z malimi kvadrati velikosti 3×3). Za takšno rešitev dobiš pri tej nalogi polovico vseh možnih točk.

Ideja rešitve



Števila iz sudokuja imamo zapisana v tekstovni datoteki. Tako moramo najprej odpreti datoteko in iz nje izpisati vsa števila po vrsticah – števila iz vrstice bodo v seznamu. Tako dobimo seznam seznamom. Nato bomo morali preveriti pogoj, da se vsa števila od 1 do 9 v nekem seznamu pojavijo samo enkrat- to si bomo pomagali z množico (set()). Nato pa preverili, da ta pogoj velja za vrstice, za stolpce ter za kvadratke. Če ta pogoj velja za vrstice, stolpce in za kvadratke bomo izpisali niz 'PRAVILNA'.

Koda, ki prebere iz datoteke

Najprej sem napisala kodo, ki prebere števila rešenega sudokuja iz tekstovne datoteke.

(sudoku.JPG)

Koda, ki preveri, da se vsako število od 1 do 9 pojavi natanko enkrat


(razlicne.JPG)

Koda, ki preveri ali je sudoku rešen pravilno

(preveri.JPG)

Razlaga algoritma

Metoda sudokuPreberi(ime):
Za parameter sprejme ime datoteke.
Najprej naredimo prazen seznam, v katerega bomo nekaj dodajali.
To datoteko odpremo za branje in jo shranimo pod ime f. To sem naredila s stavkom WITH, ki omogoča bolj zgoščen zapis dela z datotekami in tudi sam poskrbi za zaprtje datoteke.
Nato gremo z zanko for po vrsticah datoteke f. Zanka vsako vrstico doda v seznam, pri tem pa odstrani nepotrebne znake ('\n'- znak za novo vrstico) in razdeli niz glede na bele znake. Tako dobimo seznam seznamov v katerem so nizi števil.
Nize števil moramo spremeniti v cela števila, to si pomagamo s funkcijo int. Tako gremo z zanko po seznamih in z drugo zanko v podsezname in spremenimo nize števil v cela števila. Na koncu pa vrnemo seznam.
Pri metodi s try in except prestrežemo napake, do katerih je prišlo. Except exception as e – v e je opis napake do katere je prišlo, ulovimo lahko pa katero koli napako.

Razlaga algoritma

Metoda razlicne(sez):
Metoda sprejme seznam števil. S pomočjo seznamskega izraza naredimo nov seznam, v katerega dodajamo elemente seznama, če so večji od 0 in manjši ali enaki 9.
Nato pa preverimo ali velja da je dolžina novega seznama enaka dolžini množice novega seznama in enaka 9. Množica (set())odstrani večkratne ponovitve nekega števila. Enaka pa mora biti 9, saj imamo v sudokuju v vsaki vrstici ali v vsakem stolpcu ali kvadratku natanko devet elementov. Če je ta pogoj izpolnjen funkcija vrne True, v nasprotnem primeru vrne False.
Če je pa je prišlo do kakšne napake, jo ulovimo in izpišemo, to dosežemo s try in except Exception as e, s katerim prestrežemo napako in jo opišemo.

Razlaga algoritma

Metoda preveri(ime):
Metoda za parameter sprejme ime datoteke, v kateri so zapisana števila rešenega sudokuja. Datoteko odpremo, preberemo ter dobimo seznam seznamov z metodo sudokuPreberi(ime) .
V 'vrstice' shranimo seznam logičnih spremenljivk, dobimo ga s seznamskih izrazov. V seznamskem izrazu gremo po vsaki vrstici v sudokuju, to so vsi podseznami ter preverimo ali velja pogoj da so vsa števila od 1 do 9 pojavijo natanko enkrat, to dosežemo z klicanjem metode razlicne.
Podobno je za stolpce, le da preverjamo vse i-te elemente vrstic (preverijo se vsi prvi elementi v vseh podseznamih itd.). Števec i pa teče od indeksa 0 do 8 (funkcija range), to pomeni, da imamo devet elementov v stolpcu.
V kvadratke enako shranimo seznam logičnih spremenljivk. Dobimo ga tako, da pregledamo z metodo razlicne ali je pogoj izpolnjen (da se števila od 1 do 9 pojavijo natanko enkrat). Za seznam (razlicne(sez)) sprejmemo števila v sudokuju, kjer gre števec i po seznamih, j pa po podseznamih oz. drugače rečeno: števec i gre po vseh vrsticah sudokuja, števec j pa po stolpcih. Števca pa premikamo s korakom 3. Tako pregledujemo 3×3 kvadratke.
Sedaj pa želimo vedeti ali je sudoku pravilno rešen, to pomeni da vse vrstice, stolpci in kvadratki izpolnjujejo pogoj.
Ker imamo sedaj narejene sezname v katerih so logične spremenljivke za vrstice , stolpce in kvadratke, preverimo ali so v vsi elementi seznamov enaki True. Če so pomeni, da je sudoku pravilno rešen.
Najprej postavimo števec k na nič.
Nato pa gremo z zanko po indeksih seznamov in preverimo, če je vsak i-ti element enak True, če je povečamo števec za 1. To naredimo za vrstice, stolpce in kvadratke.
Ker imamo v vsakem seznamu devet elementov in ti seznami so trije (vrstice, stolpci in kvadratki), pomeni da imamo skupaj 27 vrednosti, ki so enake True. Tako je števec k enak 27. Če je na koncu števec k enak 27, je sudoku pravilno rešen in izpišemo niz 'PRAVILNA', v nasprotnem primeru izpišemo niz 'NAPACNA'. Če je pa je prišlo do kakšne napake, jo ulovimo in izpišemo, to dosežemo s try in except Exception as e, s katerim prestrežemo napako in jo opišemo.

Predstavitev testiranja kode

Testni primeri in razlaga testnih primerov

Imamo tri tekstovne datoteke v katerih so zapisana števila rešenega sudokuja. Tako bom za testiranje uporabila datoteke: pravilen.txt, napacen.txt ter pravilen1.txt.

  • sudokuPreveri('pravilen.txt') – preverimo, kaj nam koda naredi, ko vpišemo ime datoteke v kateri so zapisana števila rešenega sudokuja. Metodo smo napisali tako, da nam odpre datoteko, in zapiše vrstice v seznam. Tak rezultat tudi dobimo seznam seznamov, ki so vrstice, ki so zapisane v datoteki. Enako se zgodi pri klicanju sudokuPreveri('napacen.txt').
  • sudokuPreveri('pravi.txt') – s tem primerom bomo preizkusili kaj nam metoda vrne, če za parameter podamo neobstoječo datoteko. Metoda nam vrne sporočilo o napaki, do katere je prišlo. To napako smo ujeli s except Exception as e, s katerim lahko ulovimo katero koli napako.
  • Nato preizkusim, kaj nam vrne druga metoda razlicne([3,5,4,1,8,2,9,6,7]), metoda nam vrne logično spremenljivko True, saj seznam izpolnjuje pogoj, ki smo ga zahtevali.
  • Preverimo kaj nam metoda vrne, če za parameter sprejme seznam, ki ne izpolnjuje pogoja. Metoda razlicne([4,7,9,0,1,4,3,8,3]), nam vrne False. e) Preverimo še, kaj nam metoda vrne, če za parameter ne vpišemo seznama števil, ampak kaj drugega. Vrne nam napako, ki smo jo prestregli in opiše napako.
  • Na koncu, še rešimo problem, ki je opisan v navodilu naloge. Tako preverimo ali je sudoku, ki je zapisan v tekstovni datoteki pravilno izpolnjen ali napačno. Tako sem najprej preverila za datoteko pravilen.txt – preveri('pravilen.txt'). Metoda nam niz 'PRAVILNA', kar pomeni da je sudoku rešen pravilno.
  • Preverimo še za dve tekstovni datoteki, v katerih imamo zapisana števila rešenega sudokuja. Tako preverimo: preveri('napacen.txt'), ki nam vrne niz 'NAPACNA', kar pomeni da sudoku ni pravilno rešen, ter preveri('pravilen1.txt'), ki nam vrne niz 'PRAVILNA'. h) Na koncu še preverimo, kaj nam metoda vrne, če za parameter sprejme datoteko, ki ne obstaja. Metoda preveri('pravi.txt') vrne nam opis napak do katerih je prišlo.

Dostop do texstovnih datotek in kode


Povezava do python datoteke
koda
Tekstovne datoteke:
pravilen sudoku napacen sudoku pravilen sudoku

0%
0%