Árvores de fator de decodificação

11

Caso você tenha perdido o Encode Factor Trees , eis a definição de Factor Tree:

  • A cadeia vazia é 1.
  • Concatenação representa multiplicação.
  • Um número n fechado em parênteses (ou quaisquer caracteres emparelhados) representa o n th número primo, com 2 sendo o primeiro número primo.
    • Note-se que isso seja feito de forma recursiva: o n º principal é a árvore fator para n entre parênteses.
  • Os fatores de um número devem ser ordenados do menor para o maior.

Por exemplo, aqui estão as árvores fatoriais de 2 a 10:

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

Esse desafio usa um formato semelhante; no entanto, esse desafio é decodificar essas estruturas.

Casos de teste

Roubado descaradamente reaproveitado desde o último desafio.

Além dos 9 acima…

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

Regras

  • Os caracteres emparelhados na entrada são a sua escolha entre parênteses, colchetes, chaves ou colchetes angulares. Posso permitir outros formatos (por exemplo, tags XML), se solicitado.
  • Você deve poder manipular árvores fatoriais para qualquer número de 2 a 2 15 ou 32768.
  • Como esse é o , a resposta mais curta em bytes vence.
Nissa
fonte

Respostas:

9

Wolfram Language (Mathematica) , 52 45 bytes

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

Experimente online!

A entrada usa colchetes.

Transforma a entrada em uma expressão do Mathematica que calcula o resultado. Fazemos isso simplesmente substituindo [por Prime[1. Isso funciona porque concatenação é multiplicação no Mathematica.

Martin Ender
fonte
8

Prolog (SWI) , 134 128 127 124 bytes

Esta resposta faz parte de uma colaboração entre mim e 0 '. Nós dois trabalhamos juntos nisso, a única razão pela qual estou postando é porque ganhei Pedra, Papel e Tesoura.

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

Experimente online!

Explicação

Esta resposta é um exemplo perfeito do que torna o golfe em prólogo divertido.


Esta resposta usa o poderoso sistema Prologs para gramáticas de cláusulas definidas. Aqui está a nossa gramática pouco usada.

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

A primeira regra de construção é:

head(1)-->[].

Isso informa ao Prolog que a sequência vazia corresponde a 1.

Nossa segunda regra de construção é um pouco mais complexa.

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

Isso nos diz que qualquer sequência não vazia contém parênteses em torno de uma cláusula com essas mesmas regras, à direita de uma cláusula com essas mesmas regras.

Também nos diz que o valor desta cláusula ( Q) segue a regra:

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

Quebrando isso, Qé o produto de 2 números Ye B. Bé apenas o valor da cláusula à esquerda e Yé o Nprimeiro primo, onde Nestá o valor da cláusula entre parênteses.

Esta regra abrange as duas regras de formação da árvore de fatores

  • A concatenação se multiplica
  • Gabinete é o enésimo nono primo

Agora, para as definições de predicado. Na versão sem golfe, existem dois predicados em jogo (no meu código atual, encaminhei os predicados para a frente). Os dois predicados relevantes aqui são isprime/1: o que corresponde a um número primo e o prime/2qual, dado Ne Y, corresponde a iff Yé o Nth primo. Primeiro nós temos

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

Isso funciona com uma definição bastante padrão de primalidade, insistimos em que não há número entre 2 e I, incluindo 2, mas não Ique divide I.

O próximo predicado também é bastante simples

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

Usamos findnsolspara encontrar os primeiros Nnúmeros primos e, em seguida, retornamos o último. O truque aqui é que, embora findnsolsnão seja garantido encontrar os primos menores N , por causa da maneira como o SWI lida com betweenele, ele sempre encontrará primos menores mais cedo. No entanto, isso significa que temos que cortar para impedir que encontre mais números primos.


Os golfe

Podemos encaminhar a razão em nosso código duas vezes. Uma vez que isprimeé usado apenas uma vez que sua definição pode ser movida para dentro de prime. O próximo é mover-se primediretamente para dentro do DCG, no entanto, como usamos um corte primepara impedir a findnsolsprodução de números primos demais, temos um problema. O corte corta todo o DCG, em vez de apenas o pouco que queremos. Após um pouco de pesquisa na documentação, descobrimos que once/1poderia ser usado para cortar apenas essa parte, mas não todo o DCG. No entanto, mais escavações na documentação revelaram que o ->operador também poderia ser usado para executar uma tarefa semelhante. O ->operador é aproximadamente equivalente a, ,!,então movemos nosso corte para o outro lado append/3e o substituímos por ->.

No SWI-Prolog, os predicados (e regras) podem receber nomes de operadores como nomes, o que nos permite descartar os parênteses normalmente necessários. Assim, podemos economizar 6 bytes chamando a regra \.

Post Rock Garf Hunter
fonte
1

JavaScript (ES6), 98 bytes

Inspirado pela resposta Python de notjagan . Transforma a expressão de entrada em uma sequência executável enorme e feia.

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

Mesclar as funções Ce gem uma única pode economizar alguns bytes, mas exigiria ainda mais recursão.

Casos de teste

Arnauld
fonte