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ı .110001100125=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ış .23201830101101000016=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 . N10000
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ük2nnngünlük2nn 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.