Attiva alcuni bit e ottieni un quadrato


26

Dato un numero intero , devi trovare il numero minimo di bit che devono essere invertiti in per trasformarlo in un numero quadrato . È consentito invertire solo i bit al di sotto di quello più significativo .N>3N

Esempi

  • N=4 è già un numero quadrato ( ), quindi l'output previsto è .220
  • N=24 può essere trasformato in un numero quadrato invertendo 1 bit: ( ), quindi l'output previsto è .110001100125=521
  • N=22 non può essere trasformato in un numero quadrato invertendo un singolo bit (i risultati possibili sono , , e ), ma può essere fatto invertendo 2 bit: ( ), quindi l'output previsto è .23201830101101000016=422

Regole

  • Va bene se il tuo codice è troppo lento o genera un errore per i casi di test più grandi, ma dovrebbe almeno supportare in meno di 1 minuto.3<N<10000
  • Questo è !

Casi 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")

O in formato amichevole copia / incolla:

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

Quasi la metà delle risposte non viene eseguita 100048606su TIO, è un problema?
Magic Octopus Urn

@MagicOctopusUrn Grazie, ho aggiornato le regole per chiarire che il supporto di è facoltativo. N10000
Arnauld,

1
Anche questa sarebbe una bella domanda con il codice più veloce (senza la limitazione della dimensione dell'input)
qwr

@qwr Sì, probabilmente. O se vuoi diventare hardcore: dato , trova la più piccola tale che . N f ( N ) = kKNf(N)=K
Arnauld,

Risposte:


14

Rubino, 74 byte

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

Provalo online!

Questo genera semplicemente la sequenza (che è molto più che sufficiente), XORs con n , e quindi prende il numero di 1s nella sua rappresentazione binaria se il numero di bit è inferiore uguale o uguale a log 2 n , oppure n altrimenti. Prende quindi il numero minimo di bit capovolti. Restituire n invece del numero di bit capovolti quando il bit più alto capovolto è maggiore del log 2 n impedisce a questi casi di essere scelti come minimo, come n[12,22,...,n2]nlog2nnnlog2nn sarà sempre maggiore del numero di bit che ha.

Grazie a Piccolo per aver salvato un byte.


Puoi salvare un byte usando (n^x*x).to_s 2;...invece di(n^x*x).to_s(2);...
Piccolo

@Piccolo Non riesco a credere che mi sia mancato, grazie!
Maniglia della porta

6

Gelatina , 12 byte

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

Provalo online!

Dai un'occhiata a una suite di test!

Collegamento monadico. Dovrebbe essere golfabile. Ma sono troppo stupido per pensare a un modo per sbarazzarsi della ³s. È la mia prima risposta in cui uso con successo filtri / mapping / loop in generale insieme a una catena diadica \ o /

Spiegazione

², BẈEðƇ² ^ B§Ṃ - Programma completo / collegamento Monadic. Chiama l'argomento N.
     ðƇ - Filter-keep [1 ... N] con la seguente catena diadica:
², BẈE - Il quadrato dell'articolo corrente ha la stessa lunghezza di bit di N.
² - Quadrato.
 , - Abbina a N.
  B - Converti entrambi in binario.
   Ẉ - Recupera le loro lunghezze.
    E - E controlla se si equivalgono.
       ² ^ - Dopo aver filtrato, quadrare i risultati e XOR con N.
         B - Rappresentazione binaria di ciascuno.
          § - Somma di ciascuno. Conta il numero di 1 in binario.
           Ṃ - Minimo.

5

Buccia , 20 byte

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

Provalo online!

Spiegazione

▼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ḋsalva 2 byte. Ripeti il ​​tuo punteggio quadrato perfetto.
Mr. Xcoder

@ Mr.Xcoder: Peccato per il punteggio .. Ma mi sono sbarazzato di un po 'di più, ora puntando a 16; P
ბიმო

5

Perl 6 , 65 byte

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

Provalo online!

Mi sento un po 'sporco per provare un quadrato perfetto cercando un punto nella rappresentazione di stringa della radice quadrata del numero, ma ... qualsiasi cosa per radere i byte.


4

05AB1E , 20 15 byte

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

-5 byte grazie a @ Mr.Xcoder usando una porta della sua risposta Jelly .

Provalo online o verifica tutti i casi di test (i tre casi di test più grandi vengono rimossi perché scadono dopo 60 secondi; impiegano ancora circa 35-45 secondi con gli altri casi di test).

Spiegazione:

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
Va bene allora, una valida 15-byter: Lnʒ‚b€gË}^b€SOß. Purtroppo, però, interrompe la tua suite di test
Mr. Xcoder

1
@ Mr.Xcoder Grazie! E la mia suite di test si interrompe quasi sempre dopo aver giocato a golf qualcosa .. XD Ma ora è stato risolto.
Kevin Cruijssen,

Immagino di non essere bravo a scrivere test suite in 05AB1E ¯ \ _ (ツ) _ / ¯, è bello che tu l'abbia corretto :)
Mr. Xcoder,


3

Gaia , 18 byte

Near-port della mia risposta Jelly .

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

Provalo online!

Abbattersi

s¦⟪, b¦l¦y⟫⁇ ⟪^ bΣ⟫¦⌋ - Programma completo. Chiamiamo l'ingresso N.
s¦ - Square ogni intero nell'intervallo [1 ... N].
  ⟪⟫⁇ - Seleziona quelli che soddisfano una determinata condizione, quando attraversati
                     un blocco diadico. L'uso di un blocco diadico consente di risparmiare un byte perché il
                     input, N, è implicitamente usato come un altro argomento.
   , - Associa l'elemento corrente e N in un elenco.
    b¦ - Li converte in binario.
      l¦ - Ottieni le loro lunghezze.
        y - Quindi controlla se sono uguali.
           ⟪⟫¦ - Esegue tutti gli interi validi attraverso un blocco diadico.
            ^ - XOR ciascuno con N.
             bΣ - Converti in binario e somma (conta gli 1 in binario)
                 ⌋ - Minimo.

2

Brachylog , 56 41 byte

Non supererà nessun record di lunghezza, ma ho pensato di pubblicarlo comunque

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

Provalo online!


Ho appena realizzato che zippare è una cosa. Lo accorcerò dopo essere tornato dal ristorante
Kroppeb il

1
@Arnauld Sì, il problema principale era che per ogni i nell'intervallo (0, n + 1) ho ricalcolato l'intervallo, quadrato e binario. Mettere questo fuori ha richiesto alcuni byte in più ma ora è molto più veloce
Kroppeb

2

assembly x86-64, 37 byte

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

Bene, questo calcola anche l'esempio più alto in meno di un secondo.

Il cuore dell'algoritmo è xor / popcount come al solito.

    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

Suggerisci di sostituire almeno una delle tue movs con unxchg
ceilingcat il

Per quanto ne so ce n'è solo uno che salverebbe un byte ( mov %ecx,%eax) e non posso lasciare che% ecx muoia lì.
ObsequiousNewt,


1

Carbone , 31 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

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 byte

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;}

Provalo online!


Modifica: penso che la mia soluzione originale ( provalo online! ) Non sia valida, perché una delle variabili m, globale per salvare qualche byte non specificando il tipo, è stata inizializzata al di fuori di f(n)e quindi ha dovuto essere reinizializzata tra le chiamate


Codice non registrato e commentato:

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

modifiche:

  • Salvato 2 byte grazie a ceilingcat
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.