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.


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.


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


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


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]

@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

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.


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]]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.