Поменять соотношение

22

задача

Учитывая положительное целое число n, выведите, n+1если nнечетное, и выведите, n-1если nявляется четным.

вход

Целое положительное число. Вы можете предположить, что целое число находится в пределах возможностей обработки языка.

Выход

Целое положительное число, указанное выше.

Testcases

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 Это достаточно хорошо известно, и я уверен, что OP сделал это специально.
Орджан Йохансен

Ответы:

24

C, 20 байтов

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

Попробуйте онлайн .

feersum
источник
7
@LeakyNun Я не пишу функцию, в которой отсутствует оператор возврата.
feersum
18
@EriktheOutgolfer Нет. Нет. Нух-э-э. Нет
feersum
10
@Sisyphus Но это код-гольф , и он работает по моей ссылке TIO, поэтому он действителен.
Эрик Outgolfer
7
@EriktheOutgolfer Я хочу сказать, что ваше утверждение («присвоение первому аргументу эквивалентно оператору возврата») фактически неверно. Может ли такой код генерировать рабочий ответ при определенных обстоятельствах - это другой вопрос (который я рассмотрел в своем первом комментарии, заявив, что я не планирую публиковать такой код).
feersum
8
@EriktheOutgolfer Если ответ основан на поведении, связанном с реализацией, он должен указывать реализацию. Этот ответ не, поэтому этот код будет недействительным.
Сизиф
17

Stack Cats , 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), чтобы это сделать? РЕДАКТИРОВАТЬ: ОК НВМ, нашел соответствующий мета-пост . « Я считаю их как разницу в количестве символов для кратчайшего эквивалентного вызова без них. « ... » perl -nle 'stuff'на 2 символа больше perl -e 'stuff', поэтому он рассчитывает еще на 2 символа ». Так (space)-nчто на 3 байта больше, чем без флага.
Кевин Круйссен
@KevinCruijssen Это зависит от того, сколько байтов вам действительно нужно добавить к обычному вызову. В Perl и многих других рабочих языках вы можете вызывать код с помощью, -e "code"а затем вставлять дополнительные флаги перед e, например -pe "code". Тогда -pфлаг равен только одному байту. Однако у Stack Cats такого -eаргумента нет, поэтому вам всегда нужно добавлять полное <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 байта. Простое DECзамечание 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инструкцию register-register в начало или конец функции. Это практически не влияет на скорость, но добавляет 2 байта. ( RETИнструкция также добавляет байт, и есть некоторые накладные расходы, связанные с необходимостью выполнения и возврата из вызова функции, что означает, что это один из примеров, когда встраивание дает выигрыш как в скорости, так и в размере, а не просто в классической скорости -for-space trade.) Во всем, написанном как функция, этот код увеличивается до 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действие на INCrement:

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

Желе , 3 байта

-*ạ

Попробуйте онлайн!

псевдокод: abs((-1)**n - n)

Дрянная Монахиня
источник
Я действительно планировал (ab) использовать -1.
Эрик Outgolfer
Простите за это.
Утренняя монахиня
Нет, извините, молодец! Я не
понял
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 paint & touchpad для ноутбука ... Визуальное объяснение

Yytsi
источник
10

Python, 16 байт

lambda x:-(-x^1)

Попробуйте онлайн!

sagiksp
источник
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, поведение диадических операторов по умолчанию и функция ,модификатора обращены в обратную сторону, что означает, что две запятые в ответе v0.1 больше не нужны.

Однако v0.2 был выпущен после испытания, так что этот не конкурирующий

Skidsdev
источник
5
Поздравляю с новым языком!
Утренняя монахиня
Делает ли .1<2,%?+:-я то, что думаю?
Нил
@ Не совсем, вам понадобится запятая перед тем, -как она будет правильно выполнять операцию, и в этом случае она будет иметь ту же длину, что и мой ответ
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

Python, 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);
user63956
источник
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 (сссшхх)

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

Python, 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.

numbermaniac
источник
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

Brain-Flak , 36 байт

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

Попробуйте онлайн!

Лично я очень доволен этим ответом, потому что он намного короче, чем я бы назвал традиционным методом решения этой проблемы.

объяснение

Первый бит кода

(({})(()))

преобразует стек от просто nк

n + 1
  1
  n

Тогда, пока вершина стека не равна нулю, мы уменьшаем его и переворачиваем знак числа под ним

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

Мы удаляем ноль и добавляем два оставшихся числа

{}({}{})
Мастер пшеницы
источник
2

Mathematica, 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возвращается.

numbermaniac
источник
2
Вы можете сохранить три байта, злоупотребляя Mathematica по [[0]]возможности: #-1[-1][[#~Mod~2]]&.
Грег Мартин
Это безумие, никогда бы не подумал об этом. Готово, спасибо!
номер
2

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

-::^~-^-

Попробуйте онлайн!

объяснение

Если бы все было наоборот (уменьшить, если нечетное, увеличить, если четное), это было бы довольно легко сделать.

Мы бы просто перевернули последний бит.

::^~-^

Исправление здесь состоит в том, что мы переворачиваем последний бит, в то время как отрицательный. Отрицательные числа равны 1 от отрицания чисел, ~так что это создает смещение, решающее проблему.

Таким образом, мы просто вынимаем программу и оборачиваем ее -.

-::^~-^-
Мастер пшеницы
источник
1

Java 8, 16 10 байт

n->-(-n^1)

Java 7, 34 28 байт

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

Скучные порты удивительного C-ответа @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()принимает значение цифры.

Nutle
источник
Я думаю, что вам нужно, -(-1)^nа не +(-1)^nтак как мы должны вернуться, n-1если nдаже
Джузеппе
@Giuseppe о, да, конечно, глупая ошибка
Nutle
1

Casio-Basic, 27 байтов

piecewise(mod(n,2),1,-1)+n

26 байт для функции, +1 для ввода nв поле параметров.

numbermaniac
источник
0

Пакетный, 20 байтов

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

Самостоятельно заново открыл алгоритм @ feersum, честно!

Нил
источник