Herkese merhabalar! Bugün 10. gün ile birlikteyiz. Sekizinci ve dokuzuncu günü çok geç saatlerde çözdüğüm için maalesef buraya yazacak vakit bulamadım. Onları da ilerleyen günlerde paylaşacağım. Hadi gelin bu bölümdeki bulmacamıza bakalım:
Hikayemizin adı ‘Katot Işın Tüpü‘ :
Halatlardan kaçınır, nehre dalar ve kıyıya kadar yüzersiniz.
Elfler nehrin yukarısında tekrar buluşmak üzere bir şeyler bağırırlar ama nehir ne dediklerini tam olarak anlayamayacak kadar gürültülüdür. Köprüyü geçmeyi bitirirler ve gözden kaybolurlar.
Elflerin el cihazınızdaki iletişim sistemini çalıştırmaya öncelik vermesinin nedeni bu gibi durumlar olmalı. Çantanızdan çıkarıyorsunuz, ancak ekranındaki büyük bir çatlaktan yavaşça akan su miktarı size muhtemelen hemen işe yaramayacağını söylüyor.
Tabii cihazın video sisteminin yerine geçecek bir şey tasarlayamazsanız! Her ikisi de hassas bir saat devresi tarafından çalıştırılan bir tür katot ışınlı tüp ekran ve basit bir CPU gibi görünüyor. Saat devresi sabit bir hızda tik atıyor; her tik bir döngü olarak adlandırılıyor.
CPU tarafından gönderilen sinyali bulmakla başlayın. CPU’nun 1 değeriyle başlayan tek bir X kaydı vardır. Sadece iki talimatı destekler:
- addx V işleminin tamamlanması iki döngü alır. İki döngüden sonra, X yazmacı V değeri kadar artırılır (V negatif olabilir.)
- noop işleminin tamamlanması bir döngü sürer. Başka bir etkisi yoktur.
CPU, bir şekilde ekrana ne çizeceğini söylemek için bir programdaki (bulmaca girdiniz) bu talimatları kullanır.
Aşağıdaki küçük programı düşünün:
noop addx 3 addx -5Bu programın yürütülmesi aşağıdaki gibi ilerler:
- İlk döngünün başlangıcında noop komutu yürütülmeye başlar. İlk döngü sırasında X 1’dir. İlk döngüden sonra noop komutu hiçbir şey yapmadan yürütmeyi bitirir.
- İkinci döngünün başlangıcında addx 3 komutu yürütülmeye başlar. İkinci döngü sırasında X hala 1’dir.
- Üçüncü döngü sırasında X hala 1’dir. Üçüncü döngüden sonra, addx 3 komutu yürütmeyi bitirir ve X’i 4’e ayarlar.
- Dördüncü çevrimin başlangıcında, addx -5 komutu yürütülmeye başlar. Dördüncü döngü sırasında X hala 4’tür.
- Beşinci döngü sırasında X hala 4’tür. Beşinci döngüden sonra, addx -5 komutu yürütmeyi bitirir ve X’i -1 olarak ayarlar.
Belki yürütme boyunca X kaydının değerine bakarak bir şeyler öğrenebilirsiniz. Şimdilik, 20. döngü sırasında ve bundan sonraki her 40 döngüde (yani 20., 60., 100., 140., 180. ve 220. döngülerde) sinyal gücünü (döngü sayısı ile X kaydının değerinin çarpımı) göz önünde bulundurun.
https://adventofcode.com/2022/day/10
Örneğin, bu daha büyük programı düşünün:
addx 15
addx -11
addx 6
addx -3
addx 5
addx -1
addx -8
addx 13
addx 4
noop
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx 5
addx -1
addx -35
addx 1
addx 24
addx -19
addx 1
addx 16
addx -11
noop
noop
addx 21
addx -15
noop
noop
addx -3
addx 9
addx 1
addx -3
addx 8
addx 1
addx 5
noop
noop
noop
noop
noop
addx -36
noop
addx 1
addx 7
noop
noop
noop
addx 2
addx 6
noop
noop
noop
noop
noop
addx 1
noop
noop
addx 7
addx 1
noop
addx -13
addx 13
addx 7
noop
addx 1
addx -33
noop
noop
noop
addx 2
noop
noop
noop
addx 8
noop
addx -1
addx 2
addx 1
noop
addx 17
addx -9
addx 1
addx 1
addx -3
addx 11
noop
noop
addx 1
noop
addx 1
noop
noop
addx -13
addx -19
addx 1
addx 3
addx 26
addx -30
addx 12
addx -1
addx 3
addx 1
noop
noop
noop
addx -9
addx 18
addx 1
addx 2
noop
noop
addx 9
noop
noop
noop
addx -1
addx 2
addx -37
addx 1
addx 3
noop
addx 15
addx -21
addx 22
addx -6
addx 1
noop
addx 2
addx 1
noop
addx -10
noop
noop
addx 20
addx 1
addx 2
addx 2
addx -6
addx -11
noop
noop
noop
İlginç sinyal güçleri aşağıdaki gibi belirlenebilir:
- döngü sırasında X kaydı 21 değerine sahiptir, dolayısıyla sinyal gücü 20 * 21 = 420’dir. (20. döngü ikinci addx -1’in ortasında gerçekleşir, bu nedenle X kaydının değeri başlangıç değeri olan 1 artı o noktaya kadar olan diğer tüm addx değerleridir: 1 + 15 – 11 + 6 – 3 + 5 – 1 – 8 + 13 + 4 = 21.)
- döngü sırasında, X kaydı 19 değerine sahiptir, bu nedenle sinyal gücü 60 * 19 = 1140’tır.
- döngü sırasında, X kaydı 18 değerine sahiptir, bu nedenle sinyal gücü 100 * 18 = 1800’dür.
- döngü sırasında, X kaydı 21 değerine sahiptir, bu nedenle sinyal gücü 140 * 21 = 2940’tır.
- döngü sırasında, X kaydı 16 değerine sahiptir, bu nedenle sinyal gücü 180 * 16 = 2880’dir.
- döngü sırasında, X kaydı 18 değerine sahiptir, bu nedenle sinyal gücü 220 * 18 = 3960’tır.
Bu sinyal güçlerinin toplamı 13140’tır.
20’nci, 60’ıncı, 100’üncü, 140’ıncı, 180’inci ve 220’nci döngüler sırasındaki sinyal gücünü bulun. Bu altı sinyal gücünün toplamı nedir?
Benim kodum şu şekilde:
with open('instructions.txt', 'r', encoding="utf-8") as f: # Open the file
lines = f.readlines() # Read the lines of the file
lines = [line.strip() for line in lines] # Remove the newline character from each line
ans = 0 # initialize the values
cycle = 0 # initialize the cycle
X = 1 # initialize the X
cycle_list = list(range(20,221,40)) # Our cycles that will be used to calculate the answer
# This is the main loop that is going through the instructions.txt file.
for line in lines:
if line == "noop": # If the line is "noop" then we just increment the cycle
cycle += 1
# print(line)
if cycle in cycle_list: # If the cycle is in the cycle_list then we add the answer
print(X,cycle,line)
ans += X * cycle
else: # If the line is not "noop" then we have to do some calculations
ins, value = line.split(" ") # Split the line into the instruction and the value
# print(ins, value)
cycle += 1 # Increment the cycle
if cycle in cycle_list: # If the cycle is in the cycle_list then we add the answer
print(X,cycle,line)
ans += X * cycle
cycle += 1 # Increment the cycle
if cycle in cycle_list: # If the cycle is in the cycle_list then we add the answer
print(X,cycle,line)
ans += X * cycle
X += int(value)
print(cycle_list)
print(ans)
Öncelikle kendi inputumu instructions.txt adlı bir dosyaya kaydettim. Ve bu dosyayı satır satır okuyabilecek bir for döngüsü yazdım. Eğer satır “noop” değerini içeriyorsa, cycle değişkenini 1 arttırır ve cycle_list dizisinde bulunuyorsa, X ve cycle değişkenlerinin çarpımını ans değişkenine ekler.
Eğer satır “noop” değerini içermiyorsa, satırın ins ve value değerlerini ayırarak değişkenlere atar. Daha sonra, aynı işlemleri tekrarlar (burada farklı olan şey iki kere cycle değişkenini 1 arttırıyoruz. Bunun yerine neden direk 2 arttırmadık derseniz bunun nedeni cycle değerinin 20,40,100,140,180 ve 220 değerini atlamadan bulabilmesini sağlamak) ve X değişkenini value değerini kadar artırır.
Son olarak, cycle_list dizisini ve ans değişkenini ekrana yazar.
İkinci Bölüm:
Görünüşe göre X kaydı bir sprite’ın yatay konumunu kontrol ediyor. Spesifik olarak, sprite 3 piksel genişliğindedir ve X kaydı bu sprite’ın ortasının yatay konumunu ayarlar. (Bu sistemde “dikey konum” diye bir şey yoktur: eğer sprite’ın yatay konumu piksellerini CRT’nin o anda çizdiği yere koyuyorsa, o zaman bu pikseller çizilecektir).
CRT üzerindeki pikselleri sayarsınız: 40 genişlik ve 6 yükseklik. Bu CRT ekranı piksellerin en üst sırasını soldan sağa çizer, sonra bunun altındaki sırayı ve bu şekilde devam eder. Her satırdaki en soldaki piksel 0 konumundadır ve her satırdaki en sağdaki piksel 39 konumundadır.
CPU gibi, CRT de saat devresine yakından bağlıdır: CRT her döngü sırasında tek bir piksel çizer. Ekranın her pikselini bir # olarak temsil edersek, her satırdaki ilk ve son pikselin çizildiği döngüler burada verilmiştir:
Cycle 1 -> ######################################## <- Cycle 40 Cycle 41 -> ######################################## <- Cycle 80 Cycle 81 -> ######################################## <- Cycle 120 Cycle 121 -> ######################################## <- Cycle 160 Cycle 161 -> ######################################## <- Cycle 200 Cycle 201 -> ######################################## <- Cycle 240Bu nedenle, CPU talimatlarını ve CRT çizim işlemlerini dikkatlice zamanlayarak, her piksel çizildiği anda sprite’ın görünür olup olmadığını belirleyebilmeniz gerekir. Sprite, üç pikselinden biri çizilmekte olan piksel olacak şekilde konumlandırılmışsa, ekran yanan bir piksel (#) üretir; aksi takdirde, ekran pikseli karanlık (.) bırakır.
Yukarıdaki daha büyük örnekten ilk birkaç piksel aşağıdaki gibi çizilir:
Sprite position: ###.....................................
Start cycle 1: begin executing addx 15
During cycle 1: CRT draws pixel in position 0
Current CRT row: #
During cycle 2: CRT draws pixel in position 1
Current CRT row: ##
End of cycle 2: finish executing addx 15 (Register X is now 16)
Sprite position: ...............###......................
Start cycle 3: begin executing addx -11
During cycle 3: CRT draws pixel in position 2
Current CRT row: ##.
During cycle 4: CRT draws pixel in position 3
Current CRT row: ##..
End of cycle 4: finish executing addx -11 (Register X is now 5)
Sprite position: ....###.................................
Start cycle 5: begin executing addx 6
During cycle 5: CRT draws pixel in position 4
Current CRT row: ##..#
During cycle 6: CRT draws pixel in position 5
Current CRT row: ##..##
End of cycle 6: finish executing addx 6 (Register X is now 11)
Sprite position: ..........###...........................
Start cycle 7: begin executing addx -3
During cycle 7: CRT draws pixel in position 6
Current CRT row: ##..##.
During cycle 8: CRT draws pixel in position 7
Current CRT row: ##..##..
End of cycle 8: finish executing addx -3 (Register X is now 8)
Sprite position: .......###..............................
Start cycle 9: begin executing addx 5
During cycle 9: CRT draws pixel in position 8
Current CRT row: ##..##..#
During cycle 10: CRT draws pixel in position 9
Current CRT row: ##..##..##
End of cycle 10: finish executing addx 5 (Register X is now 13)
Sprite position: ............###.........................
Start cycle 11: begin executing addx -1
During cycle 11: CRT draws pixel in position 10
Current CRT row: ##..##..##.
During cycle 12: CRT draws pixel in position 11
Current CRT row: ##..##..##..
End of cycle 12: finish executing addx -1 (Register X is now 12)
Sprite position: ...........###..........................
Start cycle 13: begin executing addx -8
During cycle 13: CRT draws pixel in position 12
Current CRT row: ##..##..##..#
During cycle 14: CRT draws pixel in position 13
Current CRT row: ##..##..##..##
End of cycle 14: finish executing addx -8 (Register X is now 4)
Sprite position: ...###..................................
Start cycle 15: begin executing addx 13
During cycle 15: CRT draws pixel in position 14
Current CRT row: ##..##..##..##.
During cycle 16: CRT draws pixel in position 15
Current CRT row: ##..##..##..##..
End of cycle 16: finish executing addx 13 (Register X is now 17)
Sprite position: ................###.....................
Start cycle 17: begin executing addx 4
During cycle 17: CRT draws pixel in position 16
Current CRT row: ##..##..##..##..#
During cycle 18: CRT draws pixel in position 17
Current CRT row: ##..##..##..##..##
End of cycle 18: finish executing addx 4 (Register X is now 21)
Sprite position: ....................###.................
Start cycle 19: begin executing noop
During cycle 19: CRT draws pixel in position 18
Current CRT row: ##..##..##..##..##.
End of cycle 19: finish executing noop
Start cycle 20: begin executing addx -1
During cycle 20: CRT draws pixel in position 19
Current CRT row: ##..##..##..##..##..
During cycle 21: CRT draws pixel in position 20
Current CRT row: ##..##..##..##..##..#
End of cycle 21: finish executing addx -1 (Register X is now 20)
Sprite position: ...................###..................
Programın tamamlanmasına izin vermek CRT’nin aşağıdaki görüntüyü üretmesine neden olur:
##..##..##..##..##..##..##..##..##..##..
###...###...###...###...###...###...###.
####....####....####....####....####....
#####.....#####.....#####.....#####.....
######......######......######......####
#######.......#######.......#######.....
Programınız tarafından verilen görüntüyü oluşturun. CRT’nizde hangi sekiz büyük harf görünüyor?
Benim bu bulmaca için çözümüm şu şekilde:
with open('instructions.txt', 'r', encoding="utf-8") as f: # Open the file
lines = f.readlines() # Read the lines of the file
lines = [line.strip() for line in lines] # Remove the newline character from each line
G = [['?' for _ in range(40)] for _ in range(6)]
ans = 0
x = 1
cycle = 0
cycle_list = list(range(20,221,40))
def handle_tick(cycle, x):
'''It takes the current cycle and the current position of the cart, and updates the global variable `G`
to reflect the current state of the track
Parameters
----------
cycle
the current cycle number
x
the current position of the cart
'''
global ans
global G
t1 = cycle-1
G[t1//40][t1%40] = ('#' if abs(x-(t1%40))<=1 else ' ')
if cycle in cycle_list:
ans += x*cycle
for line in lines:
if line == 'noop':
cycle += 1
handle_tick(cycle,x)
else:
ins, value = line.split(" ")
cycle += 1
handle_tick(cycle,x)
cycle += 1
handle_tick(cycle,x)
x += int(value)
print(ans)
for r in range(6):
print(''.join(G[r]))
Bu seferki kod, döngü içerisinde yapılan işlemleri bir fonksiyon kullanarak daha okunaklı hale getirir. Ayrıca ek olarak, G adlı bir 2 boyutlu dizi oluşturduk. handle_tick() adında bir fonksiyon tanımladık. Ve bu fonksiyon, cycle ve x değişkenlerini alarak global ans ve G değişkenlerini günceller. Bu fonksiyon, cycle ve x değişkenlerini kullanarak G dizisinin bir satırını oluşturur ve cycle değişkeninin cycle_list dizisinde bulunuyorsa, ans değişkenine x ve cycle değişkenlerinin çarpımını ekler. 26. satırdaki kod şunu yapar:
t1,xveGdeğişkenlerini kullanarak bir harita oluşturur. Bu satır,t1değişkeninin değerine göreGadlı iki boyutlu bir dizinin bir elemanını seçer ve bu elemanın değerini belirler. Bu değer,xdeğişkeninin değerine göre belirlenir. Örneğin, eğert1değişkeninin değeri 10 vexdeğişkeninin değeri 5 ise,G[t1//40][t1%40]ifadesiG[0][10]elemanını seçer ve bu elemanın değerini belirler.- Bu değer,
xdeğişkeninin değeriyle karşılaştırılarak belirlenir. Eğerxdeğişkeninin değeri ilet1%40değişkeninin değeri arasındaki fark 1 veya daha küçük ise, bu elemanın değeri “#” olarak ayarlanır. Aksi halde, bu elemanın değeri ” ” (boşluk) olarak ayarlanır.
Daha sonra, kodunuz bir döngü kullanarak dosyadaki her bir satırı tek tek işler. Eğer satır “noop” değerini içeriyorsa, cycle değişkenini 1 arttırır ve handle_tick() fonksiyonunu çağırarak güncel durumu gösterir.
Eğer satır “noop” değerini içermiyorsa, satırın ins ve value değerlerini ayırarak değişkenlere atar. Daha sonra, aynı işlemleri tekrarlar ve x değişkenini value değerini kadar artırır.
Son olarak, ans değişkenini ve G dizisinin satırlarını ekrana yazar.
AoC’un onuncu günü de bu kadardı. Vakit ayırıp okuduğunuz için teşekkür ederim. Eğer yazıyı beğendiyseniz, kodlamaya meraklı arkadaşlarınızla paylaşmayı unutmayın
Herhangi bir sorunuz olursa veya benimle iletişim kurmak isterseniz tüm sosyal medya hesaplarıma bu linke tıklayarak ulaşabilirsiniz. Ayrıca tüm çözümlerimi görebilmeniz için bir github reposu açtım. Bu repoya da bu linkten ulaşabilirsiniz.
