Un po ', un bocconcino o un byte?


45

Ispirato da questa sfida

Dato un numero intero nell'intervallo 0 <= n < 2**64, genera il contenitore di dimensioni minime da cui può rientrare

  • bit: 1
  • bocconcino: 4
  • byte: 8
  • breve: 16
  • int: 32
  • lungo: 64

Casi test:

0 -> 1
1 -> 1
2 -> 4
15 -> 4
16 -> 8
123 -> 8
260 -> 16
131313 -> 32
34359750709 -> 64

Questo è , quindi vince la risposta più breve in byte.


10
Sarebbe molto più semplice se 2fosse un risultato troppo ...
ETHproductions,

1
@ETHproductions Sarebbe ma ahimè, non lo è (mi ci è voluto molto per scrivere un algoritmo che lo ha fatto)
Blue

Vorrei aver capito il problema. ... aspetta, tutto ciò che vuole è la quantità di bit necessari per contenere il numero, arrotondato alla struttura fondamentale successiva?
il

2
Grazie! L'ho capito quando ho scritto il commento e l'ho modificato troppo tardi. Immagino di aver bisogno di un'anatra di gomma con cui parlare ...
z0rberg del

2
@Daniel le risposte qui adottano un approccio completamente diverso rispetto all'altra domanda. Quando dico "ispirato da" non significa "duplicato di". Nessuna risposta potrebbe essere banalmente modificata per essere valida per questa domanda
Blue

Risposte:


3

05AB1E , 10 byte

bg.²îD1Q+o

Spiegazione

bg         Push the length of the binary representation of input without leading zeros
  .²î      Push x = ceil(log2(length))
     D1Q+  Add 1 if x == 1 or add 0 otherwise
         o Push pow(2,x) and implicitly display it

Provalo online!


22

Python, 39 byte

f=lambda n:4**(n>1)*(n<16)or 2*f(n**.5)

Conta quante volte si deve prendere la radice quadrata per nessere al di sotto 16, con un involucro speciale per evitare output di 2.

Se fossero inclusi 2, potremmo farlo

f=lambda n:n<2or 2*f(n**.5)

con True per 1.


41 byte:

f=lambda n,i=1:i*(2**i>n)or f(n,i<<1+i%2)

Raddoppia ripetutamente l'esponente ifino a quando 2**i>n. Salta da i=1a i=4spostando un altro bit quando iè dispari.

Alt 45 byte:

f=lambda n,i=4:4**(n>1)*(2**i>n)or 2*f(n,i*2)

7
Non smette mai di stupirmi di come puoi trovare tante soluzioni per un problema. Fondamentalmente come programmatore ho imparato a trovare una soluzione a un problema e lavorare con esso fino a quando non funziona. Suppongo che ho ancora molto da imparare sul golf! Rispetto.
ElPedro,

@xnor, come viene generata la tua prima risposta 1quando la radice quadrata di 0 o 1 è sempre 1 (ricorsività infinita in or 2*f(n**.5))?
Dfernan,

2
@dfernan Credo che la parte dopo la orsia valutata solo se la parte prima valuta qualcosa di falso (zero). Per n = 0 e per n = 1, n>1valuta in False, che è trattato come zero in un'espressione numerica e n<16valuta in True, che è trattato come in un'espressione numerica. Così 4**(n>1)*(n<16)è 1.
trichoplax,

1
@trichoplax, è vero. Grazie per la spiegazione.
Dfernan,

12

J, 19 byte

Verbo monadico che prende il numero a destra e sputa la dimensione del contenitore. Ci sono un paio di modi equivalenti per scriverlo, quindi ho incluso entrambi.

2^2(>.+1=>.)@^.#@#:
2^s+1=s=.2>.@^.#@#:

Spiegato dall'esplosione:

2^2(>.+1=>.)@^.#@#: NB. takes one argument on the right...
                 #: NB. write it in binary
               #@   NB. length (i.e. how many bits did that take?)
  2          ^.     NB. log base 2 of that
   (>.     )@       NB. ceiling
      +1=>.         NB. +1 if needed (since no container is two bits wide)
2^                  NB. base 2 exponential

La cosa bella è che vediamo due modi diversi di prendere la base di registro 2 in J. Il primo è l'ovvio 2^., che è un logaritmo numerico. Il secondo è #@#:, che può essere letto come "lunghezza della rappresentazione base-2". Questo è quasi equivalente a one-plus-floor-of-log-base-2, tranne che #:0è l'elenco di un elemento 0, che è esattamente quello che vogliamo. Questo batte 1+2<.@^.1&>.di 8 byte.

In uso presso il REPL:

   f =: 2^2(>.+1=>.)@^.#@#:
   f 131313
32
   f 34359750709
64
   (,.f"0) 0 1 2 15 16 123 260
  0  1
  1  1
  2  4
 15  4
 16  8
123  8
260 16

Vecchia soluzione da 20 byte eccessivamente intelligente.

2&^.(>.+1=>.&.)@#@#: NB. takes one argument on the right...
                #@#: NB. how many bits
2&^.                 NB. log base 2 of that
     >.              NB. ceiling
       +1=>.         NB. +1 if needed (since no container is two bits wide)
    (       &.)      NB. undo log base 2

9

Python, 53 50 49 byte

lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]

1
lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]è più corto di un byte
Blu,

Stavo per pubblicare qualcosa di simile. +1
ElPedro,

8

Mathematica, 44 39 38 byte

Grazie @orlp per 5 byte e @MartinEnder per 1 byte.

FirstCase[{1,4,8,16,32,64},x_/;2^x>#]&

Trova i primi elementi nella lista in modo {1, 4, 8, 16, 32, 64}tale che il numero 2 ^ sia maggiore dell'input.


8

Pip , 19 byte

(a<2**_FI2**,7RM2i)

Provalo online!

Come funziona

                     a is 1st cmdline arg, i is 0 (implicit)
         2**,7       Construct powers of 2 from 0 to 6 [1 2 4 8 16 32 64]
              RM2    Remove 2
       FI            Filter for elements for which:
 a<2**_                a is less than 2 to that element
(                i)  Get 0th item of resulting list and autoprint

7

JavaScript (ES7), 35 byte

n=>[1,4,8,16,32,64].find(b=>2**b>n)

2
Una versione ricorsiva come quella f=(n,b=1)=>2**b>n&&b-2?b:f(n,b*2)dovrebbe essere leggermente più corta.
Arnauld,

6

Mathematica, 46 43 38 byte

Grazie a JungHwan Min e Martin Ender per aver salvato 3 byte! Grazie a ngenisis per un grande risparmio di 5 byte!

2^⌈Log2@BitLength@#⌉/.{2->4,0->1}&

Funzione senza nome che accetta un numero intero non negativo come input e restituisce un numero intero positivo. BitLength@#calcola il numero di bit nell'input, quindi 2^⌈Log2@...⌉calcola la potenza minima di 2 che è almeno pari al numero di bit. Infine, /.{2->4,0->1}si occupa del caso speciale in cui non c'è "niblit" tra bit e nybble e risolve anche la risposta per l'input strano 0.


2
Salvare 3 byte utilizzando BitLength@#invece di ⌊1+Log2@#⌋. Quindi, invece di sostituire con 1te, puoi sostituire 0, salvando altri 2 byte e sei legato per primo.
ngenisi,

1
Questo può effettivamente essere fatto interamente con BitLength. Vedi la mia risposta
ngenisis,

4

Julia, 40 byte

n->filter(x->n<big(2)^x,[1;2.^(2:6)])[1]

Questa è una funzione anonima che genera una matrice di potenze di 2 da 0 a 6, escluso 2, e la filtra solo su quegli elementi x in modo tale che 2 x sia maggiore dell'input. Il primo di questi elementi è la risposta. Sfortunatamente questo richiede la promozione da 2 a a BigIntper evitare l'overflow su x = 64.

Questo è in realtà abbastanza simile alla risposta Python di orlp, anche se non l'ho visto prima di inventare questo approccio.

Provalo online!


4

Perl 6 , 30 byte

{first 1+<*>$_,1,4,8,16,32,64}

+<è l'operatore di spostamento bit sinistro di Perl 6, che molte altre lingue chiamano <<.


4

Haskell, 31 byte

f n=[2^i|i<-0:[2..],2^2^i>n]!!0

Alt 32 byte:

f n|n<2=1|n<16=4|1>0=2*f(sqrt n)

2

Java, 143 byte.

int f(long a){a=Long.toBinaryString(a).length();if(a<2)return 1;if(a<5)return 4;if(a<9)return 8;if(a<17)return 16;if(a<33)return 32;return 64;}

1
So di poterlo abbreviare, lo faccio io quando sono al computer.
Pavel,

2
salvare 50 byte: return a<2?1:a<5?4:a<9?8:a<17?16:a<33?32:64;
Mindwin

@Mindwin Lo so, ma sto viaggiando e non avrò accesso a un computer per un po '. Ci penserò io.
Pavel,

Il punteggio lo rende un ... byte d'amore ?
Ingegnere Toast,

2

Haskell, 43 byte

f x=head$filter((>x).(2^))$[1,4,8,16,32,64]

2

Rubino, 39 36 byte

->n{2**[0,*2..6].find{|p|2**2**p>n}}

Grazie GB per l'aiuto nel golf


Dovrebbe funzionare anche senza parentesi. Inoltre, l'elenco potrebbe essere 0,2,3,4,5,6 e utilizzando 1 << 2 ** p.
GB

... perché allora potresti usare 0, * 2..6.
GB

2

Java 8, 65 55 byte

Questa è un'espressione lambda che prende a longe restituisce a int. Non ho mai giocato a golf in Java prima, quindi questo dovrebbe essere facilmente battibile:

x->{int i=1;while(Math.pow(2,i)<=x)i<<=1+i%2;return i;}

Provalo online!


Per 47 byte , potremmo avere:

x->{int i=1;while(1L<<i<=x)i<<=1+i%2;return i;}

Tuttavia, 1L<<itrabocca per valori di ritorno superiori a 32, quindi questo non riesce per il testcase finale.


1
Questo ritorna 4quando testato con 16quando dovrebbe restituire 8. Inoltre puoi ancora giocare a golf questa soluzione rimuovendo le parentesi in giro i<<=1+i%2;poiché senza {}s, il ciclo while eseguirà solo la riga successiva
Kritixi Lithos

@KritixiLithos dovrebbe essere risolto ora - scusa, il mio Java è diventato arrugginito ...
FlipTack

2

Mathematica, 30 byte

2^(f=BitLength)[f@#-1]/. 2->4&

Spiegazione:

Lascia che Nsia l'insieme di numeri interi non negativi. Definire due funzioni N, BitLengthe NextPowercome segue:

BitLength(n) := min {x in N : 2^x - 1 >= n}
NextPower(n) := 2^(min {x in N : 2^x >= n})

Questa soluzione calcola essenzialmente NextPower(BitLength(n))dato un numero intero n >= 0. Perché n > 0, possiamo vederlo NextPower(n) = 2^BitLength(n-1), così NextPower(BitLength(n)) = 2^BitLength(BitLength(n)-1).

Ora il Mathematica BitLengthintegrato è d'accordo con la definizione che ho dato n >= 0. Per n < 0, BitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n], quindi BitLength[-1] == BitLength[0] == 0. Quindi otteniamo la risposta desiderata di 1per n==0.

Dal momento che saltiamo direttamente da bit a stuzzichino, dobbiamo sostituire le risposte di 2con 4.


1
Ben costruito! (Peccato che lo spazio sia necessario.)
Greg Martin

2

bash, 49 byte 48 byte

for((y=1;$[y==2|$1>=1<<y];$[y*=2])){ :;};echo $y

o

for((y=1;$[y==2|$1>=1<<y];)){ y=$[y*2];};echo $y

Salvare in uno script e passare il numero da testare come argomento.

Modifica: sostituito || con |, che funziona perché gli argomenti sono sempre 0 o 1.

Nota: funziona con numeri interi fino al numero intero positivo più grande che può essere gestito dalla tua versione di bash. Se ho tempo, lo modificherò per funzionare fino a 2 ^ 64-1 nelle versioni di bash che usano l'aritmetica firmata a 32 bit.

Nel frattempo, ecco una soluzione a 64 byte che funziona con numeri arbitrariamente grandi (in qualsiasi versione bash):

for((x=`dc<<<2o$1n|wc -c`;$[x==2||x&(x-1)];$[x++])){ :;};echo $x

2

Impilato, 34 30 byte

@n 1 2 6|>2\^,:n 2 log>keep 0#

o

{!1 2 6|>2\^,:n 2 log>keep 0#}

Il primo prende input su TOS e lascia output su TOS; la seconda è una funzione. Provalo qui!

Spiegazione

@n 1 2 6|>2\^,:n 2 log>keep 0#
@n                               set TOS to `n`
   1 2 6|>2\^,                   equiv. [1, ...2 ** range(2, 6)]
              :                  duplicate it
               n                 push `n`
                 2 log           log base-2
                      >          element-wise `>`
                       keep      keep only truthy values
                            0#   yield the first element

Ecco un esempio di come funziona sul sostituto :

> 8    (* input *)
(8)
> @n 1 2 6|>2\^,:n 2 log>keep 0#    (* function *)
(4)
>    (* output *)
(4)

Casi test

> {!1 2 6|>2\^,:n 2 log>keep 0#} @:f
()
> (0 1 2 15 16 123 260 131313 34359750709) $f map
((1 1 4 4 8 8 16 32 64))
> 

Oppure, come programma completo:

{!1 2 6|>2\^,:n 2 log>keep 0#} @:f

(0 1 2 15 16 123 260 131313 34359750709) $f map

out

2

Racchetta 45 byte

(findf(λ(x)(>(expt 2 x)m))'(1 4 8 16 32 64))

Ungolfed:

(define (f m)
  (findf (λ (x) (> (expt 2 x) m))          ; find first function
         '(1 4 8 16 32 64)))

Altre versioni:

(define (f1 m)
  (for/last ((i '(1 4 8 16 32 64))         ; using for loop, taking last item
             #:final (> (expt 2 i) m))     ; no further loops if this is true
    i))

e usando la lunghezza della stringa:

(define (f2 m)
  (for/last
      ((i '(1 4 8 16 32 64))
       #:final (<= (string-length
                    (number->string m 2))  ; convert number to binary string
                   i))
    i))

test:

(f 0)
(f 1)
(f 2)
(f 15)
(f 16)
(f 123)
(f 260)
(f 131313)
(f 34359750709)

Produzione:

1
1
4
4
8
8
16
32
64

1

Ottava, 40 36 31 29 byte

Semplice funzione anonima. Si presume che il valore di input sia un numero intero - vedere l'avvertenza alla fine.

@(a)(b=2.^[0 2:6])(a<2.^b)(1)

Il codice funziona come segue:

  • Innanzitutto viene creato e salvato un array delle lunghezze di bit consentite (1,4,8,16,32,64) b.

  • Successivamente troviamo il numero di bit necessari per memorizzare il numero di input aconfrontandolo con la dimensione massima di ciascun contenitore bper vedere quali sono abbastanza grandi.

  • Quindi utilizziamo il vettore indice risultante per estrarre bnuovamente le dimensioni del contenitore .

  • Infine prendiamo il primo elemento nell'array risultante che sarà il contenitore più piccolo possibile.

Puoi provarlo online qui .

Basta eseguire il seguente codice e quindi farlo ans(x).


L'unica avvertenza è che la doppia precisione viene utilizzata per impostazione predefinita per le costanti, il che significa che funziona solo con numeri fino al valore più alto rappresentabile da un galleggiante a doppia precisione inferiore a 2 ^ 64.

Ciò può essere risolto assicurando che il numero fornito alla funzione sia un numero intero anziché un doppio. Ciò può essere ottenuto chiamando la funzione, ad esempio con: ans(uint64(x)).


1

PHP, 49 46 44 byte

echo(2**ceil(log(log(1+$argn,2),2))-2?:2)+2;

Esegui in questo modo:

echo 16 | php -R 'echo(2**ceil(log(log(1+$argv[1],2),2))-2?:2)+2;';echo

Spiegazione

echo                       # Output the result of the expression
  (
    2**                    # 2 to the power
      ceil(log(            # The ceiling of the power of 2 of bitsize
        log(1+$argn,2),    # Number of bits needed
        2
      ))
      - 2 ?:               # Subtract 2 (will be added back again)
      2;                   # If that results in 0, result in 2 (+2=4).
  ) + 2                    # Add 2.

Ritocchi

  • Hai salvato 3 byte eliminando il $r=compito
  • Salvato 2 byte utilizzando -Rper rendere $argndisponibile

1

CJam , 18 byte

2ri2b,2mLm]_({)}|#

Provalo online!

Spiegazione

2                   Push 2
 ri                 Read an integer from input
   2b,              Get the length of its binary representation
      2mLm]         Take the ceiling of the base-2 log of the length
           _(       Duplicate it and decrement it
             {)}|   Pop the top element, if it's 0, increment the next element
                     Effectively, if ceil(log2(input)) was 1, it's incremented to 2,
                     otherwise it stays the same.
                 #  Raise 2 to that power

0

C, 71 52 byte

i;f(long long n){for(i=1;n>>i;i*=2);return i-2?i:4;}

Un input di (1<<15)+1o più non lo spezzerebbe a causa del comportamento firmato di long long? Il tipo che vuoi davvero è quello uint64_tche richiede #include <stdint.h>che è ancora un perdente rispetto unsigned long long! Le intestazioni sono la rovina del golf in c.
dmckee,

@dmckee Immagino che potrebbe romperlo, ma sembra funzionare almeno sul mio computer. Non ho trovato un esempio che non funzionerebbe. Ho pensato di usare unsigned long longo uint64_t, ma dato che sembra funzionare, ci long longsono andato.
Steadybox,

0

QBIC , 27 byte

:~a<2|_Xq]{~a<2^t|_Xt\t=t*2

Spiegazione

:        Get cmd line parameter N, call it 'a'
~a<2     IF 'a' is 0 or 1 (edge case)
|_Xq]    THEN quit, printing 1 ('q' is auto-initialised to 1). ']' is END-IF
{        DO - infinite loop
    2^t  't' is our current number of bits, QBIC sets t=4 at the start of the program.
         2^t gives the maximum number storable in t bytes.
 ~a<     IF the input fits within that number,
|_Xt     THEN quit printing this 't'
\t=t*2   ELSE jump to the next bracket (which are spaced a factor 2 apart, from 4 up)
         DO-loop is auto-closed by QBIC.

0

Pyke, 13 byte

7Zm@2-#2R^<)h

Provalo qui!

7Zm@          -   [set_bit(0, i) for i in range(7)] <- create powers of 2
    2-        -  ^.remove(2)
      #    )h - filter(^, V)[0]
       2R^    -   2 ** i
          <   -  input < ^

0

PHP, 43 byte

for(;1<<2**$i++<=$argn;);echo 2**$i-=$i!=2;

Corri con echo <number> | php -R '<code>'.

esegue $iun ciclo fino a quando 2**(2**$i)è più grande dell'input. (Tweak: <<invece di **eliminare le parentesi)
Dopo il loop, $ i è uno troppo alto; quindi ottiene un decremento prima di calcolare l'output
, ma non per $i==2.

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.