Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle
Tek tek bitleri ayarlayan, temizleyen, değiştiren ve denetleyen yardımcıları uygulayın; alt küme sıralama problemlerinde alt kümeleri temsil etmek için bit maskeleri kullanın.
Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Coding Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Coding Interview Prep kursu toplamda 4 dersten oluşur.
Bit Maskeleri Nedir
Bit maskesi, başka bir tamsayıdaki belirli bitleri seçmek, değiştirmek veya denetlemek için kullanılan bir tamsayıdır. Maskenin, ilgilendiğiniz konumlarda 1'leri; diğer konumlarda ise 0'ları vardır. Bit düzeyi işleçlerle birlikte kullanılan maskeler, diğer bitleri etkilemeden ayrıntılı bit işlemleri yapmanızı sağlar.
Dört temel maske işlemi şunlardır: ayarlama (bir biti açma), temizleme (bir biti kapatma), tersleme (bir biti değiştirme) ve denetleme (bir bitin 1 olup olmadığını sınama). Her biri, 1 << k maskesiyle farklı bir işleç kullanır: sırasıyla OR, AND-NOT, XOR ve AND.
# The four fundamental bit mask operations
def set_bit(n, k): return n | (1 << k) # OR to set
def clear_bit(n, k): return n & ~(1 << k) # AND-NOT to clear
def toggle_bit(n, k): return n ^ (1 << k) # XOR to toggle
def check_bit(n, k): return (n >> k) & 1 # shift+AND to check
n = 0b10110101 # 181
print(f'n = {bin(n)}')
print(f'set bit 1: {bin(set_bit(n, 1))}')
print(f'clear bit 2: {bin(clear_bit(n, 2))}')
print(f'toggle bit 0: {bin(toggle_bit(n, 0))}')
print(f'check bit 4: {check_bit(n, 4)}')Bit Ayarlama: Biti Açma
bit k'yi ayarlamak (mevcut değerinden bağımsız olarak 1 yapmak) için sayıya 1 << k maskesiyle OR uygulayın. 0 OR 1 = 1 ve 1 OR 1 = 1 olduğundan hedef bit 1 olur. Diğer tüm bitlere 0 ile OR uygulanır ve bu bitler değişmeden kalır.
Bir biti ayarlama işlemini tekrar tekrar uygulamak sonucu değiştirmez; bir kez uygulamakla aynı etkiyi verir. Bit k zaten 1 ise sonuç değişmez. Bu özellik, mevcut durumunu önemsemeden bir özelliği etkinleştirmek istediğiniz bayrak yönetiminde önemlidir.
def set_bit(n, k):
mask = 1 << k
return n | mask
# Set various bits
n = 0b00001010 # 10
print(f'Original: {bin(n)} = {n}')
for k in [0, 3, 6, 7]:
result = set_bit(n, k)
print(f'Set bit {k}: {bin(result)} = {result}')
# Idempotence: setting already-set bit does nothing
n = 0b1111
print(f'\nAlready set: {bin(set_bit(n, 2))} = {bin(n)} (unchanged)')
# Setting multiple bits at once with a combined mask
mask = (1 << 0) | (1 << 2) | (1 << 4) # bits 0, 2, 4
print(f'Set bits 0,2,4: {bin(0 | mask)} = {0 | mask}')Bit Temizleme: Biti Kapatma
bit k'yi temizlemek (mevcut değerinden bağımsız olarak 0 yapmak) için sayıya maskenin tümleyeniyle AND uygulayın: n & ~(1 << k). ~(1 << k) tümleyeni, bit k dışında tüm bitleri 1 olarak içerir; bit k ise 0'dır. 0 ile AND uygulamak hedef biti 0 yapar; 1 ile AND uygulamak diğer tüm bitleri korur.
Ayarlama gibi temizleme işlemini tekrar uygulamak sonucu değiştirmez. Zaten 0 olan bir biti temizlemek sayıyı değiştirmez. Python'da ~(1 << k) her k için doğru çalışır; çünkü Python işaret genişletmesini otomatik olarak yönetir ve tümleyen kavramsal olarak üst bitlerin tamamını 1 yapar.
def clear_bit(n, k):
mask = ~(1 << k) # all 1s except bit k
return n & mask
n = 0b11111111 # 255: all bits set
print(f'Original: {bin(n)} = {n}')
for k in [0, 3, 6, 7]:
result = clear_bit(n, k)
print(f'Clear bit {k}: {bin(result)} = {result}')
# Clear multiple bits with combined mask complement
def clear_bits(n, positions):
mask = 0
for k in positions:
mask |= (1 << k)
return n & ~mask
result = clear_bits(0b11111111, [1, 3, 5, 7])
print(f'Clear bits 1,3,5,7: {bin(result)} = {result}') # 0b01010101 = 85Bit Tersleme: Biti Değiştirme
bit k'yi terslemek (0'dan 1'e veya 1'den 0'a çevirmek) için sayıya 1 << k maskesiyle XOR uygulayın. 1 ile XOR uygulamak biti tersler; 0 ile XOR uygulamak biti değiştirmez. Bu, XOR işleminin tek bir bite uygulanan temel özelliğidir.
Tersleme, dört işlem arasında aynı sonucu vermeyen tek işlemdir; iki kez uygulandığında başlangıçtaki değere dönülür. Bu nedenle, sıkıştırılmış bir tamsayı gösterimindeki açma/kapatma anahtarı veya mantıksal bayrak gibi iki durum arasında geçiş yapan özellikler için idealdir.
def toggle_bit(n, k):
return n ^ (1 << k)
n = 0b10101010 # 170
print(f'Original: {bin(n)}')
print(f'Toggle bit 0: {bin(toggle_bit(n, 0))}') # off->on: 10101011
print(f'Toggle bit 1: {bin(toggle_bit(n, 1))}') # on->off: 10101000
print(f'Toggle bit 7: {bin(toggle_bit(n, 7))}') # on->off: 00101010
# Toggle is its own inverse: two toggles = no change
result = toggle_bit(toggle_bit(n, 3), 3)
print(f'Double toggle bit 3: {bin(result)} == original {bin(n)}? {result == n}')
# Toggle all lower k bits
def toggle_lower_k(n, k):
mask = (1 << k) - 1 # k ones in the lowest positions
return n ^ mask
print(f'Toggle lower 4 bits of {bin(n)}: {bin(toggle_lower_k(n, 4))}')Bit Denetleme: Bir Bitin 1 Olup Olmadığını Sınama
bit k'nin ayarlanmış olup olmadığını denetlemek için n'yi k konumu kadar sağa kaydırın ve 1 ile AND uygulayın: (n >> k) & 1. Bu işlem bit k'yi 0. konuma getirir ve üst bitleri maskeler; geriye 0 (bit k 0'dı) veya 1 (bit k 1'di) kalır. Alternatif olarak Doğru/Yanlış sonucu için bool(n & (1 << k)) kullanabilirsiniz.
Bir biti denetlemek değiştirici değildir; n'yi değiştirmez. Her konumu bağımsız olarak kaydırıp maskeleyerek birden çok biti denetleyebilirsiniz. Bu, alt küme numaralandırmasında ve bit maskesi durumlarıyla dinamik programlamada kullanılan bir sayının bit gösterimi üzerinde yineleme yapmanın temelidir.
def check_bit(n, k):
return (n >> k) & 1
def is_bit_set(n, k):
return bool(n & (1 << k))
n = 0b10110101 # 181
print(f'n = {bin(n)} = {n}')
for k in range(8):
print(f'Bit {k}: {check_bit(n, k)} ({"set" if check_bit(n, k) else "clear"})')
# Count set bits using check_bit
def count_set_bits(n):
return sum(check_bit(n, k) for k in range(n.bit_length()))
print(f'\nSet bits in {n}: {count_set_bits(n)}')
# Get bit representation as list (LSB first)
def to_bit_list(n, width=8):
return [check_bit(n, k) for k in range(width)]
print(f'Bit list (LSB first): {to_bit_list(n)}')Alt Küme Gösterimi için Bit Maskeleri
n bitli bir tamsayı, n öğeli bir kümenin alt kümesini temsil edebilir: öğe k alt kümedeyse bit k 1, değilse 0'dır. Bu yöntem bir alt kümeyi tek bir tamsayıya sıkıştırır ve O(1) işlemlerini mümkün kılar: üyelik denetimi (mask & (1 << k)), öğe ekleme (mask | (1 << k)), öğe çıkarma (mask & ~(1 << k)) ve küme birleşimi/kesişimi (mask1 | mask2 ve mask1 & mask2).
n öğe ile 2^n olası alt küme vardır ve bunların her biri 0 ile 2^n - 1 arasındaki n bitlik bir tamsayıyla benzersiz biçimde temsil edilir. 0 ile 2^n - 1 arasındaki tüm tamsayılar üzerinde yineleme yapmak, tüm alt kümeleri numaralandırır.
# Subset representation with bitmasks
elements = ['A', 'B', 'C', 'D']
n = len(elements)
def subset_from_mask(mask):
return [elements[k] for k in range(n) if (mask >> k) & 1]
# Enumerate all 2^n subsets
print('All subsets:')
for mask in range(1 << n): # 0 to 15 for n=4
print(f' {mask:04b}: {subset_from_mask(mask)}')
# Set operations
mask_ab = 0b0011 # {A, B}
mask_bc = 0b0110 # {B, C}
print(f'\nUnion: {subset_from_mask(mask_ab | mask_bc)}')
print(f'Intersection: {subset_from_mask(mask_ab & mask_bc)}')
print(f'Difference A\\B: {subset_from_mask(mask_ab & ~mask_bc & 0b1111)}')Bir Maskenin Tüm Alt Kümeleri Üzerinde Yineleme
Bit maskeli dinamik programlamada genellikle belirli bir maskenin tüm alt kümeleri üzerinde yineleme yapmanız gerekir. Yaygın bir yöntem, sub = mask ile başlayıp sub 0'a ulaşana kadar sub = (sub - 1) & mask ifadesini kullanarak yineleme yapmaktır. Her yinelemede farklı bir alt maske elde edilir. Tüm maskeler boyunca toplam karmaşıklık O(3^n)'dir; çünkü her öğe dış maskede olup alt maskede olmayabilir, her ikisinde de bulunabilir veya hiçbirinde bulunmayabilir.
Bu teknik, 'diziyi XOR'ları eşit alt kümelere ayırma' veya 'herhangi bir alt kümenin en büyük AND sonucunu bulma' gibi problemlerde karşımıza çıkar. Alt maskeleri verimli biçimde numaralandırabilme, ileri düzey bit maskesi DP'sinin ayırt edici özelliklerinden biridir.
def all_submasks(mask):
submasks = []
sub = mask
while sub > 0:
submasks.append(sub)
sub = (sub - 1) & mask
submasks.append(0) # empty subset
return submasks
mask = 0b1011 # {0, 1, 3}
elements = ['A', 'B', 'C', 'D']
def show(m): return '{' + ','.join(elements[k] for k in range(4) if (m>>k)&1) + '}'
print(f'All submasks of {bin(mask)} = {show(mask)}:')
for sub in all_submasks(mask):
print(f' {bin(sub):6s}: {show(sub)}')
print(f'Total: {len(all_submasks(mask))} submasks (should be 2^{bin(mask).count("1")} = {2**bin(mask).count("1")})')Bit Maskesi DP'si: Gezgin Satıcı Problemine Genel Bakış
Bit maskesi DP'si, durumun ziyaret edilmiş öğelerin bir alt kümesini içerdiği problemleri çözer. Klasik örnek Gezgin Satıcı Problemidir (TSP): n şehri ziyaret eden en düşük maliyetli turu bulun. Durum, dp[mask][city] = mask içindeki şehirleri ziyaret edip city şehrinde sona ermenin en düşük maliyeti şeklindedir. n şehir olduğunda 2^n × n durum bulunur ve zaman karmaşıklığı O(n^2 × 2^n) olur; bu, n ≤ 20 için uygulanabilirdir.
Maske, sıkıştırılmış bir ziyaret kümesi görevi görür. Bitleri ayarlamak, temizlemek ve denetlemek sırasıyla şehirleri ziyaret etmeye, şehirlerden ayrılmaya ve şehirleri sorgulamaya karşılık gelir. Bu, bit maskesi DP'sinin temelidir: durum için bitleri kompakt bir küme olarak kullanmak.
# TSP with bitmask DP
import sys
def tsp(dist):
n = len(dist)
INF = float('inf')
# dp[mask][v] = min cost to reach v having visited cities in mask
dp = [[INF] * n for _ in range(1 << n)]
dp[1][0] = 0 # start at city 0, only city 0 visited (mask=1=0b0001)
for mask in range(1 << n):
for v in range(n):
if dp[mask][v] == INF: continue
if not (mask >> v) & 1: continue # v must be in mask
for u in range(n):
if (mask >> u) & 1: continue # u must not be visited
new_mask = mask | (1 << u)
dp[new_mask][u] = min(dp[new_mask][u], dp[mask][v] + dist[v][u])
full_mask = (1 << n) - 1
return min(dp[full_mask][v] + dist[v][0] for v in range(1, n))
dist = [[0,10,15,20],[10,0,35,25],[15,35,0,30],[20,25,30,0]]
print('TSP minimum tour cost:', tsp(dist)) # should be 80Çok Bitli Maskeleme: Alan Çıkarma
Bazen yalnızca tek bir biti değil, çok bitli bir alanı — bitlerin ardışık bir aralığını — çıkarmanız gerekir. start konumundan start+length-1 konumuna kadar bitleri çıkarmak için length ardışık 1 bitinden oluşan bir maske oluşturun: mask = (1 << length) - 1; ardından (n >> start) & mask ifadesini kullanın.
Bu teknik, birkaç küçük değerin tek bir tamsayıda saklandığı paketlenmiş tamsayı biçimlerini (IP adresleri, piksel verileri veya donanım yazmaçları gibi) ayrıştırırken kullanılır. Örneğin, 16 bitlik bir RGB565 pikselinde kırmızı değer 15-11. bitlerde, yeşil değer 10-5. bitlerde ve mavi değer 4-0. bitlerde saklanır.
def extract_field(n, start, length):
mask = (1 << length) - 1 # e.g., length=3 => mask=0b111
return (n >> start) & mask
# RGB565 pixel format: RRRRRGGGGGGBBBBB
pixel = 0b1111100111001000 # 63432
red = extract_field(pixel, 11, 5) # bits 15-11
green = extract_field(pixel, 5, 6) # bits 10-5
blue = extract_field(pixel, 0, 5) # bits 4-0
print(f'Pixel: {hex(pixel)}')
print(f'Red: {red} ({bin(red)})')
print(f'Green: {green} ({bin(green)})')
print(f'Blue: {blue} ({bin(blue)})')
# Packing values back
def pack_rgb565(r, g, b):
return (r << 11) | (g << 5) | b
packe = pack_rgb565(red, green, blue)
print(f'Repacked: {hex(packed) if (packed := pack_rgb565(red,green,blue)) else 0}')Mülakat Problemlerinde Bit Maskeleri
Bit maskeleri şu mülakat problemi türlerinde yaygın olarak görülür:
- Alt kümeleri listeleme: 0 ile 2^n-1 arasındaki maskeleri kullanarak 2^n alt kümenin tümünde gezinme
- Durum sıkıştırma DP'si: ziyaret edilmiş düğüm veya öğe kümesini DP durumunda bit maskesi olarak kodlama
- İzin sistemleri: READ/WRITE/EXECUTE bayraklarını OR ile birleştirme, AND ile denetleme
- Izgarada ziyaret takibi: küçük ızgaralarda ziyaret edilmiş hücreleri tek bir tamsayıya sığdırma
Bit maskelerinin yararlı olduğunun önemli bir göstergesi şudur: problem bir küçük kümeyi (n ≤ 20 öğe) içerir ve üyelik kombinasyonlarını izlemeniz gerekir. Daha büyük kümeler farklı gösterimler gerektirir.
# Subset sum with bitmask enumeration
def subset_sum_exists(nums, target):
n = len(nums)
for mask in range(1 << n):
total = sum(nums[k] for k in range(n) if (mask >> k) & 1)
if total == target:
subset = [nums[k] for k in range(n) if (mask >> k) & 1]
print(f'Found subset {subset} summing to {target}')
return True
return False
subset_sum_exists([3, 1, 4, 1, 5], 10) # finds a subset summing to 10
# Check if permutation covers all required elements (bitmask approach)
required = 0b11111 # need all 5 elements
visited = 0b01101 # visited elements 0, 2, 3
all_visited = (visited & required) == required
print(f'All required visited: {all_visited}') # False: missing bits 1 and 4Verimli Bit Sayma İpuçları
Bir maskenin 1 bitleri üzerinde gezinirken iki yaygın teknik kullanılır. Kaydırma ve denetleme yöntemi: sağa kaydırıp LSB'yi denetleyin. En düşük anlamlı 1 bitini ayırma yöntemi: en düşük 1 bitini n & -n ile ayırın, işleyin ve ardından n &= n - 1 ile temizleyin. İkinci yöntem yalnızca 1 bitlerini ziyaret eder ve maske seyrek olduğunda daha hızlıdır.
Python'da popcount için bin(n).count('1') veya n.bit_count() (3.10+) da kullanılabilir. Her 1 bitinin konumunu bulmak için en yüksek 1 bitinde n.bit_length() - 1 kullanın.
# Iterate over set bit positions
def set_bit_positions(n):
positions = []
k = 0
while n:
if n & 1:
positions.append(k)
n >>= 1
k += 1
return positions
# Faster: use lowest-set-bit isolation
def set_bit_positions_fast(n):
positions = []
while n:
lsb = n & -n # isolate lowest set bit
k = lsb.bit_length() - 1 # position of that bit
positions.append(k)
n &= n - 1 # clear lowest set bit
return positions
mask = 0b10110101
print(f'Set positions (naive): {set_bit_positions(mask)}')
print(f'Set positions (fast): {set_bit_positions_fast(mask)}')
print(f'Bit count: {bin(mask).count("1")}')
print(f'Highest set bit: {mask.bit_length() - 1}')Kısa Kontrol
Bu dersteki Veri Yapıları & Algoritmalar — Kodlama Mülakatına Hazırlık kavramlarını anlayıp anlamadığınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: temel dört bit maskesi işlemi ayarlama (OR), temizleme (AND-NOT), geçiş yapma (XOR) ve denetlemedir (kaydırma-AND); tamsayılar, her bitin bir öğenin üyeliğini kodladığı alt kümeleri temsil edebilir ve böylece 2^n alt kümenin tümünde gezinmeyi mümkün kılar; ayrıca çok bitli alan çıkarma ve bit maskesi DP'si, daha karmaşık durum kodlamaları için aynı maskeleme ilkelerini kullanır. Sırada, bu derste ve önceki derste öğrendiğiniz teknikleri kullanarak bit saymayı, eksik sayıları ve bitleri tersine çevirmeyi inceleyeceğiz.
Sıkça Sorulan Sorular
“Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle” dersi ücretsiz mi?
Evet — “Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Coding Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Coding Interview Prep kursu toplamda 4 dersten oluşur.
“Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle” dersinde ne öğreneceğim?
Tek tek bitleri ayarlayan, temizleyen, değiştiren ve denetleyen yardımcıları uygulayın; alt küme sıralama problemlerinde alt kümeleri temsil etmek için bit maskeleri kullanın. Coding Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Coding Interview Prep öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Coding Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Coding Interview Prep dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Coding Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Bit Düzeyi İşleçler: AND, OR, XOR, NOT ve Kaydırmalar
- Tek Sayı ve XOR Özellikleri
- Bit Maskeleri: Ayarla, Temizle, Değiştir, Denetle
- Bitleri Sayma, Eksik Sayı ve Bitleri Ters Çevirme