Decode Factor Trees


11

Se hai perso Encode Factor Tree, ecco la definizione di un Factor Tree:

  • La stringa vuota è 1.
  • La concatenazione rappresenta una moltiplicazione.
  • Un numero n racchiuso tra parentesi (o caratteri appaiati) rappresenta il n ° numero primo, con 2 essendo il primo numero primo.
    • Si noti che questo viene fatto in modo ricorsivo: l' n- prime è l'albero dei fattori per n tra parentesi.
  • I fattori di un numero devono essere ordinati dal più piccolo al più grande.

Ad esempio, ecco gli alberi dei fattori da 2 a 10:

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

Questa sfida utilizza un formato simile; tuttavia, questa sfida è quella di decodificare queste strutture.

Casi test

Spudoratamente rubato riproposto dall'ultima sfida.

Oltre ai 9 sopra ...

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

Regole

  • I caratteri accoppiati nell'input sono la scelta tra parentesi, parentesi quadre, parentesi graffe o parentesi angolari. Potrei consentire altri formati (ad esempio tag XML) se richiesto.
  • Dovresti essere in grado di gestire gli alberi dei fattori per qualsiasi numero compreso tra 2 e 2 15 o 32768.
  • Dato che si tratta di , vince la risposta più breve in byte.

Risposte:


9

Wolfram Language (Mathematica) , 52 45 byte

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

Provalo online!

L'input utilizza parentesi.

Trasforma l'input in un'espressione Mathematica che calcola il risultato. Lo facciamo semplicemente sostituendo [con Prime[1. Questo funziona perché la concatenazione è una moltiplicazione in Mathematica.


8

Prolog (SWI) , 134 128 127 124 byte

Questa risposta fa parte di una collaborazione tra me e 0 '. Entrambi abbiamo lavorato insieme su questo, l'unica ragione per cui sto postando è perché ho vinto Rock, Paper, Scissors.

\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}.

Provalo online!

Spiegazione

Questa risposta è un perfetto esempio di ciò che rende divertente il golf nel prologo.


Questa risposta utilizza il potente sistema Prologs per grammatiche definite in clausole. Ecco la nostra grammatica ungolfed un po '.

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),!.

La prima regola di costruzione è:

head(1)-->[].

Questo dice a Prolog che la stringa vuota corrisponde a 1.

La nostra seconda regola di costruzione è un po 'più complessa.

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

Questo ci dice che qualsiasi stringa non vuota contiene parentesi attorno a una clausola con queste stesse regole, a destra di una clausola con queste stesse regole.

Ci dice anche che il valore di questa clausola ( Q) segue la regola:

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

Abbattendo questo, Qè il prodotto di 2 numeri Ye B. Bè solo il valore della clausola a sinistra ed Yè il Nprimo punto in cuiN è il valore della clausola tra parentesi.

Questa regola copre entrambe le regole di formazione dell'albero dei fattori

  • La concatenazione si moltiplica
  • La recinzione prende l'ennesimo numero primo

Ora per le definizioni del predicato. Nella versione ungolf ci sono due predicati in gioco (nel mio codice attuale ho incatenato via i predicati). I due predicati rilevanti qui sono isprime/1, che corrisponde a un numero primo e prime/2, che, dato Ne Y, corrisponde a iff Yè il Nprimo numero. Per prima cosa abbiamo

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

Funziona con una definizione piuttosto standard di primalità, insistiamo sul fatto che non esiste un numero compreso tra 2 e I, incluso 2 ma Iche non divideI .

Anche il prossimo predicato è piuttosto semplice

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

Usiamo findnsolsper trovare i primi Nnumeri che sono primi, quindi restituiamo l'ultimo. Il trucco qui è che, sebbene findnsolsnon sia garantito trovare i numeri primi più piccoli N , a causa del modo in cui SWI gestisce between, troverà sempre i numeri primi più piccoli prima. Ciò significa tuttavia che dobbiamo tagliare per impedirgli di trovare più numeri primi.


I golf

Possiamo inoltrare la ragione nel nostro codice due volte. Poiché isprimeviene utilizzato solo una volta che la sua definizione può essere spostata all'interno di prime. Il prossimo è quello di spostarsi primedirettamente all'interno del DCG, tuttavia poiché utilizziamo un cut-in primeper evitare findnsolsdi produrre troppi numeri primi, abbiamo un piccolo problema. Il taglio, taglia l'intero DCG invece del solo bit che vogliamo. Dopo un po 'di documentazione, abbiamo scoperto che once/1poteva essere usato per tagliare solo questa parte ma non l'intero DCG. Tuttavia, ulteriori ricerche sulla documentazione hanno rivelato che l' ->operatore potrebbe anche essere utilizzato per eseguire un'attività simile. L' ->operatore è approssimativamente equivalente a ,!,così abbiamo spostato il nostro taglio dall'altra parte append/3e sostituito con ->.

In SWI-Prolog i predicati (e le regole) possono essere dati agli operatori come nomi che ci permettono di eliminare le parentesi normalmente richieste. In questo modo possiamo salvare 6 byte chiamando la regola \.



1

JavaScript (ES6), 98 byte

Ispirato dalla risposta Python di notjagan . Trasforma l'espressione di input in una stringa eseguibile enorme e brutta.

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,`)

Unire le funzioni Ce gin una singola può salvare alcuni byte, ma richiederebbe una ricorsione ancora maggiore.

Casi test

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.