Визначте функцію f такою, що f (f (n)) = -n для всіх ненульових цілих чисел n


43

Цей виклик надихнув блог, який я часто програмував. Ознайомтесь з оригінальною публікацією тут: Головоломка з програмуванням


Виклик

Визначте таку функцію f:Q->Q, що f(f(n)) = -nдля всіх ненульових цілих чисел n, а де Qнабір раціональних чисел.

Деталі

Якою б мовою ви не надали перевагу, будь ласка, визначте одну функцію чи програму, fяка приймає за параметр одне число nта повертає або виводить одне число f(n).

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

Вихід повинен бути зворотним значенням з функції / програми або надрукований на STDOUT.

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

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


Оцінка балів

Застосовуються загальні правила гольф-коду - ваш бал - кількість байтів у вихідному коді.

Мінімальна відповідь вимагає, щоб домен і кодомен fбули підгрупою раціональних Q. Якщо ви обмежите свій домен та кодомейн fцілими числами Z, то ваш показник - це максимальна межа 90% від кількості байтів у вихідному коді.

Перерва на чай

У разі вирівнювання, в порядку буде використано наступне:

  1. Найменша кількість символів, що не надрукуються для друку, у вашому вихідному коді
  2. Найдавніша дата та час подання відповіді

Редагувати

Вам не потрібно підтримувати довільно розміщені номери. Будь ласка, інтерпретуйте набори Zта Qтипи даних у вибраній мові (як правило, цілі чи плаваючі точки відповідно).

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


20
f (n) = i * n - чиста математика: P
Йоганнес Кун

8
@JohannesKuhn, тому домен і кодомен обмежуються раціоналами
ardnew

Чи можете ви пояснити, що f:Q->Qозначає?
beary605

@ beary605 це означає f, що функція відображення членів Q(раціональних чисел) до інших членів (можливо, однакових) Q. дивіться en.wikipedia.org/wiki/Function_(mathematics)#Notation
ardnew

7
Я знав, що бачив це недавно, але знадобився певний час, щоб згадати, де. Менш щільно зазначена версія на StackOverflow була недавно закрита. Понад 100 відповідей.
Пітер Тейлор

Відповіді:


12

J, 9 балів (10 символів)

На основі відповіді stackoverflow :

   (*-[*_1&^)

Перша ідея (13 символів):

   ((-*)-2&|*+:)

   ((-*)-2&|*+:) _10 _9 _8 _7 _6 _5 _4 _3 _2 _1 0 1 2 3 4 5 6 7 8 9 10
_9 10 _7 8 _5 6 _3 4 _1 2 0 _2 1 _4 3 _6 5 _8 7 _10 9

   ((-*)-2&|*+:) _9 10 _7 8 _5 6 _3 4 _1 2 0 _2 1 _4 3 _6 5 _8 7 _10 9
10 9 8 7 6 5 4 3 2 1 0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _10

Це працює для цілого введення, але це дає уявний вихід для значень з плаваючою комою (функція повинна виробляти раціональний вихід для раціонального введення відповідно до специфікації)
Нестабільність

5
@ Нестабільність, специфікація заплутана в тексті, але, як я читав, це дозволяє обмежити домен і кодомен на цілі числа.
Пітер Тейлор

Чи потрібні дужки?
Cyoce

14

Пітон: 61 34 30 29 27 балів

f: Q -> Q

з математики:

       | 0.5-x   if x is in Q \ Z
f(x) = |
       | x+0.5   if x is in Z

на Python:

f=lambda x:.5+[x,-x][x%1>0]

перевірений с

filter(lambda n: n[0] != -n[1], map(lambda n:(n,f(f(n))),range(0,50)))

логіка цього:

Коли ви візьмете ціле число nі вкладете його, fви отримаєте x+0.5. Це вже не ціле число, тому наступним додатком буде те, 0.5-(x+0.5)що є -x.

Кредити

Завдяки

  • Бакуріу за те, що він знімав її з 61 символу до 34 символів.
  • Нестабільність для подальшого зменшення розміру коду до 30 символів.
  • скопіюйте для зменшення розміру коду до 29 символів (і виправлення потенційної проблеми з плаваючою точкою).
  • aditsu для згадування невідповідності, яка відбулася із змінами вище.

Примітки

Спочатку я подумав, що це буде добре

f = lambda n: 1j*n

але його f: N-> C, і це не дозволено: - /


1
Можна позбавити від: f=lambda x:x%1>0and(-x+x%1)or x+.1до 34 символів.
Бакуріу

f=lambda x:[x+.1,x%1-x](x%1>0)лише 30
Волатильність

1
Один обвуглюється коротше: f=lambda x:[x+.5,.5-x][x%1>0]. Зверніть увагу на використання .5 замість .1, щоб вирішити проблеми з точністю
скопіюйте

1
@AJMansfield 1,48 - не ціле число.
Мартін Тома

1
Ні, це не означає. Якби це зауважило, він повинен був написати "всі раціональні числа". f:Q->Qозначає лише, що f відображає раціональне число на раціональні числа. Яке моє визначення f робить.
Мартін Тома

11

C, 41 бал (41 або 45 символів)

Працює, використовуючи як 32-, так і 64-бітні.

f : Z -> Z(крім INT_MAX):

f(n){return (abs(n)%2*2-1)*n+n?(-n<n)*2-1:0;}

Якщо нам не потрібно включати, 0ми можемо поголити деякі символи (41 символи):

f : Z -> Z(крім 0& INT_MAX):

f(n){return (abs(n)%2*2-1)*n+(-n<n)*2-1;}

Ця функція працює за допомогою поділу всіх цілих чисел на 4 групи на основі їх знаку та паритету.

Отже, у нас є 4 різні комбінації:

+ even, + odd, - even, - odd

Оскільки нам потрібно переключити знак числа, але не парність після двох проходів, ми отримаємо дві різні можливі послідовності:

  + even -> - odd -> - even -> + odd -\
^-------------------------------------/

  + even -> + odd -> - even -> - odd -\
^-------------------------------------/

У цьому прикладі я вибрав перший.

Спочатку нам потрібно зіставити всі парні цілі числа на непарні цілі числа. Ми робимо це, змінюючи знак і збільшуючи число (ви можете також замість цього зменшити число):

f1(n) = -n + 1

Потім нам потрібно зіставити всі непарні цілі числа на парні цілі числа. Ми повинні переконатися, що f2(f1(n)) = -n:

f2(f1(n)) = -n
f2(-n + 1) = -n
f2(-n) = -n - 1
f2(n) = n - 1

Використовуючи ті самі методи, ми знаходимо f3і f4:

f3(n) = -n - 1
f4(n) =  n + 1

Щоб поєднати ці функції в одну єдину функцію, ми зауважимо, що кожен раз n, коли ми навіть перемикаємо знак, nі кожен раз, коли nє позитивним, ми збільшуємося на одну, а в іншому випадку - декремент на одну:

f1(n) = -n + 1 (+ even)
f2(n) =  n - 1 (- odd)
f2(n) = -n - 1 (- even)
f4(n) =  n + 1 (+ odd)

Таким чином, це може бути переписано як:

f(n) = odd(n) * n + sign(n)

де odd(n)повертається 1для непарних чисел і -1для парних чисел.

Усього 4 рішення:

f(n) = odd(n) * n + sign(n)  (edge cases: f(f(0))  -> -2, f(f(INT_MAX))   -> -8)
f(n) = even(n) * n - sign(n) (edge cases: f(f(0))  -> -2, f(f(INT_MIN+1)) -> -6)
f(n) = odd(n) * n - sign(n)  (edge cases: f(f(1))  -> -3, f(f(INT_MIN))   -> -5)
f(n) = even(n) * n + sign(n) (edge cases: f(f(-1)) -> -1, f(f(INT_MIN))   -> -5)

INT_MINзавжди можна вважати кращим випадком у всіх 4 функціях як -INT_MIN == INT_MIN=> f(f(INT_MIN)) = INT_MIN.


Це по суті те саме, що і моя відповідь GolfScript (за винятком пояснень). Це працює за 0?
Бен Рейх

@BenReich Як зазначено у відповіді, це не працює 0і для 3 інших номерів.
Тиїло

1
@Tylio Я бачу зараз. Має сенс. Здається, ви повинні брати Zбонус, лише якщо ви покриваєте 0, принаймні.
Бен Рейх

@BenReich Видалив бонус, поки я його не зафіксую.
Тіїло

9

Ось мій погляд на це.

long f(int i){return i;}
int f(long i){return -i;}

Живий приклад :

int main()
{
  for(int i=-10; i<10; i=i+3)
    std::cout << f(f(i)) << "\n";
}

Типи вводу cn можуть бути довільно підібрані відповідно до ваших потреб. Ця версія працює для цілих літералів, менших за величиною, ніж 2 ^ 32-1.


2
Проблема сказала f:Q->Q, ні f:Z->Z.
AJMansfield

@AJMansfield розділ підрахунку специфікації мав на меті запропонувати бонусні бали за визначені функції f:Z->Z, вибачте за заплутане формулювання
ardnew

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

@ardnew, о, ти маєш рацію. Мене вказували на це дійсне заперечення лише за секунди до того, як поділитися ним з Lounge <C ++> в чаті SO. Мені цікаво, що робить компілятор з цього (якщо він не вбудовує дзвінки), але моя збірка гасить.
rubenvb

1
Я думаю, ви можете прибрати простір уreturn -i
Cyoce

6

JavaScript, 18

f=n=>n%1?.5-n:n+.5

Використання нової позначення жирової стрілки (Firefox 22).

Інша версія (18):

f=n=>n%1?-.5/n:.5/n

Попередня версія (20):

f=n=>n-~~n?.5-n:n+.5

Приклад:

> [-3,-2,-1,1,2,3].map(f).map(f)
[3, 2, 1, -1, -2, -3]

10
Схоже, JavaScript перетворюється на CoffeeScript.
Пітер Тейлор

4

Математика 18

f=#+1/2-4#(#-⌊#⌋)&

Ось ⌊...⌋функція підлоги. Він використовує лише раціональні числа (не списки, складні числа тощо)

f[10]
f[f[10]]

21/2

-10

f[-5]
f[f[-5]]

-9/2

5


3

x86 мова складання (FASM). Аргумент і результат - в регістрі eax.

Працює правильно для -2 ^ 30 <N <+ 2 ^ 30-1

16 байт виконуваного коду.

        use32

f_n:
        lea     edx, [2*eax]
        xor     edx, eax
        btc     eax, 30
        shl     edx, 1
        jnc     .end
        neg     eax
.end:
        retn

Нитчіпкінг ваших номерів; 2E30 буде 2 * 10 ^ 30, а не 2 ^ 30, як я думаю, ви хочете.
Нік Т

@NickT Моя помилка. Виправлено.
johnfound

Я впевнений, що ви повинні рахувати байти у вихідному коді.
nyuszika7h

3

Звичайний Lisp: 35 байт

(defun f(x)(/(if(> 1 x)-1/2 1/2)x))

Схема (і ракетка): 36 байт

(define(f x)(/(if(> 1 x)-1/2 1/2)x))

Безголовка з коментарями та поясненнями:

(define (f x)
  (/             ;; divide
     (if (> 1 x) ;; if x is below 1 
         -1/2    ;; then -1/2 (the fraction)
         1/2)    ;; else 1/2 (the fraction)
      x))        ;; gets divided with x

Для будь-якого числа xв перетвориться у фракцію , яка є реальним точним числом на обох мовах.[1,->]if1/2

Частина, що розділиться, стане (/ 1/2 x)тим, що стане дробом, 1/(x*2)який завжди знаходиться нижче 1. Бо 1це буде 1/2, бо 2це і 1/4т.д.

Для будь-якого числа нижче 1 , то ifвийде в частці -1/2, що виконує функцію робити (/ -1/2 x)що , -1/(2*x)але так як можна очікувати , що значення буде результат попереднього запуску ми можемо підставити е 1 / (х * 2) , що робить подвійне застосування-1/((1/(x*2))*2) = -x

Наприклад, 1перетворюється на 1/2другу програму(/ -1/2 1/2) ==> -1


Як це працює?
AJMansfield

@AJMansfield додав інформацію. Просто запитайте, чи є щось незрозуміле. Читання синтаксису LISP - це як грецьке, якщо ви цього не навчились, і для того, щоб звикнути, потрібно кілька тижнів.
Сільвестер

3

C, 60 (⌈66 * .9⌉)

int f(int x){if(!x&1||!~x)return ~x;if(x<0)return x-1;return x+1;}

Ось неконденсована версія:

int f(int x){
    if(!x&1 || !~x) return ~x;
    if(x<0) return x-1;
    return x+1;
}

Цей метод працює з використанням лише цілих чисел, тому він отримує бонус на 90%. Я спочатку писав це на Java, але зрозумів, що ця програма, зокрема, може отримати вигоду від логічних операторів у стилі С.

Оскільки ціле число не відповідає -INT_MIN, замість цього f(f(INT_MIN))повертається INT_MIN.

Основне відображення алгебраїчно досить просто. Виконання оператора x=f(x)замінює x на:

  • x+1, якщо xпозитивний і непарний
  • -x+1, якщо xє позитивним і рівним
  • x-1, якщо xнегативний і непарний
  • -x-1, якщо xнегативний і рівномірний

Результат кожного випадку підпадає під наступний випадок при наступному застосуванні функції до x.

Як бачите, складання справи із справи, що йде за ним, дає результат -x.

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


3

> <> , 21 + 3 = 24 байти, 22 бали

:0)$:0($:1$2%2*-*+-n;

Скористайтеся офіційним інтерпретатором Python та використовуйте параметр -vкомандного рядка для введення вводу вартістю 3 байти.

У мене є відчуття, що це може бути краще - я продовжую дивитись на це і намагатись бити в гольф.

За умови введення n, програма виводить

(n>0) - ((n<0) + n * (1 - 2*(n%2)))

де (n>0)і (n<0)булеві. Це еквівалентно відповіді Желатіна на Python

(n>0) - (n<0) - n * (-1)**n

але ><>не має вбудованого оператора експоненції, тому ми використовуємо його (1 - 2*(n%2))замість (-1)**n.

Далі йде математична теорія - читайте, якщо (і лише якщо) вас цікавить:

Для будь-якої функції , f: Z -> Zтакі , що f(f(n)) = -nдля всіх nін Z, ми бачимо відразу , що f(f(f(f(n)))) = n, або, іншими словами, f^4це функція тотожності. Зокрема, fє зворотним, і його зворотна функція є f^3. Таким чином , fперестановка Z, і так як f^4 = Id, то це означає , що кожна орбіта (або цикл) з fмає розмір або 1, 2, або 4.

Далі ми це бачимо f(0) = 0. Доказ: f(0) = f(-0) = f(f(f(0))) = -f(0)так f(0) = 0, за бажанням. І навпаки, припустимо x, це цикл довжини 1або 2, так f(f(x)) = x. Тоді -x = xтак x = 0.

Таким чином f, складається повністю з 4-х циклів, за винятком фіксованої точки (1-циклу) при 0.

Крім того, кожен 4-цикл повинен мати форму (x, y, -x, -y), і тоді поверніть навколо циклу ми можемо припустити , що xі yобидва позитивні. І навпаки, кожен такий продукт 4-циклів, що розділяє ненулі цілі числа, визначає вибір f.

Таким чином, кожен вибір fоднозначно відповідає спрямованому графу, вершинами якого є додатні цілі числа, таким чином, що кожна вершина потрапляє точно на одну стрілку, або вступаючи, або залишаючи її. Точніше, в нижньому непрямому графіку кожна вершина має ступінь точно 1. (Кожен 4-й цикл (x y -x -y)із xта yпозитивом відповідає стрілці x --> y.)

Функція в цій відповіді (і кілька інших відповідей тут) відповідає графіку , де 1 --> 2, 3 --> 4і в цілому 2k-1 --> 2k.

Такі графіки знаходяться у взаємно однозначній з нескінченними послідовностями упорядкованих пар (a_n, p_n), де кожен a_nє позитивне ціле число , і кожен p_nє або 0чи 1: дана послідовність (a_1, p_1), (a_2, p_2), (a_3, p_3), ..., ми перша пара 1з 1 + a_1, а потім формують або стрілку 1 --> 1 + a_1або стрілку в 1 + a_1 --> 1залежності від того , p_1є 0чи 1. По суті, стрілка є або <знаком, або >знаком, залежно від паритету p_1.

Далі, візьміть найменше непарне натуральне число kі підрахуйте k, точно a_2кроки, СКОРОЧИТИ будь-яке число, яке вже з чимось уже поєднане. З'єднайте kз результатом і встановіть напрямок стрілки залежно від p_2вище. Потім повторіть із (a_3, p_3)тощо.

Кожна стрілка в підсумку визначатиметься таким чином, тому процес чітко визначений. Функція у цій відповіді відповідає послідовності (1,0), (1,0), (1,0), ..., оскільки на кроці nнайменше непарне ціле число є 2n-1і не має цілих чисел, більших, ніж 2n-1вони були зв'язані з чим-небудь, тому ми отримуємо 2n-1 --> 2nдля кожного n(стрілки орієнтовані таким чином, тому що кожна p_nдорівнює 0).

Можливість цієї множини полягає в тому (N*2)^N = N^N, що останнім абзацом цієї відповіді дорівнює 2^N, кардинальність дійсних чисел.


Параметри командного рядка, як правило, кожен байт.
кіт

@cat Дивіться розділ "Спеціальні виклики" на цьому мета-пості .
Матмандан

2

Щоб виправити попередню відповідь J (у мене недостатньо репутації, щоб коментувати оригінал):

(*+[*1-~2*2|])

Він просто замінює _1&^з 1-~2*2|], що дає протилежний знак. Тому я змінив значення -на +(що має значення лише при введенні 1та _1).

Ось тести:

   (*+[*1-~2*2|])6 3 _9 _8 1r2 _4.6 0 1 _1
7 _2 8 _9 1 7.28 0 2 _2
   (*+[*1-~2*2|])7 _2 8 _9 1 7.28 0 2 _2
_6 _3 9 8 0 _10.3568 0 _1 1

   NB. f^:2 = f@:f
   (*+[*1-~2*2|])^:(2)6 3 _9 _8 1r2 _4.6 0 1 _1
_6 _3 9 8 2 _5.0832 0 _1 1

Як бачите, домен та діапазон мають усі реальні числа, але він працює лише для цілих чисел (включаючи 0).

Пояснення:

(   *     + [ *  1-~    2*     2|]    )
 signum n + n * pred (twice (n mod 2))

2

GolfScript ceiling(26*.9)=24

Гольфскрипт обробляє лише цілі числа, тому застосуйте Zбонус на загальну суму 24 бали:

.{..0>2*(\)2%!2*(@*+}{ }if

Окремий випадок з 0 припадає на 8 символів. Ігноруючи 0, ми можемо відповісти на 17 балів:

..0>2*(\)2%!2*(@*+

Цей код робить ціле число xу верхній частині стека:

  • Якщо xце 0, залиште 0на стеці і не застосовуйте більше правил.
  • Якщо xце рівномірно, заперечуйте x.
  • Якщо xє позитивним, додайте 1.
  • Якщо xвід’ємник, віднімайте 1.

Це логічно з'єднує набори з 4 чисел у циклі, де fпроходять елементи циклу, а протилежні кути циклу є негативом один одного. Кожне ціле число є частиною рівно 1 такого циклу, за винятком 0, який має спеціальний обхід. Наприклад, для {-8, -7, 7, 8}:

  • 7 f -> 8
  • 8 f -> -7
  • -7 f -> -8
  • -8 f -> 7

Єдині відповідні тестові випадки, про які я міг придумати, - це негативний непарний, негативний парний, позитивний непарний, навіть позитивний 0, і тоді я кинувся, -1і 1оскільки їх близькість, 0можливо, спричинила проблеми:

[-10 -5 -1 0 1 5 10]
{.{..0>2*(\)2%!2*(@*+}{ }if}:f;
{f f}%
-> [10,5,1,0,-1,-5,-10]

Я впевнений, що фактичний GolfScript можна дещо покращити. Не здається, що він повинен містити 26 символів! Раді почути кілька пропозицій.


2

Ява, просто для розваги

Ось реалізація, яка робить фактичну біекцію між ℤ і ℤ², яка є одночасно непарною функцією (g (-x) == -g (x)). Він розглядає відповідний елемент ℤ² як складне число і помножує його на "i", а потім перетворює назад у ℤ.

f (x) = g⁻¹ (ig (x))
f (f (x)) = g⁻¹ (-g (x)) = - x

Функція працює в O (1).

public class Ffn {
    public static int f(int n) {
        if (n == 0) {
            return 0;
        }
        // adjust sign
        int s = n > 0 ? 1 : -1;
        int m = n * s;
        // calculate square "radius"
        int r = (int) (Math.sqrt(2 * m - 1) + 1) / 2;
        int q = r * 2;
        // starting point
        int x = r, y = r;
        int k = q * (r - 1) + 1;

        if (m - k < q) {
            // go left
            x -= m - k;
        }
        else {
            // go left
            x -= q;
            // go down
            y -= m - k - q;
        }

        // multiply by i
        int x2 = -y * s, y2 = x * s;
        // adjust sign
        s = y2 < x2 || y2 == x2 && x2 < 0 ? -1 : 1;
        x2 *= s;
        y2 *= s;

        if (y2 == r) {
            // go left
            k += r - x2;
        }
        else {
            // go left and down
            k += q + r - y2;
        }
        return k * s;
    }

    public static void main(final String... args) {
        for (int i = 0; i < 1000000; ++i) {
            if (f(f(i)) != -i || f(f(-i)) != i) {
                System.out.println(i);
            }
        }
    }
}

PS З Новим роком!


Я вважаю, що пробіли не потрібні.
pppery

2

Пітон 3 - 38

Подібний @ відповідь лосиного, але f(n) == n. Працює для всіх цілих значень.

f=lambda x:x*(isinstance(x,int)*2.0-1)

2

Перл, 33 (пробіл)

sub f{($=)=@_;$=-$_[0]?-$=:"$=.1"}

Редагувати:

  • $=.".1"скорочено до "$=.1"(дякую ardnew).

Математика:

Математика

Безголівки:

# script.pl
sub f {
  ($=) = @_;   # short for $= = int($_[0]); 
               # "int" is implicit in assignments to $=;
               # ($=) can be prepended by "local" to get
               # the function free of side effects.

  $= - $_[0] ? # short for $= != $_[0], check if input is integer
    -$=        # input is not an integer  
  : $= . ".1"  # input is integer
}  

# Testing
chomp;
$_ = sprintf "f(f($_)) = f(%s) = %s\n", f($_), f(f($_));

Приклади:

perl -p script.pl
7
f(f(7)) = f(7.1) = -7
2
f(f(2)) = f(2.1) = -2
0
f(f(0)) = f(0.1) = 0
-1
f(f(-1)) = f(-1.1) = 1
-10
f(f(-10)) = f(-10.1) = 10
-1.23
f(f(-1.23)) = f(1) = 1.1
3.4
f(f(3.4)) = f(-3) = -3.1
1.0
f(f(1.0)) = f(1.1) = -1

надійне рішення - тестові випадки з плаваючою комою, які ви демонструєте, не потрібні за специфікацію (повинні були запропонувати бонусні бали за це!) ось ваш алгоритм з кількома очищеннями, що надходять за 22 sub f{yzxzzc?-$_:x.$_}
години

1
@ardnew: Дякую Але я не згоден, що ваше рішення використовує той самий алгоритм. Алгоритм sub f{yzxzzc?-$_:x.$_}є НЕ стан вільної, вона використовує стан через змінну $_. Через це fбільше не є функцією (в математичному сенсі), тому що можливі різні значення для одного і того ж вхідного значення залежно від стану (погода $_містить xчи ні). Мій алгоритм не використовує стан, інформація кодується у вихідному значенні. Цілі ліки перетворюються в реальні числа шляхом додавання .1. І справжні числа перетворюються назад в цілі числа з переключеним знаком.
Хайко Обердік

Цікаво - у вашій реалізації не використовуються дані про стан через первісне призначення, а не через якусь особливу властивість $=?
ardnew

Я не усвідомлював, що я також не зміг власної вимоги (що fбуде визначено Q->Q) з цим xзнаком. також $=.".1"може бути скорочений до"$=.1"
ardnew

@ardnew: Особливість властивості $=полягає лише в тому, що вона приймає лише цілі числа. Те ж саме може бути досягнуто за допомогою звичайної змінної: $a=int$_[0]. Але це коштує три додаткові байти через функцію int.
Хайко Обердік

2

Юлія, 26 років

julia> f(n::Int)=n//1
f (generic function with 1 method)
julia> f(n)=int(-n)
f (generic function with 2 methods)
julia> f(f(4))
-4

Не супер конкурентоспроможний, але дуже Джуліан, оскільки він покладається на багаторазову доставку. Це просто робить na Rational, якщо це Int, або int зі знаком мінус, якщо це щось інше. Можна заперечити, що це дві функції, але Джулія вважає це однією функцією з двома методами, і це рівнозначно визначенню однієї функції з викладом if на типі n.


Це не те, що математик називав би функцією: в Джулія 3==3//1повертається, trueале f(3//1)==f(3)повертається false.
Омар

2

Цукерки , 20 18 байт

Використовує трюк 3 -> 4 -> -3 -> -4 -> 3.

~A2%{|m}1A0>{+|-}.

Щоб викликати його, використовуйте перемикач -i на інтерпретаторі

Приклад подвійного виклику:

$ candy -i 7 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> 8
$ candy -i 8 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> -7
$ candy -i -7 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> -8
$ candy -i -8 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> 7

Довга форма:

peekA
pushA
digit2
mod          # even/odd
if
else
  negate     # negate even numbers
endif
digit1
pushA
digit0
greater      # positive/negative
if
  add        # add two numbers from stack (original stack value, and delta)
else
  sub        # diff two numbers from stack (original stack value, and delta)
endif
retSub

2

Діялог APL, 9 балів

×-⍨⊢ׯ1*⊢

Джерело завдовжки 9 байтів і кваліфікується на бонус (що зовсім не допомагає). Він також використовує формулу з верхнього відповіді ТА.




1

Java, 113 байт

Підхід досить простий. Це закінчилося більше байтів, ніж я передбачав, але, можливо, можна трохи зіграти в гольф.

public class F{public static int f(int x){if(x<0)x+=-2147483647-++x;x+=1073741824;return x<0?-2147483647-++x:x;}

По суті, він створює 4 різних "області" x, використовуючи той факт, що Java із задоволенням дозволяє змінним загортатися. Мені довелося зробити кілька хитрих перетворень для від'ємних чисел, що є основною причиною, що це в кінцевому рахунку більше, ніж передбачалося.

Працює для всіх x крім -2147483648.


1

Та сама послідовність чисел (3, 4, -3, -4, 3 ...), як відповідь гольфскрипту, але реалізована в perl (42 символи після пробілу місця)

sub f{($_[0]%2?1:-1)*$_[0]+($_[0]<0?-1:1)}

Більш розбірливо:

sub f { ($_[0] % 2 ? $_[0] : -$_[0] ) + ( $_[0] < 0 ? -1 : 1 ) }

Або ще більш розбірливо:

sub f {
  my $n = shift;
  my $sign = $n >= 0 ? 1 : -1;
  # note that in perl $n % 2 is the same as int($n) % 2
  if( $n % 2 ) {
    # odd: add one to magnitude
    return $n + $sign
  } else {
    # even: subtract one from magnitude then invert
    return -($n - $sign)
  }
}

Вихід:

ski@anito:~/mysrc/.../acme$ echo 3 | perl -e 'sub f{($_[0]%2?1:-1)*$_[0] + ($_[0]<0?-1:1)}; my $x = <>; for(0..10) { print "$_: $x\n"; $x = f($x); }'
0: 3
1: 4
2: -3
3: -4
4: 3
5: 4
6: -3
7: -4
8: 3
9: 4
10: -3

Сказане також працює для нецілих чисел: ski @ anito: ~ / mysrc /.../ acme $ echo 1.1234 | perl -e 'sub f {($ _ [0]% 2? 1: -1) * $ _ [0] + ($ _ [0] <0? -1: 1)}; мій $ x = <>; для (0..4) {print "$ _: $ x \ n"; $ x = f ($ x); } '0: 1.1234 1: 2.1234 2: -1.1234 3: -2.1234 4: 1.1234
скибрянський

1

Сід, 25 байт.

|sed s/0+/0-/|sed s/^/0+/

Використання:

$ echo 1.23 |sed s/0+/0-/|sed s/^/0+/
0+1.23
$ echo 0+1.23 |sed s/0+/0-/|sed s/^/0+/
0+0-1.23

1

Матлаб, 26 символів

f=@(n) (n<0)-(n<0)-n*(-1)^n

2
Це неправдива відповідь, оскільки домен і кодомейн функції не повинні бути складними.
Wrzlprmft

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

1

C ++ - 63 55,8

Ось як виглядає код:

int f(int n){return (n&45056?n^45056:n|45056)*(n&45056?-1:1);}

Він не працює на цілі числа, четвертий байт яких дорівнює 0xB, оскільки він використовує це значення для відстеження пропусків. В іншому випадку працює на будь-якому члені Z, включаючи нуль.


ви можете пояснити це? при першому огляді здається, що ви зберігаєте лічильник дзвінків fстатичною змінною. але тоді в чому сенс sqrt?
ardnew

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

Я поняття не маю, звідки ви взяли 55.8, але ваш поточний код - 62 байти. Редагувати: Неважливо, я неправильно не прочитав питання.
nyuszika7h

Обмеження, що четвертий байт не може дорівнювати 0xB, на жаль, робить це не вагомою відповіддю на виклик, що вимагає, щоб він працював (принаймні) на цілі числа.
pppery

1

Оновлено функцію, яку надає Synthetica (очевидно, той, хто зараз повинен отримати в цьому кредит)

Мова: Python

Кількість символів: 41, включаючи пробіл

f=lambda x:-float(x) if str(x)==x else`x`

Будь ласка, вкажіть також назву мови, якою ви користувались, також введіть кількість символів.
ProgramFOX

Мені подобається, як це також працює з не цілими числами. Молодці. :)
cjfaure

f=lambda x:-float(x) if str(x)==x else`x`зовсім трохи коротше: 41, включаючи пробіли
ɐɔıʇǝɥʇuʎs

Спасибі Synthetica, я навіть не знав про трюк зворотних подій! : D
HolySquirrel

На цілі числа fповертає рядок; специфікація говорить, що вона повинна повертати раціональне число.
Омар

1

Пролог, 36 байт

Код:

X*Y:-X//1=:=X,Y is 0.5+X;Y is 0.5-X.

Пояснили:

Dyadic predicate which converts integers to floats and floats back to negated integers.

Приклад:

10*X.
X = 10.5

10*Y,Y*X.
X = -10,
Y = 10.5


1

Миша-2002 , 21 19 12 байт

$A1%[1%_|1%]

Визначає функцію A; зателефонуйте так #A,#A,?;;(що буде чекати, коли користувач введе будь-яке число). Крім того, називайте його так, #A,#A,n;;де nє будь-яке число.


1

Юлія, 21 рік

f(x)=(1-2(1>x>-1))/2x

Тоді

julia> f(f(12//1))
-12//1

p // q - буквальне позначення Юлією раціональних чисел.

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