Віднімання церкви


13

Віднімання церкви

Обчислення лямбда завжди було захопленням моїм, і виникаюча поведінка передачі функцій одне одному надзвичайно складна. Церковні цифри - це зображення природних чисел, що виникають при повторному застосуванні функції (як правило, одинарне додавання константи). Наприклад, число нуль повертає x і "ігнорує" функцію введення, один є f(x), два є f(f(x))і так далі:

ident = lambda x: x
zero = lambda f: ident
succ = lambda n: lambda f: lambda x: f(n(f)(x))
one = succ(zero)
add1 = lambda x: x + 1
to_int = lambda f: f(add1)(0)
print(to_int(one))
>>> 1

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

add = lambda m: lambda n: lambda f: lambda x: n(f)(m(f)(x))
print(to_int(add(one)(two)))
>>> 3

Доповнення зрозуміти досить легко. Однак для новачків може бути немислимо думати, як виглядає віднімання у кодованій Церквою системі числення. Що може означати скасування функції?

Виклик

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

Вхідні дані

Дві церковні цифри, які були закодовані у вашому виборі мови. Вхід може бути позиційним або кривим. Щоб довести, що це справжні церковні цифри, їм доведеться виконувати будь-яку функцію та застосовувати їх неодноразово ( add1наведено в прикладах, але це може бути add25,mult7 або будь-який інший одномісний функція) .

Вихідні дані

Церковна цифра. Слід зазначити, що якщо m < nтоді, m - nце завжди те саме, що ідентичність функції.

Приклади:

minus(two)(one) = one
minus(one)(two) = zero
...

також прийнятно:

minus(two, one) = one
minus(one, two) = zero

Кредит:

Ця суть github за те, що я дав мені питонську реалізацію церковних чисел.


1
(Коментар у суті невірний; exp(m, n)обчислює m^nзвичайно.)
Ніл

1
Я не впевнений, що ви маєте на увазі, що "вхід може бути позиційним або кар'єрним". Чи правильно визначити головну функцію як lambda m,n,f:apply f m-n times(або навіть lambda m,n,f,x:apply f m-n times to x) замість lambda m,n:lambda f:...? Або це просто стосується двох входів mі n?
xnor

Також, можемо ми взяти аргументи mі nв іншому порядку? Це допомогло б при завивці.
xnor

@xnor до тих пір, поки ви можете довести, що він віднімає дві церковні цифри, тоді ви можете взяти вхід у будь-який момент.
Райан Шефер

Відповіді:


9

Haskell , 35 байт

(r%s)f x=s(x:)(iterate f x)!!r(+1)0

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

Кажуть , що rі sє церковні кодування mі n. Ми хочемо r%sзастосувати f m-nрази до деякого початкового значення x. Спочатку ми генеруємо нескінченний список

iterate f x = [x, f x, f (f x), f (f (f x)), ...]

потім використовуйте s(x:)для додавання nкопій x, тобто зміщуйте кожен nіндекс значень право:

s(x:)(iterate f x) = [x, x, x, ...,  x, f x, f (f x), f (f (f x)), ...]

Потім ми обчислюємо mбезпосередньо як r(+1)0і беремо m'-й елемент цього списку як !!r(+1)0. Рішення без індексації може замість цього зробити head$r tail$..., тобто скинути перший елементm рази а потім взяти перший елемент, але синтаксис індексації значно коротший.

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


3

Python 2 , 82 80 байт

eval('!u:!v:v(!n:!f:!x:n(!g:!h:h(g(f)))(!u:x)(!u:u))(u)'.replace('!','lambda '))

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

2 байти Thx, щоб Нік Кеннеді, відзначаючи непотрібну пару паронів.

Анонімна функція, яка реалізує мінус.

Переважно це лише стиснення визначення, знайденого на сторінці Вікіпедії; не так, як я справді розумію код. Але цікаво!


Виходячи із суті, про яку згадував ОП, !u:!v:v(!n:!f:!x:n(!g:!h:h(g(f)))(!y:x)(!x:x))(u)схоже, що вона зберігає 2 байти, але я не дуже розумію код!
Нік Кеннеді

@NickKennedy gettingsharper.de/2012/08/30 / ... якщо ви зацікавлені
Райан Schaefer

@Ryan Schaefer: Гарний "трюк"!
Chas Brown

3

Python 2 , 77 байт

lambda r,s:s(lambda r:lambda f:lambda x:r(lambda(_,x):(x,f(x)))((x,x))[0])(r)

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

Ми робимо церковний декремент, відстежуючи попереднє значення для кожної ітерації та виводячи це в кінці. 39% довжини коду - це "lambda"...


приємно! Я чекав відповіді гольф-пітона, який не просто дивився на реалізацію суті. Чи думали ви про використання eval, як інша відповідь для подальшого гольфу?
Райан Шефер

@RyanSchaefer Я перевірив річ eval / substitution, коли побачив іншу відповідь, але насправді тут на 2 байти довше, щоб замінити 5 лямбда. На жаль, Python справді багатослівний як у визначенні функцій, так і в маніпуляції з рядками. І не вистачає вбудованого "композиту", який би врятував шар лямбда.
xnor

2

C ++ (клакс) , 112 байт

#define L(x,y)[&](auto x){return y;}
auto m=L(u,L(v,v(L(n,L(f,L(x,n(L(g,L(h,h(g(f)))))(L(u,x))(L(u,u))))))(u)));

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

Це на сьогодні самий незрозумілий C ++ код, який я коли-небудь писав. З цього приводу я думаю, що відміняння цього коду лише погіршить його.


2

Низький навантаження , 37 байт

(~(((!())~):*^(~!:(:)~*(*)*)~^^!)~^^)

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

Внутрішня (((!())~):*^(~!:(:)~*(*)*)~^^!)- це predфункція, реалізована за допомогою пар:

(               ( start pred function )!
  (
    (!())~      ( push zero below argument )!
  ):*^          ( do that twice )!

  (             ( start pair-increasing function )!
    ~!          ( remove second argument)!
    :           ( duplicate first argument )!
    (:)~*(*)*   ( increment first return value )!
  )
  ~^^           ( run pair-increasing function n times )
  !             ( remove first in returned pair )!
)


1

JavaScript (Node.js) , 87 85 81 76 74 байт

f=>g=>h=>x=>f(([x,[g,a]])=>[g(x),a])([x,g(a=>[x=>x,a])(f(a=>[h,a])())])[0]

Спробуйте в Інтернеті! Не збираюсь вигравати жодної нагороди, але я подумав, що спробую інший підхід.

a=>[h,a]це етап, який застосовується h, а a=>[x=>x,a]етап, який не застосовується h. Застосовуємо перший час функціонування fта другий час функціонування g. Потім застосовуємо зворотні функції ([f,[g,a]])=>[g(x),a] f. Це пропускає gдругий етап і виконуєf-g перші етапи за бажанням. Потім залишається витягнути остаточне значення.

Зверху кортежі можуть бути перетворені на лямбда-функції, що призводить до наступного вираження:

f=>g=>h=>x=>f(e=>e(x=>d=>d(g=>a=>e=>e(g(x))(a))))(e=>e(x)(g(a=>e=>e(x=>x)(a))(f(a=>e=>e(h)(a))())))(x=>a=>x)

1

J , 56 байт

c=:3 :0
t=.^:y
5!:1<'t'
)
m=.2 :'c 0>.(>:u 5!:0->:v 5!:0)0'

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

Примітка: від TIO рахується -3 байтиm=.

Функції вищого порядку в J досягаються за допомогою прислівників та сполучників. Тут церковним числом є дієслова дієприслівника, утворена сполученням сполучення "сила" (до якого багаторазово застосовується дієслово) та цілого числа. Наступне дієслово c(для "create") використовує J Atomic Представлення J, щоб перетворити ціле число в таке герундійне:

c=:3 :0
t=.^:y
5!:1<'t'
)

Наш оператор "мінус" (який є сполучником) віднімає правильну цифру церковного символу зліва. Однак це не передбачає конкретного втілення церковних числівників, у тому числі й від нашого cдієслова. Натомість вона спирається на загальне визначення і перетворює кожну цифру церковного роду в прислівник, перевертаючи її 5!:0, а потім застосовуючи це прислівник до дієслова приріст >:, а потім застосовуючи його до 0.

Потім він віднімає і приймає максимум з 0, і застосовується, cщоб отримати кінцевий результат: нову цифру церковного символу.


1

Мова Вольфрама (Mathematica) , 55 48 47 39 байт (33 символи)

#2[(fx#[g#@g@f&][x&][#&])&]@#&

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

Символ is 0xF4A1, спеціальна кодова точка Mathematica, яка позначає стрілку праворуч для \[Function]. Дивіться тут для отримання додаткових пояснень. Ось як виглядає код на передньому кінці Mathematica:

введіть тут опис зображення

Ми можемо зробити це в 40 байт / 32 символи , що може бути коротшим, залежно від схеми вимірювання:#2[n⟼f⟼x⟼n[g⟼#@g@f&][x&][#&]]@#&

Версія без гольфу - це дослівний переклад класичного визначення pred :

pred = n \[Function] f \[Function] x \[Function] n[g \[Function] h \[Function] h[g[f]]][u \[Function] x][u \[Function] u];
subtract[m_, n_] := n[pred][m]

що виглядає так на передньому кінці Mathematica:

введіть тут опис зображення

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

c@0=#& &;c@n_=#@*c[n-1][#]&

(Ип-golfed: c[0] = Identity &; c[n_] = Function[a, a@*c[n-1][a]])

щоб ми мали

Table[c[n][f][x], {n, 0, 6}]
(*    {x, f[x], f[f[x]], f[f[f[x]]], f[f[f[f[x]]]], f[f[f[f[f[x]]]]], f[f[f[f[f[f[x]]]]]]}    *)

і

subtract[c[7],c[5]][f][x]
(*    f[f[x]]    *)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.