Esta é uma batata:
@@
@@@@
@@@@@@
@@@@@@
@@@@
@@
De maneira mais geral, uma batata tamanho N é definida como a seguinte forma:
Se N for par, são 2 @
símbolos centralizados , seguidos por 4 @
símbolos centralizados , seguidos por 6 @
símbolos centralizados , até N @
símbolos centrais ; então, N @
símbolos centralizados , seguidos por N-2 @
símbolos centrais , até 2.
Se N for ímpar, uma batata tamanho N é gerada da mesma maneira como descrito acima, mas começamos com 1 @
símbolo, em vez de 2 .
Uma batata é descascada começando no canto superior direito e removendo um @
sinal a cada etapa, seguindo no sentido anti-horário. Por exemplo, descascar uma batata tamanho 3 é assim:
@
@@@
@@@
@
@@@
@@@
@
@@
@@@
@
@@
@@
@
@@
@@
@@
@
@
@
@
Desafio
Escreva um programa que, com uma entrada inteira, exiba todas as etapas para descascar uma batata desse tamanho.
Espaços em branco / novas linhas à direita são permitidos.
Pontuação
Isso é código-golfe ; o código mais curto em bytes vence.
Casos de teste de amostra
N = 2
@@
@@
@
@@
@@
@
N = 7
@
@@@
@@@@@
@@@@@@@
@@@@@@@
@@@@@
@@@
@
@@@
@@@@@
@@@@@@@
@@@@@@@
@@@@@
@@@
@
@@
@@@@@
@@@@@@@
@@@@@@@
@@@@@
@@@
@
@@
@@@@
@@@@@@@
@@@@@@@
@@@@@
@@@
@
@@
@@@@
@@@@@@
@@@@@@@
@@@@@
@@@
@
@@
@@@@
@@@@@@
@@@@@@
@@@@@
@@@
@
@@
@@@@
@@@@@@
@@@@@@
@@@@
@@@
@
@@
@@@@
@@@@@@
@@@@@@
@@@@
@@
@
@@
@@@@
@@@@@@
@@@@@@
@@@@
@@
@@
@@@@
@@@@@@
@@@@@@
@@@@
@
@@
@@@@
@@@@@@
@@@@@@
@@@
@
@@
@@@@
@@@@@@
@@@@@
@@@
@
@@
@@@@
@@@@@
@@@@@
@@@
@
@@
@@@
@@@@@
@@@@@
@@@
@
@
@@@
@@@@@
@@@@@
@@@
@
@@@
@@@@@
@@@@@
@@@
@
@@
@@@@@
@@@@@
@@@
@
@@
@@@@
@@@@@
@@@
@
@@
@@@@
@@@@
@@@
@
@@
@@@@
@@@@
@@
@
@@
@@@@
@@@@
@@
@@
@@@@
@@@@
@
@@
@@@@
@@@
@
@@
@@@
@@@
@
@
@@@
@@@
@
@@@
@@@
@
@@
@@@
@
@@
@@
@
@@
@@
@@
@
@
@
@
Catálogo
Baseado em Este número é primo?
<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 290px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 101224; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 12012; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>
Respostas:
Perl, 129 bytes
128 bytes de código +
-n
sinalizador.Você precisará de
-nE
sinalizadores para executá-lo:Explicações: (detalharei mais quando tiver um momento)
A primeira parte
$p=($r=$"x$n++."@"x$_.$/).$p.$r,$_-=2while$_>0;
gera a batata inicial: começa na linha do meio da batata e adiciona duas linhas a cada iteração: uma antes da sequência anterior, uma depois de. Observe que$"
é um espaço e, como$n
não é inicializado, inicia em 0 e$/
é uma nova linha.Observe muito a dizer sobre o
say$_=$p;
que imprime a batata inicial enquanto a armazena$_
(que mais tarde será mais fácil de manipular).Finalmente,
say y/A/ /r while s/(^| )A(.*\n? *)@/$1 $2A/m||s/@( *\n?.*)A/A$1 /||s/@/A/
descasca a batata. A última posição em que um@
foi removido contém umA
(é arbitrário, poderia ter qualquer símbolo). Portanto, cada iteração consiste em encontrar oA
, substituindo-o por um espaço e, enquanto isso, substituindo o próximo@
por aA
. Isso é feito graças a duas expressões regulares:s/(^| )A(.*\n? *)@/$1 $2A/m
quandoA
está no lado esquerdo da batata (A(.*\n? *)@
permite ir à direita ou para baixo) es/@( *\n?.*)A/A$1 /
quandoA
está no lado direito (@( *\n?.*)A
permite subir ou à esquerda).s/@/A/
substitui o primeiro@
por umA
(que é a inicialização). Como sempre temos umA
na string, precisamos substituí-lo por um espaço ao imprimi-lo, é isso quey/A/ /r
acontece.Apenas para os olhos , a versão animada parece bastante agradável: (para rodar em um terminal, é aproximadamente o mesmo código, mas com
clear
esleep
)fonte
Befunge,
319254 bytesA motivação para esse algoritmo foi tentar evitar o máximo possível de ramificação, uma vez que um único caminho de execução é geralmente mais fácil de jogar golfe. O código é, portanto, composto de apenas dois loops: o loop externo iterando sobre os quadros do processo de peeling e o loop interno renderizando a batata para cada quadro.
O loop de renderização está basicamente emitindo apenas uma sequência de caracteres, o caractere para cada iteração sendo determinado por uma fórmula bastante complicada que pega o número do quadro do processo de peeling e o índice da sequência de saída e retorna um
@
, um espaço ou um nova linha, conforme necessário.Experimente online!
fonte
Python 3.5.1, 520 bytes
Explicação
Ideia básica: alterne entre iterar cada linha e remover o caractere mais à esquerda e iterar cada linha removendo o caractere mais à direita enquanto ainda
@
restar s.No geral, uma triste tentativa de um procedimento direto.
fonte