Kupas kentangnya

20

Ini adalah kentang:

  @@
 @@@@
@@@@@@
@@@@@@
 @@@@
  @@

Lebih umum, kentang ukuran N didefinisikan sebagai bentuk berikut:

Jika N adalah genap, itu adalah 2 @simbol berpusat , diikuti oleh 4 @simbol berpusat , diikuti oleh 6 @simbol berpusat , semuanya hingga @simbol berpusat N ; kemudian, @simbol berpusat N , diikuti oleh simbol berpusat N-2 @, sampai ke 2.
Jika N aneh, kentang ukuran N dihasilkan dengan cara yang sama seperti yang dijelaskan di atas, tetapi kita mulai dengan 1 @simbol, bukan 2 .

Sebuah kentang dikupas dengan mulai di sudut kanan atas, dan menghapus satu @tanda setiap langkah, dengan cara berlawanan arah jarum jam. Misalnya, mengupas kentang ukuran-3 terlihat seperti ini:

 @
@@@
@@@
 @

​
@@@
@@@
 @

 ​
 @@
@@@
 @

  ​
 @@
 @@
 @

 ​
 @@
 @@
 ​

 ​
 @@
 @
 ​

​
 @
 @
 ​

 ​
​
 @
 ​


Tantangan

Tulis sebuah program, yang, diberi input integer, menampilkan semua langkah mengupas kentang sebesar itu.
Trailing whitespace / newlines diizinkan.

Mencetak gol

Ini adalah ; kode terpendek dalam byte menang.


Contoh Uji Kasus

N = 2

@@
@@

@
@@


@@


 @



N = 7

   @   
  @@@  
 @@@@@ 
@@@@@@@
@@@@@@@
 @@@@@ 
  @@@  
   @   


  @@@  
 @@@@@ 
@@@@@@@
@@@@@@@
 @@@@@ 
  @@@  
   @   


   @@  
 @@@@@ 
@@@@@@@
@@@@@@@
 @@@@@ 
  @@@  
   @   


   @@  
  @@@@ 
@@@@@@@
@@@@@@@
 @@@@@ 
  @@@  
   @   


   @@  
  @@@@ 
 @@@@@@
@@@@@@@
 @@@@@ 
  @@@  
   @   


   @@  
  @@@@ 
 @@@@@@
 @@@@@@
 @@@@@ 
  @@@  
   @   


   @@  
  @@@@ 
 @@@@@@
 @@@@@@
  @@@@ 
  @@@  
   @   


   @@  
  @@@@ 
 @@@@@@
 @@@@@@
  @@@@ 
   @@  
   @   


   @@  
  @@@@ 
 @@@@@@
 @@@@@@
  @@@@ 
   @@  



   @@  
  @@@@ 
 @@@@@@
 @@@@@@
  @@@@ 
   @   



   @@  
  @@@@ 
 @@@@@@
 @@@@@@
  @@@  
   @   



   @@  
  @@@@ 
 @@@@@@
 @@@@@ 
  @@@  
   @   



   @@  
  @@@@ 
 @@@@@ 
 @@@@@ 
  @@@  
   @   



   @@  
  @@@  
 @@@@@ 
 @@@@@ 
  @@@  
   @   



   @   
  @@@  
 @@@@@ 
 @@@@@ 
  @@@  
   @   




  @@@  
 @@@@@ 
 @@@@@ 
  @@@  
   @   




   @@  
 @@@@@ 
 @@@@@ 
  @@@  
   @   




   @@  
  @@@@ 
 @@@@@ 
  @@@  
   @   




   @@  
  @@@@ 
  @@@@ 
  @@@  
   @   




   @@  
  @@@@ 
  @@@@ 
   @@  
   @   




   @@  
  @@@@ 
  @@@@ 
   @@  





   @@  
  @@@@ 
  @@@@ 
   @   





   @@  
  @@@@ 
  @@@  
   @   





   @@  
  @@@  
  @@@  
   @   





   @   
  @@@  
  @@@  
   @   






  @@@  
  @@@  
   @   






   @@  
  @@@  
   @   






   @@  
   @@  
   @   






   @@  
   @@  







   @@  
   @   







   @   
   @   








   @   
 ​
 ​
 ​
 ​  


Katalog

Berdasarkan Apakah nomor ini prima?

VarmirGadkin
sumber
5
Selamat datang di PPCG! Pertanyaan pertama yang bagus.
clismique
1
Apakah membuntuti spasi / baris baru diperbolehkan?
Loovjo
1
Saya tidak memiliki keterampilan Retina tetapi saya akan tertarik melihatnya - jika memungkinkan.
Jerry Jeremiah
@ JamesHolderness Terima kasih! Saya telah memperbaikinya.
VarmirGadkin

Jawaban:

5

Perl, 129 byte

128 byte kode + -nbendera.

$p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;say$_=$p;say y/A/ /r while s/(^| )A(.*
? *)@/$1 $2A/m||s/@( *
?.*)A/A$1 /||s/@/A/

Anda perlu -nEbendera untuk menjalankannya:

perl -nE '$p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;say$_=$p;say y/A/ /r while s/(^| )A(.*
? *)@/$1 $2A/m||s/@( *
?.*)A/A$1 /||s/@/A/' <<< 7

Penjelasan: (Saya akan memerinci lebih banyak ketika saya punya waktu sebentar)
Bagian pertama $p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;,, menghasilkan kentang awal: dimulai dari garis tengah kentang, dan menambahkan dua baris pada setiap iterasi: satu sebelum string sebelumnya, satu setelah. Perhatikan bahwa itu $"adalah spasi, dan karena $ntidak diinisialisasi, itu dimulai pada 0, dan $/merupakan baris baru.

Perhatikan banyak hal tentang say$_=$p;yang mencetak kentang awal saat menyimpannya $_(yang nantinya akan lebih mudah dimanipulasi).

Akhirnya, say y/A/ /r while s/(^| )A(.*\n? *)@/$1 $2A/m||s/@( *\n?.*)A/A$1 /||s/@/A/kupas kentangnya. Posisi terakhir di mana a @dihapus mengandung A(sewenang-wenang, itu bisa berupa simbol apa saja). Jadi setiap iterasi terdiri dalam menemukan A, menggantinya dengan spasi, dan sementara itu menggantikan yang berikutnya @dengan a A. Itu dilakukan berkat dua regex: s/(^| )A(.*\n? *)@/$1 $2A/mketika Aada di sisi kiri kentang ( A(.*\n? *)@memungkinkan untuk pergi di kanan atau ke bawah), dan s/@( *\n?.*)A/A$1 /ketika Aberada di sisi kanan ( @( *\n?.*)Amemungkinkan untuk naik atau di sebelah kiri). s/@/A/mengganti yang pertama @dengan A(itulah inisialisasi). Karena kita selalu memiliki Astring, kita perlu menggantinya dengan spasi saat mencetaknya, itulah yang y/A/ /rterjadi.


Hanya untuk mata , versi animasi terlihat cukup bagus: (untuk dijalankan di terminal, kira-kira kode yang sama tetapi dengan cleardan sleep)

perl -nE 'system(clear);$p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;say$_=$p;select($,,$,,$,,0.1),system(clear),say y/A/ /r while(s/(^| )A(.*\n? *)@/$1 $2A/m||s/@( *\n?.*)A/A$1 /||s/@/A/)&&/@/' <<< 10
Dada
sumber
1
Ini bagus! Saya tidak pernah bersenang-senang menonton program animasi :)
VarmirGadkin
3

Befunge, 319 254 byte

&:00p1+:40p2/10p>:40g%20p:40g/30p\:10g30g`:!00g:2%!-30g-*\30g*+:20g1+v
+10g-::40g\-*2*30g+\-1+00g2%!+\00g2/1++20g-:::40g\-*2*+30g-\4*00g2*-v>
v+1\,-**2+92!-g02g00**84+1`\+*`g02g01\*!`g02g01+**!-g02\`g03:/2g00-4<
>:40g00g:2%+*`!#v_$1+:55+,00g::*1-2/+`#@_0

Motivasi untuk algoritma ini adalah untuk mencoba dan menghindari percabangan sebanyak mungkin, karena satu jalur eksekusi umumnya lebih mudah untuk bermain golf. Dengan demikian kode terdiri dari hanya dua loop: loop luar iterasi di atas frame dari proses peeling, dan loop dalam rendering kentang untuk setiap frame.

Rendering loop pada dasarnya hanya menghasilkan urutan karakter, karakter untuk setiap iterasi ditentukan oleh formula yang agak rumit yang mengambil nomor bingkai dari proses peeling dan indeks urutan output dan mengembalikan salah satu @, spasi, atau baris baru, seperti yang dipersyaratkan.

Cobalah online!

James Holderness
sumber
1
Wow, ini indah.
416E64726577
2

Python 3.5.1, 520 byte

n=int(input())L=lenR=rangeP=printdefg(a,b):f=list(a)ifb:foriinR(L(f)):iff[i]=="@":f[i]=""breakelse:foriinR(L(f)-1,-1,-1):iff[i]=="@":f[i]=""breakreturn"".join(f)l=[]s=(2-n%2n)*(((n-2n%2)/2)1)i=2-n%2whilei<=n:l.append("@"*i)i=2j=L(l)-1whilej>=0:l.append(l[j])j-=1y=[rforrinR(int((L(l)/2)-1),-1,-1)]forhinR(L(y)-1,-1,-1):y.append(y[h])defH(q):foreinR(L(l)):P((""*y[e])q[e])P("")H(l)k=0m=0whilek<s:fortinR(L(l)):if'@'inl[t]andm%2==0:l[t]=g(l[t],True)k=1H(l)if'@'inl[t]andm%2==1:l[t]=g(l[t],False)k=1p=l[:]p.reverse()H(p)m=1

Penjelasan

Ide dasar: Berganti-ganti antara iterasi setiap baris dan menghapus karakter paling kiri dan iterasi setiap baris menghapus karakter paling kanan saat masih ada yang @tersisa.

n=int(input())
L=len
R=range
P=print
# g() returns a line in the potato with leftmost or rightmoxt '@' removed
def g(a,b):
    f=list(a)
    if b:
        for i in R(L(f)):
            if f[i]=="@":
                f[i]=" "
                break
    else:
        for i in R(L(f)-1,-1,-1):
            if f[i]=="@":
                f[i]=" "
                break
    return "".join(f)

l=[]
# s is the total number of '@'s for size n
s=(2-n%2+n)*(((n-2+n%2)/2)+1)
i=2-n%2

# store each line of potato in l
while i<=n:
    l.append("@"*i)
    i+=2
j=L(l)-1
while j>=0:
    l.append(l[j])
    j-=1

# this is used for spacing
y=[r for r in R(int((L(l)/2)-1),-1,-1)]
for h in R(L(y)-1,-1,-1):
    y.append(y[h])

# print the potato
def H(q):
    for e in R(L(l)):
        P((" "*y[e])+q[e])
    P("\n")

H(l)
k=0
m=0

# while there are still '@'s either
# go down the potato removing leftmost '@' 
# go up the potato removing rightmost '@'
while k<s:
    for t in R(L(l)):
        if '@' in l[t] and m%2==0:
            l[t]=g(l[t],True)
            k+=1
            H(l)               
        if '@' in l[t] and m%2==1:
            l[t]=g(l[t],False)
            k+=1
            p=l[:]
            p.reverse()
            H(p)
    m+=1

Secara keseluruhan upaya yang menyedihkan pada prosedur langsung.

Bobas_Pett
sumber