adikti.com
Sudoku Bulmacasını Cebirsel Geometri ile Çözmek

Sudoku Bulmacasını Cebirsel Geometri ile Çözmek

1 Mayıs 2025
6 dk okuma
İçindekiler
index

Giriş: Sudoku ve Matematik

Sudoku, dünya çapında popüler olan basit kurallara sahip bir mantık bulmacasıdır. 9x9’luk bir ızgarada, her satır, her sütun ve her 3x3’lük alt kare 1’den 9’a kadar rakamları tam olarak bir kez içermelidir. Genellikle bu bulmacalar deneme yanılma veya daha sistematik geri izleme (backtracking) algoritmalarıyla çözülür.

Peki ya Sudoku’yu daha soyut matematiksel araçlarla, örneğin cebirsel geometri ile modelleyip çözebileceğimizi söylesem? Bu yazıda, Sudoku kısıtlarını polinom denklemlerine dönüştürerek ve bilgisayar cebiri tekniklerini kullanarak bu bulmacaya nasıl farklı bir bakış açısı getirebileceğimizi inceleyeceğiz. Ayrıca, teorik yaklaşımın aksine pratik bir Python çözücüsüne de göz atacağız.

Sudoku Kurallarını Polinomlara Dönüştürmek

Temel fikir, 9x9=81 hücrenin her birini bir x_i değişkeni (burada i 1’den 81’e kadar) olarak temsil etmektir. Amacımız, bu değişkenlerin Sudoku kurallarına uymasını sağlayan bir denklem sistemi kurmaktır.

Kısıt 1: Her Hücre 1 ile 9 Arasında Bir Değer Almalı

Her x_i değişkeninin {1, 2, …, 9} kümesinden bir değer almasını nasıl zorunlu kılarız? Bunu başarmak için her x_i için şu polinomu tanımlayabiliriz:

F_i(x_i) = (x_i - 1)(x_i - 2)...(x_i - 9)

Bir x_i değerinin 1 ile 9 arasında olması ancak ve ancak F_i(x_i) = 0 denkleminin sağlanması durumunda geçerlidir. Eğer x_i = 5 ise, çarpımın terimlerinden biri (5-5)=0 olacağından F_i(5) = 0 olur. Eğer x_i = 10 ise, hiçbir terim sıfır olmaz ve F_i(10) sıfırdan farklıdır.

Definition (Değer Kısıtlama Polinomu)

Her i (1’den 81’e kadar) için, x_i’nin {1, …, 9} kümesinde bir değer almasını sağlayan polinom F_i(x_i) = (x_i - 1)(x_i - 2)...(x_i - 9) şeklindedir. Sudoku çözümünde F_i(x_i) = 0 olmalıdır.

Kısıt 2: Satır, Sütun ve Bloklarda Benzersizlik

Aynı satırda, sütunda veya 3x3’lük blokta bulunan iki farklı hücrenin (örneğin x_i ve x_j, i farklı j) aynı değeri almaması gerekir. Bu “benzersizlik” kısıtını nasıl ifade ederiz?

Öncelikle, aynı grup içinde yer alan (aynı satır, sütun veya blokta) tüm hücre çiftlerini içeren bir küme tanımlayalım: E = {(i, j) | 1 <= i < j <= 81, x_i ve x_j aynı grupta}

Şimdi, her (i, j) E kümesindeki çift için x_i ve x_j değerlerinin farklı olmasını sağlayan bir polinom denklemi istiyoruz. Orijinal makalede G_ij adında bir polinom tanımlanmış olsa da, bu kısmın matematiksel doğruluğu ve pratikteki uygulanabilirliği tartışmalıdır.

Daha standart ve yaygın bir yaklaşım, x_i ve x_j’nin farklı olması kısıtını, yeni bir yardımcı y_ij değişkeni kullanarak y_ij * (x_i - x_j) - 1 = 0 denklemiyle ifade etmektir. Bu denklem, x_i - x_j ifadesinin sıfır olmamasını, yani x_i ve x_j’nin farklı olmasını garanti eder.

Lemma (Benzersizlik Kısıtı)

Standart cebirsel modellemede, aynı gruptaki x_i ve x_j hücrelerinin farklı değerler alması kısıtı, genellikle her (i, j) çifti için y_ij * (x_i - x_j) = 1 denklemini sağlayacak bir y_ij yardımcı değişkeninin varlığını gerektirerek ifade edilir.

Cebirsel Model: İdealler ve Varyeteler

Tüm Sudoku kısıtlarını bir araya getiren cebirsel yapıyı ideal kullanarak tanımlarız. K[x_1, ..., x_81] polinom halkasında (burada K genellikle Q (rasyonel sayılar) veya C (karmaşık sayılar) gibi bir cisimdir) şu ideali oluştururuz:

I ideali, tüm F_i(x_i) = 0 denklemleri ve her (i,j) E kümesindeki çift için y_ij * (x_i - x_j) - 1 = 0 denklemleri tarafından üretilir.

Bu idealin sıfırlarının kümesi, yani varyetesi V(I), tüm Sudoku kısıtlarını sağlayan (x_1, ..., x_81) vektörlerinin kümesidir. Sudoku bulmacasının çözümleri tam olarak V(I) içindeki tamsayı koordinatlı noktalardır.

Belirli Bir Bulmacayı Çözmek

Genellikle bir Sudoku bulmacasında bazı hücreler başlangıçta doldurulmuştur. Diyelim ki L, {1, …, 81}‘in bir alt kümesi olmak üzere, L içindeki i indisli hücreler için başlangıç değerleri a_i verilmiş olsun. Bu ek bilgiyi modele katmak için ideali genişletiriz:

I_S ideali, I idealine x_i = a_i başlangıç koşullarının (i L’de olmak üzere) eklenmesiyle oluşturulur.

Eğer Sudoku bulmacasının tek bir çözümü (a_1, ..., a_81) varsa, I_S idealinin indirgenmiş Gröbner bazı (reduced Gröbner basis) şu şekilde olacaktır:

\{x_1 - a_1, x_2 - a_2, ..., x_81 - a_81\}

Important (Gröbner Bazı ve Çözüm)

İyi tanımlı (tek çözümlü) bir Sudoku bulmacası için I_S idealinin indirgenmiş Gröbner bazını hesaplamak, doğrudan bulmacanın çözümünü verir. x_i = a_i denklemleri çözümün değerleridir.

Gröbner bazları, polinom denklem sistemlerini çözmek için güçlü bir araçtır ve bilgisayar cebiri sistemleri (CAS) kullanılarak hesaplanabilir.

Teori vs. Pratik: Hesaplama Maliyeti

Bu cebirsel yaklaşım teorik olarak çok şık olsa da, 81 değişkenli bir sistem için Gröbner bazı hesaplamak hesaplama açısından aşırı pahalıdır. Pratikte, Sudoku çözmek için çok daha verimli algoritmalar mevcuttur.

En yaygın ve etkili yöntemlerden biri geri izleme (backtracking) algoritmasıdır.

Pratik Bir Yaklaşım: Python ile Geri İzleme Algoritması

Aşağıda, standart bir geri izleme tekniği kullanarak Sudoku çözen basit bir Python programı örneği bulunmaktadır:

sudoku_solver.py
N = 9
EMPTY = 0
def print_board(board):
"""Sudoku tahtasını formatlı yazdırır."""
print("-------------------------")
for i in range(N):
print("| ", end="")
for j in range(N):
if board[i][j] == EMPTY:
print(". ", end="")
else:
print(f"{board[i][j]} ", end="")
if (j + 1) % 3 == 0:
print("| ", end="")
print()
if (i + 1) % 3 == 0:
print("-------------------------")
def is_valid(board, row, col, num):
"""Bir sayının belirli bir hücreye yerleştirilip yerleştirilemeyeceğini kontrol eder."""
# Satır kontrolü
if num in board[row]:
return False
# Sütun kontrolü
if num in [board[i][col] for i in range(N)]:
return False
# 3x3 blok kontrolü
start_row, start_col = row - row % 3, col - col % 3
for i in range(3):
for j in range(3):
if board[i + start_row][j + start_col] == num:
return False
return True
def find_empty_cell(board):
"""Boş bir hücrenin konumunu bulur (satır, sütun)."""
for r in range(N):
for c in range(N):
if board[r][c] == EMPTY:
return r, c
return None # Boş hücre yoksa
def solve_sudoku(board):
"""Sudoku'yu çözen ana geri izleme fonksiyonu."""
find = find_empty_cell(board)
if not find:
return True # Bulmaca çözüldü
else:
row, col = find
for num in range(1, 10): # 1-9 arası sayıları dene
if is_valid(board, row, col, num):
board[row][col] = num # Geçerliyse yerleştir
if solve_sudoku(board): # Özyinelemeli olarak devam et
return True
# Çözüme götürmediyse geri al (backtrack)
board[row][col] = EMPTY
return False # Bu hücre için geçerli sayı bulunamadı
# Ana Kısım (Örnek Kullanım)
if __name__ == "__main__":
board = [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
]
print("Başlangıçtaki Sudoku:")
print_board(board)
print("\nÇözülüyor...\n")
if solve_sudoku(board):
print("Çözülmüş Sudoku:")
print_board(board)
else:
print("Çözüm bulunamadı.")

Bu algoritma, boş bir hücre bulur, 1’den 9’a kadar geçerli bir sayı yerleştirmeyi dener ve özyinelemeli olarak devam eder. Eğer bir noktada tıkanırsa (geçerli sayı bulunamazsa), önceki adıma döner ve farklı bir sayı dener.

Sonuç

Sudoku bulmacasını cebirsel geometri kullanarak modellemek, probleme farklı ve matematiksel olarak zengin bir bakış açısı sunar. Polinomlar, idealler ve Gröbner bazları gibi kavramlar, Sudoku’nun yapısını derinlemesine anlamamızı sağlar. Ancak, hesaplama verimliliği açısından bu teorik yaklaşım, geri izleme gibi standart algoritmik yöntemlerin gerisinde kalır. Yine de, basit bir mantık bulmacasının ardındaki soyut matematiksel yapıları görmek oldukça etkileyicidir!