Kartoffel schälen

20

Das ist eine Kartoffel:

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

Im Allgemeinen wird eine Kartoffel der Größe N als die folgende Form definiert:

Wenn N gerade ist, sind es 2 zentrierte @Symbole, gefolgt von 4 zentrierten @Symbolen, gefolgt von 6 zentrierten @Symbolen, bis hin zu N zentrierten @Symbolen; dann N zentrierte @Symbole, gefolgt von N-2 zentrierten @Symbolen, bis hinunter zu 2.
Wenn N ungerade ist, wird eine Kartoffel der Größe N auf dieselbe Weise wie oben beschrieben erzeugt, aber wir beginnen mit 1 @Symbol anstatt mit 2 .

Eine Kartoffel wird geschält, indem man in der oberen rechten Ecke beginnt und @jedes Zeichen gegen den Uhrzeigersinn entfernt. Das Schälen einer Kartoffel der Größe 3 sieht beispielsweise so aus:

 @
@@@
@@@
 @

​
@@@
@@@
 @

 ​
 @@
@@@
 @

  ​
 @@
 @@
 @

 ​
 @@
 @@
 ​

 ​
 @@
 @
 ​

​
 @
 @
 ​

 ​
​
 @
 ​


Herausforderung

Schreiben Sie ein Programm, das bei einer Ganzzahleingabe alle Schritte zum Schälen einer Kartoffel dieser Größe anzeigt.
Nachgestellte Leerzeichen / Zeilenumbrüche sind erlaubt.

Wertung

Das ist ; der kürzeste Code in Bytes gewinnt.


Beispiel-Testfälle

N = 2

@@
@@

@
@@


@@


 @



N = 7

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


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


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


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


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


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


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


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


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



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



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



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



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



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



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




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




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




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




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




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




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





   @@  
  @@@@ 
  @@@@ 
   @   





   @@  
  @@@@ 
  @@@  
   @   





   @@  
  @@@  
  @@@  
   @   





   @   
  @@@  
  @@@  
   @   






  @@@  
  @@@  
   @   






   @@  
  @@@  
   @   






   @@  
   @@  
   @   






   @@  
   @@  







   @@  
   @   







   @   
   @   








   @   
 ​
 ​
 ​
 ​  


Katalog

Basiert auf Ist diese Zahl eine Primzahl?

VarmirGadkin
quelle
5
Willkommen bei PPCG! Schöne erste Frage übrigens.
Clismique
1
Dürfen Leerzeichen / Zeilenumbrüche nachgestellt werden?
Loovjo
1
Ich habe keine Retina-Kenntnisse, aber ich würde mich dafür interessieren - wenn es möglich ist.
Jerry Jeremiah
@ JamesHolderness Danke! Ich habe das behoben.
VarmirGadkin

Antworten:

5

Perl, 129 Bytes

128 Byte Code + -nFlag.

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

Sie benötigen -nEFlags, um es auszuführen:

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

Erklärungen: (Ich werde sie genauer beschreiben, wenn ich einen Moment Zeit habe.)
Der erste Teil $p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;generiert die ursprüngliche Kartoffel: Er beginnt in der Mitte der Kartoffel und fügt bei jeder Iteration zwei Zeilen hinzu: eine vor der vorherigen Zeichenfolge, eine nach. Beachten Sie, dass $"es sich um ein Leerzeichen handelt. Da $nes nicht initialisiert ist, beginnt es bei 0 und $/ist eine neue Zeile.

Beachten Sie viel zu sagen darüber, say$_=$p;dass die ursprüngliche Kartoffel gedruckt wird, während sie aufbewahrt wird $_(was später einfacher zu bearbeiten sein wird).

Zum Schluss say y/A/ /r while s/(^| )A(.*\n? *)@/$1 $2A/m||s/@( *\n?.*)A/A$1 /||s/@/A/die Kartoffel schälen. Die letzte Position, an der a @entfernt wurde, enthält a A(es ist willkürlich, es könnte ein beliebiges Symbol sein). Also besteht jede Iteration darin, das zu finden A, es durch ein Leerzeichen zu ersetzen und in der Zwischenzeit das nächste @durch ein zu ersetzen A. Dies geschieht dank zweier Regex: s/(^| )A(.*\n? *)@/$1 $2A/mWenn sich der Aauf der linken Seite der Kartoffel befindet ( A(.*\n? *)@nach rechts oder unten gehen kann) und s/@( *\n?.*)A/A$1 /wenn sich der Aauf der rechten Seite befindet ( @( *\n?.*)Anach oben oder links gehen kann). s/@/A/Ersetzt das erste @durch ein A(das ist die Initialisierung). Da wir immer ein Ain der Zeichenfolge haben, müssen wir es beim Drucken durch ein Leerzeichen ersetzen y/A/ /r.


Nur für die Augen sieht die animierte Version ziemlich gut aus: (um in einem Terminal zu laufen, ist es ungefähr der gleiche Code, aber mit clearund 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
quelle
1
Das ist toll! Ich hatte noch nie so viel Spaß beim Anschauen eines animierten Programms :)
VarmirGadkin
3

Befunge, 319 254 Bytes

&: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

Die Motivation für diesen Algorithmus bestand darin, Verzweigungen so weit wie möglich zu vermeiden, da ein einziger Ausführungsweg im Allgemeinen einfacher zum Golfen ist. Der Code besteht somit nur aus zwei Schleifen: Die äußere Schleife durchläuft die Frames des Schälprozesses und die innere Schleife gibt die Kartoffel für jedes Frame wieder.

Die Wiedergabeschleife gibt im Wesentlichen nur eine Folge von Zeichen aus, wobei das Zeichen für jede Iteration durch eine ziemlich komplizierte Formel bestimmt wird, die die Rahmennummer des Abziehprozesses und den Index der Ausgabesequenz nimmt und entweder ein @, ein Leerzeichen oder ein zurückgibt Zeilenumbruch nach Bedarf.

Probieren Sie es online!

James Holderness
quelle
1
Wow, das ist wunderschön.
416E64726577
2

Python 3.5.1, 520 Bytes

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

Erläuterung

Grundidee: Wechseln Sie zwischen dem Durchlaufen jeder Zeile und dem Entfernen des Zeichens ganz links und dem Durchlaufen jeder Zeile, wobei das Zeichen ganz rechts entfernt wird, solange noch Zeichen @übrig sind.

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

Insgesamt ein trauriger Versuch eines unkomplizierten Verfahrens.

Bobas_Pett
quelle