Lua, 562 535 529 513 507 504 466 458 Bayt
Şu ana kadarki en büyük golf oyunuma kadar , hala çalışacağım 100 baytı kesebileceğimi düşünüyorum, fakat bunu zaten biraz zaman aldı gibi bir cevap olarak gönderiyorum :). Haklıydım, 100 bayttan fazla veri kesdim! İyileştirilecek çok yer olduğunu sanmıyorum.
bu fonksiyon hücre başına bir karakter içeren bir 2D dizi ile çağrılmalıdır.
@KennyLau ile çalışırken 40 byte kurtarıldı , onun için teşekkürler!
Bravo! 500'ün altında!
function f(m)t=2u=1i=1j=1s=" "::a::if s~=m[i][j]and(i<#m and m[i+1][j]~=s)~=(j<#m[i]and m[i][j+1]~=s)~=(i>1 and m[i-1][j]~=s)~=(j>1 and m[i][j-1]~=s)then goto b end
i,t=i%t+1,#m>t and t==i and t+1or t j=j>1 and j-1or u u=u<#m[1]and j==1 and u+1or u goto a::b::io.write(m[i][j])m[i][j]=s
i,j=i<#m and s~=m[i+1][j]and i+1or i>1 and s~=m[i-1][j]and i-1or i,j<#m[i]and s~=m[i][j+1]and j+1or j>1 and s~=m[i][j-1]and j-1or j
if s==m[i][j]then return end goto b end
Ungolfed
Açıklamalar bir kere golf oynamayı bitirdikten sonra gelecek, şimdilik, size bu kaynak kodun okunabilir bir versiyonunu ödünç vereceğim: D İşte açıklamalar!
Düzenleme: en son değişikliklerle güncellenmedi, güncellemeden önce hala golf. Aynı açıklamalar için de geçerli
function f(m) -- declare the function f which takes a matrix of characters
t=2 -- initialise the treshold for i
-- when looking for the first end of the snake
u=1 -- same thing for j
i,j=1,1 -- initialise i and j,our position in the matrix
s=" " -- shorthand for a space
::a:: -- label a, start of an infinite loop
if m[i][j]~=s -- check if the current character isn't a space
and(i<#m -- and weither it is surrounded by exactly
and m[i+1][j]~=s) -- 3 spaces or not
~=(j<#m[i]
and m[i][j+1]~=s) -- (more explanations below)
~=(i>1
and m[i-1][j]~=s)
~=(j>1
and m[i][j-1]~=s)
then goto b end -- if it is, go to the label b, we found the head
i,t= -- at the same time
i%t+1, -- increment i
#m>t and t==i and t+1or t -- if we checked all chars in the current range, t++
j=j>1 and j-1or u -- decrement j
u=u>#m[1]and j==1 and u+1or u-- if we checked all chars in the current range, u++
goto a -- loop back to label a
::b:: -- label b, start of infinite loop
io.write(m[i][j]) -- output the current char
m[i][j]=s -- and set it to a space
i,j=i<#m -- change i and j to find the next character in the snake
and m[i+1][j]~=s -- this nested ternary is also explained below
and i+1 -- as it takes a lot of lines in comment ^^'
or i>1
and m[i-1][j]~=s
and i-1
or i,
j<#m[i]
and m[i][j+1]~=s
and j+1
or j>1
and m[i][j-1]~=s
and j-1
or j
if m[i][j]==s -- if the new char is a space
then -- it means we finished
return -- exit properly to avoid infinite
end -- printing of spaces
goto b -- else, loop back to label b
end
İşte bu programın nasıl çalıştığı hakkında bazı ayrıntılı açıklamalar geliyor.
Öncelikle, etiketli döngüyü düşünelim, a
sol üst köşeye en yakın ucu bulmamıza izin veriyor. Sonu yoksa sonsuza dek döngüde kalacaktır, ancak bu bir problem değil: D.
4x4 ızgarada, burada yılan mesafeleri (solda) ve bakılma sırası (sağda).
1 2 3 4 | 1 2 4 7
2 3 4 5 | 3 5 8 11
3 4 5 6 | 6 9 12 14
4 5 6 7 | 10 13 15 16
Bu karakterin her biri için, son olarak, iki koşulu kontrol etmek zorundadır: - Boşluk olmamak - Tam olarak 3 boşlukla (veya tam olarak 1 boşluksuz) çevrelenmek
Bu koşullar aşağıdaki kod parçasını kontrol eder
r=m[i][j]~=s
and(i<#m and m[i+1][j]~=s)
==not(j<#m[i] and m[i][j+1]~=s)
==not(i-1>0 and m[i-1][j]~=s)
==not(j-1>0 and m[i][j-1]~=s)
and m[i][j]
or r
-- special note: "==not" is used as an equivalent to xor
-- as Lua doesn't know what is a xor...
Karakterin boşluk olup olmadığını kontrol etmek, ifade ile sağlanır m[i][j]~=s
.
W'nin sadece 1 boşluksuz tarafından çevrilip çevrilmediğini kontrol etmek, çevremiz için yukarıdaki şartları yerine getirerek sağlanır;
m[i+1][j]~=" " ⊕ m[i][j+1]~=" " ⊕ m[i-1][j]~=" " ⊕ m[i][j-1]~=" "
Ve son olarak, yukarıdakilerin tümü doğru olarak değerlendirilirse, üçlü sondakileri geri döndürür and
-> m[i][j]
. Aksi takdirde, izin vermeyelim r
:)
Şimdi yılanın başı bizde, hadi sonuna kadar gidelim! Yılanı yinelemek esas olarak şu iç içe geçmiş üçlüler tarafından sağlanır:
i,j=i<#m and m[i+1][j]~=s and i+1or i-1>0 and m[i-1][j]~=s and i-1or i,
j<#m[i]and m[i][j+1]~=s and j+1or j-1>0 and m[i][j-1]~=s and j-1or j
Eski değerleri saklamak için aptallara ihtiyaç duymamak için yeniden ayarladık i
ve j
aynı anda hem yapıya sahipler, hem de basit koşullar kullanıyorlar, bu yüzden bunları iç içe şeklinde sunacağım, bunları if
okumanıza izin vermeli daha kolayca. :)
i=i<#m and m[i+1][j]~=s and i+1or i-1>0 and m[i-1][j]~=s and i-1or i
Çevrilebilir:
if(i<#m)
then
if(m[i+1][j]~=" ")
then
i=i+1
end
elseif(i-1>0)
then
if(m[i-1][j]~=" ")
then
i=i-1
end
end
Dene!
İşte bunu çalıştırmak için kullandığım kod, çevrimiçi kopyalayıp yapıştırarak test edebilirsiniz .
function f(m)t=2u=1i=1j=1s=" "::a::if s~=m[i][j]and(i<#m and m[i+1][j]~=s)~=(j<#m[i]and m[i][j+1]~=s)~=(i>1 and m[i-1][j]~=s)~=(j>1 and m[i][j-1]~=s)then goto b end
i,t=i%t+1,#m>t and t==i and t+1or t j=j>1 and j-1or u u=u<#m[1]and j==1 and u+1or u goto a::b::io.write(m[i][j])m[i][j]=s
i,j=i<#m and s~=m[i+1][j]and i+1or i>1 and s~=m[i-1][j]and i-1or i,j<#m[i]and s~=m[i][j+1]and j+1or j>1 and s~=m[i][j-1]and j-1or j
if s==m[i][j]then return end goto b end
test1={}
s1={
" tSyrep ",
" r p ",
" in Sli ",
" g Sile",
" Snakes n",
"Ser ylt",
"a eh ilS ",
"fe w t ",
" emo h ",
" Sre ",
}
for i=1,#s1
do
test1[i]={}
s1[i]:gsub(".",function(c)test1[i][#test1[i]+1]=c end)
end
f(test1)