Gọt vỏ khoai tây


20

Đây là một củ khoai tây:

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

Tổng quát hơn, một củ khoai tây cỡ N được định nghĩa là hình dạng sau:

Nếu N chẵn, nó là 2 @biểu tượng trung tâm , tiếp theo là 4 @biểu tượng trung tâm , tiếp theo là 6 @biểu tượng trung tâm , tất cả các cách lên đến N @biểu tượng trung tâm ; sau đó, @các ký hiệu N ở giữa , theo sau là các ký hiệu trung tâm N-2 @, giảm xuống còn 2.
Nếu N là số lẻ, một củ khoai tây có kích thước N được tạo ra giống như mô tả ở trên, nhưng chúng ta bắt đầu bằng 1 @ký hiệu, thay vì 2 ký hiệu .

Một củ khoai tây được gọt vỏ bằng cách bắt đầu ở góc trên cùng bên phải, và loại bỏ một @dấu hiệu mỗi bước, đi theo chiều ngược chiều kim đồng hồ. Ví dụ, gọt vỏ khoai tây cỡ 3 trông như thế này:

 @
@@@
@@@
 @

​
@@@
@@@
 @

 ​
 @@
@@@
 @

  ​
 @@
 @@
 @

 ​
 @@
 @@
 ​

 ​
 @@
 @
 ​

​
 @
 @
 ​

 ​
​
 @
 ​


Thử thách

Viết một chương trình, với một đầu vào số nguyên, hiển thị tất cả các bước bóc vỏ khoai tây có kích thước đó.
Trailing khoảng trắng / dòng mới được cho phép.

Chấm điểm

Đây là ; mã ngắn nhất tính bằng byte thắng.


Các trường hợp kiểm tra mẫu

N = 2

@@
@@

@
@@


@@


 @



N = 7

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


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


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


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


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


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


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


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


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



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



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



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



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



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



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




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




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




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




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




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




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





   @@  
  @@@@ 
  @@@@ 
   @   





   @@  
  @@@@ 
  @@@  
   @   





   @@  
  @@@  
  @@@  
   @   





   @   
  @@@  
  @@@  
   @   






  @@@  
  @@@  
   @   






   @@  
  @@@  
   @   






   @@  
   @@  
   @   






   @@  
   @@  







   @@  
   @   







   @   
   @   








   @   
 ​
 ​
 ​
 ​  


Mục lục

Dựa vào số này có phải là số nguyên tố không?


5
Chào mừng đến với PPCG! Nhân tiện, câu hỏi đầu tiên rất hay.
clismique

1
Là dấu trắng khoảng trắng / dòng mới được phép?
Loovjo

1
Tôi không có kỹ năng Retina nhưng tôi sẽ thích thú khi thấy điều đó - nếu có thể.
Jerry Jeremiah

@JamesHoldiness Cảm ơn! Tôi đã sửa nó.
VarmirGadkin

Câu trả lời:


5

Perl, 129 byte

128 byte mã + -ncờ.

$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/

Bạn sẽ cần -nEcờ để chạy nó:

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

Giải thích: (Tôi sẽ trình bày chi tiết hơn khi tôi có một khoảnh khắc)
Phần đầu tiên $p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;, tạo ra khoai tây ban đầu: nó bắt đầu từ dòng giữa của khoai tây và thêm hai dòng ở mỗi lần lặp: một trước chuỗi trước, một sau. Lưu ý rằng đó $"là một khoảng trắng và vì $nkhông được khởi tạo, nó bắt đầu từ 0 và $/là một dòng mới.

Lưu ý nhiều điều để nói về việc say$_=$p;in khoai tây ban đầu trong khi lưu trữ nó $_(sau này sẽ dễ thao tác hơn).

Cuối cùng, say y/A/ /r while s/(^| )A(.*\n? *)@/$1 $2A/m||s/@( *\n?.*)A/A$1 /||s/@/A/gọt vỏ khoai tây. Vị trí cuối cùng @bị xóa có chứa một A(tùy ý, nó có thể là bất kỳ ký hiệu nào). Vì vậy, mỗi lần lặp bao gồm việc tìm A, thay thế nó bằng một khoảng trắng và trong khi đó thay thế tiếp theo @bằng a A. Điều đó được thực hiện nhờ hai regex: s/(^| )A(.*\n? *)@/$1 $2A/mkhi Abên trái khoai tây ( A(.*\n? *)@cho phép đi bên phải hoặc xuống) và s/@( *\n?.*)A/A$1 /khi Abên phải ( @( *\n?.*)Acho phép đi lên hoặc bên trái). s/@/A/thay thế cái đầu tiên @bằng một A(đó là khởi tạo). Vì chúng ta luôn có một Achuỗi, chúng ta cần thay thế nó bằng một khoảng trắng khi in nó, đó là những gì y/A/ /r.


Chỉ cần nhìn bằng mắt , phiên bản hoạt hình trông khá đẹp mắt: (để chạy trong một thiết bị đầu cuối, nó gần giống mã nhưng có clearsleep)

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

1
Điều đó thật tuyệt! Tôi chưa bao giờ có nhiều niềm vui khi xem một chương trình hoạt hình :)
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

Động lực của thuật toán này là cố gắng và tránh phân nhánh càng nhiều càng tốt, vì một đường thực hiện duy nhất thường dễ chơi golf hơn. Do đó, mã này chỉ bao gồm hai vòng lặp: vòng lặp bên ngoài lặp qua các khung của quá trình bóc vỏ và vòng lặp bên trong hiển thị khoai tây cho mỗi khung.

Vòng lặp kết xuất về cơ bản chỉ là xuất ra một chuỗi các ký tự, ký tự cho mỗi lần lặp được xác định bởi một công thức khá phức tạp, lấy số khung của quá trình lột và chỉ số của chuỗi đầu ra và trả về một @, một khoảng trắng hoặc một dòng mới, theo yêu cầu.

Hãy thử trực tuyến!


1
Wow, nó thật đẹp
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

Giải trình

Ý tưởng cơ bản: Thay thế giữa việc lặp xuống từng dòng và loại bỏ ký tự ngoài cùng bên trái và lặp lại từng dòng để loại bỏ ký tự ngoài cùng bên phải trong khi vẫn còn @s.

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

Nhìn chung, một nỗ lực đáng buồn ở một thủ tục đơn giản.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.