Adatta i fattori nel campo


11

Dato un numero intero positivo inferiore a 1000, visualizza tutti i possibili rettangoli con quell'area.

Compito

Supponiamo che l'input sia 20. Possiamo creare un rettangolo 20 × 1, 10 × 2 o 5 × 4, quindi questo è un output valido:

********************

**********
**********

*****
*****
*****
*****

Si noti che ogni possibile rettangolo appare esattamente una volta.

I rettangoli possono apparire in qualsiasi ordine, orientamento o posizione, ma non è possibile sovrapporre o toccare due rettangoli, neppure agli angoli. È inoltre valido quanto segue:

********************

            ****
**********  ****
**********  ****
            ****
            ****

punteggio

L'area del riquadro di delimitazione (BBA) di un'uscita è l'area del rettangolo minimo che racchiude tutti i rettangoli. Nel primo esempio di output, la dimensione è 20 × 9, quindi il BBA è 180. Nel secondo esempio di output, la dimensione è 20 × 7, quindi il BBA è solo 140.

Trova il BBA dell'uscita quando l'ingresso è 60, 111, 230, 400 e 480 e aggiungili. Moltiplica questa somma per la dimensione del tuo codice in byte. Il risultato è il tuo punteggio; vince il punteggio più basso.

Regole

  • Il programma (o la funzione) deve produrre un output valido per qualsiasi numero intero positivo inferiore a 1000.
  • L'output deve contenere solo asterischi ( *), spazi ( ) e newline.
  • Può esserci una quantità di spazio tra i rettangoli, ma questo vale per il BBA.
  • Le linee o le colonne iniziali o finali, se hanno solo spazi, non contano ai fini del BBA.

I casi speciali possono essere codificati?
Calvin's Hobbies,

@Calvin'sHobbies Sì, ma dubito che sarà di grande aiuto.
Ypnypn,

3
@ Calvin'sHobbies La soluzione Volkswagen.
Level River St

Risposte:


3

Rubino, 228 byte * 21895 = 4992060

->n{a=(0..n*2).map{$b=' '*n}
g=0
m=n*2
(n**0.5).to_i.downto(1){|i|n%i<1&&(m=[m,n+h=n/i].min
g+=h+1
g<m+2?(a[g-h-1,1]=(1..h).map{?**i+$b}):(x=(m-h..m).map{|j|r=a[j].rindex(?*);r ?r:0}.max 
(m-h+1..m).each{|j|a[j][x+2]=?**i}))}
a}

Diverse modifiche rispetto al codice non salvato. Il più grande è il cambiamento di significato della variabile mdall'altezza del rettangolo di squarest, all'altezza del rettangolo di squarest plus n.

In sostanza, *40è stato modificato con il *nsignificato di un sacco di spazi bianchi non necessari a destra per grandi n; e -2viene modificato, il 0che significa che i rettangoli tracciati nella parte inferiore mancano sempre delle prime due colonne (ciò si traduce in un impaccamento più scarso per i numeri la cui unica fattorizzazione è (n/2)*2)

Spiegazione

Ho finalmente trovato il tempo di tornare a questo.

Per un dato momento nil campo più piccolo deve avere abbastanza spazio sia per il rettangolo più lungo 1*nche per il rettangolo squarest x*y. Dovrebbe essere evidente che il layout migliore può essere ottenuto se entrambi i rettangoli hanno i lati lunghi orientati nella stessa direzione.

Ignorando il requisito per gli spazi bianchi tra i rettangoli, troviamo che l'area totale è o (n+y)*x = (n+n/x)*xo n*(x+1). Ad ogni modo, questo valuta n*x + n. Compreso lo spazio bianco, dobbiamo includere un extra xse posizioniamo i rettangoli da un capo all'altro o nse posizioniamo i rettangoli uno accanto all'altro. Il primo è quindi preferibile.

Ciò fornisce i seguenti limiti inferiori (n+y+1)*xper l'area del campo:

n     area
60    71*6=426
111  149*3=447
230  254*10=2540
400  421*20=8240
480  505*20=10100

Questo suggerisce il seguente algoritmo:

Find the value (n+y+1) which shall be the field height
Iterate from the squarest rectangle to the longest one
  While there is space in the field height, draw each rectangle, one below the other, lined up on the left border.
  When there is no more space in the field height, draw the remaining rectangles, one beside the other, along the bottom border, taking care not to overlap any of the rectangles above.
  (Expand the field rightwards in the rare cases where this is necessary.)

In realtà è possibile ottenere tutti i rettangoli per i casi di test richiesti entro i limiti inferiori sopra menzionati, ad eccezione di 60, che fornisce il seguente 71 * 8 = 568 output. Questo può essere leggermente migliorato a 60 * 9 = 540 spostando i due rettangoli più sottili a destra di un quadrato e poi in alto, ma il risparmio è minimo, quindi probabilmente non vale alcun codice aggiuntivo.

10
12
15
20
30
60
******
******
******
******
******
******
******
******
******
******

*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
*****  *
       *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
****   *
       *
***    *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
*** ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *
    ** *

Questo dà una superficie totale di 21895.

Codice Ungolfed

f=->n{
  a=(0..n*2).map{' '*40}                                      #Fill an array with strings of 40 spaces
  g=0                                                         #Total height of all rectangles
  m=n                                                         #Height of squarest rectangle (first guess is n) 
  (n**0.5).to_i.downto(1){|i|n%i<1&&(puts n/i                 #iterate through widths. Valid ones have n%i=0. Puts outputs heights for debugging.
    m=[m,h=n/i].min                                           #Calculate height of rectangle. On first calculation, m will be set to height of squarest rectangle.
    g+=h+1                                                    #Increment g
    g<n+m+2?                                                  #if the rectangle will fit beneath the last one, against the left margin
      (a[g-h-1,1]=(1..h).map{'*'*i+' '*40})                      #fill the region of the array with stars
    :                                                         #else  
      (x=(n+m-h..n+m).map{|j|r=a[j].rindex('* ');r ?r:-2}.max    #find the first clear column
      (n+m-h+1..n+m).each{|j|a[j][x+2]='*'*i}                    #and plot the rectangle along the bottom margin
    )
  )}
a}                                                            #return the array

puts f[gets.to_i]


1

Rubino, 56 byte

90385 * 56 = 5061560 supponendo che l'output sia uguale a quello di Martin (credo lo sia.)

->n{1.upto(n){|i|i*i<=n&&n%i==0&&puts([?**(n/i)]*i,'')}}

Ecco un'altra utile funzione, in un utile programma di test

f=->n{1.upto(n){|i|i*i<=n&&n%i==0&&print(n/i,"*",i,"\n")};puts}

f[60];f[111];f[230];f[400];f[480]

Che fornisce il seguente output, per riferimento:

60*1
30*2
20*3
15*4
12*5
10*6

111*1
37*3

230*1
115*2
46*5
23*10

400*1
200*2
100*4
80*5
50*8
40*10
25*16
20*20

480*1
240*2
160*3
120*4
96*5
80*6
60*8
48*10
40*12
32*15
30*16
24*20
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.