Basculez quelques bits et obtenez un carré


26

Étant donné un entier , vous devez trouver le nombre minimum de bits qui doivent être inversés dans N pour le transformer en nombre carré . Vous êtes uniquement autorisé à inverser les bits en dessous du plus significatif .N>3N

Exemples

  • est déjà un nombre carré ( 2 2 ), donc la sortie attendue est 0 .N=4220
  • peut être transformé en nombre carré en inversant 1 bit: 11000 1100 1 ( 25 = 5 2 ), donc la sortie attendue est 1 .N=24110001100125=521
  • ne peut pas être transformé en nombre carré en inversant un seul bit (les résultats possibles étant 23 , 20 , 18 et 30 ) mais cela peut être fait en inversant 2 bits: 10110 10 0 0 0 ( 16 = 4 2 ) , donc la sortie attendue est 2 .N=2223201830101101000016=422

Règles

  • C'est bien si votre code est trop lent ou génère une erreur pour les plus grands cas de test, mais il devrait au moins prendre en charge en moins d'une minute.3<N<10000
  • C'est du !

Cas de test

    Input | Output
----------+--------
        4 | 0
       22 | 2
       24 | 1
       30 | 3
       94 | 4
      831 | 5
      832 | 1
     1055 | 4
     6495 | 6
     9999 | 4
    40063 | 6
   247614 | 7        (smallest N for which the answer is 7)
  1049310 | 7        (clear them all!)
  7361278 | 8        (smallest N for which the answer is 8)
100048606 | 8        (a bigger "8")

Ou au format convivial copier / coller:

[4,22,24,30,94,831,832,1055,6495,9999,40063,247614,1049310,7361278,100048606]

Près de la moitié des réponses ne s'exécutent pas 100048606sur TIO, est-ce un problème?
Urne de poulpe magique

@MagicOctopusUrn Merci, j'ai mis à jour les règles pour qu'il soit plus clair que la prise en charge de est facultative. N10000
Arnauld

1
Ce serait aussi une bonne question de code le plus rapide (sans la restriction de taille d'entrée)
qwr

@qwr Oui, probablement. Ou si vous voulez devenir hardcore: étant donné , trouvez le plus petit NkN tel que . f(N)=k
Arnauld

Réponses:


14

Rubis, 74 octets

->n{(1..n).map{|x|a=(n^x*x).to_s 2;a.size>Math.log2(n)?n:a.count(?1)}.min}

Essayez-le en ligne!

Cela génère simplement la séquence (ce qui est beaucoup plus que suffisant), la XOR avec n , puis prend soit le nombre de 1 dans sa représentation binaire si le nombre de bits est inférieur supérieur ou égal à log 2 n , ou n sinon. Il prend alors le nombre minimum de bits retournés. Renvoyer n au lieu du nombre de bits inversés lorsque le bit inversé le plus élevé est supérieur à log 2 n empêche ces cas d'être choisis comme minimum, car n[12,22,,n2]nlog2nnnlog2nn sera toujours supérieur au nombre de bits dont il dispose.

Merci à Piccolo d' avoir enregistré un octet.


Vous pouvez enregistrer un octet en utilisant (n^x*x).to_s 2;...au lieu de(n^x*x).to_s(2);...
Piccolo

@Piccolo Je ne peux pas croire que j'ai raté ça, merci!
Poignée de porte

6

Gelée , 12 octets

²,BẈEðƇ²^B§Ṃ

Essayez-le en ligne!

Découvrez une suite de tests!

Lien monadique. Devrait être jouable au golf. Mais je suis trop stupide pour penser à un moyen de me débarrasser de l' ³art. C'est ma première réponse dans laquelle j'utilise avec succès le filtrage / mappage / bouclage en général avec une chaîne dyadique \ o /

Explication

², BẈEðƇ² ^ B§Ṃ - Programme complet / Liaison monadique. Appelez l'argument N.
     ðƇ - Filtrer-garder [1 ... N] avec la chaîne dyadique suivante:
², BẈE - Le carré de l'élément actuel a la même longueur de bits que N.
² - Carré.
 , - Jumeler avec N.
  B - Convertissez les deux en binaire.
   Ẉ - Récupérez leurs longueurs.
    E - Et vérifiez s'ils sont équivalents.
       ² ^ - Après filtrage, mettez au carré les résultats et XOR avec N.
         B - Représentation binaire de chacun.
          § - Somme de chacun. Compte le nombre de 1 en binaire.
           Ṃ - Minimum.

5

Coque , 20 octets

▼mΣfo¬→S↑(Mo¤ż≠↔ḋİ□ḋ

Essayez-le en ligne!

Explication

▼mΣf(¬→)S↑(M(¤ż≠↔ḋ)İ□ḋ) -- example input n=4
        S↑(           ) -- take n from n applied to (..)
                     ḋ  -- | convert to binary: [1,0,0]
                   İ□   -- | squares: [1,4,9,16,...]
           M(     )     -- | map with argument ([1,0,0]; example with 1)
                 ḋ      -- | | convert to binary: [1]
             ¤  ↔       -- | | reverse both arguments of: [1] [0,0,1]
              ż≠        -- | | | zip with inequality (absolute difference) keeping longer elements: [1,0,1]
                        -- | : [[1,0,1],[0,0,0],[1,0,1,1],[0,0,1,0,1],[1,0,1,1,1],....
                        -- : [[1,0,1],[0,0,0],[1,0,1,1],[0,0,1,0,1]]
    f(  )               -- filter elements where
       →                -- | last element
      ¬                 -- | is zero
                        -- : [[0,0,0]]
 mΣ                     -- sum each: [0]
▼                       -- minimum: 0

▼mΣfo¬←ṠMz≠ȯfo£İ□ḋπŀ2Lḋenregistre 2 octets. RIP vous parfait score carré.
M. Xcoder

@ Mr.Xcoder: Dommage pour le score .. Mais je m'en suis débarrassé de plus, maintenant je vis le 16; P
ბიმო

5

Perl 6 , 65 octets

{min map {+$^a.base(2).comb(~1) if sqrt($a+^$_)!~~/\./},^2**.msb}

Essayez-le en ligne!

Je me sens un peu sale pour tester un carré parfait en recherchant un point dans la représentation sous forme de chaîne de la racine carrée du nombre, mais ... tout pour raser les octets.


4

05AB1E , 20 15 octets

Lnʒ‚b€gË}^b€SOß

-5 octets grâce à @ Mr.Xcoder utilisant un portage de sa réponse Jelly .

Essayez-le en ligne ou vérifiez tous les cas de test (les trois plus grands cas de test sont supprimés car ils expirent après 60 secondes; il faut encore environ 35 à 45 secondes avec les autres cas de test).

Explication:

L            # Create a list in the range [1, input]
             #  i.e. 22 → [0,1,2,...,20,21,22]
 n           # Take the square of each
             #  i.e. [0,1,2,...,20,21,22] → [0,1,4,...,400,441,484]
  ʒ     }    # Filter this list by:
   ,         #  Pair the current value with the input
             #   i.e. 0 and 22 → [0,22]
             #   i.e. 25 and 22 → [25,22]
    b        #  Convert both to binary strings
             #   i.e. [0,22] → ['0','10110']
             #   i.e. [25,22] →  ['10000','11001']
     g      #  Take the length of both
             #   i.e. ['0','10110'] → [1,5]
             #   ['10000','11001'] → [5,5]
       Ë     #  Check if both are equal
             #   i.e. [1,5] → 0 (falsey)
             #   i.e. [5,5] → 1 (truthy)
^            # After we've filtered, Bitwise-XOR each with the input
             #  i.e. [16,25] and 22 → [6,15]
 b           # Convert each to a binary string again
             #  i.e. [6,15] → ['110','1111']
  S         # Change the binary strings to a list of digits
             #  i.e. ['110','1111'] → [['1','1','0'],['1','1','1','1']]
    O        # Take the sum of each
             #  i.e. [['1','1','0'],['1','1','1','1']] → [2,4]
ß            # And then take the lowest value in the list
             #  i.e. [2,4] → 2

1
D' accord , alors, 15-byter valide: Lnʒ‚b€gË}^b€SOß. Malheureusement, cela casse votre suite de tests
M. Xcoder

1
@ Mr.Xcoder Merci! Et ma suite de tests se casse presque toujours après avoir joué quelque chose. XD Mais c'est maintenant corrigé aussi.
Kevin Cruijssen

Je suppose que je ne suis pas bon pour écrire des suites de tests dans 05AB1E ¯ \ _ (ツ) _ / ¯, c'est bien que vous l'ayez corrigé :)
M. Xcoder


3

Gaia , 18 octets

Près du port de ma réponse Jelly .

s¦⟪,b¦l¦y⟫⁇⟪^bΣ⟫¦⌋

Essayez-le en ligne!

Panne

s¦⟪, b¦l¦y⟫⁇ ⟪^ bΣ⟫¦⌋ - Programme complet. Appelons l'entrée N.
s¦ - Carrez chaque entier dans la plage [1 ... N].
  ⟪⟫⁇ - Sélectionnez ceux qui remplissent une certaine condition, lorsqu'ils sont parcourus
                     un bloc dyadique. L'utilisation d'un bloc dyadique économise un octet car le
                     l'entrée, N, est implicitement utilisée comme un autre argument.
   , - Associez l'élément actuel et N dans une liste.
    b¦ - Convertissez-les en binaire.
      l¦ - Obtenez leurs longueurs.
        y - Vérifiez ensuite si elles sont égales.
           ⟪⟫¦ - Exécutez tous les entiers valides via un bloc dyadique.
            ^ - XOR chacun avec N.
             bΣ - Convertir en binaire et somme (compter les 1 en binaire)
                 ⌋ - Le minimum.

2

Brachylog , 56 41 octets

Ça ne battra aucun record de longueur mais je pensais que je le posterais quand même

⟨⟨{⟦^₂ᵐḃᵐ}{h∋Q.l~t?∧}ᶠ{ḃl}⟩zḃᶠ⟩{z{∋≠}ᶜ}ᵐ⌋

Essayez-le en ligne!


La fermeture éclair vient de se réaliser. Je vais le raccourcir après mon retour du dîner
Kroppeb

1
@Arnauld Oui, le principal problème était que pour chaque i dans la plage (0, n + 1), je recalculais la plage, la mettais au carré et en binaire. Mettre cet extérieur a récupéré quelques octets de plus, mais c'est beaucoup plus rapide maintenant
Kroppeb

2

assemblage x86-64, 37 octets

Bytecode:

53 89 fb 89 f9 0f bd f7 89 c8 f7 e0 70 12 0f bd
d0 39 f2 75 0b 31 f8 f3 0f b8 c0 39 d8 0f 42 d8
e2 e6 93 5b c3

Eh bien, cela calcule même l'exemple le plus élevé en moins d'une seconde.

Le cœur de l'algorithme est xor / popcount comme d'habitude.

    push %rbx
    /* we use ebx as our global accumulator, to see what the lowest bit
     * difference is */
    /* it needs to be initialized to something big enough, fortunately the
     * answer will always be less than the initial argument */
    mov %edi,%ebx
    mov %edi,%ecx
    bsr %edi,%esi
.L1:
    mov %ecx,%eax
    mul %eax
    jo cont     /* this square doesn't even fit into eax */
    bsr %eax,%edx
    cmp %esi,%edx
    jnz cont    /* can't invert bits higher than esi */
    xor %edi,%eax
    popcnt %eax,%eax
    cmp %ebx,%eax   /* if eax < ebx */
    cmovb %eax,%ebx
cont:
    loop .L1
    xchg %ebx,%eax
    pop %rbx
    retq

Suggérez de remplacer au moins l'un de vos movs par unxchg
plafondcat

Autant que je sache, il n'y en a qu'un qui sauverait un octet ( mov %ecx,%eax) et je ne peux pas laisser mourir% ecx.
ObsequiousNewt

1

Wolfram Language (Mathematica) , 67 octets

Min@DigitCount[l=BitLength;#~BitXor~Pick[s=Range@#^2,l@s,l@#],2,1]&

Essayez-le en ligne!

Prend {1,2,,n}et les équerre. Ensuite, les nombres avec le même BitLengthque l'entrée sont Pickédités et BitXorédités avec l'entrée. Ensuite, l' Minimum DigitCountde 1s en binaire est retourné.


1

Fusain , 31 octets

NθI⌊EΦEθ↨×ιι²⁼LιL↨θ²ΣE↨責⁼λ§ιμ

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

Nθ                              Input N
       θ                        N
      E                         Map over implicit range
          ιι                    Current value (twice)
         ×                      Multiply
        ↨   ²                   Convert to base 2
     Φ                          Filter over result
               ι                Current value
                  θ             N
                 ↨ ²            Convert to base 2
              L L               Length
             ⁼                  Equals
    E                           Map over result
                       θ        N
                      ↨ ²       Convert to base 2
                     E          Map over digits
                           λ    Current base 2 digit of N
                             ι  Current base 2 value
                              μ Inner index
                            §   Get digit of value
                          ⁼     Equals
                         ¬      Not (i.e. XOR)
                    Σ           Take the sum
   ⌊                            Take the minimum
  I                             Cast to string
                                Implicitly print




1

C (gcc) ,  93  91 octets

g(n){n=n?n%2+g(n/2):0;}m;i;d;f(n){m=99;for(i=0;++i*i<2*n;m=g(d=i*i^n)<m&d<n/2?g(d):m);n=m;}

Essayez-le en ligne!


Edit: Je pense que ma solution d'origine ( Essayez-la en ligne! ) N'est pas valide, car l'une des variables,, mglobale pour économiser quelques octets en ne spécifiant pas de type, a été initialisée en dehors de f(n)et a donc dû être réinitialisée entre les appels


Code non golfé et commenté:

g(n){n=n?n%2+g(n/2):0;} // returns the number of bits equal to 1 in n
m; //miminum hamming distance between n and a square
i; //counter to browse squares
d; //bitwise difference between n and a square
f(n){m=99; //initialize m to 99 > size of int (in bits)
    for(
        i=0;
        ++i*i<2*n; //get the next square number, stop if it's greater than 2*n
        g(d=i*i^n)<m&&d<n/2&&(m=g(d)) //calculate d and hamming distance
//      ^~~~~~~~~~~^ if the hamming distance is less than the minimum
//                    ^~~~^ and the most significant bit of n did not change (the most significant bit contains at least half the value)
//                           ^~~~~~~^ then update m
       );
    n=m;} // output m

Modifications:

  • Enregistré 2 octets grâce au plafond
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.