Due dozzine di baciare approssimazioni numeriche


26

Dato un numero compreso tra 1 e 24, invia il numero baciante al meglio delle attuali conoscenze (alcuni numeri avranno più di un risultato accettabile). La conoscenza della geometria non è essenziale poiché gli output sono tutti elencati di seguito.

Dalla pagina di Wikipedia sul problema del numero di baci :

un numero di baci è definito come il numero di sfere di unità non sovrapposte che possono essere disposte in modo tale che tocchino ciascuna un'altra sfera di unità

Cioè, data una sfera unitaria, quante più sfere unitarie possono toccarla senza che si sovrappongano? La domanda verrà posta nello spazio dimensionale N, dove una sfera è intesa come una sfera dimensionale N-1.

Per esempio:

  • nello spazio bidimensionale, un cerchio unitario può toccare altri 6 circoli unitari.
  • nello spazio tridimensionale, una sfera unitaria può toccare altre 12 sfere unitarie.

La pagina Wikipedia elenca i valori per uno spazio da 1 a 24 dimensioni. Tuttavia, alcuni di questi non sono ancora noti con precisione, quindi viene dato solo un limite inferiore e superiore. La tabella viene riprodotta qui in modo che rimanga fissa, indipendentemente da eventuali futuri restringimenti delle gamme dovuti a nuove prove. Le soluzioni vengono giudicate in base a questa tabella fissa, anche se la pagina di Wikipedia verrà modificata in futuro.

Tabella dei limiti

Dimension   Lower bound     Upper bound
1           2               2
2           6               6
3           12              12
4           24              24
5           40              44
6           72              78
7           126             134
8           240             240
9           306             364
10          500             554
11          582             870
12          840             1357
13          1154            2069
14          1606            3183
15          2564            4866
16          4320            7355
17          5346            11072
18          7398            16572
19          10668           24812
20          17400           36764
21          27720           54584
22          49896           82340
23          93150           124416
24          196560          196560

Ingresso

La dimensione: un numero intero compreso tra 1 e 24 (incluso).

Qui "intero" indica che l'input non avrà una parte frazionaria - può essere 2o 3mai 2.5. Una soluzione può comunque accettare input come float o stringa, ad esempio.

Produzione

Un numero nell'intervallo pertinente, dal limite inferiore al limite superiore per quell'input (incluso).

L'output deve essere deterministico (sempre lo stesso per lo stesso input).

L'output deve essere intero. Ad esempio, per l'ingresso 5delle possibili uscite sono validi 40, 41, 42, 43, 44. Nota che questa è una restrizione sul valore, non sul tipo. È accettabile restituire un galleggiante, purché abbia zero parti frazionarie. Ad esempio, 41.5non sarebbe valido, ma 41.0sarebbe valido.

punteggio

Questo è . Il tuo punteggio è il numero di byte nel tuo codice. Per ogni lingua, il vincitore è la soluzione con il punteggio più basso.


6
Problema di approssimazione davvero interessante.
qwr,

Risposte:


11

Julia 0.6 , 52 byte

n->ceil(n<8?3.7exp(.51n)-5.1:n<24?9exp(.41n):196560)

Provalo online!

Come?

Apprendimento automatico! (Kinda. Forse. Non proprio. )

Innanzitutto, dal tracciare i dati del limite inferiore e superiore su N e alcuni tentativi ed errori manuali, sembrava che una funzione esponenziale potesse adattarsi bene per N> = 8. Dopo alcuni tentativi di trovare questa funzione manualmente, ho fatto ricorso all'uso di un parametro funzione di sintonizzazione per sintonizzare (dove K = 8 a 24) per trovare a, b e c in modo tale che l'espressione fornisca valori che rientrano nell'intervallo corretto per ogni K (con un intervallo successivamente più piccolo di valori possibili e precisioni corrispondentemente più alte per a, b, c in diverse esecuzioni della funzione). C'erano alcuni di questi insiemi di valori, sebbene nessuno di questi potesse adattarsi esattamente al caso N = 24, quindi sono andato con uno che aveva 0 e ho codificato il valore per N = 24.aebK+cc

Per N inferiore, da 1 a 7, speravo di trovare un'espressione o un polinomio più semplice, ma non riuscivo a trovare quello adatto. Quindi, tornando al montaggio di , questa volta per K = 1 a 7 (anche se non pensavo davvero che un esponenziale sarebbe stato il giusto in questo caso, basato sulle tendenze della trama visiva). Fortunatamente, ci sono parametri a, b, c che potrebbe dare valori corretti per tutta la gamma qui (almeno entro una chiamata).aebK+cceil


6
Non considererei un gridsearch come un apprendimento automatico. È una forza bruta se non altro.
qwr,

5
Ma è dentro MLBase!!! J / k, le linee attorno a ML sono sfocate come sempre, ma questo probabilmente è troppo semplice per meritare l'apprendimento automatico delle etichette. Inoltre, è sempre utile inserire una parola d'ordine!
Sundar - Ripristina Monica il

quando diciamo Machine Learning, pensiamo principalmente ai polinomi con n = 2 o regexps
aaaaa dice di reintegrare Monica il

2
quando dico apprendimento automatico, penso a reti neurali, alberi decisionali, HMM, perceptron ...
qwr

@qwr Sono in ritardo, ma la regressione è davvero considerata parte dell'apprendimento automatico, oltre a tutte queste cose. (E altro ancora! SVM, ecc.)
Quintec,

7

x86, 62 59 53 50 byte

La mia soluzione utilizza una tabella di ricerca byte e lo spostamento di 2 (nessun calcolo FP). Le dimensioni da 9 a 23 offrono un margine di manovra sufficiente per il cambio. Ingresso eaxe uscita ecx.

-3 scambiando eaxe ecxpoiché cmp $imm, %alè più breve di cmp $imm, %cl.

-4 non trattando il caso N = 24 separatamente ma applicando l'adeguamento a tutti i casi 1024 casi.

-2 non tornando presto (stupido)

-3 usando la tabella come offset e movzblinvece di azzerare conxor

start:
        dec     %eax                # 1-indexed table

        movzbl  table(%eax), %ecx   # return byte directly
        cmp     $8, %al
        jl      exit

        sal     $6, %ecx            # * 64 
        cmp     $19, %al
        jl      exit

        sal     $4, %ecx            # * 16
        sub     $48, %ecx

exit:   
        ret

#.data
table:  .byte   2, 6, 12, 24, 40, 72, 126, 240              # * 1
        .byte   5, 8, 10, 14, 19, 26, 41, 68, 84, 116, 167  # * 64  
        .byte   18, 28, 49, 92, 192                         # * 1024 - 48

Hexdump (tabella in .textinvece di .data)

00000502  48 0f b6 88 1c 05 00 00  3c 08 7c 0d c1 e1 06 3c  |H.......<.|....<|
00000512  13 7c 06 c1 e1 04 83 e9  30 c3 02 06 0c 18 28 48  |.|......0.....(H|
00000522  7e f0 05 08 0a 0e 13 1a  29 44 54 74 a7 12 1c 31  |~.......)DTt...1|
00000532  5c c0                                             |\.|

1
Il tavolo è di sola lettura, quindi normalmente lo inseriresti .rodata, .datacomunque. (O su Windows, a quanto pare .rdata). La .rodatasezione viene collegata come parte del segmento di testo.
Peter Cordes,

1
E a proposito, le persone normali scrivono shl, specialmente quando il tuo numero è senza segno (non movzbllo caricavi movsbl). Naturalmente salè solo un altro nome per lo stesso codice operativo. gcc emette sal, ma è abbastanza raro vederlo nel codice scritto a mano.
Peter Cordes,

7

JavaScript (ES6), 60 byte

f=(n,k=2)=>n<24?--n?f(n,k*24/(17+~'_8443223'[n])):~~k:196560

Provalo online!

Come?

a24=196560

Tutti gli altri termini vengono calcolati in modo ricorsivo, utilizzando:

{a1=2an+1=an×24qn

qn

{q1=8q2=12q3=12q4=13q5=14q6=14q7=13qn=16,for n>7

portando ai seguenti rapporti:

3,2,2,2413,127,127,2413,32,32,,32

Il risultato finale viene infine pavimentato e restituito.

Riepilogo dei risultati

I risultati approssimativi sono dati con 2 cifre decimali.

  n |   a(n-1) | multiplier |      a(n) | output |          expected
----+----------+------------+-----------+--------+-------------------
  1 |      n/a |        n/a |         2 |      2 |                2
----+----------+------------+-----------+--------+-------------------
  2 |        2 |          3 |         6 |      6 |                6
  3 |        6 |          2 |        12 |     12 |               12
  4 |       12 |          2 |        24 |     24 |               24
  5 |       24 |      24/13 |     44.31 |     44 |        [40,..,44]
  6 |    44.31 |       12/7 |     75.96 |     75 |        [72,..,78]
  7 |    75.96 |       12/7 |    130.21 |    130 |      [126,..,134]
  8 |   130.21 |      24/13 |    240.39 |    240 |              240
  9 |   240.39 |        3/2 |    360.58 |    360 |      [306,..,364]
 10 |   360.58 |        3/2 |    540.87 |    540 |      [500,..,554]
 11 |   540.87 |        3/2 |    811.31 |    811 |      [582,..,870]
 12 |   811.31 |        3/2 |   1216.97 |   1216 |     [840,..,1357]
 13 |  1216.97 |        3/2 |   1825.45 |   1825 |    [1154,..,2069]
 14 |  1825.45 |        3/2 |   2738.17 |   2738 |    [1606,..,3183]
 15 |  2738.17 |        3/2 |   4107.26 |   4107 |    [2564,..,4866]
 16 |  4107.26 |        3/2 |   6160.89 |   6160 |    [4320,..,7355]
 17 |  6160.89 |        3/2 |   9241.34 |   9241 |   [5346,..,11072]
 18 |  9241.34 |        3/2 |  13862.00 |  13862 |   [7398,..,16572]
 19 | 13862.00 |        3/2 |  20793.01 |  20793 |  [10668,..,24812]
 20 | 20793.01 |        3/2 |  31189.51 |  31189 |  [17400,..,36764]
 21 | 31189.51 |        3/2 |  46784.26 |  46784 |  [27720,..,54584]
 22 | 46784.26 |        3/2 |  70176.40 |  70176 |  [49896,..,82340]
 23 | 70176.40 |        3/2 | 105264.59 | 105264 | [93150,..,124416]
----+----------+------------+-----------+--------+-------------------
 24 |           (hard-coded)            | 196560 |           196560 

1
La prima cosa che ho visto sono stati gli operatori bit a bit all'interno di una funzione JavaScript ricorsiva; la prima cosa che ho pensato è stata "Cosa sta facendo Arnauld ..."
Matt

Tavolo davvero carino. L'hai fatto manualmente?
qwr,

1
@qwr Sì, si tratta principalmente di modifiche a Notepad ++. Ho appena usato uno script per generare i valori nelle prime 4 colonne.
Arnauld,

4

Gelatina , 29 26 byte

“~D=ⱮziEc+y’Dḣ+⁵÷7PĊ«“£#;’

Provalo online!

Come funziona

“~D=ⱮziEc+y’Dḣ+⁵÷7PĊ«“£#;’  Main link. Argument: n

“~D=ⱮziEc+y’                Set the return value to 485523230101001100011122.
            D               Decimal; convert the return value to base 10.
             ḣ              Head; take the first n elements of the digit list.
              +⁵            Add 10 to each element.
                ÷7          Divide the sums by 7.
                  P         Take the product.
                   Ċ        Ceil; round up to the nearest integer.
                     “£#;’  Yield 196560.
                    «       Take the minimum.

1

JavaScript (Node.js) , 120 99 byte

Dropped 21 byte. Grande riduzione grazie al suggerimento di tsh di aggiungere un buco all'inizio dell'array (salvando due byte che vanno da n-1a ne puntando a numeri arrotondati all'interno dei limiti inferiore e superiore, riducendoli così dalla notazione a virgola fissa come 1154alla notazione esponenziale come 2e3.

Ancora una volta, il mio obiettivo originale era quello di mostrare quanto leggero sarebbe il modo "stupido" (ad es. Non usare una vera matematica, come la risposta di Arnauld. È impressionante che ci fosse ancora spazio per ridurla senza trasformazioni o calcoli.

n=>[,2,6,12,24,40,72,126,240,306,500,582,840,2e3,2e3,3e3,5e3,6e3,8e3,2e4,2e4,3e4,5e4,1e6,196560][n]

Provalo online!

Il doppio della lunghezza della risposta di Arnauld, 0 quantità della complessità.

JavaScript (Node.js) , 129 128 byte

(-1 byte grazie al suggerimento di utilizzare il bitshifting)

f=(n)=>[2,6,12,24,40,72,126,240].concat([5,8,10,14,19,26,41,68,84,116,167].map(x=>x<<6),[17,28,49,91].map(x=>x<<10),196560)[n-1]

Provalo online!

Per soddisfare le esigenze di essere interessante, ho rubato la logica dalla risposta x86 e ne ho ricavato l'array. Rendendolo più lungo di 9 byte. Ma leggermente più interessante.


sbadigli almeno prova qualcosa di interessante
qwr

Ho pensato che dimostrare l'approccio più diretto (e quindi tecnicamente la lunghezza più lunga ragionevole) fosse piuttosto interessante. Arnauld's è probabilmente il più breve che puoi ottenere in JS, ma il più lungo è solo il doppio dei byte.
Anthony,

1
Il punto della tabella di ricerca dei byte è forse usare un bytestring o semplicemente qualcosa come "02060c1828487ef0" dove ogni voce è un byte o 2 caratteri in esadecimale, se preferisci. La memorizzazione diretta dei numeri in decimale richiede fino a 3 caratteri. Usa anche
bitshifting

2
Dovresti almeno rimuovere f=, cambiare (x)in x, aggiungere un buco e cambiare x-1in x. TIO ; e magari intorno ad essi fino TIO 99 byte
TSH

5
Benvenuti in PPCG! :)
Shaggy,

1

Runico, 173 byte

>i:8(?D5X1+1C,*212,+16,+1c2*,+1cX,+Sp3X7+a,*5X1+a,-1+kn$;
      R:c2*(?D4X1+1C,*212,+16,+1c2*,+Sp9*1+:4XY(?Dkn$;
             R`196560`r@;              ;$*C1nk,C1L

(Nota che l'angolo in basso a destra dovrebbe essere conteggiato per i byte: sono implicitamente riempiti di spazi.)

L'ex di TIO ha bisogno di un aggiornamento su cui si basa questa risposta (e sto correggendo alcuni altri buchi prima di chiedere a Dennis di ricostruire). Ma inserendo un valore (assicurati di aggiungere uno spazio bianco sulle righe 2 e 3 se usi più di un carattere per il valore sulla prima riga). Ecco il modo più semplice per scrivere i valori necessari:

0-9,a-f  ->  1-15
2Xn+     ->  20+n

Provalo online!

Funzionalmente questa è una porta della risposta Julia di Sundar (ma Runic non ha un comando per spingere ein pila (o davvero, nessun valore decimale), quindi era necessaria un'approssimazione). L'approssimazione per eingressi inferiori a 8 è più precisa, poiché la perdita di precisione ha comportato valori al di fuori dell'intervallo consentito di uscite (ad es. 7Produrrebbe 125). Ceil()è stato realizzato convertendolo in un personaggio e poi di nuovo in un numero (questo non è riuscito per valori eccezionalmente grandi, quindi a 40k l'ho fatto dividere per 100, fare la conversione in e indietro, quindi moltiplicare di nuovo per 100).

Probabilmente c'è spazio per semplificare la disposizione (ad es. Eseguendo il punto di entrata in verticale, in basso, o cercando un modo per comprimere le approssimazioni e), ma sono contento di poter fare il calcolo.

/?D5X1+1C,*212,+16,+1c2*,+1cX,+Sp3X7+a,*5X1+a,-1+kn$;
  R:c2*(?D4X1+1C,*212,+16,+1c2*,+Sp9*1+:4XY(?Dkn$;
\(8:i<   R`196560`r@;              ;$*C1nk,C1L

161 byte.

Aggiornamento dell'interprete:

Con la lettura dell'input di fissaggio push , Runic ora ha diverse funzioni matematiche e la possibilità di analizzare le stringhe come doppie. Ciò semplificherà enormemente questa risposta, ma la lascerò per mostrare lo sforzo che ci ho messo (ho aggiunto le funzioni matematiche a argomento singolo e l'analisi delle stringhe poco dopo la pubblicazione: avevo già attivato Sin / Cos / Tan la mia lista di cose da fare, ma non avevo considerato Exp, Abs, Log, ecc. e si stavano esaurendo i caratteri). TIO dovrebbe aggiornarsi nelle prossime 24-48 ore, a seconda di quando Dennis lo vede.

212,+16,+1c2*,+1cX,+ridurrebbe a -> 1'eAcon questo aggiornamento dell'interprete. Aapre un carattere e un valore ed esegue un'operazione matematica su quel valore in base al carattere spuntato ( ein questo caso è Exp()e Exp(1)restituisce e ).

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.