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


26

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

Приклади

  • - це квадратне число ( 2 2 ), тому очікуваний вихід дорівнює 0 .N=4220
  • можна перетворити на квадратне число, перевернувши 1 біт: 11000 1100 1 ( 25 = 5 2 ), тому очікуваний вихід дорівнює 1 .N=24110001100125=521
  • не можна перетворити на квадратне число, перевернувши один біт (можливі результати - 23 , 20 , 18 і 30 ), але це можна зробити, перевернувши 2 біти: 10110 10 0 0 0 ( 16 = 4 2 ) , тому очікуваний вихід 2 .N=2223201830101101000016=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 Спасибі, я оновив правила, щоб зрозуміти, що підтримка необов’язкова. N10000
Арнольд

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]nlog2nnn не дозволяє цим випадкам бути обраним як мінімум, як nlog2nn завжди буде більше, ніж кількість біт, яку вона має.

Завдяки 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.