CPPLASTIC Telegram 361
У Prolog 🦉 фішка, що все описується предикатами. А ми з вами звикли, що предикат — це функція, яка повертає bool. І я все ніяк не міг зрозуміти, а як же звідти щось інше діставати. Зрозуміло, що там зіставлення з шаблоном, як в якомусь Haskell чи Erlang, але все одно. Навіть дивився приклади — та не вкладалося в голові. Розповідаю, отже.

Є, наприклад, предикат number_string. Працює отак:
?- number_string(42, "42").
true.

Можна перевіряти, чи число співпадає зі своїм представленням у вигляді рядка. Зручно, але шо далі? А ось що:
?- number_string(42, Str).
Str = "42".

?- number_string(Num, "42").
Num = 42.

Тобто ви просто ставите замість одного з параметрів змінну (з великої літери), а воно, якщо може, матчить його зі значенням, з яким предикат видаватиме true. Причому це можна робити в обидва боки! Іншими словами, у вас параметри предиката — це і «вхідні», і «вихідні» разом. How cool is that?!

Ось парсинг першого рядка вхідних даних, що я давав на початку попереднього допису:
parse_button_a(Line, X, Y) :-
split_string(Line, ",:", " ", ["Button A", Xs, Ys]),
parse_num('X', Xs, X),
parse_num('Y', Ys, Y).

У parse_button_a я за задумом першим параметром даю текстовий рядок й очікую, що X та Y воно виведе само. Для цього мають виконуватися правила під ним. Перше правило: якщо я цей рядок сплітаю по комі та двокрапці (і прибираю зайві пробіли), то очікую, що останній параметр заматчиться зі списком з трьох штук. Перша — це сталий рядок "Button A", а другий та третій — це рядки зі значеннями для координат (наприклад, "X+94" та "Y+34"). Два наступних правила вже працюють якраз з ними й фактично дістають з рядків числа. Глянемо всередину.
parse_num(Var, String, Number) :-
atom_chars(String, [Var, Sign|Rest]),
atom_chars(NumStr, [Sign|Rest]),
atom_number(NumStr, Number).

Тут три параметри — назва координати (Var), рядок з попереднього правила та відповідне числове значення. atom_chars матчить рядок зліва зі списком атомів (а ля констант) справа. Тож перший з них бере рядок і деконструює його на Var ('X'), Sign ('+') і решту (['9', '4']). Друге правило фактично робить це у зворотній бік: справа ми даємо ['+', '9', '4'], а зліва отримуємо '+94'. Цими двома правилами ми, по-перше, переконалися, що це справді X, який ми очікуємо, а по-друге, ми його відрізали з рядка, щоб не заважав. А третій предикат матчить атом (вважайте, що рядок) зліва ('+94') з числом справа (там буде 94). І потім, якщо все це заматчилося, це число йде в параметри самого parse_num.

Ну короч ось так я запарсив увесь файл, а потім читернув та використав солвер лінійних рівнянь ))
solve_machine(Ax, Ay, Bx, By, Px, Py, A, B) :-
A in 0..100,
B in 0..100,

A * Ax + B * Bx #= Px,
A * Ay + B * By #= Py,

Tokens #= A * 3 + B,

labeling([min(Tokens)], [A,B]).

Він «отримує» перші шість параметрів у вигляді чисел і підбирає й «виводить» такі A й B, щоб ціна була найменша. Вуаля! )

Звісно, Prolog цим не обмежується. Теоретична база все одно потрібна, бо він і так доволі повільний (пів секунди на дві задачі), а на додачу дуже легко запитати щось, відповідь на що він шукатиме мільярд років. Попри це я зацінив!

І навіть при розвʼязанні задач на 17-й день іншою мовою, я у момент відчаю швиденько написав на Prolog робочу віртуальну машину на 8 команд з трьома регістрами памʼяті, щоб звірити результати.

Дуже раджу теж спробувати.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤩43🔥1



tgoop.com/cpplastic/361
Create:
Last Update:

У Prolog 🦉 фішка, що все описується предикатами. А ми з вами звикли, що предикат — це функція, яка повертає bool. І я все ніяк не міг зрозуміти, а як же звідти щось інше діставати. Зрозуміло, що там зіставлення з шаблоном, як в якомусь Haskell чи Erlang, але все одно. Навіть дивився приклади — та не вкладалося в голові. Розповідаю, отже.

Є, наприклад, предикат number_string. Працює отак:

?- number_string(42, "42").
true.

Можна перевіряти, чи число співпадає зі своїм представленням у вигляді рядка. Зручно, але шо далі? А ось що:
?- number_string(42, Str).
Str = "42".

?- number_string(Num, "42").
Num = 42.

Тобто ви просто ставите замість одного з параметрів змінну (з великої літери), а воно, якщо може, матчить його зі значенням, з яким предикат видаватиме true. Причому це можна робити в обидва боки! Іншими словами, у вас параметри предиката — це і «вхідні», і «вихідні» разом. How cool is that?!

Ось парсинг першого рядка вхідних даних, що я давав на початку попереднього допису:
parse_button_a(Line, X, Y) :-
split_string(Line, ",:", " ", ["Button A", Xs, Ys]),
parse_num('X', Xs, X),
parse_num('Y', Ys, Y).

У parse_button_a я за задумом першим параметром даю текстовий рядок й очікую, що X та Y воно виведе само. Для цього мають виконуватися правила під ним. Перше правило: якщо я цей рядок сплітаю по комі та двокрапці (і прибираю зайві пробіли), то очікую, що останній параметр заматчиться зі списком з трьох штук. Перша — це сталий рядок "Button A", а другий та третій — це рядки зі значеннями для координат (наприклад, "X+94" та "Y+34"). Два наступних правила вже працюють якраз з ними й фактично дістають з рядків числа. Глянемо всередину.
parse_num(Var, String, Number) :-
atom_chars(String, [Var, Sign|Rest]),
atom_chars(NumStr, [Sign|Rest]),
atom_number(NumStr, Number).

Тут три параметри — назва координати (Var), рядок з попереднього правила та відповідне числове значення. atom_chars матчить рядок зліва зі списком атомів (а ля констант) справа. Тож перший з них бере рядок і деконструює його на Var ('X'), Sign ('+') і решту (['9', '4']). Друге правило фактично робить це у зворотній бік: справа ми даємо ['+', '9', '4'], а зліва отримуємо '+94'. Цими двома правилами ми, по-перше, переконалися, що це справді X, який ми очікуємо, а по-друге, ми його відрізали з рядка, щоб не заважав. А третій предикат матчить атом (вважайте, що рядок) зліва ('+94') з числом справа (там буде 94). І потім, якщо все це заматчилося, це число йде в параметри самого parse_num.

Ну короч ось так я запарсив увесь файл, а потім читернув та використав солвер лінійних рівнянь ))
solve_machine(Ax, Ay, Bx, By, Px, Py, A, B) :-
A in 0..100,
B in 0..100,

A * Ax + B * Bx #= Px,
A * Ay + B * By #= Py,

Tokens #= A * 3 + B,

labeling([min(Tokens)], [A,B]).

Він «отримує» перші шість параметрів у вигляді чисел і підбирає й «виводить» такі A й B, щоб ціна була найменша. Вуаля! )

Звісно, Prolog цим не обмежується. Теоретична база все одно потрібна, бо він і так доволі повільний (пів секунди на дві задачі), а на додачу дуже легко запитати щось, відповідь на що він шукатиме мільярд років. Попри це я зацінив!

І навіть при розвʼязанні задач на 17-й день іншою мовою, я у момент відчаю швиденько написав на Prolog робочу віртуальну машину на 8 команд з трьома регістрами памʼяті, щоб звірити результати.

Дуже раджу теж спробувати.

BY Cіпласпластик


Share with your friend now:
tgoop.com/cpplastic/361

View MORE
Open in Telegram


Telegram News

Date: |

Done! Now you’re the proud owner of a Telegram channel. The next step is to set up and customize your channel. Polls best-secure-messaging-apps-shutterstock-1892950018.jpg Hashtags Ng, who had pleaded not guilty to all charges, had been detained for more than 20 months. His channel was said to have contained around 120 messages and photos that incited others to vandalise pro-government shops and commit criminal damage targeting police stations.
from us


Telegram Cіпласпластик
FROM American