Codifique um número inteiro


33

Dado inteiro positivo n > 2. Nós o convertemos em uma matriz da seguinte maneira:

  1. Se for igual para 2retornar uma matriz vazia
  2. Caso contrário, crie uma matriz de todos nos fatores primos classificados de forma crescente, então cada elemento substitua por seu índice na sequência de números primos e, finalmente, converta cada elemento em matriz

Por exemplo, vamos converter o número 46em matriz. Em primeiro lugar, converta-o na matriz de seus principais fatores:

[2, 23]

Number 23é o 9primeiro primo, então substitua 2por array vazio e 23por [9]. A matriz agora se torna:

[[], [9]]

Os fatores primos de 9são 3e 3, portanto:

[[], [3, 3]]

Faça o mesmo para ambos 3:

[[], [[2], [2]]]

E finalmente:

[[], [[[]], [[]]]]

Agora, para codificá-lo, simplesmente substituímos cada colchete aberto por 1cada colchete e 0, em seguida, removemos todos os zeros finais e soltamos um 1do final. Este é o nosso número binário. Usando o exemplo acima:

[ ] [ [ [ ] ] [ [ ] ] ]

| | | | | | | | | | | |
| | | | | | | | | | | |
V V V V V V V V V V V V

1 0 1 1 1 0 0 1 1 0 0 0

Agora basta soltar os três últimos zeros e o último 1. O número passa a 10111001ser 185decimal. Essa é a saída esperada. Observe que, na matriz, os colchetes de conversão binária da matriz principal não estão incluídos.

Entrada

Número inteiro positivo nmaior que 2.

Saída

Inteiro codificado n.

Regras e formato IO

  • Aplicam-se regras padrão.
  • A entrada pode ser string ou número (mas no caso de string, ela deve estar na base 10).
  • A saída pode ser sequência ou número (mas, no caso de sequência, deve estar na base 10).
  • Isso é , a resposta mais curta em bytes vence!

Casos de teste

Mais casos de teste, mediante solicitação.

3 ---> 1
4 ---> 2
5 ---> 3
6 ---> 5
7 ---> 6
8 ---> 10
9 ---> 25
10 ---> 11
10000 ---> 179189987
10001 ---> 944359
10002 ---> 183722
10003 ---> 216499
10004 ---> 2863321
10005 ---> 27030299
10006 ---> 93754
10007 ---> 223005
10008 ---> 1402478

Caixa de areia


Você deve remover o caso de teste, 2pois os envios não são necessários para lidar com isso.
Mr. Xcoder

4
Rasgar idiomas que não possuem embutidos principais.
Mr. Xcoder

3
@Paulo. "[...] criar matriz de todos os fatores primos de n ordenados ascendente"

1
@Quelklef. Eu estava trabalhando na implementação do ATP (apenas por diversão, nada sério) e tentei de alguma forma representar todos os números usando matrizes aninhadas. Então, essa codificação é a primeira ideia que tive.

1
@WheatWizard. Não quero dizer o sentido matemático preciso da palavra número inteiro . Eu vou deixar isso. :-)

Respostas:


12

Casca , 35 31 30 29 26 25 24 22 20 19 15 bytes

-7 bytes graças a @Zgarb!

Economizou 4 bytes extras, indiretamente, graças ao Zgarb

ḋhΣhgφṁȯ`Jḋ2⁰ṗp

Experimente online!

Explicação

     φ             -- Define a recursive function which calls itself ⁰ and is applied to an Integer
      ṁ       p    -- map then concatenate over its prime factors
             ṗ     --   return their indices into the primes
            ⁰      --   and then recur, applying ⁰ to that number
       ȯ`Jḋ2       --   then surround it between the list [1,0] (binary 2)
    g              -- group adjacent equal elements
   h               -- drop last element (trailing 0s)
  Σ                -- concatenate
 h                 -- drop the last element
ḋ                  -- interpret as base 2

Eu acho que isso deve funcionar para 27 bytes, mas o TIO
expira

2
Não importa, 25 bytes e funcionando. Finalmente, um caso de uso para φ, o ponto de correção lambda!
Zgarb

Uau, eu nunca realmente entendeu seus casos de uso, até agora
H.PWiz

Nós adicionamos lambdas de fixpoint ao Husk muito cedo, antes da implementação de programas de várias linhas. Acho que pensamos que eles seriam a melhor maneira de lidar com a recursão. Mas eles são bastante obscuros, além de economizar um byte em casos especiais como este.
Zgarb

`:0:1pode ser `Jḋ2.
Zgarb

7

Geléia ,  22 20  19 bytes

-1 graças a Erik the Outgolfer (zeros de cauda de ambos os lados t, e não da direita œr)

ÆfÆC$ÐLŒṘO%3ḟ2Ḋt0ṖḄ

Um link monádico que pega um número inteiro maior que 2 e retorna um número inteiro maior que 0 (2 também retornaria 0 conforme a especificação original).

Experimente online!

Quão?

Isso quase exatamente replica a descrição fornecida, apenas com alguma manipulação ordinal para a criação da matriz binária ...

ÆfÆC$ÐLŒṘO%3ḟ2Ḋt0ṖḄ - Link: number n (>=2)
     ÐL             - loop until no more changes occur:
    $               -   last two links as a monad:
Æf                  -     prime factorisation (includes duplicates & vectorises)
  ÆC                -     count primes less than or equal (vectorises)
                    -   ...note for entries of 2 this yields [1]
                    -      then for entries of 1 it yields [], as required
       ŒṘ           - get a Python representation - just like in the OP,
                    -    something like: "[[], [[[]], [[]]]]" (for an input of 46)
         O          - convert to ordinals e.g. [91,91,93,44,32,91,91,91,93,93,44,32,91,91,93,93,93,93]
          %3        - modulo by 3         e.g. [ 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 0, 0]
            ḟ2      - filter discard twos e.g. [ 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0]
              Ḋ     - dequeue             e.g. [ 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0]
               t0   - strip zeros         e.g. [ 1, 0, 1, 1, 1, 0, 0, 1, 1]
                 Ṗ  - pop                 e.g. [ 1, 0, 1, 1, 1, 0, 0, 1]
                  Ḅ - binary to decimal   e.g. 185

Ah, sim, eu definitivamente posso; obrigado.
Jonathan Allan

6

Python 2 , 212 177 bytes

lambda n:int(g(n).rstrip("0")[1:-1],2)
g=lambda n:"1%s0"%"".join(map(g,p(n)))
def p(n,i=0,j=1):
 while n>1:
  j+=1;P=q=1;exec"P*=q*q;q+=1;"*~-j;i+=P%q
  while n%j<1:yield i;n/=j

Experimente online!

A falta de componentes principais realmente prejudica a contagem de bytes e atinge o tempo limite no TIO com números primos maiores. Usos xnor 's verificação primality.


Python 2 + gmpy2 , 175 bytes

lambda n:int(g(n).rstrip("0")[1:-1],2)
g=lambda n:"1%s0"%"".join(map(g,p(n)))
def p(n,i=0,j=1):
 while n>1:
  j+=1;i+=is_prime(j)
  while n%j<1:yield i;n/=j
from gmpy2 import*

Experimente online!

Esta versão não atinge o tempo limite nos casos de teste maiores (ou seja, 10000 - 10008).


5

Mathematica, 125 119 bytes

Flatten[#//.{{1}->{1,0},a_/;a>1:>{1,List/@PrimePi[Join@@Table@@@FactorInteger@a],0}}]/.{1,d__,1,0..}:>{d}~FromDigits~2&

Usa uma abordagem ligeiramente diferente; converte índices primos em {1, index, 0}e 2 em{1, 0} .

Experimente na Wolfram Sandbox

Uso:

f = Flatten[ ...

f[10008]

1402478


Resposta original funciona em 10008, mas esta falha #
Kelly Lowder 14/08

1
@KellyLowder Fixed!
JungHwan Min 14/08/19


2

J, 74 73 66 bytes

3 :'#.(}.~ >:@i.&1)&.|.2+}.;<@(_2,~_1,[:>:[:_1&p:q:) ::<"0@;^:_ y'

Experimente online!

Esta é uma verdadeira bagunça que certamente precisa de mais golfe (por exemplo, remoção da definição explícita da função). Eu acho que o boxe que eu faço é especialmente o que está trazendo o número de bytes, já que eu realmente não sei o que estou fazendo lá (foram muitas tentativas e erros). Além disso, estou bastante certo de que há alguns built-ins que eu estou esquecendo (por exemplo, eu me sinto como _2,~_1,, provavelmente, tem um built-in).

Explicação (ungolfed)

Preâmbulo

Sente-se com força, porque essa não será uma breve explicação. Ironicamente, uma linguagem concisa foi combinada com uma pessoa detalhada.

Vou dividir isso em algumas funções

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode codifica o número inteiro usando _1 e _2 em vez de [e]
  • convert converte uma lista de _1 e _2 em uma lista de 1 e 0
  • drop descarta o último 1 e zeros à direita
  • decode converte de uma lista binária em um número

Vou percorrer uma amostra de 46, que expressa no formato não destruído, está concluída

   decode drop convert encode 46
185

Codificar

Há muito o que explicar aqui.

3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::< "0@;^:_ y'
                                           ^:_      Do until result converges
                                          ;          Raze (remove all boxing)
                                       "0            For each
                               q:                     Factorize
                         _1&p:                        Get index of prime
                   >:                                 Add 1 (J zero-indexes)
            _1,                                       Prepend -1
        _2,~                                          Append -2
     <                                                Box resulting array
                                   ::                If there is an error
                                     <                Box the element

Observe que a definição de função explícita 3 : '[function]'avalia a função como se estivesse no REPL com o argumento correto substituindo todas as instâncias de y(isso significa que eu posso evitar ter que usar caps ( [:), atops ( @) e ats ( @:) ao custo de alguns bytes).

Aqui está o que parece para cada iteração sucessiva na entrada de 46

┌─────────┐    ┌──┬─────┬─────────┬──┐    ┌──┬──┬──┬──┬───────┬───────┬──┬──┐
│_1 1 9 _2│ => │_1│_1 _2│_1 2 2 _2│_2│ => │_1│_1│_2│_1│_1 1 _2│_1 1 _2│_2│_2│ =>
└─────────┘    └──┴─────┴─────────┴──┘    └──┴──┴──┴──┴───────┴───────┴──┴──┘

┌──┬──┬──┬──┬──┬─────┬──┬──┬─────┬──┬──┬──┐    
│_1│_1│_2│_1│_1│_1 _2│_2│_1│_1 _2│_2│_2│_2│ => the final iteration is just every
└──┴──┴──┴──┴──┴─────┴──┴──┴─────┴──┴──┴──┘    value in its own box

Esta função utiliza advers ( ::) para aninhar os valores entre "colchetes" (os colchetes usados ​​aqui são -1 e -2). Basicamente, toda vez que fatoramos e convertemos em índices de números primos, _1 é anexado e _2, que atuam como colchetes. Quando a função é chamada nesses elementos, apenas os retorna como estão, pois q:ocorrerá um erro ao tentar fatorar um número negativo. É também uma sorte que q:faz não erro na tentativa de fatorar 1 e em vez disso retorna a matriz vazia (como desejado).

Converter

3 : '2 + }. ; y'
            ;     Raze (remove boxing)
         }.       Behead (remove head)
     2 +          Add 2

Converter é muito mais simples. Apenas remove todo o boxe, assim como o primeiro elemento, e depois converte tudo em 1s e 0s (simplesmente adicionando 2)

Solta

(}.~ >:@i.&1)&.|.
             &.|.  Reverse, apply the left function, and then undo
 }.~ >:@i.&1        Drop the leading zeroes and first 1
        i.&1         Index of first one
     >:              Add 1
 }.~                 Drop

Isso inverte a lista, localiza o primeiro e, em seguida, descarta todos os valores até aquele, e inverte a lista novamente.

Decodificar

Decodificar é a função #.interna que pega uma lista de 1s e 0s e a converte em um número binário.


2

Retina , 244 227 225 bytes

+%(G`
\d+
$*0¶$&$*
+`^00(0+)
0$1¶$0
A`^(00+?)\1+$
^0+
$0;1
+`(1+)¶0+(?=¶)
$0;1$1
+`¶(11+?)(\1)*$
¶$1¶1$#2$*1
1$

m`^11$
[]
m`^1+
[¶$.0$*0¶]
+s`(0+);(1+)(.+¶)\1¶
$1;$2$3$2¶
0+;1+¶

)`1+
$.0
T`[]¶`10_
10+$

1
01
+`10
011
^0+

1

Experimente online!

Essa é uma abordagem direta, seguindo o algoritmo demonstrado na pergunta. A geração de índice principal é de complexidade exponencial, portanto, o tempo limite para entradas maiores

Explicação:

+%(G`                Repeatedly apply on each line:
\d+                      If the line is a number, convert it to unary 0s and 1s
$*0¶$&$*
+`^00(0+)                Generate all prefixes of the zeros greater than 1
0$1¶$0
A`^(00+?)\1+$            Remove non-prime strings of zeros
^0+                      Index the first zero set (00) as 1
$0;1
+`(1+)¶0+(?=¶)           Index the rest of the zeroes as their prime index
$0;1$1
+`¶(11+?)(\1)*$          Compute prime factors of input value
¶$1¶1$#2$*1
1$                       Remove the 1 factor (not really prime)

m`^11$                   Turn all 2 prime factors to []
[]
m`^1+                    Surround all non-2 prime factors in brackets
[¶$.0$*0¶]
+s`(0+);(1+)(.+¶)\1¶     Convert non-2 prime factors to their index
$1;$2$3$2¶
0+;1+¶                   Remove the list of primes

)`1+                     Return all primes back to decimal ready to be repeated
$.0
T`[]¶`10_            Then convert all [ to 1 and ] to 0, and remove linefeeds
10+$                 Remove the final 1 and trailing zeroes

1                    Convert from binary to unary
01
+`10
011
^0+

1                    Convert from unary to decimal

1

Haskell , 162 160 155 bytes

sum.zipWith((*).(2^))[0..].tail.snd.span(<1).(r%)
r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]
_%1=[]
((i,q):p)%n|mod n q<1=r%div n q++0:r%i++[1]|1<3=p%n

Experimente online!

Explicação:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]] define uma lista infinita de tuplas de primos e seus índices: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...] .

A função (%)pega essa lista re um número ne converte o número na representação inversa da matriz de fatores. Isso é feito avançando raté encontrarmos um primo que se divide n. Em seguida, de forma recursiva determinar a representação do índice deste nobre e coloque-a 0e 1e preceder a representação ndividida pela prime.

Pois n=46, isso gera a lista [0,0,0,1,1,0,0,1,1,1,0,1]da qual os zeros à esquerda ( snd.span(<1)) e os próximos 1( tail) são descartados. Depois que a lista é convertida para um número decimal multiplicando elemento-wise com uma lista de potências de dois e somando-se a lista resultante: sum.zipWith((*).(2^))[0..].


0

JavaScript, 289 bytes

Os bytes são a soma do código JavaScript sem quebras de linha após as vírgulas (inseridas apenas para melhor formatação e legibilidade) (256 bytes) e os caracteres adicionais para a opção de linha de comando, necessária ao usar o Chrome (33 bytes).

'use strict'
var f=(n,i=2,r=[])=>n>1?n%i?f(n,i+1,r):f(n/i,i,r.concat(i)):r,
c=(p,r=1,i=2)=>i<p?f(i)[1]?c(p,r,i+1):c(p,r+1,i+1):r-1?f(r).map(h):[],
h=a=>c(a),
s=a=>a.reduce((r,e)=>r+s(e),'1')+' ',
o=i=>+('0b'+s(f(i).map(h)).trim().replace(/ /g,'0').slice(1,-1))

E uma versão mais longa e melhor legível:

'use strict';
const f = (n,i=2,r=[]) => n>1 ? n%i ? f(n,i+1,r) : f(n/i,i,r.concat(i)) : r;
const c = (p,r=1,i=2) => i<p ? f(i)[1] ? c(p,r,i+1) : c(p,r+1,i+1) : r-1 ? f(r).map(h) : [];
const h = i => c(i);
const s = a => a.reduce((r,e) => r+s(e),'1')+' ';
const o = i => +('0b'+s(f(i).map(h)).trim().replace(/ /g,'0').slice(1,-1));

Algumas breves explicações:

f é um algoritmo de fatoração recursivo da cauda puramente funcional.

cconta em que local ro número primo pocorre na sequência de números primos e retorna [](se p=2e r=1) ou fatora e processa outrosr por meio de recursão.

hé uma função auxiliar pequena que, infelizmente, é necessária como mapchama a função fornecida com numberOfCurrentElemento segundo e wholeArrayo terceiro argumento, substituindo, assim, os valores padrão fornecidos cse passarmos diretamente essa função (levei algum tempo para resolver essa armadilha; substituir hpor sua definição levaria alguns bytes a mais).

stransforma a matriz gerada em uma sequência. Nós usamos em blankvez de 0para que possamos usar trim()emo .

oé a função a ser chamada com o valor de entrada ique retorna a saída. Ele gera a representação de string binária exigida pela especificação e a converte em um número (decimal).

Editar: é necessário iniciar o Chrome chrome --js-flags="--harmony-tailcalls"para ativar a otimização da recursão da cauda (consulte https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Isso também requer o uso do modo estrito.

O teste a seguir mostra que a computação é um pouco lenta para alguns valores (o mais longo é de mais de seis segundos 10007no meu computador). Curiosamente, sem a otimização da recursão da cauda, ​​o cálculo é muito mais rápido (sobre o fator 5) quando não há excesso de pilha.

for (let i=3; i<=10008; i==10 ? i=10000 : ++i) {
    let time = new Date().getTime();
    let val = o(i);
    time = new Date().getTime() - time;
    document.write(i + ': ' + o(i) + ' (computed in ' + time + ' ms)<br>');
}

0

tinylisp , 209 bytes

(load library
(d [(q((N)(map(q((P)([(length(filter prime?(1to P))))))(reverse(prime-factors N
(d B(q((L)(c 1(insert-end 0(foldl concat(map B L
(d T(q((N)(if(mod N 2)(/ N 2)(T(/ N 2
(q((N)(T(from-base 2(t(B([ N

A última linha é uma função sem nome que calcula a codificação especificada. Experimente online!

Versão pré-golfe

Este é o código que eu tinha antes de começar a jogar:

(load library)

(def prime-index
 (lambda (P)
  (length (filter prime? (1to P)))))

(def to-list
 (lambda (N)
  (map to-list
   (map prime-index
    (reverse (prime-factors N))))))

(def to-bits
 (lambda (L)
  (cons 1
   (insert-end 0
    (foldl concat
     (map to-bits L))))))

(def trim
 (lambda (N)
  (if (mod N 2)
   (div2 N 2)
   (trim (div2 N 2)))))

(def encode
 (lambda (N)
  (trim
   (from-base 2
    (tail (to-bits (to-list N)))))))

0

05AB1E , 18 bytes

ΔÒ.Ø>}¸»Ç3%2K0ܨ2β

Experimente online!

Explicação:

Δ    }       # loop until a fixed point
 Ò           # replace each number with its prime factorization
  .Ø>        # replace each prime with its 1-based index
¸»           # after the loop: join to a string
  Ç          # get ASCII value of each character
   3%        # modulo 3 (maps '[' to 1, ']' to 0, ' ' to 2, ',' to 2)
     2K      # remove 2s
       0Ü    # trim trailing 0s
         ¨   # remove the last 1
          2β # parse as base 2
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.