Lunghezza del gancio


27

Un diagramma Young è una disposizione di caselle in righe giustificate a sinistra e colonne giustificate in alto. Per ogni casella, tutti gli spazi sopra di essa e alla sua sinistra sono occupati.

XXXXX
XXX
XXX
X

La lunghezza del gancio di una scatola è il numero di scatole alla sua destra nella sua riga e sotto di essa nella sua colonna, contando anche se stessa una volta. Ad esempio, la seconda casella ha una lunghezza del gancio di 6:

X****
X*X
X*X
X

Ecco tutte le lunghezze dei ganci:

86521
532
421
1

Il tuo obiettivo è calcolare il prodotto delle lunghezze del gancio, qui 8*6*5*2*1*5*3*2*4*2*1*1 = 115200.

(Leggi la formula della lunghezza del gancio se sei interessato al motivo per cui questa espressione è importante.)

Input: una raccolta di dimensioni di riga come numeri come [5,3,3,1]o come simbolo unario ripetuto come [[1,1,1,1,1], [1,1,1], [1,1,1], [1]]o "XXXXX XXX XXX X". Puoi aspettarti che l'elenco sia ordinato in ordine crescente o decrescente, come desideri. L'elenco sarà non vuoto e conterrà solo numeri interi positivi.

Output: il prodotto delle lunghezze del gancio, che è un numero intero positivo. Non preoccuparti di overflow o runtime di numeri interi.

Non sono consentiti built-in specifici per diagrammi Young o partizioni intere.

Casi test:

[1] 1
[2] 2
[1, 1] 2
[5] 120
[2, 1] 3
[5, 4, 3, 2, 1] 4465125
[5, 3, 3, 1] 115200
[10, 5] 798336000

Risposte:


13

CJam, 20 19 byte

{ee::+W%}_q~%z%:+:*

Questo prende l'elenco unario in stile CJam in ordine crescente. Per esempio:

[[1] [1 1 1] [1 1 1] [1 1 1 1 1]]

115200

Come funziona

Questa versione è fornita da Dennis e utilizza il fatto che Block ArrayList %a CJam: D funzioni ancora

{       }_             e# Put this block on stack and make a copy
          q~           e# Read the input and evaluate it to put the array of arrays on stack
            %          e# Use the copy of the block and map the array using that block
 ee                    e# Here we are mapping over each unary array in the input. ee converts
                       e# the array to [index value] pair.
   ::+                 e# Add up each index value pair. Now we have the horizontal half of
                       e# hook length for each row
      W%               e# Reverse the array to make sure the count is for blocks to the right
             z%        e# Transpose and do the same mapping for columns
               :+      e# Now we have all the hook lengths. Flatten the array
                 :*    e# Get the product of all hook lengths.

Questa è la versione originale di 20 byte

1q~:,Wf%z:ee{:+)*}f/

Questo include un elenco in stile CJam di dimensioni di riga in ordine crescente. Per esempio:

[1 3 3 5]

115200

Come funziona

Se lo guardiamo, la lunghezza del gancio di ciascun blocco in un diagramma a blocchi Young è la somma dell'indice di quel blocco nella sua riga e colonna, contando all'indietro. cioè avvia l'indice in ogni riga dal lato destro e avvia l'indice in ciascuna colonna dal basso.

Prendiamo l'input in ordine crescente di dimensione delle righe per iniziare facilmente l'indice dal basso in ogni colonna. Innanzitutto, otteniamo l'indice per riga e lo invertiamo. Quindi trasponiamo. Poiché l'ordine delle righe originale è stato invertito, prendendo l'indice in questo diagramma trasposto si otterrà direttamente l'indice dal basso verso l'alto.

Espansione del codice

1                       e# This serves as the initial term for product of hook lengths
 q~                     e# Read the input and eval it to put an array on stack
   :,                   e# For each row-size (N), get an array of [0..N-1]
     Wf%                e# Reverse each row so that each row becomes [N-1..0]
        z               e# Transpose for the calculation of blocks below each block
         :ee            e# Enumerate each row. Convert it into array of [index value] pairs
            {    }f/    e# Apply this mapping block to each cell of each row
             :+         e# Add the index value pair. Here, index is the blocks below the
                        e# block and value is the blocks to the right of it in the Young diag
               )        e# Increment the sum by 1 to account for the block itself
                *       e# Multiply it with the current holding product, starting with 1

Provalo online qui


{ee::+W%}_q~%z%:+:*(19 byte) Formato di input:[[1][1 1 1][1 1 1][1 1 1 1 1]]
Dennis

@Dennis Nice (ab) uso dell'ordine arity per %: P
Ottimizzatore

6

J, 24 byte

*/@,@(1|@-+/\."1++/\)@:>

25 byte (con spiegazione):

*/@,@(+/\."1|@<:@++/\)@:>

Prende l'input come elenco di elenchi ascendenti di cifre unarie simili all'esempio [[1], [1,1,1], [1,1,1], [1,1,1,1,1]].

Uso:

   f=.*/@,@(+/\."1|@<:@++/\)@:>

   f 1;1 1 1;1 1 1;1 1 1 1 1
115200

Metodo

  • Crea una matrice binaria dall'input
  • Calcola le differenze di funzionamento in entrambe le dimensioni.
  • Per ogni cella aggiungi i due risultati, sottrai 1, prendi il valore assoluto (per mappare le celle originariamente zero su 1)
  • Ravel la matrice e prendere il prodotto dei numeri.

Risultati intermedi mostrati sull'input 1 1 1 1 1;1 1 1;1 1 1;1 (5,3,3,1 in unary)( questo è per una versione precedente con lunghezze decrescenti ma usando lo stesso metodo ):

   ]c=.1 1 1 1 1;1 1 1;1 1 1;1
┌─────────┬─────┬─────┬─┐
│1 1 1 1 1│1 1 1│1 1 1│1│
└─────────┴─────┴─────┴─┘

   (>)  c
1 1 1 1 1
1 1 1 0 0
1 1 1 0 0
1 0 0 0 0

   (+/\.@:>)  c
4 3 3 1 1
3 2 2 0 0
2 1 1 0 0
1 0 0 0 0

   (+/\."1@:>)  c
5 4 3 2 1
3 2 1 0 0
3 2 1 0 0
1 0 0 0 0

   ((+/\."1++/\.)@:>)  c
9 7 6 3 2
6 4 3 0 0
5 3 2 0 0
2 0 0 0 0

   ((+/\."1<:@++/\.)@:>)  c
8  6  5  2  1
5  3  2 _1 _1
4  2  1 _1 _1
1 _1 _1 _1 _1

   ((+/\."1|@<:@++/\.)@:>)  c
8 6 5 2 1
5 3 2 1 1
4 2 1 1 1
1 1 1 1 1

   (,@(+/\."1|@<:@++/\.)@:>)  c
8 6 5 2 1 5 3 2 1 1 4 2 1 1 1 1 1 1 1 1

   (*/@,@(+/\."1|@<:@++/\.)@:>)  c
115200

Versione esplicita della stessa lunghezza:

3 :'*/,|<:(+/\."1++/\)>y'

Provalo online qui.


4

Pyth - 21 byte

Sto perdendo molti byte nel calcolo verticale. Mi concentrerò sul golf.

*Fs.em+lf>Td>Qkt-bdbQ

Accetta input come [5, 3, 3, 1].

Provalo qui online .


4

Pyth, 18 byte

*Fsm.e+k-bdf>TdQeQ

Accetta input in ordine crescente, ad esempio [1, 3, 3, 5].

Dimostrazione.


Soluzione alternativa, 19 byte

*Fs.em+s>Rd<Qk-bdbQ

3

Python 2, 89 88 byte

p=j=-1;d={}
for n in input():j+=1;i=0;exec"a=d[i]=d.get(i,j);p*=n-i+j-a;i+=1;"*n
print-p

(Grazie a @xnor per un folle salvataggio di byte combinando p e j)

La d.getsembra un po 'sospetto per me, ma per il resto io sono relativamente contento di questo. Ho provato altri approcci, come la ricorsione e la zippatura, ma questo è l'unico che sono riuscito a ottenere sotto i 100.

Prende input da STDIN come elenco in ordine crescente, ad es [1, 3, 3, 5].


3

Haskell, 68 byte

f[]=1
f g@(h:t)=(h+length t)*f[x-1|x<-g,x>1]
p[]=1
p g@(_:t)=f g*p t

Esempio di utilizzo: p [5,4,3,2,1]->4465125

fesegue la scansione da sinistra a destra moltiplicando la lunghezza dell'hook più esterno con una chiamata ricorsiva a se stessa in cui ogni elemento dell'elenco di input viene ridotto di 1(rilasciandolo quando raggiunge 0). pscansiona dall'alto verso il basso moltiplicando fl'intera lista con pla coda.


2

R, 174 byte

Quindi ... Questa soluzione è piuttosto lunga e probabilmente potrebbe essere più giocata a golf. Ci penserò !

v=c();d=length;m=matrix(-1,l<-d(a<-scan()),M<-max(a));for(i in 1:l)m[i,(1:a[i])]=c(a[i]:1);for(j in 1:M)m[,j]=m[,j]+c((((p=d(which(m[,j]>0)))-1)):0,rep(0,(l-p)));abs(prod(m))

Ungolfed:

v=c()          #Empty vector
d=length       #Alias

m=matrix(-1,l<-d(a<-scan()),M<-max(a)) #Builds a matrix full of `-1`

for(i in 1:l)
    m[i,(1:a[i])]=c(a[i]:1) #Replaces each row of the matrix by `n` to 1, `n` being the 
                            #corresponding input : each number is the number of non-empty
                            #cells at its left + itself

for(j in 1:M)
    m[,j]=m[,j]+c((((p=d(which(m[,j]>0)))-1)):0,rep(0,(l-p)))

    #This part calculates the number of "non-empty" (i.e. without `-1` in a column), -1,
    #because the count for the cell itself is already done.
    # Then, it creates a vector of those count, appending 0's at the end if necessary 
    #(this avoids recycling)

abs(prod(m)) #Outputs the absolute value of the product (because of the `-1`'s)

1

Python 2, 135 128 byte

Questo prende un elenco di tipi Python da stdin:

r=input()
c=[-1]*r[0]
for a in r:
 for b in range(a):c[b]+=1
s=1
y=0
for a in r:
 for x in range(a):s*=a-x+c[x]-y
 y+=1
print s

Questa è un'implementazione molto canonica, ma finora non ho trovato nulla di molto più intelligente. Ho la sensazione che ci saranno soluzioni molto più brevi anche con linguaggi di programmazione "reali".

Otteniamo il numero di caselle in ogni riga come input. Questa soluzione conta innanzitutto il numero di caselle in ciascuna colonna, che viene memorizzata c(in realtà è il conteggio meno 1 per semplificarne l'utilizzo nel calcolo successivo). Quindi scorre su tutte le caselle e moltiplica le lunghezze del gancio. La lunghezza del gancio stesso è banale da calcolare una volta che hai il conteggio delle caselle in ogni riga e colonna.


1
Sembra che non stai usando m?
xnor

Avrei potuto giurare di averlo cancellato! Ricordo di aver notato che lo stavo usando solo una volta e di aver sostituito l'unico utilizzo. Ma poi devo essermi perso per eliminare effettivamente la variabile. :(
Reto Koradi,

1

JavaScript ( ES6 ) 69

Una funzione che accetta una matrice di numeri interi in ordine crescente ordine .

Esegui lo snippet per testare (solo Firefox)

F=x=>x.map(r=>{for(i=-1;++i<r;p[i]=-~p[i])t*=r-i+~~p[i]},p=[],t=1)&&t

// TEST
out=x=>O.innerHTML += x + '\n';

test=[
 {y:[1], h: 1}
,{y:[2], h: 2}
,{y:[1, 1], h: 2}
,{y:[5], h: 120}
,{y:[2, 1], h: 3}
,{y:[5, 4, 3, 2, 1], h: 4465125}
,{y:[5, 3, 3, 1], h: 115200}
,{y:[10, 5], h: 798336000}
]

test.forEach(t=>{ 
  t.y.reverse(); // put in ascending order
  r=F(t.y);
  out((r==t.h? 'Ok':'Fail')+' Y: ['+t.y+'] Result:'+r+' Check:'+t.h)
})  
<pre id=O></pre>


1

Python, 95 91 byte

Questa è un'implementazione Python della risposta Haskell di nimi . Suggerimenti di golf benvenuti.

f=lambda z:z==[]or(z[0]+len(z)-1)*f([i-1for i in z if~-i])
p=lambda z:z==[]or f(z)*p(z[1:])

Benvenuti nel golf di Python! Puoi fare z and _ or 1come z==[]or _quando zè un elenco, usando il fatto che True==1. Le dichiarazioni di funzione di Python sono più formulate di Haskell, quindi spesso dà un buon profitto nel definire una singola funzione ricorsiva che esegue sia i cicli ricorsivi interni che quelli esterni, anche se non so quanto sia fattibile qui.
xnor

@xnor "Benvenuti nel golf di Python"?
Sherlock9,

Oh, scusa, fai golf a Python. Ti associo a In realtà.
xnor

@xnor Molto, molto prima di iniziare a giocare a golf a Python. Sono un po 'seccato che non ricordi: P
Sherlock9,

Non posso parlare per xnor, ma riconosco gli utenti principalmente per il loro avatar.
Dennis
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.