Biraz bit geçin ve bir kare alın


26

Tamsayı bir Verilen , sen ihtiyaç içinde tersyüz edilmesine o bit minimum sayıda bulmak zorunda bir çevirmek için kare sayısı . En önemlisinin altındaki bitleri ters çevirmenize izin verilir .NN>3N

Örnekler

  • 2 2N=4 zaten bir kare sayı ( ), bu nedenle beklenen çıktı .220
  • N=24 , 1 bit: ( ) ters çevirerek kare bir sayıya dönüştürülebilir , bu nedenle beklenen çıktı .11000→1100125=521
  • N=22 , tek bir bit ters çevrilerek kare sayıya dönüştürülemez (olası sonuçlar , , ve ), ancak 2 bit ters çevrilerek yapılabilir: ( ), yani beklenen çıkış .2320183010110→1000016=422

kurallar

  • Kodunuzun çok yavaş olması veya daha büyük test senaryoları için bir hata atması iyi olabilir, ancak en az 1 dakikadan daha az bir sürede desteklemesi gerekir .3<N<10000
  • Bu !

Test durumları

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

Veya kopyala / yapıştır dostu formatta:

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

Yanıtların neredeyse yarısı 100048606TIO’da yerine getirilmiyor , bu bir sorun mu?
— Magic Octopus Urn

@MagicOctopusUrn Teşekkürler, 10000'ü desteklemenin isteğe bağlı olduğunu daha açık hale getirmek için kuralları güncelledim . N≥10000
— Arnauld,

1
Bu da en hızlı kodlu güzel bir soru olacaktır (giriş boyutu kısıtlaması olmadan)
— qwr

@qwr Evet, muhtemelen. Eğer sert gitmek isterseniz Veya: Verilen , en küçük bulmak öyle ki . kNf(N)=k
— Arnauld,

Yanıtlar:


14

Ruby, 74 bayt

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

Çevrimiçi deneyin!

Bu sadece dizisini oluşturur (fazlasıyla yeterlidir), XOR onu n ile alır ve sonra bit sayısı daha azsa, ikili gösteriminde 1 sayısını alır. log 2 n'ye eşit veya daha büyük , aksi takdirde n . Daha sonra çevrilen minimum bit sayısını alır. Tekrar N çevrilmiş yüksek bit daha büyük olduğu zaman bunun yerine ters çevrilmiş bit sayısı log 2 N kadar, asgari olarak seçilen edilmesini önler bu gibi durumlarda , n[12,22,…,n2]ngünlük2⁡nnngünlük2⁡nn her zaman sahip olduğu bit sayısından daha büyük olacaktır.

Bayt tasarrufu için Piccolo'ya teşekkürler .


Bunun (n^x*x).to_s 2;...yerine bir bayt kaydedebilirsiniz(n^x*x).to_s(2);...
— Piccolo

@ Piccolo Bunu kaçırdığıma inanamıyorum, teşekkürler!
— Doorknob

6

Jöle , 12 bayt

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

Çevrimiçi deneyin!

Test odasına göz atın!

Monadik bağlantı. Golf edilebilir olmalı. Ama onlardan kurtulmanın bir yolunu düşünmek için çok aptalım ³. Bu benim ilk cevabım, genel olarak bir dyadic zinciri ile birlikte filtreleme / haritalama / döngüleme işlemini başarıyla kullandığım.

açıklama

², BẈEðƇ² ^ B§Ṃ - Tam program / Monadic bağlantısı. Argümanı N olarak adlandır.
     Filter - Aşağıdaki diyadik zincirli filtre tutma [1 ... N]:
², BẈE - Geçerli öğenin karesi N ile aynı bit uzunluğuna sahiptir.
² - Kare.
 , - N ile eşleştirin
  B - İkisini de ikiliye dönüştürün.
   Ẉ - Uzunluklarını al.
    E - Ve eşit olup olmadıklarını kontrol edin.
       ² ^ - Filtrelemeden sonra sonuçları kareleyin ve NOR ile N yapın.
         B - Her birinin ikili gösterimi.
          § - Her birinin toplamı. İkili sayıdaki 1 sayısını sayar.
           Minimum - Minimum.

5

Kabuğu , 20 bayt

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

Çevrimiçi deneyin!

açıklama

▼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ḋ2 bayt kaydeder. RIP size mükemmel kare puanı.
— Bay Xcoder,

@ Mr.Xcoder: Skordan dolayı utanç duyuyorum. Ama şimdi 16'yı hedef alan biraz daha kurtuldum; P
— ბიმო

5

Perl 6 , 65 bayt

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

Çevrimiçi deneyin!

Sayıların karekökünün dize temsili bir süre bakarak mükemmel bir kare için test biraz kirli hissediyorum, ama ... bayt tıraş için bir şey.


4

05AB1E , 20 15 bayt

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

Jelly cevabının bir portunu kullanan @ Mr.Xcoder sayesinde -5 bayt .

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın (en büyük üç test vakası kaldırıldı çünkü 60 saniyeden sonra zaman aşımına uğradı; yine de diğer test vakalarıyla 35-45 saniye sürüyor).

Açıklama:

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
Tamam o zaman, geçerli bir 15-Byter: Lnʒ‚b€gË}^b€SOß. Ne yazık ki, test takımını kırar
— Bay Xcoder

1
@ Mr.Xcoder Teşekkürler! Ve test takımım neredeyse her zaman bir şeyi golf oynadıktan sonra kırılıyor .. XD Ama şimdi de düzeltildi.
— Kevin Cruijssen,

Sanırım 05AB1E 'de test takımları yazma konusunda iyi değilim ¯ \ _ (ツ) _ / ¯, düzeltmiş olmanız çok hoş :)
— Bay Xcoder


3

Gaia , 18 bayt

Jelly cevabımın yakın limanı .

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

Çevrimiçi deneyin!

Yıkmak

s¦⟪, b¦l¦y⟫⁇ ⟪^ bΣ⟫¦⌋ - Tam program. N girişini çağıralım.
s¦ - [1 ... N] aralığında her tamsayıyı kare.
  Ran⟫⁇ - Koştuğunda belli bir koşulu yerine getirenleri seç
                     ikili bir blok. Dyadic blok kullanarak bir bayt kazandırır çünkü
                     giriş, N, örtük olarak başka bir argüman olarak kullanılır.
   , - Geçerli öğeyi ve N'yi bir listede eşleştirin.
    b them - Onları ikiliye dönüştürün.
      l¦ - Uzunluklarını al.
        y - O zaman eşit olup olmadıklarını kontrol edin.
           Valid ⟫¦ - Tüm geçerli tamsayıları ikili bir blok üzerinden çalıştırın.
            ^ - Her biri N olan XOR
             bΣ - İkili ve toplama çevir (ikilikteki 1leri say)
                 Minimum - Minimum.

2

Brachylog , 56 41 bayt

Uzunluk kayıtlarını kırmayacak ama yine de göndereceğimi sanıyor

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

Çevrimiçi deneyin!


Sıkıştırmanın farkına varmış bir şey.
— Lokantadan

1
@Arnauld Evet, asıl sorun, aralıktaki her i için (0, n + 1) aralığı yeniden hesapladım, kare haline getirdim ve ikili olarak yaptım. Bunu dışarıya koymak bir kaç bayt daha aldı ancak şimdi çok daha hızlı
— Kroppeb

2

x86-64 derleme, 37 bayt

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

Güzel, bu en yüksek örneği bile bir saniyeden daha kısa sürede hesaplar.

Algoritmanın kalbi her zamanki gibi xor / popcount'tur.

    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

Senin en az birini yerine öner movbir s'ylexchg
— ceilingcat

Söyleyebildiğim kadarıyla bir byte ( mov %ecx,%eax) kazandıracak tek bir tane var ( ) ve% ecx'in orada ölmesine izin veremem.
— ObsequiousNewt

1

Wolfram Dili (Mathematica) , 67 bayt

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

Çevrimiçi deneyin!

Alır {1,2,...,n}ve onları kareler. Daha sonra, aynı olan sayılar BitLengthgirdi olarak edilir Picked ve BitXorgiriş ile ed. Daha sonra , s cinsinden ikili Minimum döndürülür.DigitCount1


1

Kömür , 31 bayt

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

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Açıklama:

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 bayt

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

Çevrimiçi deneyin!


Düzenleme: Orijinal çözümümün ( Çevrimiçi deneyin! ) Geçerli olmadığını düşünüyorum, çünkü değişkenlerden biri, mtür belirterek birkaç bayttan tasarruf etmek için genel değişkenlerden biri dışında başlatıldı f(n)ve bu nedenle çağrılar arasında yeniden başlatılması gerekiyordu.


Ungolfed ve yorumlanan kod:

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

Düzenlemeler:

  • Ceilingcat sayesinde 2 bayt kurtardı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.