Okunamayan , 2199 2145 2134 2104 2087 2084 bayt
Destekler hem k
/ j
hem de ▲
/ '▼
sözdizimini destekler.
İyi Okunamayan geleneğinde, burada kesme işareti ve çift tırnak arasındaki farkı gizlemek için orantılı fontta biçimlendirilmiş programdır:
' '' '' ''' "" "" "" "" ' '' ' ' '''' ' ' '''' "' '' "' '' ''" ' '' '' ''' "" ' ''' "" ' ''' "" " ' '''" "" "" " ' '' '' '''" "" "" "" " ' '' ' ' '''' " ' '' '' '' ' ' '' '' '' '''' '''" "" "" "" "" " ' '' '''" "" " ' '' ''' '' ''' "" "" ' '' '' ''' "" ' ''' "" ' ''' "" ' '' ' ' '''' ''' "" "" "" ' ''' "" ' ''' "" ' '' "' '' '' '' '' "' '' '' ' ' '' '' '''' ' ' ''''"'" " ' '' ' ' '' '' '' '''' '' '' '''" " ' '''" " ' '''" "" ' '' ''' "" """" ' '''" " ' '''" " ' '''" "" ' '' '' '' '' "' '' '' '' ' ' '''' ' ' ''''" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" ' ''' "" ' ''' "" " ' '''" "' "" " ' '' '' '''" "" ' '' '' '' '' "' '' '' ''" ' '' ' ' '''' '' '' '''"" " ' '' '' '' '''" "" "" "" " ' '' '' '' '''" "" "" "" " ' '' '' '' '''" "" ' '' '' '' '' ' ' '''' '' '' ''' "" " ' '' '' '' '' ' ' '''' ' ' '''' '' "" "" ' '' ' ' '' ' ' '''' ' ' '' ' ' '''' '''' '' '' '' '''' '' '' ''' ''' "" ' ''' "" ' ''' "" " ' '' ' ' '''' ' ' '' ' ' '' '' '''' '''' '' '' "" "" ' '' '' '' "' '' "' '' '' '' '' ' ' ''''" ' '' '' ''"' '' "' '' ''" "" "" ' ''' "" ' ''' "" ' '' '' '' "' '' "' '' ' ' ''''"' '' ' ' ''''"" ' '' '' '' '' ' ' '' '' '' ' ' '''' ' ' '''' ' ' '''' '''' ' ' '''' '''" "" ' '' '' ' ' '' '' '''' ' ' '''' ' ' '''' ''' "" "" "" "" ' '' '' '' "'" " ' '''" " ' '''" "" ' '' ''' "" "" ' '' '' '' '' "' '' '' '' ' ' ''''"' ''' "" " ' '' '' '''" " ' '''" " ' '' ' ' '''' '' '' '''" " ' '''" " ' '' " ' '' ' ' '' '' '''' ' ' '''' '''" "' '' '' '' ' ' ''''" ' '' "' '' '' '' ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" " ' '' '' ' ' '' '' '''' '''"" "" "" "" ' '' '' '' "' '' ' ' '' '''' '' ' ' '' '' '''' ' ' '''' "' ''" ' '' '' '' ''' "" "" "" " ' '''" " ' '''" "" ' '' '' '' '' "' '' '' '' "'" " ' '''" "" ' '' '' ''' "" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' ""' '' "' '' ' ' '' '' '''' ' ' '' ' ' '''' '' '' '''' "' '' ' ' '' '' ''''" ' '' '' '' ' ' '' '' '' '''' ''' "" ' '' '' '' ' ' '''' ''' "" "" " ' '' '' "" "" ' '' '' ''' "" ' ''' "" ' '' ' ' '''' '' '' ''' "" ' ''' "" ' ''"' '' ''' "" "" "" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" " ' '' '' '' ' ''' "" ' '' ' ' '''' '' '' ''' "" ' ''' "" " ' '' '' ' ' '' '' '' '''' '' "" " ' '''" "" ' ''' "" "" "" " ' '''" "" ' '' ''' "" "" "" ' '' " ' '''"" "" "" " ' '' '' '' '''" "" ' '' '' ' ' '' '' '' '''' '' '' '' "' '' ''" "' '' ' ' '' '' '' '''' '' '' ''" ' '' '' '' "' '' ' ' '' '' '''' '' '' '' ' '' ' ' '''' '' '' ''' "" "" "" "' ''"' '' '' ' ' '''' " ' '' '' '''"" ' ''' "" " ' '' '' '' '''" "" "" "" ' ''' "" ' '' ' ' '' '''' '' "' ''" " ' '' '' '''" "' '' ' ' '''' ' ' '''' ' ' '''' '' ''" ' '' ' ' '''' "' '' ' ''' "" " ' '' '' ' ' '' '' '' '''' '' '' '' ' ' '' '' '' '''' '' '' ''" ' '' '' '' '''" "" "" " ' '' '' '' '''" "" ' '' '' '' ''' "" "" "" "" '" "" "" "" ' '' '' '' ''' "" "'"' '' '' '' '' ' ' '' '' '''' ' ' '' '' '''' "" ' ''' "" ' '' '' '' ' ' '' ' ' '' '' '' '''' '' '' '''' "' '' '' ''"' '' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ' ' '''' ' ' ''''"' '' ' ''' "" ' ''' "" ' ''' "" ' ''' "" "" "" " ' '''" "" ' '' '' '' "' '' ''" "" ' '' ' ' '' '' '''' '' '' '' "' '' ' ' '''' "' '' '' ''" ' ''"' "' ''"" "" " ' '''" ""
Bu inanılmaz bir mücadeleydi. Gönderdiğiniz için teşekkür ederiz!
açıklama
Okunamayan'ın yapabileceklerinin neler yapabileceğini hissetmek için Brainfuck'un her iki yönde de sonsuz bir bantla olduğunu hayal edin, ancak bir seferde bir hücreyi hareket ettiren bir bellek işaretçisi yerine, bir işaretçiyi düzenleyerek herhangi bir bellek hücresine erişebilirsiniz. Modulo dahil olmak üzere diğer aritmetik işlemlerin elle yapılması gerektiğine rağmen, bu çözüm oldukça kullanışlı.
İşte programın yönetmen yorumu ile sahte kod olarak:
// Initialize memory pointer. Why 5 will be explained at the very end!
ptr = 5
// FIRST PASS:
// Read all characters from stdin, store them in memory, and also keep track of the
// current line number at each character.
// We need the +1 here so that EOF, which is -1, ends the loop. We increment ptr by 2
// because we use two memory cells for each input character: one contains the actual
// character (which we store here); the other will contain the line number at which the
// character occurs (updated at the end of this loop body).
while ch = (*(ptr += 2) = read) + 1:
// At this point, ch will be one more than the actual value.
// However, the most code-economical way for the following loop is to
// decrement inside the while condition. This way we get one fewer
// iteration than the value of ch. Thus, the +1 comes in handy.
// We are now going to calculate modulo 4 and 5. Why? Because
// the mod 4 and 5 values of the desired input characters are:
//
// ch %5 %4
// ^ 1
// v 2
// k 3
// j 4
// ▲ 0 2
// ▼ 0 0
//
// As you can see, %5 allows us to differentiate all of them except ▲/▼,
// so we use %4 to differentiate between those two.
mod4 = 0 // read Update 2 to find out why mod5 = 0 is missing
while --ch:
mod5 = mod5 ? mod5 + 1 : -4
mod4 = mod4 ? mod4 + 1 : -3
// At the end of this loop, the value of mod5 is ch % 5, except that it
// uses negative numbers: -4 instead of 1, -3 instead of 2, etc. up to 0.
// Similarly, mod4 is ch % 4 with negative numbers.
// How many lines do we need to go up or down?
// We deliberately store a value 1 higher here, which serves two purposes.
// One, as already stated, while loops are shorter in code if the decrement
// happens inside the while condition. Secondly, the number 1 ('""") is
// much shorter than 0 ('""""""""'""").
up = (mod5 ? mod5+1 ? mod5+3 ? 1 : 3 : 2 : mod4 ? 3 : 1)
dn = (mod5 ? mod5+2 ? mod5+4 ? 1 : 3 : 2 : mod4 ? 1 : 3)
// As an aside, here’s the reason I made the modulos negative. The -1 instruction
// is much longer than the +1 instruction. In the above while loop, we only have
// two negative numbers (-3 and -4). If they were positive, then the conditions in
// the above ternaries, such as mod5+3, would have to be mod5-3 etc. instead. There
// are many more of those, so the code would be longer.
// Update the line numbers. The variables updated here are:
// curLine = current line number (initially 0)
// minLine = smallest linenum so far, relative to curLine (always non-positive)
// maxLine = highest linenum so far, relative to curLine (always non-negative)
// This way, we will know the vertical extent of our foray at the end.
while --up:
curLine--
minLine ? minLine++ : no-op
maxLine++
while --dn:
curLine++
minLine--
maxLine ? maxLine-- : no-op
// Store the current line number in memory, but +1 (for a later while loop)
*(ptr + 1) = curLine + 1
// At the end of this, minLine and maxLine are still relative to curLine.
// The real minimum line number is curLine + minLine.
// The real maximum line number is curLine + maxLine.
// The total number of lines to output is maxLine - minLine.
// Calculate the number of lines (into maxLine) and the real minimum
// line number (into curLine) in a single loop. Note that maxLine is
// now off by 1 because it started at 0 and thus the very line in which
// everything began was never counted.
while (++minLine) - 1:
curLine--
maxLine++
// Make all the row numbers in memory positive by adding curLine to all of them.
while (++curLine) - 1:
ptr2 = ptr + 1
while (ptr2 -= 2) - 2: // Why -2? Read until end!
*ptr2++
// Finally, output line by line. At each line, we go through the memory, output the
// characters whose the line number is 0, and decrement that line number. This way,
// characters “come into view” in each line by passing across the line number 0.
while (--maxLine) + 2: // +2 because maxLine is off by 1
ptr3 = 5
while (ptr -= 2) - 5:
print (*((ptr3 += 2) + 1) = *(ptr3 + 1) - 1) ? 32 : *ptr3 // 32 = space
ptr = ptr3 + 2
print 10 // newline
Program mantığı için çok fazla. Şimdi bunu Okunamayan'a çevirmemiz ve birkaç ilginç golf oyunu kullanmamız gerekiyor .
Değişkenler her zaman Sayısal olarak Okunamayan öğesinden çıkarılır (örn . a = 1
Gibi bir şey olur *(1) = 1
). Bazı sayısal değişmezler diğerlerinden daha uzundur; en kısa olanı 1, ardından 2'dir, vb. Ne kadar uzun negatif sayı olduğunu göstermek için, -1 ile 7 arasındaki sayılar:
-1 '""""""""'""""""""'""" 22
0 '""""""""'""" 13
1 '""" 4
2 '""'""" 7
3 '""'""'""" 10
4 '""'""'""'""" 13
5 '""'""'""'""'""" 16
6 '""'""'""'""'""'""" 19
7 '""'""'""'""'""'""'""" 22
Açıkça, # 1 değişkenini kodda en sık meydana gelen olana tahsis etmek istiyoruz . İlk süre döngüsünde, bu kesinlikle mod5
, bu 10 kez geliyor. Ancak mod5
, ilk while döngüsünden sonra artık ihtiyacımız yok, bu yüzden aynı bellek konumunu daha sonra kullandığımız diğer değişkenlere yeniden tahsis edebiliriz. Bunlar ptr2
ve ptr3
. Şimdi değişken toplamda 21 kez referans alınmıştır. (Oluşum sayısını kendiniz saymaya çalışıyorsanız a++
, değeri almak için iki kez, değeri bir kez almak ve bir kez ayarlamak için bir kez saymayı unutmayın .)
Yeniden kullanabileceğimiz tek bir değişken var; Modulo değerlerini hesapladıktan sonra, ch
artık gerekli değildir. up
ve dn
aynı sayıda kez gelince, her ikisi de iyidir. Diyelim birleştirme ch
ile up
.
Bu toplam 8 benzersiz değişken bırakır. 0 ile 7 arasındaki değişkenleri tahsis edebilir ve 8'de hafıza bloğunu başlatabiliriz (karakterleri ve satır numaralarını içeren) 8. 7, length1 kodunda aynı uzunlukta olduğundan, −1 - 6 değişkenlerini de kullanabiliriz ve hafıza bloğunu 7'de başlatabiliriz. Bu şekilde, hafıza bloğunun başlangıç konumuna her referans kodda biraz daha kısadır! Bu bize aşağıdaki görevlerle devam eder:
-1 dn
0 ← ptr or minLine?
1 mod5, ptr2, ptr3
2 curLine
3 maxLine
4 ← ptr or minLine?
5 ch, up
6 mod4
7... [data block]
Şimdi bu en baştaki başlatmayı açıklıyor: 5 çünkü 7 (hafıza bloğunun başlangıcı) eksi 2 (ilk sırada koşulu zorunlu artış). Aynısı son döngüdeki 5'in diğer iki oluşumu için de geçerlidir.
Unutmayın ki, 0 ve 4'ten beri kodun uzunluğu aynı ptr
ve minLine
her iki şekilde de tahsis edilebiliyor. ... Ya da yapabilirler?
Dönerken ikinci sondaki gizemli 2 ne olacak? Bu 6 olmamalı mı? Sadece veri bloğundaki sayıları azaltmak istiyoruz, değil mi? 6'ya ulaştığımızda, veri bloğunun dışındayız ve durmalıyız! Arabellek taşması hatası hatası arızası güvenlik açığı olur!
Durmazsak ne olacağını bir düşün. Değişkenler 6 ve 4'ü azaltırız mod4
. Değişken 6'dır . Bu sadece ilk defa döngüde kullanılır ve artık burada ihtiyaç duyulmaz, bu yüzden zarar vermez. Peki ya değişken 4? Ne düşünüyorsun, değişken 4 olmalı mı ptr
yoksa olmalı minLine
mı? Bu doğru, minLine
artık bu noktada da kullanılmıyor! Böylece, değişken # 4, minLine
güvenle azaltabilir ve zarar vermeyebiliriz!
GÜNCELLEME 1! Fark ile 2145 bayt 2199 golfed dn
olabilir ayrıca ile birleştirilecektir mod5
rağmen mod5
hala için değerin hesaplanmasında kullanılır dn
! Yeni değişken ataması şimdi:
0 ptr
1 mod5, dn, ptr2, ptr3
2 curLine
3 maxLine
4 minLine
5 ch, up
6 mod4
7... [data block]
GÜNCELLEME 2! 2145'ten 2134 bayta kadar olan, mod5
şu anda dn
bir süre döngüsünde 0 olarak sayılan ile aynı değişkende olduğundan, mod5
artık açıkça 0 olarak başlatılması gerekmediğinin farkına varmak suretiyle golf oynadı .
GÜNCELLEME 3! İki şeyi gerçekleştirerek 2134'ten 2104 bayta kadar golf oynadı. “Negatif modülo” fikri için değer o olmasına rağmen ilk mod5
, aynı mantık için geçerli değildir mod4
karşı biz asla testi nedeniyle mod4+2
vb Dolayısıyla değişen mod4 ? mod4+1 : -3
için mod4 ? mod4-1 : 3
2110 bayt götürüyor. İkincisi, mod4
her zaman 0 veya 2 olduğundan, mod4
0 yerine 2 olarak başlatabilir ve iki üçlemi ( mod4 ? 3 : 1
yerine mod4 ? 1 : 3
) tersine çevirebiliriz .
GÜNCELLEME 4! Modulo değerlerini hesaplayan süre döngüsünün her zaman en az bir kez çalıştığını ve böyle bir durumda Okunamayan'ın son ifadenin değerini başka bir ifadede yeniden kullanmanıza izin verdiğini fark ederek 2104'ten 2087 bayta kadar golf tutulur. Böylece, while --ch: [...]; up = (mod5 ? mod5+1 ? [...]
biz şimdi yerine up = ((while --ch: [...]) ? mod5+1 ? [...]
(ve bunun içindeki döngü içinde, mod4
ilk olarak hesaplıyoruz , bu yüzden bu mod5
son ifadedir).
GÜNCELLEME 5! 2087'den 2084 bayta kadar olan ve sabitleri 32
ve 10
(boşluk ve yeni satırları) yazmak yerine 10 sayısını (şimdi kullanılmayan) değişken # 2'de (hadi arayalım ten
) saklayabileceğimi fark ederek . Bunun yerine ptr3 = 5
yazarız ten = (ptr3 = 5) + 5
, sonra 32
olur ten+22
ve print 10
olur print ten
.