Table of Contents

The Emperor's New Sudoku

Responsabili:

Scopul temei:

Termen de predare:

Întrebări

Dacă aveți nelămuriri, puteți să ne contactați pe forumul dedicat temei de casă nr. 3.

Actualizări:

Reguli Sudoku

Pentru a putea rezolva aceasta tema trebuie sa fiti familiari cu jocul Sudoku.

Sudoku se joacă într-o grilă care este alcătuită din 9 x 9 căsuțe separate în 9 rânduri (poziționate orizontal) și 9 coloane (poziționate vertical) grupate în pătrate cu dimensiuni 3 x 3.

Obiectivul jocului este sa se completeze fiecare patrat cu cifre de la 1 la 9 astfel incat:

Exemplu_grid_sudoku

Mai multe informatii despre joc gasiti aici.

Structura formatului BMP

Vom lucra cu fisiere BMP, deci, cu fisiere binare.

O imagine BMP are urmatoarea structura:

Header-ele pe care le puteti folosi in implementare se afla in scheletul de cod asociat temei.

Urmatiti cu foarte mare atentie exemplul de aici si incercati sa intelegeti cum e reprezentata o imagine BMP inainte de a incepe implementarea. Daca e ceva neclar, puteti intreba oricand pe forum.

Puteti folosi utilitare precum xxd sau hexdump pentru a putea vizualiza continutul unui fisier binar (in cazul nostru, a unei imagini bmp). Vedeti si raspunsurile de aici .

Introducere

Prietenul tau, Emperor Tiramisu, a inceput sa se joace sudoku, dar nu stie exact regulile. Din acest motiv are nevoie de ajutorul tau pentru a stii daca a completat corect sau nu matricea. Deoarece stie ca sunteti studenti la ACS el vrea de la voi sa “automatizati” acest proces. Veti primi de la el o poza cu tabla lui de sudoku si va trebui sa ii spuneti daca a castigat sau a pierdut.

Task 1 - 10p

Emperor Tiramisu a decis sa comunice cu tine prin intermediul unui server (mai specific, de HTTP, insa nu conteaza acest aspect in rezolvarea temei - mai multe informatii referitoare la ce este un server de http gasiti aici - Nu este relevant pentru implementarea temei!). Din cauza aceasta mesajul primit de la el a ajuns la tine in format JSON. Prima ta sarcina este sa transformi mesajul primit intr-o imagine bmp. Ca sa poti face asta trebuie sa stii ce inseamna JSON.

Informatii JSON

Informatii JSON

JSON (JavaScript Object Notation) este un format de reprezentare și interschimb de date între aplicații informatice. Este un format text, inteligibil pentru oameni, utilizat pentru reprezentarea obiectelor și a altor structuri de date și este folosit în special pentru a transmite date structurate prin rețea. Se bazeaza pe un model de forma: “cheie”:“valoare”.

Exemplu urmator arata cum am putea stoca date despre o persona in format JSON.


{
  "firstName": "John",
  "lastName": "Smith",
  "age": 27,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    }
  ],
  "children": [],
  "spouse": null
}

Mai multe informatii despre formatul JSON.

Pentru a parsa datele de intrare din fisier va recomandam sa folositi o biblioteca externa precum cJSON sau JSMN. Nu sunteti restrictionati doar la aceste 2 biblioteci externe, ci puteti folosi ce doriti voi doar pentru lucrul cu jsoane. Va trebui sa motivati in README de ce ati ales biblioteca externa pe care ati folosit-o/ati facut prelucrarea de mana.

Orice folosire de cod din alte surse pentru a va ajuta in implementarea altor parti din tema va atrage după sine depunctarea cu punctajul aferent temei, conform regulamentului

Exemplu input

Puteti gasi fisierul json aici. Il copiati local si il salvati cu extensia ”.json”.

In exemplul de mai jos, campul “bitmap” nu este populat complet.

Input:

board_0.json
{
	"bitmap":	[0,0,0,...,0,0,0,0,0,0,0,255,255,255,255,255,255,...],
	"file_header":	{
		"offset":	54,
		"signature":	"BM",
		"reserved":	0,
		"file_size":	16114
	},
	"info_header":	{
		"colors_used":	0,
		"size":	40,
		"colors_important":	0,
		"image_size":	16060,
		"y_pixels_per_meter":	0,
		"x_pixels_per_meter":	0,
		"width":	73,
		"planes":	1,
		"bit_count":	24,
		"compression":	0,
		"height":	73
	}
}

Output:

O imagine in format bmp.

Informatiile despre file header si info header nu trebuiesc hardcodate. Le veti citi din json. In caz contrar veti fi depunctati.

Informatii despre imagine

O imagine este formata dintr-o multime de pixel, iar fiecare pixel este reprezentat (in cazul nostru) prin 3 valori (R, G, B), ele reprezentand intensitatea culorilor: Rosu, Verde si Albastru (folosind combinatii din aceste culori se pot forma altele). Puteti observa aici cum intensitatea unei culori, schimba culoarea finala.

Imaginea este de 73×73 pixeli, 9×9 patratele care respecta urmatoarele dimensiuni:

  1. o margine de 1 pixel neagra/gri
  2. o margine de 1 pixel alba in jurul cifrei
  3. cifra de 5×5

Marginile nu se dubleaza nicaieri. Peste tot in imagine marginile au grosimea de 1 pixel. Marginile care delimiteaza un subpatrat sunt negre, dar cele din interiorul sectiunii sunt gri.

Exemplu de sectiune de 3×3 patrate (pentru a intelege ceva din exemplu recomandam sa va uitati de pe un Desktop). Daca notam cu “X” un pixel roz (r:255, g:175, b:175) din cifra, cu “.” un pixel alb(r:255, g:255, b:255) din fundal, cu “O” un pixel negru (r:0, g:0, b:0) din margine si cu 0 un pixel gri (r:128, g:128, b:128):


OOOOOOOOOOOOOOOOOOOOOOOOO
O.......0.......0.......O
O.....X.0.XXXXX.0.XXXXX.O
O.....X.0.....X.0.....X.O
O.....X.0.XXXXX.0.XXXXX.O
O.....X.0.X.....0.....X.O
O.....X.0.XXXXX.0.XXXXX.O
O.......0.......0.......O
O00000000000000000000000O
O.......0.......0.......O
O.X...X.0.XXXXX.0.XXXXX.O
O.X...X.0.X.....0.X.....O
O.XXXXX.0.XXXXX.0.XXXXX.O
O.....X.0.....X.0.X...X.O
O.....X.0.XXXXX.0.XXXXX.O
O.......0.......0.......O
O00000000000000000000000O
O.......0.......0.......O
O.XXXXX.0.XXXXX.0.XXXXX.O
O.....X.0.X...X.0.X...X.O
O.....X.0.XXXXX.0.XXXXX.O
O.....X.0.X...X.0.....X.O
O.....X.0.XXXXX.0.XXXXX.O
O.......0.......0.......O
OOOOOOOOOOOOOOOOOOOOOOOOO

Task 2 - 20p

Dupa ce ati reusit sa obtineti o imagine din mesajul primit de la Emperor Tiramisu, puteti observa ca nu se pricepe nici la comunicatii HTTP. Mesajul a fost encodat gresit iar imaginea obtinuta are o problema. Urmatorul pas pentru voi este repararea imaginii.

Aveti deja datele stocate in memorie! Nu mai este nevoie sa cititi inca o data din fisier

Hint

Hint

Hint: Cifrele sunt mirrored (acesta este singurul caz posibil). Pastrand aceeasi notatie de mai sus avem:


Rezultatul obtinut in urma parsarii jsonului:                  Outputul asteptat:
            000000000                                             000000000
            0.......0                                             0.......0
            0.XXXXX.0                                             0.XXXXX.0
            0.X.....0                                             0.....X.0
            0.XXXXX.0                           ->                0.XXXXX.0
            0.X.....0                                             0.....X.0
            0.XXXXX.0                                             0.XXXXX.0
            0.......0                                             0.......0
            000000000                                             000000000

Input:

Imaginea de la cerinta anterioara.

Output:

output_task1

Task 3 - 30p

Dupa toate prelucrarile anterioare asupra setului de date primit de la Emperor Tiramisu, in final putem verifica daca jocul de sudoku este completat corect sau nu. Pentru a face acest lucru trebuie sa verificati daca se respecta cele 3 reguli ale jocului de sudoku. Acest lucru implica recunoasterea de cifre dintr-o imagine bmp.

Hint

Hint

Deoarece comunicatia cu Emperor Tiramisu se face printr-un server remote, veti afisa starea jocului in format json, intr-un fisier “output_task3_board##.json” (unde ”##” reprezinta numarul boardului primit ca input). Jsonul va avea 2 campuri: campul “input_file” - numele fisierului de intrare si in campul “game_state” - “Win!” daca Emperor Tiramisu a reusit sa completeze corect jocul sau “Loss :(” in caz contrar.

Orice tabla de joc care contine casute necompletate sau alte simboluri in afara de cele adimse (cifre de la 1 la 9) se considera pierduta.

Aveti deja datele stocate in memorie! Nu mai este nevoie sa cititi inca o data din fisier

Input

Imaginea obtinuta ca output la punctul anterior.

Output

output_task3.json
{
	"input_file":	"board0.json",
	"game_state":	"Win!"
}

Task 4 - 40p

Se pare ca Emperor Tiramisu s-a plictisit sa completeze jocurile de sudoku (si sa afle de la voi ca a gresit :-)), iar acum ati inceput sa primiti jocuri neterminate pe care trebuie sa le rezolvati.

La acest task veti citi o imagine .bmp cu cifre lipsa si veti completa spatiile goale cu cifrele potrivite. Cifrele scrise de voi vor avea alta culoare fata de cele din imaginiea initiala: magenta (r:255, g:0, b:255).

Se garanteaza ca testele nu vor avea o complexitate ridicata (nu va fi necesar backtrackingul).

Input input_task4.bmp

Output output_task4.bmp

Bonus - 35p

Acum ca ati trecut prin toate aceste taskuri de la Emperor Tiramisu ar trebui sa reusiti (cu putin ajutor din partea noastra) sa rezolvati singuri un joc de sudoku, de la 0.

Asemenea taskului 4, veti primi ca input o imagine bmp cu o tabla de sudoku necompletat, iar voi va trebui sa rezolvati jocul folosind un algoritm propriu sau urmarind pseudocodul de mai jos.

Pseudocod Backtracking

Pseudocod Backtracking

solve_sudoku (board, row, col)
	set nextRow and nextCol to the next position
	if board[row, col] is not open then // skip pinned numbers
		return [nextRow, nextCol] is out of bounds
				or solve_sudoku(nextRow, nextCol) is true
	end if

	for each number in {1..9} do
		if is_valid (board, row, col, number) is true then
			set board[row, col] to number
			
			if [nextRow, nextCol] is out of bounds
			    or solve_sudoku(nextRow, nextCol) is true then
					return true; // we have a solution
			end if

            restore board[row, col] to "open" // backtrack
		end if
	end for
	
	return false // no more numbers to try. all failed.
end solve_sudoku

is_valid (board, row, col, number)
	- function that returns 1 if the "number" cand be placed in the board, 
		on "row" and "col", and does not violate the 3 rules of sudoku.


Cifrele lipsa vor fi completate din nou cu magenta. In cazul in care jocul nu poate fi completat, va trebui sa suprascrieti fiecare cifra din imagine cu un X, scris cu rosu (r: 255, g: 0, b:0).

Format X

Format X


000000000
0.......0
0.X...X.0
0..X.X..0
0...X...0
0..X.X..0
0.X...X.0
0.......0
000000000

Input output_bonus.bmp

Output input rezolvabil output_bonus.bmp

Output input nerezolvabil output_task4_nerezolvabil.bmp

Resurse si checker-ul local

Resursele pentru tema se pot descarca de aici. Sunt prezente:

Daca aveti prima varianta a checkerului va rugam sa o luati pe aceasta.
Instructiuni pentru rularea checkerului, gasiti in READMEul acestuia.

Fisiere de intrare/iesire

Restrictii si precizari

Temele care nu folosesc alocare dinamica vor avea o depunctare de pana la 50 de puncte din punctajul temei, in functie de gravitate! De asemenea, nu va fi acordat punctajul pe bonus in acest caz!

Nu descarcati imaginile atasate in enunt pentru testare! Acestea nu respecta formatul BMP! Pentru testare folositi numai imaginile puse la dispozitie in arhiva de testare. Imaginile de mai sus au doar caracter informativ.

Listă depunctări

Lista nu este exhaustivă. Se pot aplica chiar depunctări mai mari în cazuri excepționale.