Поради щодо зберігання мовою для гольфу


16

Я пишу мову з гольфу.

Ви пропонуєте змінні, стек (и), стрічки, регістри тощо для зберігання мовою коду-гольфу? А як щодо неявного введення?

Приблизні визначення:

  • Змінний просто ім'я ( як правило , один персонаж довго мови гольфу) , що значення може бути присвоєно, а потім вилучається з цим ім'ям.
  • Регістр подібний змінним, але вона має свій власний (зазвичай однобайтових) команду для установки / отримання значення.
  • Стек є змінною довжиною масиву / списком значень, де найбільш недавно додані значення (значення «зверху») є ті, які модифікуються.
  • Черги , як стек, за винятком значення «на дні » є ті , які модифікуються.
  • Стрічка являє собою статичний масив / список значень , де кожне значення має індекс. Основна відмінність стека від стрічки полягає в тому, що значення на стрічці змінюються на місці.

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


1
Думаю, ви повинні включити визначення цих термінів у своє запитання
Kritixi Lithos

2
@Fatalize Технічно метод зберігання не залежить від того, яку мову гольфу ви робите, вид мови для гольфу залежить від способу зберігання ...
ETHproductions

1
@ETHproductions Вони повністю взаємозалежні.
Фаталізувати

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

2
Існує дуже тісний взаємозв'язок між способом зберігання і типом мови, але я думаю, що ви повинні дивитися на обидва. Наприклад, "імперативні" мови (ті, які виконують свої вказівки строго зліва направо) можуть бути на основі стека (CJam, 05AB1E), на основі стрічки (BrainF ***) або зовсім іншого (V, який використовує одна велика 2D-рядок під назвою "буфер" разом з кількома регістрами). Є також мови, що базуються на префіксах (Pyth), мови, що базуються на інфіксах (Japt, Pip, і в основному кожен основний язик), мови на основі посилань (Jelly) тощо. Всі вони навряд чи використовують жоден із згаданих методів.
ETHproductions

Відповіді:


4

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

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

Але в більшості випадків вам навіть не потрібен оператор, і мова зробить це неявно. Саме тоді потрібно розглянути більш стандартизовану модель, таку як стеки чи черги. На сьогодні найбільш вдалим виявилося негласне програмування, яке навіть не згадує безпосередньо про зберігання.

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

Але зауважте, що ви можете кодувати форму двійкового дерева лише у 2 бітах на оператора. Тож, якщо у вашій мові є менше 64 операторів, ви можете ігнорувати традиційні моделі і просто закодувати повне дерево у запасні біти (називайте їх комбінованими та прозорими прапорами нижче). Навіть якщо операторів більше, ви можете зробити досить непоганий за замовчуванням (наприклад, модель Jelly) та 3 модифікатори, щоб змінити його.

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

Для довідки, розмір ідеального кодування бінарного дерева є логарифмом каталонських чисел . А розмір ідеального кодування "бінарного" дага - це логарифм A082161 , але, очевидно, недоцільно. Це передбачає, що оператор з різним порядком аргументів двох різних операторів, додаючи ще один біт, коли його немає.

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


7

Пропоную всім їм!

Більш серйозно, всі вони корисні деякий час, і чим більше, тим краще! Неявне введення ніколи не є поганим , просто встановіть прапор, щоб вимкнути його. Змінні корисні, тому їх не потрібно знаходити на стеці чи стрічці; те саме з регістрами. Стеки корисні для зберігання даних, а також стрічки. Я рекомендую спробувати реалізувати кілька, скажімо, стек і регістри, або стек і змінні, наприклад GolfScript. Якщо ви можете зробити кожну функцію одним байтом, то ваша мова, ймовірно, буде ефективною в гольфі, оскільки ви можете використовувати переваги кожної.

Приклад:

  • Скажіть, я хочу взяти два числа як вхідні дані та додати їх довжину рядків
  • Змінні можуть бути кращими для цього (стек може не бути)
  • Приклад коду в GolfScript (з неявним введенням):

    ~,\,+
    ~ # Eval input (e.g. "1 2" > 1, 2)
    , # Take Length
    \ # Reverse items on the stack
    , # Take Length
    + # Add
      # Implicit output
    

    Однак зі змінними (я знаю, що це довше, просто не потрібно міняти місцями в стеку):

    ~,:a;,:b;ab+
    ~ # Eval input
    , # Get length
    :a# Store in "a"
    ; # Discard value left on stack
    , # Length
    :b# Store in "b"
    ; # Discard
    a # Recall a
    b # Recall b
    + # Add
      # Implicit output
    

Перевантаження

Ще одна річ, яка може бути корисною, - це перевантаження. Наприклад, якщо у вас є функція зберігання змінної, можливо, вона може бути використана як монада (функція з одним входом; я не впевнений у терміні поза J / K / APL) для додавання до стеку чи стрічки.

Приклад:

c12 # Stores "1" into register 2
c1] # Pushes "1" onto the stack ("]" is used to denote the end of the monad)

Можливо, якщо аргумент викликається неправильними типами, він додається до черги, яка потім використовується для заповнення значень, якщо стек порожній?
Esolanging Fruit

5

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

З наведених визначень найкращими будуть ті, на які я вважаю, що працювали б - стек та регістри.
Стек, тому що стрічка повинна використовувати функції просто для зберігання в ній нової речі, тоді як стек повинен мати прості функції push і pop (зазвичай вбудовані в команди). Реєструється, оскільки вони займають менше байтів, порівняно зі змінними, і якщо вам потрібно щось зберігати більше, ніж 2-4 різних, ви робите щось не так.

Не обмежуйте їх функції лише тим, що їх імена чи визначення пропонують через деякі функції, такі як, put the 1st thing of the stack on top of the stackбезумовно, можуть допомогти.


5

В основному є два види зберігання, з якими потрібно по-різному оброблятись; доступ до нещодавно створених значень та / або входів; і довготривале зберігання.

Для довготривалого зберігання змінні, здається, працюють найкраще; все, що має обмежену кількість варіантів, не змінюється (хоча мови з такою властивістю, як Jelly, тим не менш, можуть робити досить добре навіть для середніх завдань). Однак, не потрібно вводити імена змінних під час зберігання змінної в більшості випадків; просто маєте команду зберігати значення у змінній та автогенерувати імена відповідно до передбачуваної схеми, щоб зберігати та отримувати значення може бути одна команда кожна у простих випадках. (Наприклад, у вас могли бути команди для відновлення останньої призначеної змінної. Друга останнім часом, третя останнім часом тощо), до невеликого фіксованого числа, плюс загальна команда, яка взяла аргумент.)

Для короткочасного зберігання ви хочете, щоб якомога більше було неявно. Майже всі мови для гольфу, які я бачив, за замовчуванням підключають вихід однієї команди до входу наступної; точний спосіб, яким це робиться, відрізняється від мови до мови, але зазвичай доходить до одного і того ж. Однак другий вхід для команди з 2 входами цікавіший. Якщо взяти його з стека, добре працює у випадках, коли значення використовуються лише один раз, але вони не масштабуються при повторному використанні значень. (Постарайтеся уникати примітивів для маніпуляції зі стеком; якщо вам доведеться вдатися до їх використання, ви витрачаєте багато байт.) Як варіант, використовуючи введення користувача або нещодавно присвоєну змінну, оскільки неявний другий аргумент, як правило, дає кілька заощаджень на байтах прості програми, хоча ви '

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


0

Пропоную стрічку та реєстр.

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

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