Поміняйте паритет


22

Завдання

Давши додатне ціле число n, вивести, n+1якщо nнепарне, а вихід, n-1якщо nпарне.

Вхідні дані

Позитивне ціле число. Ви можете припустити, що ціле число знаходиться в межах можливості обробки мови.

Вихідні дані

Позитивне ціле число, вказане вище.

Тестові шафи

input output
    1      2
    2      1
    3      4
    4      3
    5      6
    6      5
    7      8
    8      7
  313    314
  314    313

Оцінка балів

Це , тому найкоротша відповідь у байтах виграє.

Застосовуються стандартні лазівки .

Список літератури


Чи можемо ми сприйняти внесок як одинаковий?
Kritixi Lithos

2
Це, на диво, набагато простіше, якби в деяких мовах було
навпаки

3
@MistahFiggins Це досить добре відомо, що я впевнений, що ОП це зробив це спеціально.
Ørjan Johansen

Відповіді:


24

C, 20 байт

f(x){return-(-x^1);}

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


7
@LeakyNun Я не пишу функції, у якій не вистачає заяви про повернення.
feersum

18
@EriktheOutgolfer Ні. Ні. Ну-е-е. №
feersum

10
@Sisyphus Але це код-гольф , і він працює на моєму посиланні TIO, тому це дійсно.
Ерік Аутгольфер

7
@EriktheOutgolfer Що я говорю, це те, що ваше твердження ("присвоєння першого аргументу еквівалентне твердженню повернення") фактично невірно. Чи може такий код створити робочу відповідь за певних обставин - це інше питання (на яке я звернувся в своєму першому коментарі, заявивши, що не планую публікувати жодного такого коду).
feersum

8
@EriktheOutgolfer Якщо відповідь покладається на певну поведінку впровадження, вона повинна вказати реалізацію. Ця відповідь ні, тому код був би недійсним.
Сизіф

17

Стек котів , 3 + 3 ( -n) = 6 байт

-*-

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

Потрібен -nпрапор для роботи з цифровим входом і виходом.

Пояснення

Stack Cats, як правило, далеко не конкурентоспроможний через обмежений набір команд (усі вони є ін'єкціями, а більшість з них - інволюціями) і тому, що кожна програма повинна мати дзеркальну симетрію. Однак однією із задумів є переключення найменш значущого біта числа, і ми можемо компенсувати значення за допомогою одинарного заперечення, яке також існує. На щастя, це дає нам симетричну програму, тому нам не потрібно турбуватися ні про що інше:

-   Multiply the input by -1.
*   Toggle the least significant bit of the value (i.e. take it XOR 1).
-   Multiply the result by -1.

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


1
Чи завжди прапори рахуються з додатковим простором, я не думаю, що я бачив інші відповіді за допомогою прапорів (наприклад, Perl) це роблять? EDIT: Добре nvm, знайдено відповідний мета-пост . " Я зараховую їх як різницю в кількості символів до найкоротшого еквівалентного виклику без них. " ... " perl -nle 'stuff'на 2 символи більше perl -e 'stuff', тому він нараховує ще 2 символи ". Так що (space)-nна 3 байти більше, ніж без прапора.
Кевін Круїссен

@KevinCruijssen Це залежить від того, скільки байтів потрібно насправді додати до звичайного виклику. У Perl і багатьох інших мовах виробництва, ви можете викликати код з , -e "code"а потім вставити додаткові прапори перед e, наприклад -pe "code". Тоді -pпрапор - це лише один байт. Однак у Stack Cats немає такого -eаргументу, тому вам завжди потрібно додати команду full <sp>-n, а значить, це три байти.
Мартін Ендер

12

x86 Асамблея, 9 байт (для змагального вступу)

Кожен, хто намагається вирішити цю проблему на мовах високого рівня, не вистачає справжнього задоволення від маніпулювання сирими бітами. Існує так багато тонких варіацій способів зробити це, божевільно - і дуже весело думати. Ось кілька рішень, які я розробив 32-бітною мовою збірки x86.

Я заздалегідь вибачаюся, що це не типова відповідь на гольф-код. Я збираюся багато роздумувати про мислений процес ітеративної оптимізації (для розміру). Сподіваємось, це цікаво та навчально для більшої аудиторії, але якщо ти тип TL; DR, я не ображаюся, якщо пропустиш до кінця.

Очевидним та ефективним рішенням є перевірка того, чи є значення непарним чи парним (що можна зробити ефективно, переглянувши найменш значимий біт), а потім вибрати відповідно n + 1 або n − 1 відповідно. Припускаючи, що вхід передається як параметр в ECXрегістр, а результат повертається в EAXрегістр, ми отримуємо таку функцію:

F6 C1 01  |  test  cl, 1                      ; test last bit to see if odd or even
8D 41 01  |  lea   eax, DWORD PTR [ecx + 1]   ; set EAX to n+1 (without clobbering flags)
8D 49 FF  |  lea   ecx, DWORD PTR [ecx - 1]   ; set ECX to n-1 (without clobbering flags)
0F 44 C1  |  cmovz eax, ecx                   ; move in different result if input was even
C3        |  ret

(13 байт)

Але для цілей коду-гольфу ці LEAінструкції не великі, оскільки для кодування вони займають 3 байти. Простий DECrement з ECXбуде набагато коротше (тільки один байт), але це впливає на прапори, тому ми повинні бути трохи розумний в тому , як ми організуємо код. Ми можемо зробити декремент першим , а непарний / парний тест другим , але потім нам доведеться перевернути результат непарного / парного тесту.

Крім того, ми можемо змінити інструкцію умовного переміщення на гілку, що може змусити код працювати повільніше (залежно від того, наскільки передбачувана гілка - якщо введення чергуватиметься непослідовно між непарною та парною, гілка буде повільнішою; якщо є шаблон, це буде швидше), що врятує нам ще один байт.

Фактично, за допомогою цієї редакції всю операцію можна зробити на місці, використовуючи лише один регістр. Це чудово, якщо ви десь інлігіруєте цей код (і, швидше за все, ви є, оскільки він такий короткий).

    48     |  dec  eax          ; decrement first
    A8 01  |  test al, 1        ; test last bit to see if odd or even
    75 02  |  jnz  InputWasEven ; (decrement means test result is inverted)
    40     |  inc  eax          ; undo the decrement...
    40     |  inc  eax          ; ...and add 1
  InputWasEven:                 ; (two 1-byte INCs are shorter than one 3-byte ADD with 2)

(впорядковано: 7 байт; як функція: 10 байт)

Але що робити, якщо ви хочете зробити це функцією? Жоден стандартний режим виклику не використовує той самий реєстр для передачі параметрів, як це відбувається для значення, що повертається, тому вам потрібно буде додати MOVінструкцію реєстрації регістру до початку або в кінці функції. Це майже не має витрат на швидкість, але це додає 2 байти. ( RETІнструкція також додає байт, і є деякий наклад, який вводиться необхідністю здійснювати і повертатись із виклику функції. Це означає, що це один із прикладів, коли вбудована лінія створює як швидкість, так і розмір, а не просто класичну швидкість -для космосу для простору.) Загалом, написаний як функція, цей код розширюється до 10 байт.

Що ще ми можемо зробити в 10 байт? Якщо ми взагалі піклуємося про ефективність (принаймні, передбачувану ефективність), було б непогано позбутися цієї гілки. Ось безгалузеве роздвоєне рішення, що має однаковий розмір у байтах. Основна передумова проста: ми використовуємо побітовий XOR, щоб перевернути останній біт, перетворивши непарне значення в парне, і навпаки. Але є одна ніггеля - для непарних входів, яка дає нам n-1 , а для парних входів - n + 1 - прямо протилежне тому, що ми хочемо. Отже, щоб виправити це, ми виконуємо операцію за від’ємним значенням, ефективно перевертаючи знак.

8B C1     |  mov eax, ecx   ; copy parameter (ECX) to return register (EAX)
          |
F7 D8     |  neg eax        ; two's-complement negation
83 F0 01  |  xor eax, 1     ; XOR last bit to invert odd/even
F7 D8     |  neg eax        ; two's-complement negation
          |
C3        |  ret            ; return from function

(впорядковано: 7 байт; як функція: 10 байт)

Досить стрункі; важко зрозуміти, як це можна покращити. Одне, однак, привертає до мене увагу: ці дві 2-байтні NEGінструкції. Відверто кажучи, два байти здаються одним байтом занадто багато, щоб кодувати просту заперечення, але це набір інструкцій, з яким ми повинні працювати. Чи є якісь обхідні шляхи? Звичайно! Якщо ми XORна -2, можемо замінити другу дію NEGна INCвідступ:

8B C1     |  mov eax, ecx
          |
F7 D8     |  neg eax
83 F0 FE  |  xor eax, -2
40        |  inc eax
          |
C3        |  ret

(впорядковано: 6 байт; як функція: 9 байт)

Ще одна з дивацтв набору інструкцій x86 - це багатоцільова LEAінструкція , яка може зробити переміщення регістру-реєстру, додавання реєстру-реєстру, компенсування постійною та масштабування всіх в одній інструкції!

8B C1        |  mov eax, ecx
83 E0 01     |  and eax, 1        ; set EAX to 1 if even, or 0 if odd
8D 44 41 FF  |  lea eax, DWORD PTR [ecx + eax*2 - 1]
C3           |  ret

(10 байт)

ANDІнструкція як TESTінструкції ми використовували раніше, в тому , як зробити побітову І і встановити прапори відповідно, але на ANDсамому справі оновлює призначення операнда. Потім LEAінструкція масштабує це на 2, додає початкове вхідне значення та зменшення на 1. Якщо вхідне значення було непарним, це віднімає 1 (2 × 0 - 1 = −1) від нього; якщо вхідне значення було парним, до цього додається 1 (2 × 1 - 1 = 1).

Це дуже швидкий і ефективний спосіб написання коду, оскільки велика частина виконання може бути виконана в передній частині, але це не набагато купує нас у байтах, оскільки для кодування комплексу потрібно стільки LEAінструкція. Ця версія також не працює також для вкладених цілей, оскільки вимагає збереження вихідного значення введення як введення LEAінструкції. Тож з цією останньою спробою оптимізації ми насправді пішли назад, припустивши, що можливо час зупинитися.


Таким чином, для остаточного конкуруючого запису ми маємо 9-байтну функцію, яка приймає вхідне значення в ECXрегістр (напівстандартне конвенційне виклик на основі регістра на 32-бітному x86) і повертає результат у EAXрегістр (як у випадку всі умови виклику x86):

           SwapParity PROC
8B C1         mov eax, ecx
F7 D8         neg eax
83 F0 FE      xor eax, -2
40            inc eax
C3            ret
           SwapParity ENDP

Готовий до збирання з MASM; дзвінок з C як:

extern int __fastcall SwapParity(int value);                 // MSVC
extern int __attribute__((fastcall)) SwapParity(int value);  // GNU   

Не вдалося б просто dec eax; xor eax, 1; inc eaxпрацювати і зберегти ще один байт?
Ільмарі Каронен


11

Python3, 20 18 байт

lambda n:n-1+n%2*2

Досить просто. Спочатку обчислюємо n-1 і вирішуємо, додавати до нього 2, чи ні.

Якщо n парне -> n mod 2 буде 0, значить, ми додамо 2 * 0 до n-1 , в результаті чого n-1 .

Якщо n є непарним -> n mod 2 буде 1, значить, ми додамо 2 * 1 до n-1 , в результаті чого n + 1 .

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


10

Пітон, 16 байт

lambda x:-(-x^1)

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


3
Брутське форсування не знаходить жодного коротшого рішення за допомогою символів у "x+-012~|&^()*/%".
xnor

@xnor Добре, що я його тоді отримав!
sagiksp

1
І схоже, немає інших рішень однакової довжини, окрім тривіального перестановки -(1^-x).
xnor

8

MATL , 7 байт

Q:HePG)

Це дозволяє уникнути будь-яких арифметичних операцій. Спробуйте в Інтернеті!

Пояснення

Розглянемо вклад 4як приклад.

Q    % Implicit input. Add 1
     % STACK: 5
:    % Range
     % STACK: [1 2 3 4 5]
He   % Reshape with 2 rows in column-major order. Pads with a zero if needed
     % STACK: [1 3 5;
               2 4 0]
P    % Flip vertically
     % STACK: [2 4 0;
               1 3 5]
G    % Push input again
     % STACK: [2 4 0;
               1 3 5], 4
)    % Index, 1-based, in column major order. Implicitly display
     % STACK: 3

1
Приємно! Люблю це !
Стюі Гріффін

6

Braingolf v0.1 , 11 10 байт

.1>2,%?+:-

Спробуйте в Інтернеті! (Другий аргумент - код Брайнгольфа, третій аргумент - введення)

Збережено байт завдяки Нілу

Перша в світі конкуруюча відповідь Braingolf: D

Пояснення:

.            Duplicate the top of the stack
 1>          Push 1 to the bottom of the stack
   2         Push 2 to stack
    ,%       Pop last 2 items, mod them and push result
      ?      If last item > 0
       +     Add the 1 to the input
        :    Else
         -   Subtract the 1 from the input

             No semicolon in code so print last item

Braingolf v0.2 , 9 байт [неконкуренто]

.2%?1+:1-

Спробуйте в Інтернеті! (Другий аргумент - код Брайнгольфа, третій аргумент - введення)

Див. Пояснення вище. Різниця лише в Braingolf v0.2, поведінка діадеїчних операторів за замовчуванням та функція ,модифікатора зворотні, тобто 2 коми у відповіді v0.1 більше не потрібні.

Однак v0.2 був випущений після виклику, тож цей не є конкуруючим


5
Вітаємо вас з новою мовою!
Лина монашка

Чи .1<2,%?+:-робить те, що я думаю, що це робить?
Ніл

@Neil не зовсім, вам знадобиться кома перед тим, -щоб змусити її виконати правильну операцію, і в цьому випадку вона все одно буде такою ж довжиною, як і моя відповідь
Skidsdev

@Mayube Я очікував, що <повернути 1нижній вхід, так що він буде вже в правильному місці.
Ніл

@Neil, якщо вхід є парним числом, до моменту досягнення -стеку він виглядає приблизно так: [n,1]оператори Braingolf змінюються на зворотній стороні, тож воно буде виконувати 1 - n, що призведе до того -(n-1), що бажаний результат буде простоn-1
Skidsdev

5

Cubix , 10 9 байт

cO1)I(//@

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

Пояснення

Чиста версія

    c O
    1 )
I ( / / @ . . .
. . . . . . . .
    . .
    . .

Виконані символи є

I(1c)O@
I          Input
 (         Decrement
  1c       XOR with 1
    )      Increment
     O@    Output and exit

4

Пітон, 68 байт

lambda x:[m.floor(x-m.cos(m.pi*x)) for m in [__import__('math')]][0]

У дусі унікального підходу. На наступному графіку показана функція (з фіолетовими крапками, що представляють перші 10 випадків). Теоретично повинно бути можливим побудувати рішення цього питання на основі більшості (усіх?) Періодичних функцій (наприклад, sin, tan, sec). Насправді, замінити cos на sec в коді так, як і слід.

Функція демонстрації графіків


3

PHP, 15 байт

<?=-(-$argn^1);

2
Як мені це запустити? Я намагаюся перевірити, чи ;потрібно це, і намагався використовувати .phpфайл, а також перегукуючись безпосередньо в php (php7 cli.) Щоразу, коли мені кажуть, що $argnце не визначена змінна.
Андракіс

2
@Andrakis З Fпрапором і трубопроводу: echo 42 | php -F script.php.
user63956

3

Javascript, 17 12 байт

x=>x-(-1)**x

f=x=>x-(-1)**x;
<input id=i oninput=o.innerText=f(this.value) type=number><pre id=o>

Ще один підхід, 10 байт, викрадених з відповіді C (sssshhh)

x=>-(-x^1)

f=x=>-(-x^1)
<input id=i oninput=o.innerText=f(this.value) type=number><pre id=o>


1. вам не потрібно включати крапку з комою; 2.x=>x-(-1)**x
Лина монашка

Чому |0? Обидва рішення виглядають так, ніби вони повинні автоматично перетворювати рядки в числа. (Для першого рішення, якщо ви хочете уникнути децималій, використовуйте <input type=number>.)
Ніл

@Neil Дякую за повідомлення!
Меттью Рох

3

JavaScript (ES6), 14 13 12 10 байт

n=>-(-n^1)
  • 1 байт збережено завдяки Луці .
  • 2 байта , збереженого шляхом перенесення рішення feersum в C . (Якщо це нахмуриться, будь ласка, повідомте мене про це, і я повернуся до свого попереднього рішення нижче)

Спробуй це

f=
n=>-(-n^1)
i.addEventListener("input",_=>o.innerText=f(+i.value))
<input id=i type=number><pre id=o>


Оригінал, 12 байт

n=>n-1+n%2*2

2

Пітон, 20 байт

lambda n:n+(n%2or-1)

n%2or-1 поверне 1, якщо це дивно, але якщо це парно, n%2 це "false" (0), тож замість цього повертається -1. Тоді ми просто додаємо це до n.

Попереднє рішення, 23 байти

lambda n:[n-1,n+1][n%2]

n%2обчислює залишок, коли nділиться на 2. Якщо це парне, це повертає 0, а елемент 0 у цьому списку є n-1. Якщо це не дивно, це повертає 1, а елемент 1 у цьому списку є n+1.


1
Використовуйте лямбда:lambda n:[n-1,n+1][n%2]
Лина монашка

Ага так, так було коротше в даному випадку. Готово, дякую!
numbermaniac

2

Сітківка , 21 байт

.+
$*
^11(?=(11)*$)


Спробуйте в Інтернеті! Моя перша відповідь Retina з двома останніми рядками! Пояснення: Перші два рядки перетворюються з десяткових в одинарні. Третій і четвертий рядки віднімають два з парних чисел. Останній рядок перетворюється назад у десятковий, але додає і його.



2

Cubix , 11 байт

u%2!I(/+@O<

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

Пояснення

Чиста версія:

    u %
    2 !
I ( / + @ O < .
. . . . . . . .
    . .
    . .

Символи виконуються в наступному порядку:

I(2%!+O@
I        # Take a number as input
 (       # Decrement it
  2%     # Take the parity of the decremented number
         # (0 if the input is odd, 1 if it's even)
    !    # If that number is zero:
     +   #   Add 2
      O  # Output the number
       @ # Terminate the program

2

Мозок-Флак , 36 байт

(({})(())){({}[()]<([{}])>)}{}({}{})

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

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

Пояснення

Перший біт коду

(({})(()))

перетворює стек з просто nв

n + 1
  1
  n

Тоді, коли верхня частина стека не дорівнює нулю, ми її зменшуємо і перевертаємо під нею знак числа

{({}[()]<([{}])>)}

Ми знімаємо нуль і додаємо два числа, що залишилися

{}({}{})

2

Математика, 22 19 байт

Збережено 3 байти завдяки Грегу Мартіну!

#-1[-1][[#~Mod~2]]&

Попередня відповідь, 22 байти

#+{-1,1}[[#~Mod~2+1]]&

Пояснення (для попередньої відповіді)

Mathematica має хорошу особливість у тому, що такі операції, як арифметика, автоматично прошивають списки.

У цьому випадку ми беремо, Mod[#,2]що поверне 0 або 1, але нам потрібно додати 1, оскільки списки Mathematica є 1-індексованими. Якщо це навіть , це виходить до 1, тому #-1повертається. Якщо це дивно , це виходить на 2, тому #+1повертається.


2
Ви можете зберегти три байта, зловживаючи Mathematica по [[0]]можливості: #-1[-1][[#~Mod~2]]&.
Грег Мартін

Це божевільно, ніколи б про це не подумав. Готово, дякую!
numbermaniac

2

Мудрий , 8 байт

-::^~-^-

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

Пояснення

Якби це було навпаки (декремент, якщо непарне, приріст, якщо парне), зробити це було б досить просто.

Ми би просто перевернули останній шматочок.

::^~-^

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

Тому ми просто виймаємо програму і загортаємо її -.

-::^~-^-

1

Java 8, 16 10 байт

n->-(-n^1)

Java 7, 34 28 байт

int c(int n){return-(-n^1);}

Нудні порти дивовижної відповіді на @feersum .
Спробуйте тут.


Старі відповіді:

Java 8, 16 байт

n->n%2<1?n-1:n+1

Java 7, 34 байти

int c(int n){return--n%2>0?n:n+2;}

Пояснення (старої відповіді на Java 7):

Спробуйте тут.

Відповідь вище - це коротший варіант int c(int n){return n%2<1?n-1:n+1;}позбавлення від місця.

int c(int n){     // Method with integer parameter and integer return-type
  return--n%2>0?  //  If n-1 mod-2 is 1:
    n             //   Return n-1
   :              //  Else:
    n+2;          //   Return n+1
}                 // End of method



1

Befunge 93 , 18 байт

&:2%#v_1+.@
@.-1 <

Я ще не робив гольфу цим (сподіваюся).


Поради щодо гольфу: Befunge 98 має можливість використовувати kv(або jvякщо це строго 1 або 0) замість #v_. Крім того, якщо ви використовуєте Спробуйте його в Інтернеті (і я рекомендую), ви можете закінчити програму іншим& (хоча це займе 60 секунд), так що ви можете позбутися від @першого рядка, якщо використовуєте це. ось повний список команд для Befunge-98 , хоча вони можуть бути не всі коректно реалізовані в TIO, як, наприклад, &закінчення програми замість того, щоб перейти на EOF.
MildlyMilquetoast

Крім того, виглядає, що ви використовуєте befunge 93 замість 98, що має менше команд. Ви можете поправити ім'я свого посилання, якщо воно дійсно 93, а не 98
MildlyMilquetoast

@MistahFiggins, ага, ти прав, я використовував 93.
Даніель


1

R, 17 байт

(n=scan())-(-1)^n

де n=scan()приймає значення цифри.


Я думаю, що вам потрібно, -(-1)^nа не +(-1)^nтому, що нам потрібно повернутися, n-1якщо nнавіть
Джузеппе

@Giuseppe о, так, звичайно, дурна помилка
Nutle




0

Пакет, 20 байт

@cmd/cset/a"-(1^-%1)

Незалежно розкрив алгоритм @ feersum, чесно!

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