Un morceau, un morceau ou un octet?

45

Inspiré par ce défi

Pour un nombre entier compris dans la plage 0 <= n < 2**64, indiquez le conteneur de taille minimale dans lequel il peut être inséré

  • bit: 1
  • grignotage: 4
  • octet: 8
  • court: 16
  • int: 32
  • long: 64

Testcases:

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

C'est du , donc la réponse la plus courte en octets est gagnante.

Bleu
la source
10
Ce serait beaucoup plus facile si 2c'était aussi une sortie ...
ETHproductions
1
@ETHproductions Ca le ferait mais hélas, ça ne l'est pas (il m'a fallu beaucoup de temps pour écrire un algorithme qui l'a fait)
Blue
J'aimerais avoir compris le problème. ... attendez, tout ce que vous voulez, c'est la quantité de bits nécessaire pour contenir le nombre, arrondi à la structure fondamentale suivante?
Le
2
Merci! Je m'en suis rendu compte en écrivant le commentaire et en le modifiant trop tard. Je suppose que j'ai besoin d'un canard en caoutchouc pour parler à ...
z0rberg's
2
@ Daniel les réponses ici prennent une approche complètement différente de l'autre question. Lorsque je dis «inspiré par», cela ne signifie pas «dupliquer». Aucune réponse n'a pu être modifiée trivialement pour qu'elle soit valide pour cette question
Blue

Réponses:

3

05AB1E , 10 octets

bg.²îD1Q+o

Explication

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

Essayez-le en ligne!

Osable
la source
22

Python, 39 octets

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

Compte combien de fois on doit prendre la racine carrée pour nêtre en dessous 16, avec quelques casse spéciale pour éviter des sorties de 2.

Si 2 étaient inclus, nous pourrions faire

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

avec True pour 1.


41 octets:

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

Double à plusieurs reprises l'exposant ijusqu'à 2**i>n. Saute de i=1à i=4en décalant un bit supplémentaire quand iest étrange.

Alt 45 octets:

f=lambda n,i=4:4**(n>1)*(2**i>n)or 2*f(n,i*2)
Xnor
la source
7
Cela ne cesse de m'étonner de voir comment vous pouvez proposer autant de solutions à un problème. En tant que programmeur, j’ai appris à trouver une solution à un problème et à le résoudre jusqu’à ce que cela fonctionne. Je suppose qu'il me reste encore beaucoup à apprendre sur le golf! Le respect.
ElPedro
@xnor, comment votre première réponse s'affiche-t-elle 1lorsque la racine carrée de 0 ou 1 est toujours 1 (récursivité infinie en or 2*f(n**.5))?
dfernan
2
@dfernan Je crois que la partie qui suit orest évaluée uniquement si la partie qui précède a une valeur falsifiée (zéro). Pour n = 0 et pour n = 1, n>1évalue à False, traité comme zéro dans une expression numérique, et n<16évaluant à True, traité comme un dans une expression numérique. Alors 4**(n>1)*(n<16)est 1.
Trichoplax
1
@ trichoplax, c'est vrai. Merci pour l'explication.
dfernan
12

J, 19 octets

Verbe monadique prenant le numéro à droite et recrachant la taille du conteneur. Il y a deux façons équivalentes de l'écrire, alors j'ai inclus les deux.

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

Expliqué par explosion:

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

Ce qui est cool, c’est que nous voyons deux manières différentes de prendre log base 2 en J. La première est l’évident 2^., qui est un logarithme numérique. La seconde est #@#:, qui peut être lue comme "longueur de la représentation en base 2". Cela équivaut presque à one-plus-floor-of-log-base-2, à la différence que #:0c'est la liste à un élément 0, qui correspond exactement à ce que nous souhaitons. Cela bat 1+2<.@^.1&>.par 8 octets.

En usage sur le 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

Ancienne solution de 20 octets trop astucieuse.

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
algorithmeshark
la source
9

Python, 53 50 49 octets

lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]
orlp
la source
1
lambda n:[w for w in[1,4,8,16,32,64]if n<2**w][0]est un octet plus court
Bleu
Était sur le point de poster quelque chose de similaire. +1
ElPedro
8

Mathematica, 44 39 38 octets

Merci @ orlp pour 5 octets et @MartinEnder pour 1 octet.

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

Trouve en premier les éléments de la liste {1, 4, 8, 16, 32, 64}tels que 2 ^ nombre est supérieur à l'entrée.

JungHwan Min
la source
8

Pip , 19 octets

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

Essayez-le en ligne!

Comment ça marche

                     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
DLosc
la source
7

JavaScript (ES7), 35 octets

n=>[1,4,8,16,32,64].find(b=>2**b>n)
Neil
la source
2
Une version récursive telle que f=(n,b=1)=>2**b>n&&b-2?b:f(n,b*2)devrait être légèrement plus courte.
Arnauld
6

Mathematica, 46 43 38 octets

Merci à JungHwan Min et Martin Ender pour avoir économisé 3 octets! Merci à ngenisis pour une grosse économie de 5 octets!

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

Fonction sans nom prenant un entier non négatif en entrée et renvoyant un entier positif. BitLength@#calcule le nombre de bits dans l'entrée, puis 2^⌈Log2@...⌉calcule la plus petite puissance de 2 égale au moins au nombre de bits. Enfin, /.{2->4,0->1}s'occupe du cas particulier où il n'y a pas de "niblit" entre bit et nybble, et corrige également la réponse pour l'entrée étrange 0.

Greg Martin
la source
2
Sauvegardez 3 octets en utilisant à la BitLength@#place de ⌊1+Log2@#⌋. Ensuite, au lieu de remplacer par, 1vous pouvez remplacer 0, en enregistrant 2 autres octets et vous êtes lié pour le premier.
ngenisis
1
Cela peut être fait entièrement avec BitLength. Voir ma réponse
ngenisis
4

Julia, 40 octets

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

Il s'agit d'une fonction anonyme qui génère un tableau des puissances de 2 de 0 à 6, à l'exclusion de 2, et le filtre uniquement aux éléments x tels que 2 x soit supérieur à l'entrée. Le premier élément de ce type est la réponse. Malheureusement, cela nécessite la promotion de 2 en a BigIntpour éviter le débordement sur x = 64.

Ceci est en fait assez similaire à la réponse Python de orlp, bien que je ne l'aie pas vue avant de concocter cette approche.

Essayez-le en ligne!

Alex A.
la source
4

Perl 6 , 30 octets

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

+<est l'opérateur de décalage de bits à gauche de Perl 6, que beaucoup d'autres langues appellent <<.

Sean
la source
4

Haskell, 31 octets

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

32 octets alt:

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

Java, 143 octets.

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;}
Pavel
la source
1
Je sais que je peux raccourcir ça, je le fais quand je suis devant un ordinateur.
Pavel
2
économiser 50 octets: return a<2?1:a<5?4:a<9?8:a<17?16:a<33?32:64;
Mindwin
@Mindwin Je sais, mais je voyage et je n'aurai pas accès à un ordinateur pendant un moment. Je vais y arriver.
Pavel
Est-ce que la partition en fait un ... byte d'amour ?
Ingénieur Toast
2

Haskell, 43 octets

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

Ruby, 39 36 octets

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

Merci GB d'aider à jouer au golf

Alexis Andersen
la source
Devrait également fonctionner sans parenthèses. La liste pourrait également être 0,2,3,4,5,6 et 1 << 2 ** p.
GB
... parce qu'alors vous pourriez utiliser 0, * 2..6.
GB
2

Java 8, 65 à 55 octets

C'est une expression lambda qui prend un longet retourne un int. Jamais joué en Java auparavant, cela devrait donc être facile à battre:

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

Essayez-le en ligne!


Pour 47 octets , nous pourrions avoir:

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

Toutefois, les 1L<<idébordements pour les valeurs de retour supérieures à 32 sont résolus, de sorte que cela échoue pour le test final.

FlipTack
la source
1
Ce rendement 4lorsqu'il est testé avec 16quand il est censé revenir 8. Vous pouvez également encore le golf cette solution en supprimant les crochets autour i<<=1+i%2;depuis sans {}s, la boucle while sera uniquement exécuter la ligne suivante
Kritixi Lithos
@KritixiLithos devrait être corrigé maintenant - désolé, mon Java est devenu rouillé ...
FlipTack
2

Mathematica, 30 octets

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

Explication:

Soit Nl'ensemble des entiers non négatifs. Définissez deux fonctions sur N, BitLengthet NextPowercomme suit:

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

Cette solution calcule essentiellement à partir d' NextPower(BitLength(n))un entier n >= 0. Car n > 0, on peut voir ça NextPower(n) = 2^BitLength(n-1), alors NextPower(BitLength(n)) = 2^BitLength(BitLength(n)-1).

Mathematica est désormais BitLengthconforme à la définition que j'ai donnée n >= 0. Pour n < 0, BitLength[n] == BitLength[BitNot[n]] == BitLength[-1-n], donc BitLength[-1] == BitLength[0] == 0. Nous obtenons ainsi la réponse souhaitée de 1pour n==0.

Puisque nous passons directement de mors en mordillés, nous devons remplacer les réponses 2par 4.

ngenisis
la source
1
Joliment construit! (Dommage que l'espace soit nécessaire.)
Greg Martin
2

bash, 49 octets 48 octets

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

ou

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

Enregistrez dans un script et transmettez le nombre à tester en tant qu'argument.

Edit: Remplacé || avec |, ce qui fonctionne car les arguments sont toujours 0 ou 1.

Note: Ceci fonctionne pour les entiers jusqu'au plus grand entier positif que votre version de bash peut gérer. Si j'en ai le temps, je le modifierai pour qu'il fonctionne jusqu'à 2 ^ 64-1 dans les versions de bash utilisant une arithmétique signée 32 bits.

En attendant, voici une solution de 64 octets qui fonctionne pour des nombres arbitrairement grands (dans toute version bash):

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

Empilés, 34 30 octets

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

ou

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

Le premier prend en entrée le TOS et laisse la sortie en TOS; la seconde est une fonction. Essayez-le ici!

Explication

@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

Voici un exemple de travail sur le repl :

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

Cas de 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))
> 

Ou, en tant que programme complet:

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

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

out
Conor O'Brien
la source
2

Raquette 45 octets

(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)))

Autres versions:

(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))

et en utilisant la longueur de la chaîne:

(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))

Essai:

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

Sortie:

1
1
4
4
8
8
16
32
64
rnso
la source
1

Octave, 40 36 31 29 octets

Fonction anonyme simple. Il est supposé que la valeur d'entrée est un entier - voir l'avertissement à la fin.

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

Le code fonctionne comme suit:

  • Tout d'abord, un tableau des longueurs de bits autorisées (1,4,8,16,32,64) est créé et enregistré b.

  • Ensuite, nous trouvons le nombre de bits requis pour stocker le nombre saisi aen comparant la taille maximale de chaque conteneur bpour déterminer ceux qui sont assez gros.

  • Nous utilisons ensuite le vecteur d’index résultant pour extraire à nouveau la taille du conteneur b.

  • Enfin, prenons le premier élément du tableau résultant qui sera le plus petit conteneur possible.

Vous pouvez l'essayer en ligne ici .

Il suffit de lancer le code suivant, puis faites-le ans(x).


La seule réserve à cela est que la double précision est utilisée par défaut pour les constantes, ce qui signifie qu'elle ne fonctionne qu'avec des nombres allant jusqu'à la valeur la plus élevée pouvant être représentée par un flottant double précision inférieur à 2 ^ 64.

Cela peut être corrigé en s'assurant que le nombre fourni à la fonction est un entier et non un double. Ceci peut être réalisé en appelant la fonction par exemple avec: ans(uint64(x)).

Tom Carpenter
la source
1

PHP, 49 46 44 octets

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

Courez comme ça:

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

Explication

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.

Tweaks

  • Sauvegardé 3 octets en se débarrassant de la $r=tâche
  • 2 octets enregistrés en utilisant -Rpour rendre $argndisponible
aross
la source
1

CJam , 18 octets

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

Essayez-le en ligne!

Explication

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
Chat d'affaires
la source
0

C, 71 52 octets

i;f(long long n){for(i=1;n>>i;i*=2);return i-2?i:4;}
Steadybox
la source
Ne serait-ce pas une entrée (1<<15)+1ou plus de casser cela à cause du comportement signé de long long? Le type que vous voulez vraiment est uint64_tce qui nécessite #include <stdint.h>ce qui est encore un perdant comparé à unsigned long long! Les en-têtes sont le fléau du golf en c.
dmckee
@ dmckee J'imagine que cela pourrait le casser, mais cela semble fonctionner au moins sur mon ordinateur. Je n'ai pas trouvé d'exemple qui ne marcherait pas. J'ai pensé à utiliser unsigned long longou uint64_t, mais comme il semble fonctionner avec, long longje suis allé avec.
Steadybox
0

QBIC , 27 octets

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

Explication

:        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.
Steenbergh
la source
0

Pyke, 13 octets

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

Essayez-le ici!

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 < ^
Bleu
la source
0

PHP, 43 octets

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

Courez avec echo <number> | php -R '<code>'.

boucle $ijusqu'à 2**(2**$i)est plus grand que l'entrée. (Tweak: <<au lieu d' **éliminer les parens)
Après la boucle, $ i est trop élevé; il obtient donc une décrémentation avant de calculer la sortie
- mais pas pour $i==2.

Titus
la source