A espiral de multiplicação única

13

Este é inspirado no recente desafio da tabuada de Calvin's Hobbies .

Escreva uma função ou programa que aceite um número inteiro Ncomo entrada e imprima ou retorne uma espiral de multiplicação exclusiva N por N. O código deve (em teoria) trabalhar para N entre 0 e 1000 (a saída pode ser difícil). A saída deve ser equivalente à tabela produzida pelo seguinte procedimento:

  1. Preencha uma tabela de multiplicação N por N. Por exemplo, para N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. Siga uma espiral no sentido horário no canto superior esquerdo, observando os números que você visita. Quando você visitar um número que você já visitou, substitua-o por 0.

Alguns exemplos podem deixar mais claros:

n = 0:
0

n = 1:
1

n = 2:       //   Spiral order:
1  2         //   1  2
0  4         //   4  3

n = 3:
1  2  3      //   1  2  3
0  4  6      //   8  9  4
0  0  9      //   7  6  5

n = 4:
1  2  3  4   //   1   2   3   4
0  0  6  8   //  12  13  14   5
0  0  9 12   //  11  16  15   6
0  0  0 16   //  10   9   8   7

n = 5:
1   2   3   4   5
0   0   6   8  10
0   0   9  12  15
0   0   0  16  20
0   0   0   0  25

n = 10:
1   2   3   4   5   6   7   8   9  10
0   0   0   0   0  12  14  16  18  20
0   0   0   0  15   0  21  24  27  30
0   0   0   0   0   0  28  32  36  40
0   0   0   0  25   0  35   0  45  50
0   0   0   0   0   0  42  48  54  60
0   0   0   0   0   0  49  56  63  70
0   0   0   0   0   0   0  64  72  80
0   0   0   0   0   0   0   0  81  90
0   0   0   0   0   0   0   0   0 100

Os números são encontrados assim:

insira a descrição da imagem aqui

Qualquer formato de saída razoável é aceito, mas deve ser uma matriz N por N, não pode ser apenas uma lista. Formatos como os abaixo são aceitos, pois existem N colunas 1 por N facilmente distinguíveis ou linhas N por 1:

[[1 2 3][0 4 6][0 0 9]]   <-- OK

[[1 0 0][2 4 0][3 6 9]]   <-- OK

ans =                     <-- OK
    1  2  3
    0  4  6
    0  0  9   

O código mais curto em bytes vence.

Stewie Griffin
fonte
Olho com os meus olhinhos uma peneira modificada de eratóstenes! Tenho certeza de que há um padrão que você pode usar aqui e que já vi em algum lugar.
Addison Crump
2
Por que haveria uma saída para n=0onde não há zero nas tabelas de multiplicação. Eu posso entender a n=1saída 1, mas por que incluir zero?
Tom Carpenter
@ TomCarpenter, pode ter sido uma decisão ruim, mas eu sabia que haveria uma pergunta "E quanto a N = 0?", Então fiz a regra N = 0 -> 0. Em retrospecto, poderia ter sido melhor dizer que N> 0, mas agora é um pouco tarde demais, tenho medo = /
Stewie Griffin
2
@StewieGriffin Você disse que a saída deve ser uma matriz N por N; portanto, a saída n=0deve ser uma matriz 0 por 0, ou a pergunta seria inconsistente.
Alephalpha #

Respostas:

3

J, 22 bytes

,~$[:(*~:)[:,1*/~@:+i.

Ele gera uma matriz de 0 por 0 para n=0.

alefalpha
fonte
8

Mathematica 123 122 117 98 92 73 bytes

Com 24 bytes salvos, graças a LegionMammal978 e outros 19 por alephalpha!


Surpreendentemente, nesta tabela, várias instâncias de qualquer número inteiro nterão a mesma ordem relativa na espiral que na própria tabela! A primeira aparição de um número nestá na própria célula em que esse número aparece primeiro na tabela (quando um preenche a tabela linha por linha). Isso significa que a abordagem pode desconsiderar completamente a restrição em espiral, pois não afeta o resultado. (Veja a explicação abaixo.)

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&

Exemplo

ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&[10]

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {0, 0, 0, 0, 0, 12, 14, 16, 18, 20}, {0, 0, 0, 0, 15, 0, 21, 24, 27, 30}, {0, 0, 0, 0, 0, 0, 28, 32, 36, 40}, {0, 0, 0, 0, 25, 0, 35, 0, 45, 50}, {0, 0, 0, 0, 0, 0, 42, 48, 54, 60}, {0, 0, 0, 0, 0, 0, 0, 49, 56, 63, 70}, {0, 0, 0, 0, 0, 0, 0, 64, 72, 80}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 90}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}}


Grid[%]

tble


Explicação

Exploramos o fato de que a ordem espiral das posições de qualquer dígito, n, é a mesma que a ordem das posições de linha e coluna retornadas pela função Positions!

O local da primeira ocorrência de cada número (seja um pedido pela espiral ou pela posição da tabela) será o primeiro elemento retornado por Position. Essa célula de primeira ocorrência será deixada como está. As demais instâncias do número são substituídas por 0.

Vamos ver como isso funciona, examinando o caso de n==18. A idéia é começar com a tabuada de multiplicação:

(t = Table[k Range@#, {k, #}] &[10]) // Grid

e localize as posições de linha-col de cada número. Por exemplo, 18 está localizado na Linha 2, Col 9 (a primeira instância); Linha 3, Col 6; Linha 6, Col 3; e Linha 9, Col 2. Estas têm as respectivas posições de ordem espiral {44, 58, 68, 82}.

Position[t, 18]

{{2, 9}, {3, 6}, {6, 3}, {9, 2}}

como mostra a tabela a seguir.

mesa 2

As 3 instâncias finais de 18 precisam ser substituídas por 0. (Usaremos zeros azuis grandes em negrito para que possam ser facilmente identificados.)

ReplacePart[%, {{3, 6}, {6, 3}, {9, 2}} -> Style[0, {Blue, Bold, 16}]]// Grid

Tabela 3

DavidC
fonte
Existe um motivo para não escrever um Function?
precisa
1
Eu estava tendo problemas com funções puras aninhadas, mas essa iteração não exige isso. obrigado.
28415
Conto 117 bytes, excluindo a nova linha.
precisa
Além disso, mais alguns campos de golfe
LegionMammal978 28/11
Um pouco mais de golfe:ReplacePart[t=1##&~Array~{#,#},Join@@(Rest[t~Position~#]&/@Union@@t)->0]&
alephalpha 29/11
2

Python, 99 95 90 89 87 81 bytes

Código de golfe:

n=range(1,input()+1);m=[]
for x in n:l=[(x*y,0)[x*y in m]for y in n];m+=l;print l

Ungolfed:

n=range(1,input()+1);
m=[]
for x in n:
  l=[(x*y,0)[x*y in m]for y in n];
  m+=l;
  print l

Resultado:

10 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
[0, 0, 0, 0, 0, 12, 14, 16, 18, 20]
[0, 0, 0, 0, 15, 0, 21, 24, 27, 30] 
[0, 0, 0, 0, 0, 0, 28, 32, 36, 40]
[0, 0, 0, 0, 25, 0, 35, 0, 45, 50] 
[0, 0, 0, 0, 0, 0, 42, 48, 54, 60]
[0, 0, 0, 0, 0, 0, 49, 56, 63, 70] 
[0, 0, 0, 0, 0, 0, 0, 64, 72, 80]
[0, 0, 0, 0, 0, 0, 0, 0, 81, 90] 
[0, 0, 0, 0, 0, 0, 0, 0, 0, 100]
CSᵠ
fonte
@valuah thanx para barbear de bytes de entrada
CSᵠ
2

MATLAB, 96 88 87 86 79 bytes

Este é o código de 79 bytes, que segue as saídas de exemplo (para n = 0 especificamente)

n=input('');m=+(n>0);for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

Este é de 75 bytes, tem o mesmo comportamento, exceto n = 0, que produzirá uma matriz vazia conforme a implicação da pergunta (matriz N por N = 0 por 0 = matriz vazia).

n=input('');m=[];for i=1:n;a=i*(1:i);for j=a;m(m==j)=0;end;m(1:i,i)=a;end;m

Isso também funciona com o Octave . Você pode experimentá-lo online aqui . O código já foi adicionado como um arquivo chamado 'multspiral.m'. Portanto, no prompt Octave, digite multspirale pressione enter. Você deve inserir o tamanho da tabela (por exemplo, 4). A saída será impressa.


Como funciona?

Primeiro, é necessário um número de entrada conforme necessário (por exemplo, 6, 4, etc.)

n=input('');

Depois, lidamos com casos para n=0e n=1- estes recebem tratamento especial, pois são dois que não seguem a regra que estou usando para gerar as matrizes - na verdade, isso pode ser 5 bytes mais curto se não for o n=0caso obscuro .

m=+(n>0);

Então, para todos os valores de n>2, fazemos algumas repetições até que a matriz cresça no tamanho correto.

for i=2:n;

Na verdade, existem apenas três diferenças simples entre ne n+1para todos n>=2. Esses são:

  1. Uma nova coluna é adicionada mais à direita na matriz que contém os números n(1:n). Isso é facilmente calculado com:

     a=i*(1:i);
    
  2. Quaisquer elementos que serão adicionados nessa nova coluna devem ser removidos da matriz existente (definida como zero), pois sempre aparecerão mais tarde na espiral que a nova coluna. Isso é removido usando um loop for aninhado para definir todos os elementos na matriz atual que estão na nova coluna como zero.

    for j=a;
        m(m==j)=0;
    end;
    
  3. Há uma nova parte inferior da linha na qual cada elemento, exceto o que está na nova coluna, será zero. Quando a nova coluna foi adicionada, devido aos índices fora dos limites criados intencionalmente, são preenchidos automaticamente com 0. Um dos fortes recursos do MATLAB é que ele pode criar matrizes sem nenhum tratamento especial, para que possamos adicionar a nova linha e coluna simplesmente com:

    m(1:i,i)=a;
    

Finalmente, temos o fim do loop for - que, uma vez alcançado, a matriz mcontém nossa saída. Como você é flexível com seu formato de saída, a matriz é mostrada simplesmente tendo mcomo uma nova linha sem ponto e vírgula

end;
m

Como exemplo, se executarmos o programa, digite o número 10, obteremos a seguinte saída:

m =
     1     2     3     4     5     6     7     8     9    10
     0     0     0     0     0    12    14    16    18    20
     0     0     0     0    15     0    21    24    27    30
     0     0     0     0     0     0    28    32    36    40
     0     0     0     0    25     0    35     0    45    50
     0     0     0     0     0     0    42    48    54    60
     0     0     0     0     0     0    49    56    63    70
     0     0     0     0     0     0     0    64    72    80
     0     0     0     0     0     0     0     0    81    90
     0     0     0     0     0     0     0     0     0   100
Tom Carpenter
fonte
1

Haskell, 103 99 bytes

import Data.Lists
f 0=[[0]]
f n=chunksOf n$foldr(\c d->c:replace[c][0]d)[][a*b|a<-[1..n],b<-[1..n]]

Exemplo de uso: f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]].

Eu só descobri o Data.Listsmódulo que tem nice funções em listas (tais como replace) e reexportações Data.List, Data.List.Splite Data.List.Extras.

nimi
fonte
1

Ruby, 67 63 61 bytes

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}

63 bytes

->n{s,x=1..n,{};s.map{|c|s.map{|r|e=x[v=c*r]==1?0:v;x[v]=1;e}}}

67 bytes

->n{s,x=1..n,[];s.map{|c|s.map{|r|e=x.include?(v=c*r)?0:v;x<<v;e}}}

Uso:

->n{s,x=1..n,{};s.map{|c|s.map{|r|x[v=c*r]==1?0:(x[v]=1;v)}}}[10]
=> [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 0, 0, 0, 0, 12, 14, 16, 18, 20], [0, 0, 0, 0, 15, 0, 21, 24, 27, 30], [0, 0, 0, 0, 0, 0, 28, 32, 36, 40], [0, 0, 0, 0, 25, 0, 35, 0, 45, 50], [0, 0, 0, 0, 0, 0, 42, 48, 54, 60], [0, 0, 0, 0, 0, 0, 49, 56, 63, 70], [0, 0, 0, 0, 0, 0, 0, 64, 72, 80], [0, 0, 0, 0, 0, 0, 0, 0, 81, 90], [0, 0, 0, 0, 0, 0, 0, 0, 0, 100]]
Vasu Adari
fonte