Позначення префікса до нотації Postfix


19

Відмова від відповідальності: Ні, це не жарт, щоб перевернути рядок.

Завдання

Для підтримки існує лише одна операція: віднімання ( -).

У вас також є лише два атоми для підтримки: нуль ( 0) та один ( 1).

Тут позначення префікса -ABеквівалентно нотації постфікса AB-, де Aі Bє виразами.

Ваше завдання - (рекурсивно) перетворити вираз у нотації префікса до його еквівалента в нотації постфікса.

Визначення

Вираз у позначенні префікса породжується наступною граматикою:

S > -SS
S > 0
S > 1

Вираз у позначеннях постфікса породжується наступною граматикою:

S > SS-
S > 0
S > 1

Приклад

Prefix notation:  --01-0-01
Parentheses:      -(-01)(-0(-01))
Convert:          (01-)(0(01-)-)-
Postfix notation: 01-001---

Правила і свобода

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

Тестова шафа

Input       Output
1           1
0           0
-01         01-
-10         10-
--01-0-01   01-001---

Тестові шкали кредитів Даді .


1
Чи можете ви додати ще кілька тестових випадків?
Кудлатий

@Shaggy, які саме тестсеси ви б хотіли?
Лина монашка

@LeakyNun Чи добре сприймати вхід і вихід як ітератори, як я це робив в останній версії своєї відповіді?
L3viathan

@ L3viathan Я гадаю, що так ...
Leaky Nun

Відповіді:


12

мозковий ебать , 32 байти

,[[->++++<<+>]>[[-]<<[.[-]<]]>,]

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

Я використовував @як операцію, тому що її кодова точка (64) зручна. Uможливо також з однаковим числом байтів, використовуючи 3 * 85 + 1 = 256 = 0.

Пояснення

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

,[                Take input and start main loop
  [->++++<<+>]    Push input, and compute 4*input
  >[              If 4*input is nonzero (and thus input is not @):
    [-]<<           Zero out this cell and move to top of stack
    [.[-]<]         Pop from stack and output until \0 is reached
  ]
  >,              Move pointer into the correct position.  If input was @, the earlier > pushed \0 onto the stack.
]

6

Сітківка , 37 30 29 байт

M!`-*.
+m`^-(.*)¶(\d.*)
$1$2-

Спробуйте в Інтернеті! Збережено 7 байт, зрозумівши, що терміни завжди починаються з цифри, тому мені більше не потрібно обмежувати відповідність останнім -(раніше це було єдиним гарантованим дотриманням двох термінів). Збережено 1 байт, не ставлячи -s у власний рядок. Наприклад, -01стає тим, -0¶1що потім замінюється на 01-. Тепер, якщо у мене є --010ІЕ , --0¶1¶0то я хочу , щоб змінити внутрішнє , -0¶1щоб 01-так , що я можу замінити -01-¶0з 01-0-, але це на самому ділі не важливо , який з цих двох -сек я видалю, тому я видалити один на початку рядка, а це легше перевірити.


Я думаю, це твоє щось :)
Лев

@Leo Не працює взагалі, наприклад, -0-0-00слід стати 0000---.
Ніл

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

1
@Leo Зараз я щось знайшов ...
Ніл

1
@Leo З моїм останнім гольфом ми зв'язані!
Ніл

6

Haskell , 62 59 байт

f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
fst.f

Спробуйте в Інтернеті! Використання: fst.f $ "--01-0-01". 0і 1можуть бути довільні символи, що перевищують символи -.

Редагувати: -3 байти завдяки Zgarb!

Функція fрекурсивно розбирає один вираз і повертає кордон цього виразу в нотації постфікса та решту решти, дотримуючись просту граматику, з якої можна побудувати дійсні префікс-вирази:

<exp> ::= - <exp> <exp> | 0 | 1

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

Якщо ми знайдемо a -, два вирази потрібно розібрати. Це може бути досягнуто , (a,x)<-f rщоб отримати перший вираз , aа потім розібрати частину рядка xзнову , (b,c)<-f xщоб отримати другий вираз bі остаточну частину рядка c. (a,(b,c))<-f<$>f rробить це саме так, тому що <$>на картках карт функція два, другий елемент кортежу при цьому на три байти коротший, ніж (a,x)<-f r,(b,c)<-f x. Після отримання обох виразів і частина рядка, вираження зчіплюються і «-» додається: (a++b++"-",c).


1
Ви можете зберегти 3 байти, об’єднавши f(x:r)|x>'-'=([x],r)|(a,(b,c))<-f<$>f r=(a++b++"-",c)
регістри

@Zgarb Дякую! Чомусь я розглядав лише f(x:r)|x<'0',(a,(b,c))<-f<$>f r=(a++b++"-",c)|1<3=([x],r)тоді, коли шукав версію з обома випадками, що поєднуються, а це байт довше.
Лайконі

5

Haskell, 54 байти

v f""=""
v f(a:s)=last(v.v:[id|a>'-'])((a:).f)s
h=v h

Функція vприймає рядок і функцію, переставляє початковий підвираз, потім застосовує функцію до залишку рядка, поки все не буде переставлено. Стек виклику та аргумент функції разом відстежують, який вираз аналізується. Функція hвідповідає на виклик і просто vназивається самою собою, як перший манекен.


1
Оце Так! (1) Це всього 53, вам не потрібно рахувати остаточний новий рядок. (2) Перший рядок можна скоротити, v f l=lякщо пересувати його другим.
Ørjan Johansen

1
Я не думаю, що вам потрібно розбирати більше одного цілого виразу, тому ви можете зберегти байт за допомогою функції анонімного v id.
Ørjan Johansen

1
Насправді перший рядок ніколи не викликається при дійсному введенні, тому його можна просто видалити.
Ørjan Johansen

1
Розбиття на охоронців, схоже, перемагає lastтрюк на один байт.
Ørjan Johansen

4

Perl 5 , 57 байт

sub f{"@_"=~s/x((?0)|.)((?0)|.)/my$n=$2;f($1).f($n).x/re}

Я використовую xяк оператор замість -(див. Посилання TryItOnline нижче).

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

Пояснення:
/x((?0)|.)((?0)|.)/ відповідає рекурсивно повним виразом: a xна початку, потім вираз (?0)(це рекурсивний виклик) або атом ( .), за яким слідує інший вираз-або-атом.
Тоді мені потрібно зберегти другий вираз / atom ( my$n=$2;), оскільки в іншому випадку рекурсивні виклики перекриють його.
Потім функція рекурсивно викликається на першому виразі ( f($1)), потім на другому f($n), а the xдодається в кінці ( .x).


4

Python 3, 117 112 105 100 98 76 62 61 59 байт

def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]

Журнал змін:

  • видалено рядкові перерви, де це можливо (-5 байт)
  • лямбда замість повноцінної функції (-7 байт, дякую @Dada)
  • більше немає (-5 байт, дякую @Leaky Nun)
  • скасуйте зайвий гольф (-2 байти, дякую @Leaky Nun)
  • натомість працювати над глобальним списком (-22 байти)
  • насправді давайте працюємо над ітераторами (-14 байт)
  • змінити !=на >(-1 байт, копіюється з припущення @ovs ')
  • лінива хитрість оцінки (-2 байти, дякую @ovs)

Використовуйте його так:

>>> list(p(iter("--01-0-01")))
['0', '1', '-', '0', '0', '1', '-', '-', '-']


2
lambda x:p(x)[0]можливо, може замінити вашу fфункцію.
Дада

1
Вам не потрібно else, міркує.
Лина монашка

1
Чи d="-"справді економити байти?
Лина монашка

1
def p(s):x=next(s);yield from[x]*(x>"-")or[*p(s),*p(s),"-"]за 59 байт
ов

3

Pyth, 20 байт

L+&-hbTsyM.-Btbytbhb

Це створює функцію, yяка очікує рядок як параметр.

Спробуйте в Інтернеті: Демонстрація або Тестовий набір

Пояснення:

Функція yбуде аналізувати і перетворювати перший вираз префікса в постфікс-вираз. Тож якщо його зателефонують, y"10"він повернеться лише 1.

L+&-hbTsyM.-Btbytbhb
L                      define a function y(b), that returns:
   -hbT                   remove the chars "10" from the first char b
                          (T=10, and - will convert a number to a string)
  &                       if this gives the empty string (a falsy value)
 +                hb         then append b[0] to it and return it
                             (so this will parse a digit 0 or 1 from the string)
  &                       otherwise (the first char is a -)
               ytb           parse the first prefix expression from b[1:]
                             (recursive call)
          .-Btb              remove this parsed expression bifurcated from b[1:]
                             this gives a tuple [b[1:], b[1:] without first expr]
        yM                   parse and convert an expression from each one
       s                     join the results
 +                hb         and append the b[0] (the minus) to it and return

2

Сітківка , 34 31 29 байт


;
-;
¶
+`¶(.+);(.+)
$1$2-
;

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

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


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