Очистіть картоплю


20

Це картопля:

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

Більш загально, картопля розміром N визначається у вигляді такої форми:

Якщо N парне, це 2 центрировані @символи, за ними 4 центрировані @символи, далі 6 центрованих @символів, аж до N центрованих @символів; потім, N центрованих @символів, а потім символів, орієнтованих на N-2 @, аж до 2.
Якщо N непарне, картопля розміром N формується таким же чином, як описано вище, але ми починаємо з 1 @символу, а не з 2 .

Картопля очищається від шкірки, починаючи з правого верхнього кута, і знімаючи по одному @знаку кожен крок, проходячи проти годинникової стрілки. Наприклад, шкірка картоплі розміром 3 виглядає приблизно так:

 @
@@@
@@@
 @

​
@@@
@@@
 @

 ​
 @@
@@@
 @

  ​
 @@
 @@
 @

 ​
 @@
 @@
 ​

 ​
 @@
 @
 ​

​
 @
 @
 ​

 ​
​
 @
 ​


Виклик

Напишіть програму, яка з урахуванням цілого числа відображає всі етапи лущення картоплі такого розміру.
Доступні пробіли / нові рядки.

Оцінка балів

Це ; виграє найкоротший код у байтах.


Зразки тестових випадків

N = 2

@@
@@

@
@@


@@


 @



N = 7

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


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


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


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


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


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


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


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


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



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



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



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



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



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



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




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




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




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




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




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




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





   @@  
  @@@@ 
  @@@@ 
   @   





   @@  
  @@@@ 
  @@@  
   @   





   @@  
  @@@  
  @@@  
   @   





   @   
  @@@  
  @@@  
   @   






  @@@  
  @@@  
   @   






   @@  
  @@@  
   @   






   @@  
   @@  
   @   






   @@  
   @@  







   @@  
   @   







   @   
   @   








   @   
 ​
 ​
 ​
 ​  


Каталог

На основі Чи є це число простим?


5
Ласкаво просимо до PPCG! Гарне перше питання, до речі.
клісмік

1
Чи дозволено пробіли пробілів / нові рядки?
Loovjo

1
У мене немає навичок сітківки, але мені було б цікаво побачити це - якщо це можливо.
Джеррі Єремія

@JamesHolderness Дякую! Я це зафіксував.
ВармірГадкін

Відповіді:


5

Perl, 129 байт

128 байт коду + -nпрапор.

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

-nEДля запуску вам знадобляться прапори:

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

Пояснення: (Я детальніше їх деталізую, коли в мене є момент)
Перша частина, $p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;генерує початкову картоплю: вона починається із середньої лінії картоплі та додає два рядки при кожній ітерації: один перед попереднім рядком, один після. Зауважте, що $"це пробіл, і оскільки $nвін не ініціалізований, він починається з 0 і $/є новим рядком.

Зверніть увагу на те, say$_=$p;що друкує початкову картоплю під час її зберігання $_(що згодом буде простіше маніпулювати).

Нарешті, say y/A/ /r while s/(^| )A(.*\n? *)@/$1 $2A/m||s/@( *\n?.*)A/A$1 /||s/@/A/очищаємо картоплю. Остання позиція, де @було видалено, містить A(це довільно, це може бути будь-який символ). Отже, кожна ітерація полягає у знаходженні A, заміні його пробілом, а тим часом заміні наступного @на а A. Це робиться завдяки двом регулярним виразам: s/(^| )A(.*\n? *)@/$1 $2A/mколи Aліворуч знаходиться картопля ( A(.*\n? *)@дозволяє рухатись праворуч або вниз), а s/@( *\n?.*)A/A$1 /коли Aсправа - праворуч ( @( *\n?.*)Aдозволяє підніматися вгору або зліва). s/@/A/замінює перше @на A(це ініціалізація). Оскільки у нас завжди є Aрядок, нам потрібно його замінити пробілом під час друку, саме це і y/A/ /rробить.


Просто для очей анімована версія виглядає досить приємно: (для запуску в терміналі це приблизно той самий код, але з clearі 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

1
Це чудово! Мені ніколи не було так весело дивитися анімаційну програму :)
VarmirGadkin

3

Befunge, 319 254 байт

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

Мотивація цього алгоритму полягала в тому, щоб спробувати максимально уникати розгалуження, оскільки один шлях виконання, як правило, легше гольфу. Код складається, таким чином, з двох петель: зовнішня петля, що переходить на рамки процесу лущення, і внутрішня петля, що робить картоплю для кожного кадру.

Цикл візуалізації по суті є просто виведенням послідовності символів, символ для кожної ітерації визначається досить складною формулою, яка приймає номер кадру процесу злучення та індекс вихідної послідовності і повертає або an @, пробіл, або a новий рядок, як потрібно.

Спробуйте в Інтернеті!


1
Ого, це прекрасно.
416E64726577

2

Python 3.5.1, 520 байт

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

Пояснення

Основна ідея: чергувати ітерацію кожного рядка та вилучення крайнього лівого символу та повторення кожного рядка, видаляючи крайній правий символ, поки залишилось @ліве.

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

Загалом сумна спроба прямої процедури.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.