Поради щодо гольфу в TI-BASIC


26

Які загальні поради щодо гольфу в TI-BASIC для калькуляторів серії TI-83/84 +? Я шукаю ідеї, які можна застосувати до проблем із кодом-гольфу, які також принаймні дещо специфічні для TI-BASIC (наприклад, "видалити коментарі" - це не відповідь).

Будь ласка, опублікуйте одну пораду за кожну відповідь.


6
Будь ласка, завжди вкажіть, до якої версії ви звертаєтесь!
flawr

Відповіді:


22

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

:Disp "HELLO WORLD    //is the same as...
:Disp "HELLO WORLD"

For(циклі мають такий синтаксис - For(variable, start, end, increment), але ви можете пропустити приріст, і він використовуватиме 1:

:For(A,1,5     //is the same as...
:For(A,1,5,1)

і ви можете опустити кінцеві круглі дужки (в кінці рядків) на всій дошці:

:Output(1,1,A
:int(A
:round(A
etc.

Тестовано на моєму калькуляторі Silver TI-84 Silver Edition

Якщо ви вважаєте, що це більше, ніж одна ідея (випливає із закінчень), то я їх розпаду


5
.... це просто неправильно 😭
бета-розпад

2
Також спробуйте переписати код, щоб ви використовували найменшу кількість закритих дужок. Тільки в останньому виразі кожного рядка ви отримуєте круглі дужки безкоштовно, тому перемістіть найбільш вкладені висловлювання до кінця. Тобто not(iPart(B))+(A=5може бути (A=5)+not(iPart(B.
lirtosiast

4
Це стосується всього, що потребує закриття, а не лише для дужок (а саме {lists}, "strings"і [[matrices]]). Вирази автоматично закриються, коли ви досягнете нового рядка, двокрапки (очікування для нового рядка; не застосовується до рядків, хоча вони можуть містити кольори) або стрілки присвоєння змінної ( набраної кнопкою STO ▶ ` ). Така дивна риса мови.
MI MI Райт

14

Використовуйте Ans

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

Xsin(A)->R
Disp R+tanh(R

може бути

Xsin(A)
Disp Ans+tanh(Ans

економія двох байтів.


9

Використовуйте таблицю пошуку, закодовану в числах з плаваючою комою

Трохи вдосконалений рада:

Невеликі таблиці пошуку корисні для гольфу з кодом: дуже часто нам потрібна функція, яка відображає, наприклад, 0 до 1, 1 до 2, 2 до 1, а все інше до 0. Однак масиви TI-BASIC не підходять. для цієї мети: для однієї речі вони засновані на одній, а для іншої значення не може бути вилучено, поки масив не зберігається в Ans списку чи змінної.

У своїй відповіді тут я зберігаю невелику таблицю пошуку в чарівної константі в базі 11. Просто перерахуйте значення, які ви хочете використовувати,

{0,-1,5,-1,-1,2,9,-1,8,6}

перетворити на корисну форму

{1,0,6,0,0,3,10,0,9,7}

запишіть у бажану базу (база 11)

.106003A097

і перетворити на базу 10

-1+int(11fPart(11^Ans.0954191904

Найменший підхід до масиву на 8 байт довший!

{1,0,6,0,0,3,10,0,9,7}-1:Ans(X+1

TI-BASIC зберігає лише плаваючі до 14 десяткових цифр, тому ви можете зберігати до 44 біт, але лише 14 десяткових цифр.

Цей прийом часто можна вдосконалити, використовуючи грубу силу пошуку, щоб знайти магічну константу, а не базове кодування. Я все ще знаходжу відповідь вище, але легендарний гольфіст TI-BASIC Weregoose використовував цей метод, щоб генерувати відмінності між числами копрієм з 30 (тобто повторюваним списком 6, 4, 2, 4, 2, 4, 6, 2) на вікі / форумі TI-BASIC Розробник із цим фрагментом:

2+2iPart(3fPart(576e^(fPart(I/8

Чарівна константа 576 була знайдена за допомогою Mathematica, але якщо ви не володієте копією, використовуйте скрипт улюбленою мовою.


5

Поставте змінні рівняння повторних виразів.

EX:

Remainder(randInt(1,9),1
Remainder(randInt(1,9),5
Remainder(randInt(1,9),10

Може бути:

"randInt(1,9→u
Remainder(u,1
Remainder(u,5
Remainder(u,10

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

Джерело: http://tibasicdev.wikidot.com/selfmodify

-c4ooo від Omnimaga


У цьому прикладі ви можете зекономити, додавши nдо першого виразу разом із Remainder(функцією.
Conor O'Brien

5

Пропустити непотрібну ініціалізацію змінної

Поточний консенсус полягає в тому, щоб дозволити запускати весь код на новому перекладачі. Ми можемо цим скористатися - всі неініціалізовані реальні змінні починаються 0з TI-BASIC і Xminпочинаються як можливо корисне значення -10. Отже, якщо вам коли-небудь потрібно взяти загальну кількість у програмі, яка не приймає дані від Ans, або вам дійсно потрібен -10один менший байт, ця порада може вам допомогти.


Xmax 10, а Ymin і Ymax поводяться аналогічно, правда? Також є деякі інші параметри графіка, які мають деякі інші значення, я думаю.
Фабіан Рьолінг

5

Менша генерація списку

Якщо вам потрібен список {1,2,...,N}, де N, скажімо, 42, очевидний спосіб його створення

seq(X,X,1,42. 

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

cumSum(binomcdf(41,0

Це працює лише тоді, коли N є постійною, оскільки економія відбувається від заміни N-1 його значенням у коді.

Є два випадки, які дозволяють ще коротший код.

Якщо у вас уже є список L1виміру N:

cumSum(1 or L1

Якщо ви не дбаєте про замовлення:

randIntNoRep(1,N     ;random permutation of numbers from 1 to N

2
Гарантована, що вона на один байт менша (і тупо повільніше), ніж seq(X,X,1,Nнавіть коли Nне є постійною cumSum(1 or rand(N.
Міша Лавров

4

Усуньте оператори End для блоків If в кінці програми

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

[code]
If A>5
Then
Output(1,1,Ans²+Ans+A
Disp 3ln(A
End
//end of program

Може бути:

[code]
If A>5
Then
Output(1,1,Ans²+Ans+A
3ln(A
//end of program

Слід зазначити, що ця порада не працює для циклів блоків. +1 за гарну пораду
Тау,

4

Знайте свої ідіоми

Ось кілька фрагментів, які я зазвичай використовую в коді гольфу:

  • Перетворити на значення істини (0/1): not(not(AnsабоAns and 1 . Який використовувати, залежить від потрібних дужок.
  • Додайте один до истинностное значення: int(e^(Ans. Зберігає відкрите батьківство1+(Ans . Дуже корисно, тому що TI-BASIC має масиви на основі однієї основи.
  • Карта {0,1}для {1,-1}: cos(πAns. Збереже один байт 1-2Ans.

  • Функція знаку числа: tanh(ᴇ9Ans
  • Поверніть до позитивної нескінченності: -int(-Ans
  • Кількість цифр у натуральному цілому: 1+int(log(Ans
  • Комплексний номер для переліку {Re,Im}:imag(Ans{i,1

  • Перетворити рядок у список: seq(inString("...",sub(Ans,X,1)),X,1,length(Ans(де ...рядок пошуку)
  • Виріжте перший елемент списку: ΔList(cumSum(Ans
  • Виріжте останній елемент списку: ΔList(cumSum(Ans)-Ans
  • Перевірте, чи всі елементи списку L1унікальні:SortA(L1:min(ΔList(L1
  • Шукайте число X у списку (повертає перше виникнення): 1+sum(not(cumSum(Ans=X
  • Режим списку, коли існує один режим, і список містить не більше 10 елементів: (негарно, але коротко): median(Ans,10^(seq(sum(Ans=Ans(X)),X,1,dim(Ans

Я дійсно не розумію, чому це tanh(ᴇ9Ansпрацює.
SuperJedi224

1
@ SuperJedi224 Ну, ну, tanh (0 дорівнює нулю, а ліміт і ліворуч обмеження нескінченності - -1 та 1. Це наближається до експоненціально близьких до цих значень, тому минуле + -17 або близько того знаходиться в межах помилки округлення + -1. Якщо абсолютні значення вже перевищують 17, ми просто використовуємо tanh (поодинці.
lirtosiast

3

Якщо ви виявите, що використовуєте

0→G ;or any other variable
;other lines of code

Потім ви можете використовувати (щоб зберегти байт):

DelVar G;other lines of code

Це відбувається тому , що при видаленні змінної ( G), вона стає його значення по замовчуванню, в цьому випадку 0. Потім ви можете поставити інший рядок після DelVarзаяви, без нового рядка . Будьте обережні, ставлячи важливі контрольні заяви безпосередньо після DelVarзаяви.

(Випробувано на TI-84)


Це рідко корисно; змінні ініціалізуються до 0 за замовчуванням, і ви можете нульову Y, виконавши ZStandard.
lirtosiast

@ThomasKwa Мені це було корисно у багатьох випадках, особливо коли потрібно виконати скидання частково через виконання.
Conor O'Brien

2
У коді гольф? Коли? Якщо ви покажете мені програму, я думаю, я зможу оптимізувати DelVar.
lirtosiast

@ThomasKwa Не xode гольф сам по собі , скоріше, програмування на низькому просторі диска (TI-83). Я зараз не маю програми. Я повернуся до вас з цього приводу.
Conor O'Brien

1
Після декількох хвилин роздумів я можу придумати кілька сценаріїв, коли DelVar, можливо, буде найкоротшим, як, наприклад, після однорядних тверджень If.
lirtosiast

3

Які змінні списку використовувати?

Використовуючи списки, уникайте списків L₁за замовчуванням через L₆користь названих списків з однобуквеними іменами: ᶫAчерез ᶫZ(де маленький L).

Або один коштує два байти для посилання (хоча L₁це один маркер, це двобайтовий маркер), але зберігаючи значення в списку, ви можете скинути символ, зберігаючи байт:

{1,2,3,4,5→ᶫA

може бути

{1,2,3,4,5→A

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

Аналогічно, Input Aабо Prompt Aбуде зберігатися, ᶫAякщо користувач введе список замість номера.

Кілька інших команд можна використовувати без , хоча більшість з них рідко використовуються в гольфі. Наприклад, Matr►list(дозволяє видалити аргументи третього, четвертого та вищого.

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

Це не працює зі зміною одного запису списку: 1→ᶫA(3не може бути змінено на 1→A(3.

Звичайно, найкраща змінна список завжди використовується Ans.


Чекати, що? " Input A" зберігається, ᶫAякщо користувач входить до списку. "Це означає, що багато моїх програм досить легко зламати. Тоді добре, що у мене все одно немає такої кількості Inputпрограм, в основному у мене є або невеликі інструменти без перевірки помилок, або повні ігри, які використовуються GetKeyзамість Input.
Fabian Röling

1
Якщо ви дійсно зацікавлені у захисті користувача від своїх програм проти цього, ви завжди можете зберігати випадкове значення Aта перевіряти, чи змінилося воно після Input A.
Міша Лавров

2

Знайте свої змінні витрати на призначення

Якщо ви використовуєте B-байтовий виразN , чи слід йому присвоювати змінну?

Ansвитрати в 1+Nбайтах (один для рядка і один для кожного його використання, тому використовуйте Ans коли (B-1)*(N-1)>2. У Ansрядку може бути лише один , тому спробуйте всі значення дляAns які можуть бути корисні.

Реальні змінні (наприклад X) вартість 3+Nбайтів, тому використовуйте їх, коли(B-1)*(N-1)>4 .

Перелічіть змінні вартості 3+2Nбайтів, тому використовуйте їх, коли(B-2)*(N-1)>5 .

Змінні рівняння є найменш корисними: їм потрібні 4+2Nбайти. Використовуйте їх коли (B-2)*(N-1)>6.

Min. bytes in an expression to save
 N \ var. | Ans | Real | List | Eqn
------------------------------------
 2           4     5      8      9
 3           3     4      5      6
 4           2     3      4      5

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

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

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


1

int (rand over randInt (

X + int (Yrand дорівнює або менше байтів, ніж randInt (X, Y, оскільки randInt - маркер 2 байти. Деякі потенційні переваги:

X + можна вимкнути, коли нижня межа дорівнює 0, економлячи два байти

X + необхідний перед randInt (у будь-якому випадку в певних ситуаціях, наприклад, випадково від крокової функції на зразок {2,5,8,11}

X + int (Yrand (N можна використовувати так само, як randInt (X, Y, N для створення списку з N випадкових чисел)

Ініціалізація графічного екрана

Для використання таких функцій, як Line (легко за допомогою піксельних координат, необхідно ініціалізувати осі графічного екрана до квадратних пікселів та видалити осі:

AxesOff
84→Xmin
72→Ymax
ZInteger

Затискач

min(U,max(L,N

Де N - число або алгоритм, а U і L - верхня і нижня межі

Є N у списку

max(N={X,Y,Z

Більше переліку математики

L1*L2→L3

instead of

for(A,1,dim(L1
L1(A)*L2(A→L3(A
End

This also works for things like this:
not(L1
L1 and L2

Вихідні дані

Дисплей та текст (може бути ланцюжком, тому Disp A, B відобразить A, потім B на окремих рядках, а Text (28,40, A, B надрукує A поряд із B на одному рядку)

Технологія з оптимального циклу руху

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

http://tibasicdev.wikidot.com/movement

Списки розмірів жетонів

http://tibasicdev.wikidot.com/tokens

За допомогою скорингу

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