Декодування дерев-факторів


11

Якщо ви пропустили Кодування дерев-факторів , ось визначення дерева фактора:

  • Порожній рядок - 1.
  • Конкатенація являє собою множення.
  • Число n, укладене в круглі дужки (або будь-які парні символи), представляє n- е просте число, причому 2 є першим простим числом.
    • Зауважте, що це робиться рекурсивно: n- й простим числом є факторне дерево для n в дужках.
  • Коефіцієнти числа слід упорядкувати від найменших до найбільших.

Наприклад, ось факторні дерева від 2 до 10:

()
(())
()()
((()))
()(())
(()())
()()()
(())(())
()((()))

Цей виклик використовує аналогічний формат; однак ця проблема полягає в декодуванні цих структур.

Випробування

Безсоромно викрадене переставлене з останнього виклику.

На додаток до 9 вище ...

()()((()))((())) => 100
(()(()(()))) => 101
(()())(((())))(()(())) => 1001
(((((((()))))))) => 5381
(()())((((()))))(()()(())(())) => 32767
()()()()()()()()()()()()()()() => 32768

Правила

  • Парні символи у вводі - це ваш вибір дужок, дужок, дужок або кутових дужок. Я можу дозволити інші формати (наприклад, теги XML), якщо запитати
  • Ви повинні мати можливість обробляти факторні дерева для будь-якого числа від 2 до 2 15 або 32768.
  • Оскільки це , найкоротша відповідь у байтах виграє.

Відповіді:


9

Мова Вольфрама (Mathematica) , 52 45 байт

ToExpression@*StringReplace[{"["->"Prime[1"}]

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

Для введення використовуються дужки.

Перетворює вхід у вираз Mathematica, який обчислює результат. Ми робимо це просто замінивши [на Prime[1. Це працює, тому що конкатенація - це множення в Mathematica.


8

Prolog (SWI) , 134 128 127 124 байт

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

\Q-->{Q=1};"(",\N,")",\B,{findnsols(N,I,(between(2,inf,I),\+ (between(3,I,U),0=:=I mod(U-1))),L)->append(_,[Y],L),Q is Y*B}.

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

Пояснення

Ця відповідь є прекрасним прикладом того, що робить гольф у пролозі цікавим.


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

head(1)-->[].
head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.
isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).
prime(N,Y):-
  findnsols(N,I,(
    between(2,inf,I),
    isprime(I)
  ),L),
  append(_,[Y],L),!.

Перше правило будівництва:

head(1)-->[].

Це говорить Прологу, що порожній рядок відповідає 1.

Наше друге правило будівництва - це трохи складніше.

head(Q)-->"(",head(N),")",head(B),{prime(N,Y),Q is Y*B}.

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

Це також говорить нам, що значення цього пункту ( Q) відповідає правилу:

{prime(N,Y),Q is Y*B}

Розбиваючи це, Qдобуток 2 чисел Yі B. B- просто значення пункту зліва і Yє головним Nчислом, де Nє значенням пропозиції в дужках.

Це правило охоплює обидва правила формування факторного дерева

  • Конкатенація множиться
  • Додаток займає п яте місце

Тепер для визначення предикатів. У версії unololfed є два предикати (у моєму фактичному коді я вперед прикував присудки). Два релевантні предикати тут є isprime/1, що відповідає простому числу, і prime/2, що, з урахуванням Nі Y, відповідає iff Y- Nго простого числа. Спочатку маємо

isprime(I):- \+ (between(3,I,U),0 =:= I mod(U-1)).

Це працює з досить стандартним визначенням первинності, ми наполягаємо, що немає числа між 2 і I, включаючи 2, але не Iте, що розділяє I.

Наступний присудок також досить простий

prime(N,Y):-
  findnsols(N,I,(
    between(2,inf,I),
    isprime(I)
  ),L),
  append(_,[Y],L),!.

Ми використовуємо findnsolsдля пошуку перших Nчисел, які є простими, потім повертаємо останні. Хитрість тут полягає в тому, що, хоча findnsolsне гарантовано знайти найменші N праймери, через те, що SWI поводиться, betweenвін завжди знайде менші праймери раніше. Це, однак, означає, що ми повинні вирізати, щоб запобігти знаходженню більшої кількості праймів.


Гольфи

Ми можемо переслати причину в нашому коді двічі. Оскільки isprimeвикористовується лише після того, як його визначення можна перемістити всередину prime. Наступним є переміщення primeбезпосередньо всередині DCG, однак, оскільки ми використовуємо надріз primeдля запобігання появи findnsolsзанадто багато праймерів, у нас є проблема. Розріз, скорочує весь DCG замість того, щоб ми хотіли трохи. Після трохи копання документації ми виявили, що once/1можна було б використати для скорочення саме цієї частини, але не всієї DCG. Однак більше розкопок документації показало, що ->оператор також може бути використаний для виконання подібного завдання. ->Оператор приблизно еквівалентний ,!,тому ми перемістили наш розріз на іншу сторону append/3і замінити його ->.

У SWI-Prolog предикатам (і правилам) можна вказати операторів як імена, що дозволяє нам скидати круглі дужки, як правило, потрібні. Тим самим ми можемо зберегти 6 байт, викликавши правило \.



1

JavaScript (ES6), 98 байт

Натхненний відповіддю Пітхона Notjagan . Перетворює вхідний вираз у величезний та некрасивий виконуваний рядок.

s=>eval(s.split`)(`.join`)*(`.split`(`.join`(g=(n,k)=>(C=d=>n%--d?C(d):k-=d<2)(++n)?g(n,k):n)(1,`)

Об'єднання функцій Cі gфункцій в один може врятувати деякі байти, але це потребує ще більшої рекурсії.

Тестові справи

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