Você pode escrever um programa ou função que receba um número inteiro positivo e ímpar, n
onde n >= 3
, como argumento de função, argumentos de linha de comando ou em STDIN (ou equivalente para o seu sistema), e imprime em STDOUT (ou equivalente do sistema) uma espiral ASCII que gira para dentro no sentido horário, onde a borda superior tem exatamente n
caracteres. A primeira borda direita deve ter n+1
caracteres longos, obviamente. Por exemplo,
Entrada:
11
Resultado:
***********
*
********* *
* * *
* ***** * *
* * * * *
* * * * * *
* * *** * *
* * * *
* ******* *
* *
***********
As capturas:
- Seu programa não deve usar mais que
O(log n)
memória . - Seu programa pode imprimir apenas os caracteres
*
(ASCII 42),(ASCII 32),
<CR>
(ASCII 13) e<LF>
(ASCII 10). - Seu programa deve imprimir a sequência, não retorná-la da função.
- A restrição Big-O está apenas na memória , não há restrições no tempo de execução .
- Uma nova linha à direita é opcional.
- Se seu idioma não suportar tipos inteiros grandes, você não precisará oferecer suporte superior ao que ele suporta, mas não poderá usar isso como um truque para dizer "oh, bem, eu não tenho que suportar acima de X, então eu pode fazer com que uma matriz enorme tenha o tamanho máximo toda vez "
As brechas padrão são proibidas, como de costume.
n
na memória O (1).n
levalog n
bits. À medida quen
aumenta, aumenta o espaço necessário para armazená-lo. Você está dizendo para fazer isso com um número limitado de variáveis?n
?Respostas:
C,
125121 bytesVersão Golfed Isso não tem variável
k
. A variávelk
é usada na versão ungolfed apenas para facilitar a legibilidade. Tambémfor
condicionais ansa são rearranjadas e um conjunto de desnecessário{}
removido. Outro conjunto de{}
pode ser removido migrando paraputs("")
dentro dos colchetes doj
loop na posição de inicialização, mas isso significaria uma nova linha no início da saída, por isso não o fiz.Imprime uma espiral
n
larga porn+1
alta, como no exemplo.Explicação
Basicamente eu reduzir pela metade o valor de
n
(arredondando para baixo) e executar dois loops: um externoi
a partir-n/2-1
den/2+1
imprimir as linhas (i=0
é suprimida então temosn+1
linhas) e outra internaj
a partir de (-n/2
an/2
Usamos para imprimir os caracteres.)expression & 1
Para imprimir listras , e a condiçãoj*j<i*i
para decidir se as listras verticais ou horizontais devem ser impressas (verticais nas laterais onde a magnitude absolutai
é maior e horizontal nas partes superior e inferior). É necessário um ajuste+n
para ajudar na terminação correta, dependendo sen/2
é ímpar ou até.k
é normalmente 1 e fornece um ajuste para o fato de que os valores absolutosi
variam de 1 an/2+1
enquanto os valores absolutosj
variam de 0 an/2
. Sek
fosse sempre 1, obteríamos retângulos concêntricos, mas é invertido para 0 quando,i==j&i<=0
para que uma linha diagonal de células seja invertida, produzindo a espiral.ungolfed no programa de teste
Resultado
fonte
C, 118 bytes
Código antes do golfe final:
A observação principal é que o padrão é quase uma série de quadrados concêntricos. Com algumas rugas leves:
y = x + 1
diagonal precisam ser invertidos até o meio da forma.De resto, o código é simplesmente repetido em todas as posições, calculando a distância Chebyshev do centro para cada posição e emitindo um dos dois caracteres, dependendo da distância ser par ou ímpar. E emitindo uma nova linha para a última posição de cada linha.
Como existem apenas algumas variáveis escalares e os caracteres são emitidos um por um, o uso de memória é obviamente constante.
fonte
p
, acho que você se mete em meta.codegolf.stackexchange.com/q/4939/15599 . Também não tenho certeza sobre a declaração de variáveis globais ao enviar uma função. Obviamente, minha resposta seria 4 bytes mais curta se eu fizesse isso. Eu iniciei uma meta post meta.codegolf.stackexchange.com/q/5532/15599p
.C ++, 926 bytes
Isso não é elegante, mas não ocupa muita memória para grandes n. Além disso, existem (quase certamente) cerca de 20 caracteres que podem ser jogados ainda mais, mas eu não aguento mais olhar para ele.
Breve explicação:
Isso divide as linhas nas espirais em dois tipos: aqueles com ****** no meio e aqueles com \ s \ s \ s \ s \ s no meio. Então fica claro que cada linha é composta por vários "*" s, o meio e alguns "*". Descobrir exatamente quantas coisas é simples se você observar o padrão por tempo suficiente. O difícil era imprimir o centro da espiral que eu basicamente codifiquei usando uma condicional. Isso acabou sendo útil porque as linhas *** e \ s \ s \ s alternam sendo ímpares / pares.
Testes:
Entrada:
55
(Eu acho que os grandes parecem mais legais)Resultado:
Entrada:
3
Resultado:
Nota: Eu não sou um cientista da computação / estudante de CS e não sei como provar que isso usa memória O (log n). Só consigo descobrir o que fazer com base nos links da pergunta. Ficaria muito grato se alguém pudesse confirmar / negar se esta resposta é válida. Minha lógica para a validade dessa resposta é que ela nunca armazena nenhuma variável de tamanho com base em n, exceto na própria entrada. Em vez disso, um loop for que executa n vezes calcula valores inteiros com base em n. Há o mesmo número desses valores, independentemente da entrada.
Nota2: Isso não funciona para n = 1 por causa do meu método de lidar com o meio. Isso seria fácil de corrigir com condicionais; portanto, se alguém tiver alguns caracteres da minha resposta, eu o corrigirei;)
Brinque com ele no ideone.
fonte
n
. Um exemplo típico que não atende ao requisito seria algum tipo de string / buffer / array que contém uma linha completa de saída.n=1
, pois não considero interessante essa caixa especial.Haskell, 151 bytes
Exemplo de uso:
Graças à preguiça de Haskell, isso ocorre na memória constante. Ele usa a abordagem óbvia, ou seja, looping sobre
y
ex
e escolher entre*
e, dependendo
x
resp.y
é par ou ímparn/2
é par ou ímparfonte
Lisp comum - 346
Solução iterativa com uso constante de memória. O exemplo acima faz uso pesado de variáveis
#n=
e de#n#
leitor. Embora existam abordagens mais diretas, aqui comecei com uma função recursiva e a modifiquei para simular recursão comgoto
declarações: isso provavelmente é ilegível.Saída para todos os valores de entrada de 0 a 59 .
Versão recursiva original, com informações de depuração
(nota:
terpri
significanewline
)Por exemplo:
Veja também esta pasta com todos os resultados de 0 a 59 (não é o mesmo que acima, este é mais detalhado).
Versão iterativa, com informações de depuração
fonte
n
e a pilha de chamadas cresce de acordo, mas nesse caso, podemos simular a recursão com dois loops: um comn
decrescente ed
crescente (até n <= 3 ) e outro com ad
redução para zero. Não tenho muito tempo para trabalhar nisso agora, mas tentarei atualizar a resposta de acordo. Aliás, existem maneiras mais diretas de imprimir a espiral, mas foi divertido tentar defini-la recursivamente.CJam, 72 bytes
Esta é uma conversão bastante direta da minha solução C para CJam. Não é tão curto quanto você normalmente esperaria de uma solução CJam, mas essa realmente sofre com a restrição de memória. Os benefícios comuns da criação de resultados na pilha que são descartados automaticamente no final e do uso de operações sofisticadas de lista / sequência de caracteres, todos saem pela janela. Isso gera e gera a solução, um caractere por vez. A pilha contém apenas alguns números inteiros em tempo de execução e está vazia no final.
Embora não seja uma ótima exibição do uso de uma linguagem de golfe, ainda é consideravelmente mais curta que o código C, apenas porque a notação é mais compacta.
Explicação:
fonte