Come dovresti sistemare le tue sedie?


20

Insegni a una classe di studenti con preferenze interessanti su come sono sistemate le loro sedie. Esistono 3 requisiti molto specifici per la disposizione delle sedie:

  1. La maggior parte sono disposti in un rettangolo, anche se ciò significa che alcune sedie si svuotano.

  2. Devono esserci meno sedie vuote possibili.

  3. Devono essere il più "quadrati" possibile. Squarey-ness è determinato dalla distanza tra la larghezza e l'altezza del rettangolo, più basso è meglio. Ad esempio, un rettangolo che 4x7ha una quadratura di 3.

Per essere più specifici, il "punteggio" di una disposizione è la distanza tra la larghezza e l'altezza più il numero di sedie che andrebbero vuote.

Facciamo un esempio. Diciamo che hai 13 studenti. Puoi sistemare le sedie in uno di questi modi:

1x13
2x7
3x5
4x4

1x13non è molto quadrato. In effetti, 1 e 13 sono separati da 12, quindi diamo a questa disposizione 12 punti. Ha anche 0 sedie vuote, quindi aggiungiamo 0 punti, dando a questa disposizione un punteggio di 12. Non eccezionale.

2x7è sicuramente meglio. 2 e 7 sono solo 5 a parte, quindi diamo a questa disposizione 5 punti. Tuttavia, se effettivamente disponessi 2 file di sette sedie, ciò richiederebbe 14 sedie, il che significa che una sedia sarebbe vuota. Quindi aggiungiamo un punto, dando a questa disposizione un punteggio di 6.

Potremmo anche fare 3x5. 3 e 5 sono 2 a parte, quindi +2 punti. Ci vogliono 15 sedie, il che significa che avremmo due sedie extra, quindi altri +2 punti, per un punteggio di 4.

Ultima opzione, 4x4. 4 e 4 sono separati da 0, quindi diamo questo +0 punti. 4x4 prende 16 sedie, quindi 3 sedie vanno vuote, per un punteggio totale di 3. Questa è la soluzione ottimale.

In caso di pareggio, la soluzione ottimale è quella con meno sedie vuote.

La sfida

È necessario scrivere un programma o una funzione che accetta un numero intero e genera la disposizione ottimale delle sedie per quel numero di studenti. IO può essere in qualsiasi formato ragionevole. Ecco un esempio di output per un numero qualsiasi di studenti da 1 a 100:

1:  (1, 1)
2:  (1, 2)
3:  (2, 2)
4:  (2, 2)
5:  (2, 3)
6:  (2, 3)
7:  (3, 3)
8:  (3, 3)
9:  (3, 3)
10: (2, 5)
11: (3, 4)
12: (3, 4)
13: (4, 4)
14: (4, 4)
15: (4, 4)
16: (4, 4)
17: (3, 6)
18: (3, 6)
19: (4, 5)
20: (4, 5)
21: (3, 7)
22: (5, 5)
23: (5, 5)
24: (5, 5)
25: (5, 5)
26: (4, 7)
27: (4, 7)
28: (4, 7)
29: (5, 6)
30: (5, 6)
31: (4, 8)
32: (4, 8)
33: (6, 6)
34: (6, 6)
35: (6, 6)
36: (6, 6)
37: (5, 8)
38: (5, 8)
39: (5, 8)
40: (5, 8)
41: (6, 7)
42: (6, 7)
43: (5, 9)
44: (5, 9)
45: (5, 9)
46: (7, 7)
47: (7, 7)
48: (7, 7)
49: (7, 7)
50: (5, 10)
51: (6, 9)
52: (6, 9)
53: (6, 9)
54: (6, 9)
55: (7, 8)
56: (7, 8)
57: (6, 10)
58: (6, 10)
59: (6, 10)
60: (6, 10)
61: (8, 8)
62: (8, 8)
63: (8, 8)
64: (8, 8)
65: (6, 11)
66: (6, 11)
67: (7, 10)
68: (7, 10)
69: (7, 10)
70: (7, 10)
71: (8, 9)
72: (8, 9)
73: (7, 11)
74: (7, 11)
75: (7, 11)
76: (7, 11)
77: (7, 11)
78: (9, 9)
79: (9, 9)
80: (9, 9)
81: (9, 9)
82: (7, 12)
83: (7, 12)
84: (7, 12)
85: (8, 11)
86: (8, 11)
87: (8, 11)
88: (8, 11)
89: (9, 10)
90: (9, 10)
91: (7, 13)
92: (8, 12)
93: (8, 12)
94: (8, 12)
95: (8, 12)
96: (8, 12)
97: (10, 10)
98: (10, 10)
99: (10, 10)
100: (10, 10)

Come al solito, si tratta di code-golf, quindi si applicano scappatoie standard e il vincitore è la risposta più breve in byte.


Risposte:


8

Gelatina , 16 15 14 byte

÷RĊ,Rµạ/+PỤḢịZ

Provalo online! o verifica tutti i casi di test .

Come funziona

÷RĊ,Rµạ/+PỤḢịZ  Main link. Argument: n

 R              Range; yield [1, ..., n].
÷               Divide n by each k in [1, ..., n].
  Ċ             Ceil; round the quotients up to the nearest integer.
    R           Range; yield [1, ..., n].
   ,            Pair; yield A := [[ ⌈n ÷ 1⌉, ..., ⌈n ÷ n⌉ ], [ 1, ..., n ]].
     µ          Begin a new, monadic chain. Argument: A
      ạ/        Reduce A by absolute difference.
                This yields [ |⌈n ÷ 1⌉ - 1|, ..., |⌈n ÷ n⌉ - n| ].
         P      Product; reduce A by multiplication.
                This yields [ ⌈n ÷ 1⌉ × 1, ..., ⌈n ÷ n⌉ × n].
       +        Add the results to left and right, element by element. This yields
                [ |⌈n ÷ 1⌉ - 1| + ⌈n ÷ 1⌉ × 1, ..., |⌈n ÷ n⌉ - n| + ⌈n ÷ n⌉ × n ].
          Ụ     Grade up; sort the indices of the list of sums by their values.
           Ḣ    Head; extract the first value, which corresponds to the smallest
                sum. Grading up is stable, so this selects the first index of all
                with the smallest sum in case of a tie. In this event, the first
                index will have the highest absolute difference of all indices
                with the smallest sum, meaning that it has the lowest product and,
                therefore, the lowest number of empty chairs.
             Z  Zip; transpose A's rows and columns.
                This yields [[ ⌈n ÷ 1⌉, 1 ], ..., [ ⌈n ÷ n⌉, n ]].
            ị   Retrieve the pair at that index.

4

Python 2, 68 byte

lambda n:min((abs(~i-n/~i)+n/~i*~i,i+1,0-n/~i)for i in range(n))[1:]

Equivalente al più "ovvio":

lambda n:min([(i+1,0-n/~i)for i in range(n)],key=lambda(p,q):abs(p-q)+p*q)

Puoi salvare tre byte ripetendo range(-n,0), come faccio nella mia risposta . Suite di test.
Dennis,

3

Haskell, 65 byte

f x=snd$minimum[((a*b+a-b,a*b),(b,a))|a<-[1..x],b<-[1..a],a*b>=x]

Esempio di utilizzo: map f [1..5]-> [(1,1),(1,2),(2,2),(2,2),(2,3)].

Passa attraverso un ciclo esterno ada 1a x(x -> numero di studenti) e un ciclo interno bda 1a a. Mantiene tutto (b,a)dove a*b>=xe costruisce le coppie di ((arrangement points,seats left), (b,a))cui seguire l'ordine lessicografico abbiamo bisogno di trovare il minimo. Nota: aè sempre maggiore di b, quindi non abbiamo bisogno absdi squadratura. Non è necessario sottrarre xdal punteggio "posti lasciati", poiché conta solo l'ordine relativo. Infine rimuoviamo la coppia di punteggi con snd.


Perché non solo (a b + ab, (b, a))? Se minimizzi il punteggio, sicuramente minimizzi a comunque b, o mi sto perdendo qualcosa?
justinpc,

@jpcooper: a*b(numero di posti gratuiti) è il pareggio se il punteggio principale è uguale. Ad esempio n=43: a) a=7, b=7, punteggio: (49,49)b) a=9, b=5, punteggio: (49,45). Il punteggio principale è uguale, il pareggio decide, b) vince.
nimi,

Hai ragione. Avrei dovuto leggere meglio la descrizione.
justinpc,

@jpcooper: aspetta un minuto ... se rimuovo il pareggio a*b, i numeri stessi (b,a)che devo portare in giro fungono comunque da pareggio e danno gli stessi risultati (almeno) n=1..300. Un prodotto è piccolo se uno dei fattori (qui b) è piccolo. Ma fintanto che non ho prove formali, non voglio usare questo fatto. Vediamo se ne trovo uno.
nimi,

Buon punto. Sembra giusto e non dovrebbe essere troppo difficile trovare una prova. Sto cominciando a chiedermi se potrebbe esserci una soluzione lineare a questo problema.
justinpc,

2

Rubino, 64 byte

->n{(1..n).map{|w|h=(n+w-1)/w;[(h-w).abs+h*w,w*h,w,h]}.min[2,3]}

Una lambada che prende il numero di persone come argomento e restituisce un array con larghezza e altezza della soluzione ottimale.


Perché hai bisogno w*hcome secondo elemento nel tuo array? Non penso che cambi particolarmente nulla quando chiami minperché minimizzi il punteggio, ovvero il primo elemento.
Value Ink,

@ KevinLau-notKenny dalla domanda:In case of a tie, the optimal solution is the one with less empty chairs
MegaTom,

2

MATL , 18 byte

:Gy/Xkvtd|yp+&X<Z)

Provalo online!

Spiegazione

:      % Implicit input number N. Range [1 2 ... N]
G      % Push N again
y      % Duplicate second-from-top: push [1 2 ... N] again
/Xk    % Divide and round up
v      % Vertically concatenate. Gives 2×N array of rectangle sizes
td|    % Duplicate. Absolute difference of each column
y      % Duplicate second-from-top: push 2×N array again
p      % Product of each column
+      % Sum absolute differences and products
&X<    % Arg min
Z)     % Use as column index into the 2×N array. Implicitly display

2

Javascript, 98 byte

Il mio primo codice golf, quindi inserisco comunque!

f=n=>{for(o=1/0,i=1;i<=n;i++)for(j=n;i*j>=n;j--)t=i*j-n+Math.abs(i-j),o>t&&(o=t,a=[i,j]);return a}

Inizialmente il mio oera un oggetto vuoto e ho controllato se o.afosse vuoto, quindi era un caso speciale al primo turno. Ma ho trovato il trucco 1/0 nella risposta di edc65 per inizializzare la variabile su Infinity.


E proverò il trucco per usare un oggetto per memorizzare il risultato temporaneo
edc65

1

Pyth, 24 22 21 byte

Modifica : nella chiave di ordinamento, mi rendo conto che non è necessario trovare il numero di sedie vuote. È equivalente a segnare il numero totale di sedie. Questo mi ha salvato 2 byte.

h.m_+B*FbaFbm,d.EcQdS

Provalo online!


1

Matlab(174) (146)121

  function g(n),f=@(n,i)ceil(n/i);x=[];for i=1:n,x=[sortrows(x); f(n,i)*i-1/(f(n,i)*i)+abs(f(n,i)-i) i f(n,i)];end,x(1,2:3)
  • trucco 1: ho aggiunto l'importo 1-1/length*widthcome pareggio

  • trucco 2: ho calcolato number_students/lengthceiled per la larghezza del rettangolo, il limite superiore è il quadrato ma anche ceiled

  • Sono sicuro che può essere ulteriormente giocato a golf ...

Provalo


Modifica: riferito alle osservazioni di @StewieGriffin.

Modifica 2:

  • 1e nsono costanti che non richiedono di aggiungerli al punteggio complessivo.
  • Una funzione è di pochi byte in meno rispetto al programma autonomo stdin.
  • Ho usato una tecnica di ordinamento ascendente che consente di risparmiare troppi byte.

Modifica 3: test delle prestazioni.


@StewieGriffin che non è un grosso problema, può essere risolto usandounique
Abr001am

1
penso che sia a metà strada per una bella traduzione matematica per questo problema, ma rimane ancora come congettura
Abr001am

Anche pensato a questo. Vedi l'esempio di julia.
mschauer,


1

Julia, 61 59 55 53 52 byte

/ =cld
n->[m=indmax([~i*~-max(i,n/i)for i=1:n]),n/m]

Provalo online!

Come funziona

Il codice è equivalente alla seguente versione non modificata, dove cldè la divisione del soffitto.

function chairs(n)
    m = indmin([(i + 1) * (max(i, cld(n, i)) - 1) for i in 1:n])
    return [m, cld(n, m)]
end

Per trovare la disposizione ottimale, è chiaramente sufficiente esaminare le coppie [i, j] , dove 1 ≤ i ≤ n e j = ⌈n / i⌉ .

Il punteggio per tale accordo è | j - i | + (ij - n) , dove il secondo summand è il numero di sedie vuote. Invece dei punteggi effettivi, possiamo confrontare i punteggi aumentati di una costante, come ij + | j - i | + 1 .

È sufficiente considerare le coppie [i, j] dove i ≤ j poiché le disposizioni [i, j] e [j, i] sono ugualmente valide. Abbiamo a che fare con coppie strettamente discendenti impostando invece j = max (⌈n / i⌉, i) , il che assicura che j ≥ i e produrrà un punteggio non ottimale se ⌈n / i⌉ <i .

Poiché j - i ≥ 0 , abbiamo ij + | j - i | + 1 = ij + j - i + 1 = (i + 1) × (j - 1) , che può essere calcolato in meno byte di codice.

Infine indmin/ indmaxfornisce l'indice m (e quindi il valore di i ) della disposizione ottimale, che è m di ⌈n / m⌉ . I legami vengono interrotti per prima occorrenza, che corrisponde al valore più basso di i , quindi al valore più alto di j - i e quindi al valore più basso di ij - n (sedie vuote).


1

JavaScript (ES6) 74 78

Modifica mantenendo il risultato temporaneo come un array anziché 2 var, preso in prestito dalla risposta di Thiht

n=>(z=>{for(x=0;y=-~(~-n/++x),x<=y;)(s=y-x+x*y-n)>=z||(z=s,r=[x,y])})()||r

Meno golf

n=>{
  z = 1/0
  for (x=0; y=(n-1)/++x+1|0, x <= y; )
  {
    s = y-x+x*y-n;
    if (s<z)
      z=s, r=[x,y]
  }
  return r
}

Test

f=n=>(z=>{for(x=0;y=-~(~-n/++x),x<=y;)(s=y-x+x*y-n)>=z||(z=s,r=[x,y])})()||r

out=x=>O.textContent+=x+'\n'

for(i=1;i<=100;i++)out(i+' :( '+f(i)+' )')
<pre id=O></pre>


1

PHP, 129 byte

function f($i){$s=INF;for($x=1;$x<$i;$x++){if($s>$t=(abs($x-$e=ceil($i/$x))-$i+($e*$x))){$s=$t;$d[0]=$x;$d[1]=$e;}}var_dump($d);}

Ungolfed:

function f ($i){
    $s=INF;
    for($x=1; $x<$i; $x++){ // for every number less than the input
        if( $s > $t=( abs($x-$e=ceil($i/$x))-$i+($e*$x) ) ){ 
            // determine the other dimension, the score, and compare to the minimum score
            $s=$t;
            $d[0]=$x;
            $d[1]=$e;
        }
    }
    var_dump($d);
}

1

PHP, 104 byte

L'algoritmo che risolve questo problema è semplice ed è probabilmente utilizzato da altre risposte in lingue simili a PHP (JavaScript, fe):

  • iniziare con un valore elevato per il punteggio iniziale; nè abbastanza grande (dove si ntrova il valore di input); il punteggio della disposizione calcolata sulla prima iterazione ( 1, n) è(n-1)+0 ;
  • iterare per tutti i valori di larghezza tra 1e n; calcola l'altezza minima come ceil(n/width), calcola il punteggio della disposizione usando la formula fornita nella domanda (es. abs(width - height) + (width * height - n)); se il punteggio è migliore del miglior punteggio precedente, ricorda la larghezza, l'altezza e il nuovo miglior punteggio; sui legami usa il valore diwidth * height - n per la disposizione corrente e la migliore disposizione precedente per rilevare la nuova migliore disposizione;
  • È tutto.

Dopo il golf, questo algoritmo produce qualcosa del genere (racchiuso qui per la leggibilità):

for($s=$h=$j=$n=$argv[$w=$i=1];$i<=$j;$j=ceil($n/++$i)
{$c=$j-$i+$i*$j-$n;if($c<$s||$c==$s&&$i*$j<$w*$h){$w=$i;$h=$j;$s=$c;}}
echo"$w,$h";

Utilizza 137 byte (se inseriti su una sola riga) ed è lontano dai 104 byte pubblicizzati nel titolo. Il codice può essere probabilmente abbreviato di altri 2-3 byte, ma la grande fonte di miglioramento è da qualche altra parte: nei dettagli dell'algoritmo.

L'algoritmo rivisto:

Esistono diversi punti in cui è possibile migliorare l'algoritmo rimuovendo il codice inutile.

  • non è necessario ripetere la larghezza da 1a $n; per la velocità, la larghezza ( $i) deve scorrere tra 1e floor(sqrt($n))ma ciò rende il codice ancora più lungo invece di accorciarlo; ma se la larghezza non supera sqrt($n), l'altezza minima ( $j) sarà sempre maggiore di sqrt($n)(il loro prodotto deve essere almeno $n);
  • l'istruzione precedente consente di utilizzare $i <= $j(larghezza <= altezza) come condizione di terminazione per il ciclo; in questo modo, la larghezza ripeterà da 1a floor(sqrt($n))e l'altezza otterrà valori che iniziano $ne scendono aceil(sqrt($n)) (non necessariamente tutti);
  • sapendo che la larghezza è sempre più piccola o uguale all'altezza ci consente di sapere che abs(width - height)è sempre height - width( $j-$i); 5 byte salvati in questo modo;
  • il valore di input $nviene utilizzato nel calcolo del punteggio (il numero di posti non occupati è width * height - n) ma non è necessario; il punteggio non deve essere visualizzato, viene calcolato solo per il confronto delle disposizioni; rimuovendo - ndalla formula del punteggio salviamo altri 3 byte (il codice PHP è-$n ) senza perdere nulla;
  • date le ultime due affermazioni, la formula del punteggio diventa height - width + width * height ( $j-$i+$i*$j);
  • sui legami (il punteggio dell'accordo attuale è lo stesso del miglior punteggio precedente), le regole dicono di usare l'accordo con meno posti liberi; poiché la larghezza aumenta sempre e l'altezza diminuisce sempre, ilheight - width parte del punteggio diminuisce ad ogni passo;
  • se il punteggio attuale è uguale al miglior punteggio precedente, le dichiarazioni precedenti ci dicono che il numero di posti liberi della disposizione attuale è maggiore di quello della migliore disposizione precedente; questo significa che la migliore disposizione precedente vince il pareggio;
  • poiché i legami vengono sempre vinti dalla migliore disposizione precedente, una nuova disposizione diventa la nuova migliore disposizione solo quando il suo punteggio è inferiore alla migliore precedente; il codice che controlla i legami è inutile e può essere rimosso (||$c==$s&&$i*$j<$w*$h - molti byte);
  • a causa della rimozione di -$ndalla formula del punteggio, il punteggio per la prima disposizione ( 1x$n) è $n-1+1*$n(cioè 2*$n-1); il valore iniziale del miglior punteggio ( $s) può essere qualsiasi valore maggiore o uguale a2*$n ; la prima iterazione ha un punteggio migliore e diventa la migliore disposizione lasciando correre l'algoritmo senza problemi di inizializzazione.

Il nuovo codice ( 104 byte ), dopo aver applicato i miglioramenti sopra descritti è:

for($s=2*$j=$n=$argv[$i=1];$i<=$j;$j=ceil($n/++$i))
if($s>$c=$j-$i+$i*$j){$w=$i;$h=$j;$s=$c;}echo"$w,$h";

È avvolto qui per la leggibilità. Prepara il codice sopra con il marcatore PHP <?php(tecnicamente, non fa parte del codice), mettilo in un file (diciamo arrange-your-chairs.php) ed eseguilo con un numero intero maggiore di zero come argomento. Visualizzerà la larghezza e l'altezza della disposizione calcolata, separate da una virgola:

$ php arrange-your-chairs.php 1001
28,36

Un'altra soluzione (116 byte)

Un'altra soluzione che utilizza un algoritmo diverso:

for($n=$argv[1];++$j<=$n;)for($i=0;++$i<=$j;)
if($n<=$k=$i*$j)$a["$i,$j"]=($j-$i+$k-$n)*$n+$k;asort($a);echo key($a);

Mette tutte le combinazioni di almeno $n seggi in un elenco associativo; la chiave è la rappresentazione testuale dell'accordo, il valore è il punteggio dell'accordo. Quindi ordina l'elenco (crescente per valore) e ottiene la chiave della prima voce.

Ancora uno (115 byte)

foreach(range(1,$m=$n=$argv[1])as$i)
if(($d=ceil($n/$i))<=$i&&$m>=$s=$i*$d-$n+$i-$d){$m=$s;$w=$d;$h=$i;}echo"$w,$h";

Questa è la versione PHP della risposta di @ Neil (JavaScript / ES6, 85 byte).

Ci sono alcune differenze notevoli dovute alle caratteristiche di ogni lingua:

  • la risposta JS genera una matrice di nvalori (non definiti) quindi utilizza le sue chiavi per scorrere da 0a n-1; incrementa i( d=(n+i++)/i|0) per farlo iterare da 1a n; la soluzione PHP non ha bisogno di aumentare; usa range()per generare un array quindi usa i valori generati ( 1an ) per iterare;
  • la risposta JS utilizza (n+i)/iquindi converte il valore in numero intero utilizzando |0per ottenere il numero intero più piccolo maggiore di n/i; la risposta PHP risolve facilmente questo problema con la funzione PHP ceil(); JavaScript fornisce anche, Math.ceil()ma utilizza 5 byte in più rispetto alla soluzione trovata da Neil;
  • PHP fornisce la funzione array_map()che è in qualche modo simile a JS Array.map()ma non aiuta qui; la sua sintassi è dettagliata, a foreachproduce un codice più breve; è più grande del codice JS, comunque;
  • la fusione delle assegnazioni nelle condizioni usando ||non è possibile in PHP perché manca l'operatore virgola; Ho tradotto a||b||cin if(!a&&!b)callora, perché ae bsono confronti, ho negato i loro operatori (sostituito <con >=); questo produce anche un codice più grande rispetto alla versione JS;
  • altri 23 byte devono essere aggiunti solo perché i nomi delle variabili in PHP devono essere preceduti da $.

Le versioni non giocate di tutte le soluzioni e la suite di test sono disponibili su Github .


1
Questa è la risposta di golf da codice più completa che abbia mai visto.
DJMcMayhem

0

JavaSCript (ES6), 83 byte

n=>[...Array(m=n)].map((_,i)=>(d=(n+i++)/i|0)>i||(s=i*d-n+i-d)>m||(m=s,r=[d,i]))&&r

Forse potresti applicare il mio trucco (per salvare 2 byte)
Leaky Nun,

@KennyLau Non penso che aiuti; Dovrei aumentare mper compensare.
Neil,

0

Julia, 87

Penso che questo sia un passo in avanti verso la ricerca di una funzione magica per il problema:

f(i)=(i+n)÷(i+1)|>j->(j*i<n)+j
_=indmin([sqrt(n)<=i?i-f(i)*(1-i):2n for i=1:n])
_,f(_)

Guarda solo a coppie (i, j=(i+n)/(i+1))o(i, j+1)


ti prego di spiegare ulteriormente come funziona, mi hai reso curioso
riguardo alla

2
Non sono sicuro di come dovrebbe funzionare. Non definisci da nnessuna parte e sembra che tu non stia prendendo input.
Dennis,

Ah, scusa, ho appena preso ncome input. Uno dovrebbe avvolgerlo in n->.... Bello che tu possa farlo funzionare.
mschauer,

0

Oracle SQL 11.2, 173 byte

SELECT MIN(x||','||y)KEEP(DENSE_RANK FIRST ORDER BY y-x+(y*x-:1))FROM(SELECT CEIL(LEVEL/:1)x,CEIL(MOD(LEVEL+.1,:1))y FROM DUAL CONNECT BY LEVEL<=:1*:1)WHERE x<=y AND:1<=x*y;

Un-golfed

SELECT MIN(x||','||y)KEEP(DENSE_RANK FIRST ORDER BY y-x+(y*x-:1))  -- Keeps the minimal score
FROM   (SELECT CEIL(LEVEL/:1)x,CEIL(MOD(LEVEL+.1,:1))y FROM DUAL CONNECT BY LEVEL<=:1*:1) -- Generate x,y combinations 
WHERE  x<=y AND :1<=x*y  -- Filters out wrong combinations

0

Q 58 byte

{c@d?&/d:+/(-/;*/)@\:+c:{((b<a)?1b)#+(b:-_-x%a;a:1+!x)}x}

Lamba che calcola il costo minimo per un dato valore (x) e restituisce una sequenza di due valori (larghezza, altezza)

L'aggiunta di un nome a quel lambda richiede altri due caratteri (ex f: {..} invece di {..})

Test

{..}'1+!100

dove {..} è la lambda. Leggi come "applica lambda per ogni valore di 1 + primi 100 in" (in altre parole per ogni valore 1..100)

genera

1 1
2 1
2 2
2 2
3 2
3 2
3 3
3 3
3 3
5 2
4 3
4 3
4 4
4 4
4 4
4 4
6 3
6 3
5 4
5 4
7 3
5 5
..

Spiegazione

Lamdba nidificata {((b<a)?1b)#+(b:-_-x%a;a:1+!x)}genera tutte le coppie di candidati (larghezza, altezza) per x sedie come due sequenze (w1 w2 w3 ..; h1 h2 h3 ..) (larghezze e altezze). Leggi da sinistra a destra, ma valuta da destra a sinistra

a:1+!x genera valori 1..x e assegna quella sequenza a

-_- è negare piano negare e implementa ceil (ceil non è un primitivo della lingua)

b:-_-x%aapplica ceil a ciascun valore di x diviso per qualsiasi elemento im a e assegna la sequenza risultante a b. In altre parole, b è ceil ogni x divisoBy ogni 1..x

+(b;a) restituisce una sicurezza composta da seq a e seq b, quindi la capovolge (il risultato è una sequenza di coppie in cui i-pair contiene l'elemento i di a e l'elemento i di b)

b<a confronta elemento per elemento di b e a e genera una sicurezza di valori logici (vero = 1b per ciascun indice in cui b [i]

s?xrestituisce la prima posizione dell'articolo x in sequenza s. Con (b<a)?1bCerchiamo 1b (valore reale) in sequenza risultante dal confronto b e a, e otteniamo la prima posizione dove b

n#sprende n primi n elementi da seq s. Vogliamo scartare le coppie duplicate, quindi ci fermiamo quando il primo oggetto di una coppia <secondo oggetto (es. Considera 13,1 ma non 1,13).

Come effetto collaterale, ciascuna coppia della sequenza risultante ha una distanza decrescente tra aeb (ex (13 1; 7 2; 5 3; 4 4)

La coppia candidata generata da lambda nidificata viene assegnata a c. Quindi capovolgiamo c (ottiene di nuovo b, a) e applichiamo due funzioni a quell'argomento: */moltiplica e -/sottrai. Il risultato di (-/;*/)@\:+cè la differenza e il prodotto di ciascuna coppia.+/è somma e calcola il costo finale. Il costo di ogni patir è assegnato a d

& / è minimo, quindi &/d è il costo minimo. Con d?&/dtroviamo la prima occorrenza del costo minimo in d, e con c @ .. recuperiamo la coppia in quella posizione. Poiché ogni coppia ha una distanza decrescente tra a e n, il primo minimo trovato ha il massimo distante tra le altre coppie minime, quindi applichiamo la regola del pareggio correttamente

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.