Перемістіть кілька біт і отримайте квадрат


26

З огляду на ціле число , ви повинні знайти мінімальну кількість бітів, які потрібно перевернути в N, щоб перетворити його на квадратне число . Ви можете інвертувати лише біти нижче найзначнішого .N>3N

Приклади

  • - це квадратне число ( 2 2 ), тому очікуваний вихід дорівнює 0 .N=4220
  • можна перетворити на квадратне число, перевернувши 1 біт: 11000 → 1100 1 ( 25 = 5 2 ), тому очікуваний вихід дорівнює 1 .N=2411000→1100125=521
  • не можна перетворити на квадратне число, перевернувши один біт (можливі результати - 23 , 20 , 18 і 30 ), але це можна зробити, перевернувши 2 біти: 10110 → 10 0 0 0 ( 16 = 4 2 ) , тому очікуваний вихід 2 .N=222320183010110→1000016=422

Правила

  • Це добре, якщо ваш код занадто повільний або видає помилку для більших тестових випадків, але він повинен принаймні підтримувати менше ніж за 1 хвилину.3<N<10000
  • Це !

Тестові справи

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

Або в зручному для копіювання / вставлення форматі:

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

Майже половина відповідей не виконується 100048606на TIO, це проблема?
— Чарівний восьминога Урна

@MagicOctopusUrn Спасибі, я оновив правила, щоб зрозуміти, що підтримка необов’язкова. N≥10000
— Арнольд

1
Це також було б гарним питанням швидкого коду (без обмеження розміру вводу)
— qwr

@qwr Так, напевно. Або якщо ви хочете перейти на хардкор: заданий , знайдіть найменший N такий, що f ( N ) = k . kNf(N)=k
— Арнольд

Відповіді:


14

Рубін, 74 байти

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

Спробуйте в Інтернеті!

Це просто генерує послідовність (що набагато більше, ніж достатньо), XOR позначає її n , а потім приймає або число 1s у своєму двійковому поданні, якщо кількість бітів менше ніж або дорівнює log 2 n , або n інакше. Потім потрібно мінімальна кількість бітів, перевернутих. Повернення n замість кількості бітів, що перевернулися, коли найвищий біт перевернутий більший за[12,22,…,n2]nlog2⁡nnn не дозволяє цим випадкам бути обраним як мінімум, як nlog2⁡nn завжди буде більше, ніж кількість біт, яку вона має.

Завдяки Piccolo за збереження байта.


Ви можете зберегти байт, скориставшись (n^x*x).to_s 2;...замість(n^x*x).to_s(2);...
— Piccolo

@Piccolo Не можу повірити, що я пропустив це, дякую!
— Дверна ручка

6

Желе , 12 байт

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

Спробуйте в Інтернеті!

Перевірте тестовий набір!

Монадична посилання. Повинно бути гофрованим.Але я занадто німий, щоб думати про спосіб позбутися від ³s. Це моя перша відповідь, в якій я успішно використовую фільтрування / картографування / циклічне цикління взагалі разом із діадичним ланцюгом \ o /

Пояснення

², BẈEðƇ² ^ B§Ṃ - Повна програма / Монадичне посилання. Назвіть аргумент N.
     ðƇ - зберігати фільтр [1 ... N] із наступним діадичним ланцюгом:
², BẈE - Квадрат поточного елемента має ту саму довжину бітів, що і N.
² - площа.
 , - Пара з Н.
  В - Перетворення обох у двійкове.
   Ẉ - Отримайте їх довжину.
    Е - І перевірте, чи вони рівні.
       ² ^ - Після відфільтрування результати поверніть на квадрат і оберніть їх N.
         В - Двійкове представлення кожного.
          § - сума кожного. Підраховує кількість одиниць у двійкових.
           Ṃ - Мінімум.

5

Лушпиння , 20 байт

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

Спробуйте в Інтернеті!

Пояснення

▼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 байти. RIP вам ідеальний квадратний бал.
— Містер Xcoder

@ Mr.Xcoder: Ганьба щодо рахунку .. Але я позбувся ще кількох, зараз націлюючись на 16; P
— червень

5

Perl 6 , 65 байт

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

Спробуйте в Інтернеті!

Я відчуваю трохи брудності для тестування ідеального квадрата, шукаючи період у рядковому зображенні квадратного кореня числа, але ... що-небудь, щоб відтерти байти.


4

05AB1E , 20 15 байт

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

-5 байт завдяки @ Mr.Xcoder, що використовує порт його відповіді Jelly .

Спробуйте в режимі он-лайн або перевірте всі тестові випадки (три найбільші тестові випадки вилучаються, оскільки вони закінчуються через 60 секунд; для інших тестових випадків все-таки триває приблизно 35-45 сек).

Пояснення:

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
Добре, дійсний 15-byter: Lnʒ‚b€gË}^b€SOß. На жаль, це розбиває ваш тестовий набір
— Містер Xcoder

1
@ Mr.Xcoder Дякую! А мій тестовий набір майже завжди виходить з ладу після того, як я щось гольфую .. XD Але це також виправлено і зараз.
— Kevin Cruijssen

Я думаю, мені не добре писати тестові набори в 05AB1E ¯ \ _ (ツ) _ / ¯, приємно, що ви це виправили :)
— Містер Xcoder


3

Гая , 18 байт

Поблизу моєї відповіді Желе .

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

Спробуйте в Інтернеті!

Зламатися

s¦⟪, b¦l¦y⟫⁇ ⟪^ bΣ⟫¦⌋ - Повна програма. Назвемо вхідний N.
s¦ - квадрат кожного цілого числа в діапазоні [1 ... N].
  ⟪⟫⁇ - Виберіть тих, хто відповідає певній умові, коли ви пробіжетесь
                     діадичний блок. Використання діадичного блоку зберігає один байт, оскільки
                     вхід, N, неявно використовується як інший аргумент.
   , - З'єднайте поточний елемент і N у списку.
    b¦ - Перетворіть їх у двійкове.
      l¦ - Отримайте їх довжину.
        y - Потім перевірте, чи рівні вони.
           ⟪⟫¦ - запустіть усі дійсні цілі числа через діадичний блок.
            ^ - XOR кожен з N.
             bΣ - Перетворити на двійкове та суму (порахуй 1s у двійковій)
                 ⌋ - Мінімум.

2

Брахілог , 56 41 байт

Він не зламає жодних рекордів по довжині, але подумав, що все одно опублікую

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

Спробуйте в Інтернеті!


Щойно зрозуміла, що блискавка - це річ. Я вкорочую її після того, як повернусь із закусочної
— Круппеб

1
@Arnauld Так, головна проблема полягала в тому, що для кожного i в діапазоні (0, n + 1) я перерахував діапазон, відправив його у квадрат і до двійкового. Помістивши це назовні, набрали ще декілька байтів, але зараз це швидше
— Kroppeb

2

x86-64 збірка, 37 байт

Байт-код:

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

Приємно, що це обчислює навіть найвищий приклад менше ніж за секунду.

Серцем алгоритму є xor / popcount, як завжди.

    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

Запропонуйте замінити принаймні одного свого movs наxchg
— roofcat

Наскільки я можу сказати, є лише один, який би врятував байт ( mov %ecx,%eax), і я не можу дозволити там померти% ecx.
— ObsequiousNewt

1

Мова Вольфрама (Mathematica) , 67 байт

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

Спробуйте в Інтернеті!

Бере {1,2,…,н}і квадрати їх. Потім цифри, такі BitLengthяк вхід, Pickредагуються, а BitXored - з введенням. Далі MinIMUM DigitCountз 1ї в двійковій системі повертається.


1

Вугілля деревне , 31 байт

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

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 байт

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

Спробуйте в Інтернеті!


Редагувати: Я думаю, що моє оригінальне рішення ( спробуйте його в Інтернеті! ) Недійсне, оскільки одна із змінних m, глобальна для збереження кількох байтів, не вказуючи тип, була ініціалізована позаf(n) і тому довелося повторно ініціалізуватися між викликами


Невикористаний та коментований код:

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

Зміни:

  • Збережено 2 байти завдяки стельовій коті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.