Sudoku. Ivo Doko, Saša Buzov. PMF Matematički odsjek, Sveučilište u Zagrebu

Similar documents
SIMPLE PAST TENSE (prosto prošlo vreme) Građenje prostog prošlog vremena zavisi od toga da li je glagol koji ga gradi pravilan ili nepravilan.

Podešavanje za eduroam ios

Biznis scenario: sekcije pk * id_sekcije * naziv. projekti pk * id_projekta * naziv ꓳ profesor fk * id_sekcije

IZDAVANJE SERTIFIKATA NA WINDOWS 10 PLATFORMI

SAS On Demand. Video: Upute za registraciju:

Nejednakosti s faktorijelima

CJENIK APLIKACIJE CERAMIC PRO PROIZVODA STAKLO PLASTIKA AUTO LAK KOŽA I TEKSTIL ALU FELGE SVJETLA

Upute za korištenje makronaredbi gml2dwg i gml2dgn

Ulazne promenljive se nazivaju argumenti ili fiktivni parametri. Potprogram se poziva u okviru programa, kada se pri pozivu navode stvarni parametri.

BENCHMARKING HOSTELA

Uvod u relacione baze podataka

1. Instalacija programske podrške

Port Community System

GUI Layout Manager-i. Bojan Tomić Branislav Vidojević

TRAJANJE AKCIJE ILI PRETHODNOG ISTEKA ZALIHA ZELENI ALAT

Tutorijal za Štefice za upload slika na forum.

int[] brojilo; // polje cjelih brojeva double[] vrijednosti; // polje realnih brojeva

AMRES eduroam update, CAT alat za kreiranje instalera za korisničke uređaje. Marko Eremija Sastanak administratora, Beograd,

Eduroam O Eduroam servisu edu roam Uputstvo za podešavanje Eduroam konekcije NAPOMENA: Microsoft Windows XP Change advanced settings

RJEŠAVANJE BUGARSKOG SOLITERA

UPITI (Queries) U MICROSOFT ACCESSU XP

KONFIGURACIJA MODEMA. ZyXEL Prestige 660RU

JEDINSTVENI PORTAL POREZNE UPRAVE. Priručnik za instalaciju Google Chrome dodatka. (Opera preglednik)

MINISTRY OF THE SEA, TRANSPORT AND INFRASTRUCTURE

Windows Easy Transfer

KAPACITET USB GB. Laserska gravura. po jednoj strani. Digitalna štampa, pun kolor, po jednoj strani USB GB 8 GB 16 GB.

RANI BOOKING TURSKA LJETO 2017

Korak X1 X2 X3 F O U R T W START {0,1}

DANI BRANIMIRA GUŠICA - novi prilozi poznavanju prirodoslovlja otoka Mljeta. Hotel ODISEJ, POMENA, otok Mljet, listopad 2010.

PROJEKTNI PRORAČUN 1

Struktura indeksa: B-stablo. ls/swd/btree/btree.html

CJENOVNIK KABLOVSKA TV DIGITALNA TV INTERNET USLUGE

KAKO GA TVORIMO? Tvorimo ga tako, da glagol postavimo v preteklik (past simple): 1. GLAGOL BITI - WAS / WERE TRDILNA OBLIKA:

Programiranje za internet zimski semestar 2013/2014. Java kroz primjere (skripta je u fazi izradi)

Bušilice nove generacije. ImpactDrill

24th International FIG Congress

Advertising on the Web

Klasterizacija. NIKOLA MILIKIĆ URL:

PASCAL - Skripta sa zadacima i rješenjima -

TRENING I RAZVOJ VEŽBE 4 JELENA ANĐELKOVIĆ LABROVIĆ

NIS PETROL. Uputstvo za deaktiviranje/aktiviranje stranice Veleprodajnog cenovnika na sajtu NIS Petrol-a

Otpremanje video snimka na YouTube

PODSUSTAV ZA UPRAVLJANJE SPREMNIKOM UGRADBENOG RAČUNALA

Idejno rješenje: Dubrovnik Vizualni identitet kandidature Dubrovnika za Europsku prijestolnicu kulture 2020.

Naredba je uputa računalu za obavljanje određene operacije.

Office 365, upute za korištenje elektroničke pošte

Big Data: kako smo došli do Velikih podataka i kamo nas oni vode

Bear management in Croatia

ENR 1.4 OPIS I KLASIFIKACIJA VAZDUŠNOG PROSTORA U KOME SE PRUŽAJU ATS USLUGE ENR 1.4 ATS AIRSPACE CLASSIFICATION AND DESCRIPTION

math.e Fibonaccijev brojevni sustav 1 Uvod Fibonaccijev brojevni sustav math.e Vol 16. Hrvatski matematički elektronički časopis

CRNA GORA

Mindomo online aplikacija za izradu umnih mapa

INSTALIRANJE SOFTVERSKOG SISTEMA SURVEY

MS Excel VBA za studente kemije

Fakultet strojarstva i brodogradnje ZAVRŠNI RAD

Ključ neposrednog prosvjetljenja izvadak iz kolekcije predavanja besplatnini primjerak

Croatian Automobile Club: Contribution to road safety in the Republic of Croatia

Da bi se napravio izvještaj u Accessu potrebno je na izborniku Create odabrati karticu naredbi Reports.

KABUPLAST, AGROPLAST, AGROSIL 2500

ECONOMIC EVALUATION OF TOBACCO VARIETIES OF TOBACCO TYPE PRILEP EKONOMSKO OCJENIVANJE SORTE DUHANA TIPA PRILEP

Implementacija sparsnih matrica upotrebom listi u programskom jeziku C

OTVARANJE BAZE PODATAKA I IZRADA TABLICE U MICROSOFT ACCESS-u

3. Obavljanje ulazno-izlaznih operacija, prekidni rad

Programiranje. Nastava: prof.dr.sc. Dražena Gašpar. Datum:

Commissioned by Paul and Joyce Riedesel in honor of their 45th wedding anniversary. Lux. œ œ œ - œ - œ œ œ œ œ œ œ œ œ œ. œ œ œ œ œ œ œ œ œ.

OTVARANJE BAZE PODATAKA U MICROSOFT ACCESSU XP

Upotreba selektora. June 04

Služi za brisanje prethodno upisanih sadržaja u čitavom worksheetu. Opcija nije nužna, ali je korisna.

Optimizacija rojem čestica

ANALIZA PRIMJENE KOGENERACIJE SA ORGANSKIM RANKINOVIM CIKLUSOM NA BIOMASU U BOLNICAMA

IZRADA TEHNIČKE DOKUMENTACIJE

SADRŽAJ, OD NAJSTARIJIH PREMA NAJNOVIJIM BLOGOVIMA

Mogudnosti za prilagođavanje

UPUTE ZA INSTALACIJU PROGRAMA FINBOLT 2007 tvrtke BOLTANO d.o.o.

En-route procedures VFR

FORMALNI DOKAZI U PROGRAMIRANJU

WWF. Jahorina

Svojstva olovke x (0,0)

Val serija poglavlje 08

Natjecateljsko programiranje Autor i predavač ovog predavanja: Bruno Rahle Kontakt Kontakt mob: 099/BRAHLE0

Rainbows tablice CCERT-PUBDOC

Tablični kalkulator Excel 7.0 Klinča Sela 2005.

DEVELOPMENT OF SMEs SECTOR IN THE WESTERN BALKAN COUNTRIES

Donosnost zavarovanj v omejeni izdaji

Pravljenje Screenshota. 1. Korak

Srđana Obradović. Teorija brojeva u nastavi matematike. Diplomski rad

Svijet progonjen demonima

Adapted for classroom use by

Priručnik za Ekoaktivizam

FER2.net. Tutorial za 1. međuispit iz Baza podataka. web verzija tutoriala: autor: christair. Sadržaj:

Val serija 8. dio. Mnogi ljudi su pisali i pitali o "želji za znanjem." Njima se čini da je sticanje i prikupljanje znanja jedna OPS aktivnost.

UNIVERZITET U BEOGRADU RUDARSKO GEOLOŠKI FAKULTET DEPARTMAN ZA HIDROGEOLOGIJU ZBORNIK RADOVA. ZLATIBOR maj godine

Hot Potatoes. Osijek, studeni Jasminka Brezak

Halina, Hesus. (Advent) œ N œ œ œ. œ œ œ œ œ. œ. œ œ œ œ. œ œ. C F G7sus4. œ. # œ œ J œ œ œ J. œ œ. J œ. # œ. # œ œ œ

Statistička analiza algoritama za dinamičko upravljanje spremnikom

I što je uopće ta pamet, ta frustrirana, umišljena,ograničena, zgažena i ponižena ljudska pamet. Možda biserje u svinjskom koritu? Ljudska misao?

1.7 Predstavljanje negativnih brojeva u binarnom sistemu

Trening: Obzor financijsko izvještavanje i osnovne ugovorne obveze

Kapitalizam i otpor u 21. veku

Tema 2: Uvod u sisteme za podršku odlučivanju (VEŽBE)

Transcription:

Sudoku Ivo Doko, Saša Buzov PMF Matematički odsjek, Sveučilište u Zagrebu ivo.doko@gmail.com, sasa.buzov@gmail.com Sažetak: U ovom članku opisujemo kako smo riješili problem generiranja novih sudoku slagalica s jedinstvenim rješenjem, te rješavanja istih. Ključne riječi: sudoku, rješavanje sudoku, generiranje sudoku, backtracking 1. Uvod Sudoku je vrsta logičke slagalice, čija povijest seže skroz do 19. stoljeća. Bilo je naravno više različitih varijanti, a moderna sudoku (kakva nam je danas poznata svima) se prvi put pojavila u američkom časopisu Dell magazine, pod nazivom Number place 1979. godine. Objavio ju je Howard Garns, umirovljeni arhitekt, inače zaljubljenik u enigmatiku. On je uveo ograničenje da se u svakom 3x3 bloku jedna znamenka smije pojaviti samo jednom. Popularizacija sudoku je uslijedila nakon objave u japanskom časopisu Monthly Nikolist, gdje je objavljena 1984.g. pod imenom Sūji wa dokushin ni kagiru ( 数字は独身に限る ), što u doslovnom prijevodu znači broj se smije pojaviti samo jednom. Uzimanjem samo prvih slogova, dobili smo današnji naziv slagalice sudoku. 2. Sudoku i varijacije Sudoku slagalica se sastoji od jednog kvadrata, podijeljenog na 81 manjih kvadrata (polja), koji su organizirani u 3x3 blokove (ukupno 9 takvih). Cilj igre je u svako polje upisati prirodni broj od 1 do 9 tako da se niti u jednom retku, stupcu ili 3x3 bloku ista znamenka ne pojavljuje dvaput. Početni problem je djelomično popunjena slagalica s ne više od 32 broja upisana u slagalicu. Sudoku ne mora imati jedinstveno rješenje (zamislimo da nam je početni problem potpuno prazna slagalica i vidimo da rješenja ima jako puno), ali mi želimo generirati baš one koje imaju jedinstveno rješenje. Postoji puno varijacija sudokua, npr. može biti 4x4 podjeljena na 2x2 blokove, 6x6 s 2x3 blokovima, pa do 16x16 ili više (u biti, nema ograničenja na veličinu). Poznate varijante su i Wordoku gdje umjesto brojeva upisujemo slova, zatim nonomino ili Jigsaw gdje slagalica nije podijeljena na YxY blokove već na blokove random oblika, te Hypersudoku koja je ista kao i obična sudoku, ali s dodatnim

ograničenjima, tj. određena su područja na kojima se moraju pojaviti sve znamenke točno jednom (kombinacija sudoku i jigsaw sudoku). Slika 1: Lijevo je primjer sudoku slagalice, a s desne strane rješenje iste. Slika 2: lijevo je primjer jigsaw sudoku slagalice, a s desne strane rješenje iste. 3. Implementacija problema Sad kad smo pojasnili što je sudoku, odakle je i od kad je, vrijeme je da pojasnimo što smo mi ovdje radili. Mi smo željeli napisati program koji će generirati

nove sudoku slagalice (pošto dnevne novine nisu zadovoljavale naše potrebe za novim slagalicama) uz mali dodatni uvjet, da sudoku ima jedinstveno rješenje. Radili smo u programskom jeziku C++ (pošto ga dobro poznajemo tako nam je bilo najlakše). Naravno, kako bi bilo moguće provjeriti egzistenciju i eventualnu jedinstvenost rješenja, morali smo implementirati i algoritam za rješavanje sudoku slagalice. 3.1 Prezentacija problema Prvo i osnovno, treba nam prezentacija problema. Logično je bilo prezentirati sudoku kao dvodimenzionalno polje, dimenzije 9x9, pa smo tako i napravili: cell table[9][9]; gdje je cell struktura koja predstavlja polje u tablici u koje upisujemo broj, a izgleda ovako: struct cell{ int value; bool possiblevalues[9]; int numberofpossiblevalues; U strukturi cell, value predstavlja vrijednost koja je upisana u polje (0 ako nema vrijednosti na tom polju), possiblevalues je niz u koji bilježimo moguće vrijednosti za to polje (ako je vrijednost i moguća onda je possiblevalues[i-1] == true), a u numberofpossiblevalues spremamo broj mogućih vrijednosti za to polje. Zatim smo uveli još čitav niz pomoćnih varijabli i funkcija, koje nećemo sve nabrojati i objasniti jer ih ima puno, a nije ih potrebno sve razraditi kako bi se shvatio naš program, tako da ćemo objasniti samo one koje su neophodne i to kad ih spomenemo. Sad, kad imamo sudoku, krećemo dalje. Kao što smo već spomenuli, da bi mogli provjeriti egzistenciju i jedinstvenost rješenja, moramo implementirati algoritam za rješavanje sudokua. 3.2 Rješavanje sudoku slagalice Jedan od najprimitivnijih mogućih načina za rješavanje sudoku slagalice bi svakako bio isprobavanje svih mogućih kombinacija, no to i nije najbolji izbor. Uzmimo da su na početku zadana 32 broja, ostaje nam 81-32=49 praznih mjesta, za svako prazno mjesto ima 9 mogućih znamenki, što daje ukupno 49! mogućih kombinacija, a to je jako velik proj pokušaja, čak i za današnja računala. Da ubrzamo algoritam moramo iskoristiti informacije koje imamo, kako bismo odmah u startu odbacili rješenja za koja znamo da nemaju smisla. Npr. ako u gornjem lijevom uglu sudoku slagalice imamo upisan broj 1, znamo da nema smisla pokušavati s brojem 1 u prvom retku sudokua. Isto tako vrijedi za prvi stupac te pripadajući blok 3x3 polja.

1 Slika 3: koristeći informaciju da je na mjestu (1,1) upisan broj 1, znatno smo smanjili broj mogućih kombinacija na čak 20 drugih mjesta. Kako smo mi zamislili rješavanje problema, najbolje ćemo prikazati pomoću pseudokoda: unsigned long solve(char *file, unsigned long depth){ do{ do{ do{ do{ -provjeri vodi li ovaj put do mogućeg rješenja, ako ne, vrati backtrack. -ako smo pronašli rješenje, vrati ga, povećaj za 1 ukupni broj rješenja te poništi sve promjene. -provjeri postoji li mjesto u tablici za koje imamo samo jednu moguću vrijednost i ako postoji popuni ga. while (singleschange) -provjeri vodi li ovaj put do mogućeg rješenja, ako ne, vrati backtrack. -ako smo pronašli rješenje, vrati ga, povećaj za 1 ukupni broj rješenja te poništi sve promjene. -provjeri postoji li redak u koji se neka vrijednost upisati na samo jedno mjesto i ako postoji upiši tu vrijednost. while (rowschange) može -provjeri vodi li ovaj put do mogućeg rješenja, ako ne, vrati backtrack. -ako smo pronašli rješenje, vrati ga, i povećaj za 1 ukupni broj rješenja, te poništi sve promjene. -provjeri postoji li stupac u koji se neka vrijednost može upisati na samo jedno mjesto i ako postoji upiši tu vrijednost.

while (columnschange) -provjeri vodi li ovaj put do mogućeg rješenja, ako ne, vrati backtrack. -ako smo pronašli rješenje, vrati ga, i povećaj za 1 ukupni broj rješenja, te poništi sve promjene. -provjeri postoji li 3x3 blok u koji se neka vrijednost može upisati na samo jedno mjesto i ako postoji upiši tu vrijednost. while (blockschange) bestposition = mjesto u tablici za koje postoji najmanje mogućih vrijednosti broj rješenja = 0; kreiraj listu listofvalues i u nju upiši sve moguće vrijednosti za poziciju bestposition. ako je zadano da pretražujemo nasumično, ispermutiraj listofvalues. while(listofvalues nije prazna){ int current = vrijednost s početka liste valuelist; makni tu vrijednost iz liste. na poziciju bestposition postavi vrijednost current. broj nađenih rješenja += solve(file, depth+1); izbriši vrijednost koju smo postavili na bestposition. poništi sve vrijednosti koje smo promijenili (tj izbriši sve brojeve koje smo upisivali, kako bi se backtracking mogao vratiti) vrati broj pronađenih rješenja; ; Gdje su redom: bool singleschange, rowschange, columnschange, blockschange; singleschange = true ako postoji mjesto u tablici koje ima samo jednu moguću vrijednost rowschange = true ako postoji redak u koji se neka vrijednost može upisati na samo jedno mjesto columnchange = true ako postoji stupac u koji se neka vrijednost može upisati na samo jedno mjesto

blockchange = true ako postoji 3x3 blok u koji se neka vrijednost može upisati na samo jedno mjesto Promjene koje smo spominjali spremamo u varijablu changes, koja je tipa log, a log je klasa koju smo definirali kao: class log{ deque< pair<int,int> > memory; public: void add(int a, int b){ memory.push_back(make_pair(a, b)); void undo(){ while(!memory.empty()){ table[memory.front().first][memory.front().second].value= 0; memory.pop_front(); Memory služi za zapisivanje svih promjena koje je trenutni poziv funkcije solve napravio (da te promjene možemo vratiti). add dodaje poziciju u memory, a undo vraća sve promjene zapisane u memory. To bi bio grubi opis našeg algoritma, jer u stvarnom programu funkcija solve ima dodatne mogućnosti, a to su da tražimo samo jedno rješenje ili sva rješenja, da pretražujemo rješenja deterministički ili slučajno, ili da samo provjeravamo je li rješenje jedinstveno, te naravno mogućnost da pokrećemo program samo za rješavanje slagalice, ali to su promjene u pseudokodu koje nam nisu zanimljive, zanimljiv nam je algoritam kojim tražimo rješenje/a. 3.3 Generiranje sudoku slagalice Tek sad, nakon podužeg uvoda, dolazimo do biti našeg programa, do dijela koji stvarno generira sudoku slagalicu. U našem programu, to radi funkcija: void generate(char *file); Opet nam je najjednostavnije objasniti rad algoritma, koristeći pseudokod. void generate(char *file){ -upiši kanonski korijen u slagalicu; (nama je to: 1 2 3 4 6 7 8 9

) - nađi jedno rješenje za gornju slagalicu (graf se prilikom traženja rješenja pretražuje na slučajan način, kako program ne bi uvijek generirao identičnu slagalicu) koristeći funkciju solve. npr.: 9 7 2 3 1 6 4 8 4 8 2 6 7 9 1 3 1 3 6 8 9 4 2 7 8 4 1 2 3 7 9 6 2 7 9 4 6 3 8 1 6 1 3 7 8 9 4 2 7 4 3 1 2 8 6 9 9 2 8 6 7 1 3 4 3 6 1 9 4 8 2 7 - nasumično ispermutiraj retke (unutar blok redaka) - nasumično ispermutiraj stupce (unutar blok stupaca) - nasumično ispermutiraj blok retke - nasumično ispermutiraj blok stupce - nasumično ispermutiraj vrijednosti u tablici - na slučajan način generiraj vektor order[81], koji nam govori kojim redoslijedom ćemo uklanjati vrijednosti iz tablice for(i=0; i<81; i++){ -obriši vrijednost s pozicije order[i]; -provjeri je li rješenje jedinstveno, ako nije, vrati vrijednost na poziciju order[i]; 4. Zaključak Pokretanje ovog programa bezbroj puta, dok smo radili na njemu, nam ipak nije moglo dati predodžbu kakav je naš algoritam, tj. je li brz ili spor. Znali smo samo da generira sudoku s jedinstvenim rješenjem, ali da bi znali je li brz, morali smo ga s nečim usporediti. Koristeći se funkcijama iz datoteke <cfile>, napravili smo jednostavnu štopericu, i izračunali da programu u prosjeku treba 0.046s da generira sudoku slagalicu. Zatim smo za probu zakomentirali dio koda koji je provjeravao postoje li vrijednosti koje se mogu upisati na samo jedno mjesto i postoje li mjesta za koje postoji samo jedna moguća vrijednost (za stupce, retke i blokove) te pokušali rješiti jednu sudoku slagalicu samo backtrackingom. Nakon pola sata backtracking algoritam je bio na 8. dubini i tko zna koliko još daleko od rješenja, pa smo

zaključili da ne trebamo niti pokušavati na taj način generirati sudoku. Mali test nam je bio dovoljan da budemo zadovoljni performansama našeg algoritma, jer možda nije najbolji i najbrži, ali je daleko bolji nego brute force pristup i sasvim pristojan za upotrebu jer generira sudoku mnogo brže nego što mi rješavamo (bez računala, naravno). Brzine smo testirali na osobnom računalu s intelovim q6600 procesorom radnog takta 3200mhz. Literatura 1. http://web. math. hr/nastava/ui/ 2. http://en.wikipedia.org/wiki/algorithmics_of_sudoku 3. http://en.wikipedia.org/wiki/sudoku