Прелюдія синтаксису-перевірки


10

Прелюдія - це езотерична мова програмування, яка має дуже мало, але незвичних обмежень щодо того, що становить дійсну програму. Будь-який блок тексту для друку ASCII ("блок", що означає, що рядки ASCII для друку розділені новими рядками - 0x0A) є дійсним за умови, що:

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

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

Ви не повинні вважати, що вхід прямокутний.

Це код гольфу, тому виграє найкоротше подання (у байтах).

Приклади

Нижче перелічені дійсні програми Prelude (насправді вони навіть справжні програми Prelude):

?1-(v  #1)-             
1   0v ^(#    0)(1+0)#)!
    (#)  ^#1-(0 #       
1(#  1) v #  - 1+)
    vv (##^v^+
? v-(0 # ^   #)
?
  1+              1-!

Ось низка входів, усі вони недійсні :

#(#(##)##)##(
)##(##(##)#)#
#(#)
)###
#(##
(##)
(##)
(#)#
(##)
(###
#(#)
(##)
#(#)
###)
#()#
()##
#(#)##
###
###(#)

Чи є у Прелюдії коментарі, які можуть заблокувати близького батька?
Олексій А.

@ Алекс. Наведені вище правила насправді є все, щоб вирішити, чи дійсна програма чи ні.
Мартін Ендер

Класно, дякую за уточнення. Просто хотілося переконатися.
Олексій А.

Правило 1 - "Кожен стовпець тексту містить щонайбільше один із (і)"; Приклад 1, рядок 2: "1 0v ^ (# 0) (1 + 0) #)!" -> Я бачу 3 )і 2 (. Чи не повинно бути лише 1 на рядок?
Ісмаїл Мігель

1
@IsmaelMiguel "стовпець" зазвичай розуміється як посилання на вертикальні лінії (особливо в контексті сіток). Я все-таки це уточнив.
Мартін Ендер

Відповіді:


3

CJam, 57 56 байт

qN/z_{_"()"--W<},,\s:Q,{)Q/({_')/,\'(/,-}:T~\sT0e>+z+}/!

Занадто довго, можна багато в гольф. Пояснення потрібно додати, як тільки я пограю.

Коротке пояснення

У коді є дві перевірки:

  • Спочатку фільтр перевіряє, що кожен стовпець не більше 1 дужки. Кінцевим виходом фільтра є кількість стовпців з більш ніж 1 дужкою.
  • По-друге, ми перетворюємо вхід у основний формат стовпця, а потім ділимо його на кожен індекс на дві частини.
    • У кожній з цих двох частин ( Number of "(" - Number of ")") повинні робити компліменти один одному. Отже, коли ви додаєте їх, це повинно призвести до 0. Будь-яка частина, яка не відповідає цій властивості, змушує весь вхід мати відповідні дужки.
    • Я також повинен переконатися, що "(" знаходяться зліва від ")". Це означає, що значення параметра Number of "(" - Number of ")"не може бути негативним для правого блоку.

Спробуйте його онлайн тут


6

Python 2, 128 119 105 байт

def F(p):
 v=n=1
 for r in map(None,*p.split("\n")):A,B=map(r.count,"()");n+=B-A;v*=n<2>A+B
 return n*v>0

Чи знаєте ви, що ви можете картувати None у Python 2?

Пояснення

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

Крім картування None:

>>> print map(None,*[[1,2,3],[4],[5,6]])
[(1, 4, 5), (2, None, 6), (3, None, None)]

На жаль (а точніше, на щастя для всіх не гольф-цілей), це працює лише в Python 2.

Щодо nта v:

  • nдіє як стек, рахуючи 1 - <number of unmatched '(' remaining>. Для кожного, кого (ми бачимо, ми віднімаємо 1, а для кожного, що )ми бачимо, додаємо 1. Отже, якщо n >= 2в будь-який момент, то ми побачили занадто багато )s і програма недійсна. Якщо nне закінчиться на 1, у нас (залишився хоча б один незрівнянний .
  • vперевіряє дійсність і починається з 1. Якщо програма коли-небудь недійсна ( n >= 2або A+B >= 2), то vстає 0, щоб позначити недійсність.

Отже, якщо програма дійсна, то до кінця ми повинні мати n = 1, v = 1. Якщо програма недійсна, то до кінця ми повинні або мати v = 0, або v = 1, n <= 0. Тому обгрунтованість може бути коротко виражена як n*v>0.

(Дякую @feersum за безліч хороших пропозицій, які зняли 14 байт!)

Попереднє, більш читане подання:

def F(p):
 p=map(None,*p.split("\n"));v=n=0
 for r in p:R=r.count;A=R("(");B=R(")");n+=A-B;v|=A+B>1or n<0
 return n<1>v

Це божевільне використання map...
xnor

1
119 -> 106def F(p): v=n=3 for r in map(None,*p.split("\n")):A,B=map(R.count,"()");n+=A-B;v*=n>2>A+B return n*v==9
feersum

@feersum Дякую! Я намагався змінити orланцюжок порівняння, але не думав перетворюватися |=на це *=. Однак узяв ще один байт, зробивши все ще більше назад :)
Sp3000

2

J, 64 байти

Введення - це рядок із заднім рядком. Вихід 0 або 1.

(0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)

Приклад використання

   ]in=.'#(#)##',LF,'###',LF,'###(#)',LF
#(#)##
###
###(#)

   ((0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)) in
0

Метод такий

  • вирізати введення в нових рядках і помістити в матрицю ];.2
  • карта (/ )/ anything elseв 1/ -1/0 1 _1 0{~[:'()'&i.]
  • визначте s=.+/@:прислівник, який додається до дієслова, підсумовує результат виведення масиву дієслів
  • додайте значення в стовпці ]s

    • перевірити позитивний ()баланс у кожному префіксі [:(0>])s)[:+/\]
    • перевірити рівний ()баланс у всьому списку (тобто в останньому префіксі) |@{:@]
  • додайте abs (значення) у стовпці та перевірте кожен елемент на максимальне значення 1 (1<|s)s

  • оскільки всі попередні перевірки дали позитивний результат при відмові, ми додаємо їх і порівнюємо з 0, щоб отримати достовірність введених даних 0=]


2

J, 56 байт

3 :'*/0<: ::0:(+/\*:b),-.|b=.+/+.^:_1]0|:''()''=/];.2 y'

Це анонімна функція, яка приймає рядок із заднім рядком та повертає 0 або 1. Читання справа наліво:

  • ];.2 y, як і в іншому поданні J, обрізає рядок yпри всіх явищах останнього символу (саме тому для введення потрібен останній новий рядок) і складається прямокутна матриця, рядки якої є шматками, при необхідності прокладеними пробілами.

  • '()'=/порівнює кожен символ у цій матриці спочатку (з )поверненням двох матриць 0-1.

  • +.^:_1]0|:перетворює цей список з двох матриць в єдину матрицю складних чисел. Поки програма перетворює кожен (вхід в 1, кожен )в i, а кожен інший символ в 0.

  • b=.+/присвоює суму рядків цієї складної матриці b.

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

  • +/\*:b- вектор запущених сум квадратів чисел у b. Якщо кожен стовпець містить щонайбільше одну дужку, всі цифри у числах bстановлять 0, 1 або -1. У ,зв'язує цей вектор з вектором 1 | г | 'с.

  • Тепер все, що нам потрібно зробити, - це перевірити, що записи нашого об'єднаного вектора - vце неотримані числа реальних цифр, це майже */0<:v, за винятком того, що викликає помилку, якщо деякі записи vне є реальними, тому ми заміняємо <:на <: ::0:який просто повертає 0 у випадку помилки .


Чудові ідеї зі складними цифрами, але ви також повинні перевірити, якщо, 0={:+/\*:bнаприклад (, не вірно.
випадкова

О, ти маєш рацію, @randomra, я забув!
Омар

1
0=(-|)vна 2 байти коротше для перевірки негативних цифр. (Давайте переможемо CJam!: P)
randomra

1
О, і invзамість цього ^:_1 зберігає ще один байт.
randomra

1
Назад до 56 (з перевіркою балансу): 3 :'*/0=({:,]-|)(-.@|,+/\@:*:)+/+.inv]0|:''()''=/];.2 y'.
випадкова
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.