L'esclusiva spirale di moltiplicazione


13

Questo è ispirato alla recente sfida della tabella di moltiplicazione di Calvin's Hobbies .

Scrivi una funzione o un programma che accetta un numero intero Ncome input e stampa o restituisce una spirale di moltiplicazione unica N-per-N. Il codice deve (in teoria) funzionare per N tra 0 e 1000 (emetterlo però può essere difficile). L'output dovrebbe essere equivalente alla tabella prodotta con la seguente procedura:

  1. Compila una tabella di moltiplicazione N per N. Ad esempio per N = 3:

    1 2 3
    2 4 6
    3 6 9
    
  2. Segui una spirale in senso orario dall'angolo in alto a sinistra, notando i numeri che visiti. Quando visiti un numero che hai già visitato, sostituiscilo con 0.

Alcuni esempi potrebbero rendere più chiaro:

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

I numeri si trovano così:

inserisci qui la descrizione dell'immagine

È accettato qualsiasi formato di output ragionevole, ma deve essere una matrice N-by-N, non può essere solo un elenco. Sono accettati formati come quelli indicati di seguito, in quanto vi sono N colonne 1 per N facilmente distinguibili o righe N per 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   

Il codice più corto in byte vince.


Con il mio occhio spio un setaccio modificato di eratostene! Sono abbastanza sicuro che ci sia uno schema che puoi usare qui che ho visto da qualche parte.
Addison Crump,

2
Perché dovrebbe esserci un output per n=0cui non c'è zero nelle tabelle di moltiplicazione. Posso capire n=1sarebbe l'output 1, ma perché includere zero?
Tom Carpenter,

@ TomCarpenter, potrebbe essere stata una decisione sbagliata, ma sapevo che ci sarebbe stata una domanda "Che dire di N = 0?", Quindi ho fatto la regola N = 0 -> 0. In retrospettiva, sarebbe stato meglio dire che N> 0, ma è un po 'troppo tardi ora temo = /
Stewie Griffin

2
@StewieGriffin Hai detto che l'output deve essere una matrice N per N, quindi l'output per n=0dovrebbe essere una matrice 0 per 0, altrimenti la domanda sarebbe incoerente.
alephalpha,

Risposte:


3

J, 22 byte

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

Emette una matrice 0 per 0 per n=0.


8

Mathematica 123122 117 117 92 92 73 byte

Con 24 byte salvati grazie a LegionMammal978 e altri 19 di alephalpha!


Sorprendentemente, in questa tabella, più istanze di qualsiasi numero intero navranno lo stesso ordinamento relativo nella spirale come fanno nella tabella stessa! La prima apparizione di un numero si ntrova proprio nella cella in cui quel numero appare per primo nella tabella (quando si riempie la tabella riga per riga). Ciò significa che l'approccio può ignorare del tutto il vincolo a spirale, poiché non influisce sul risultato. (Vedi spiegazione sotto.)

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

Esempio

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, 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}}


Grid[%]

tble


Spiegazione

Sfruttiamo il fatto che l'ordine a spirale delle posizioni di qualsiasi cifra, n, è lo stesso dell'ordine delle posizioni riga-col restituito dalla funzione Positions,!

La posizione della prima occorrenza di ciascun numero (indipendentemente dal fatto che si ordini dalla spirale o dalla posizione della tabella) sarà il primo elemento restituito da Position. Quella prima occorrenza verrà lasciata così com'è. Le restanti istanze del numero sono sostituite da 0.

Diamo un'occhiata a come funziona, esaminando il caso di n==18. L'idea è di iniziare con la tabella di moltiplicazione:

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

e individuare le posizioni riga-col di ciascun numero. Ad esempio, 18 si trova nella riga 2, Col 9 (la prima istanza); Fila 3, Col 6; Fila 6, Col 3; e Row 9, Col 2. Queste hanno le rispettive posizioni di ordine a spirale {44, 58, 68, 82}.

Position[t, 18]

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

come mostra la tabella seguente.

Tavolo 2

Le ultime 3 istanze di 18 devono essere sostituite da 0. (Useremo grandi zeri blu in grassetto in modo che possano essere facilmente individuati.)

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

table3


C'è un motivo per non scrivere un Function?
LegionMammal978,

1
Ho avuto problemi con le funzioni pure nidificate, ma questa iterazione non lo richiede. Grazie.
DavidC,

Conto 117 byte escluso il newline.
LegionMammal978,


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

2

Python, 99 95 90 89 87 81 byte

Codice golfizzato:

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

Produzione:

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]

grazie @valuah per input byte shave
CSᵠ

2

MATLAB, 96 88 87 86 79 byte

Questo è il codice di 79 byte, che segue le uscite di esempio (per n = 0 in particolare)

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

Questo è di 75 byte, ha lo stesso comportamento ad eccezione di n = 0 che produrrà un array vuoto secondo l'implicazione della domanda (N per N array = 0 per 0 = array vuoto).

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

Questo funziona anche con Octave . Puoi provarlo online qui . Il codice è già stato aggiunto come file denominato "multspiral.m". Quindi al prompt di Ottava, digitare multspirale premere Invio. Dovresti quindi inserire la dimensione della tabella (es. 4). L'output verrà quindi stampato.


Come funziona?

Innanzitutto, questo richiede un numero di input come richiesto (ad es. 6, 4, ecc.)

n=input('');

Quindi gestiamo i casi per n=0e n=1- questi sono trattati in modo speciale in quanto sono due che non seguono la regola che sto usando per generare gli array - in realtà questo potrebbe essere più corto di 5 byte se non per il n=0caso oscuro .

m=+(n>0);

Quindi, per tutti i valori di n>2, eseguiamo alcuni loop fino a quando la matrice non raggiunge la dimensione corretta.

for i=2:n;

In realtà ci sono solo tre semplici differenze tra ne n+1per tutti n>=2. Questi sono:

  1. Una nuova colonna viene aggiunta all'estrema destra nell'array che contiene i numeri n(1:n). Questo è facilmente calcolabile con:

     a=i*(1:i);
    
  2. Tutti gli elementi che verranno aggiunti in quella nuova colonna devono essere rimossi dalla matrice esistente (impostata su zero) poiché verranno sempre più tardi nella spirale rispetto alla nuova colonna. Questo viene rimosso usando un ciclo annidato per impostare tutti gli elementi nella matrice corrente che sono nella nuova colonna su zero.

    for j=a;
        m(m==j)=0;
    end;
    
  3. C'è una nuova riga più in basso per la quale ogni elemento tranne quello che si trova nella nuova colonna sarà zero. Quando la nuova colonna viene aggiunta, a causa degli indici fuori limite che sono stati creati intenzionalmente vengono riempiti automaticamente con 0. Una delle caratteristiche forti di MATLAB è che può far crescere array senza alcuna gestione speciale, quindi possiamo aggiungere semplicemente la nuova riga e colonna con:

    m(1:i,i)=a;
    

Finalmente abbiamo la fine del ciclo for - che una volta raggiunta, la matrice mcontiene il nostro output. Poiché sei flessibile con il tuo formato di output, la matrice viene mostrata semplicemente mcome nuova riga senza punto e virgola

end;
m

Ad esempio, se eseguiamo il programma, inserisci il numero 10, otteniamo il seguente output:

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 byte

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]]

Esempio di utilizzo: f 4-> [[1,2,3,4],[0,0,6,8],[0,0,9,12],[0,0,0,16]].

Ho appena scoperto il Data.Listsmodulo che ha delle belle funzioni su elenchi (come replace) e riesportazioni Data.List, Data.List.Splite Data.List.Extras.


1

Rubino, 67 63 61 byte

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

63 byte

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

67 byte

->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]]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.