Codificar un número entero


33

Dado entero positivo n > 2. Lo convertimos en una matriz de la siguiente manera:

  1. Si es igual a 2devolver una matriz vacía
  2. De lo contrario, cree una matriz de todos nlos factores primos ordenados de forma ascendente, luego cada elemento reemplace con su índice en la secuencia de números primos y finalmente convierta cada elemento en matriz

Por ejemplo, vamos a convertir el número 46a la matriz. En primer lugar, conviértalo en una matriz de sus factores primos:

[2, 23]

El número 23es el 9primo, así que reemplácelo 2con una matriz vacía y 23con [9]. La matriz ahora se convierte en:

[[], [9]]

Los factores primos de 9son 3y 3, entonces:

[[], [3, 3]]

Haz lo mismo para ambos 3:

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

Y finalmente:

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

Ahora, para codificarlo, simplemente reemplazamos cada corchete abierto con 1y cada corchete de cierre con 0, luego eliminamos todos los ceros finales y soltamos uno 1desde el final. Este es nuestro número binario. Usando el ejemplo anterior:

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

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

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

Ahora simplemente suelte los últimos tres ceros y el último 1. El número se convierte en 10111001lo que es 185en decimal. Esa es la salida esperada. Observe que en la matriz a paréntesis de conversión binarios de la matriz principal no están incluidos.

Entrada

Entero positivo nmayor que 2.

Salida

Entero codificado n.

Reglas y formato IO

  • Aplican reglas estándar.
  • La entrada puede ser cadena o número (pero en caso de cadena debe estar en la base 10).
  • La salida puede ser cadena o número (pero en caso de cadena debe estar en la base 10).
  • Este es el , ¡la respuesta más corta en bytes gana!

Casos de prueba

Más casos de prueba a pedido.

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

Salvadera


Debe eliminar el caso de prueba 2ya que no se requieren los envíos para manejarlo.
Sr. Xcoder

44
Extraiga los idiomas que no tienen funciones integradas principales.
Sr. Xcoder

3
@Paul. "[...] crea una matriz de todos los factores primos de n ordenados ascendentemente"

1
@Quelklef. Estaba trabajando en la implementación de ATP (solo por diversión, nada serio) y traté de representar de alguna manera cada número usando matrices anidadas. Entonces, esta codificación es la primera idea que se me ocurrió.

1
@WheatWizard. No me refiero al sentido matemático preciso de la palabra entero . Lo voy a dejar :-)

Respuestas:


12

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

-7 bytes gracias a @Zgarb!

Ahorró 4 bytes adicionales, indirectamente, gracias a Zgarb

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

Pruébalo en línea!

Explicación

     φ             -- 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

Creo que esto debería funcionar para 27 bytes, pero TIO agota el tiempo de espera durante la inferencia de tipo ...
Zgarb

2
No importa, 25 bytes y funcionando. Finalmente un caso de uso para φel punto fijo lambda!
Zgarb

Wow, nunca he entendido realmente sus casos de uso, hasta ahora
H.PWiz

Agregamos lambdas de punto fijo a Husk muy temprano, antes de que se implementaran programas de varias líneas. Supongo que pensamos que serían la mejor manera de manejar la recursividad. Pero son bastante oscuros, aparte de guardar un byte en casos especiales como este.
Zgarb

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

7

Jalea ,  22 20  19 bytes

-1 gracias a Erik the Outgolfer (ceros de cola desde ambos lados t, en lugar de desde la derecha œr)

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

Un enlace monádico que toma un entero mayor que 2 y devuelve un entero mayor que 0 (2 devolvería 0 según la especificación original también).

Pruébalo en línea!

¿Cómo?

Esto replica casi exactamente la descripción dada, solo con alguna manipulación ordinal para la creación de la matriz binaria ...

Æ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, sí, definitivamente puedo; Gracias.
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

Pruébalo en línea!

La falta de primos incorporados realmente perjudica el recuento de bytes, y se agota en TIO con primos más grandes. Usos XNOR 's cheque primalidad.


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*

Pruébalo en línea!

Esta versión no agota el tiempo en los casos de prueba más grandes (es decir, 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&

Utiliza un enfoque ligeramente diferente; convierte índices primos a {1, index, 0}, y 2 a {1, 0}.

Pruébalo en Wolfram Sandbox

Uso:

f = Flatten[ ...

f[10008]

1402478


La respuesta original funciona en 10008, pero esta falla
Kelly Lowder

1
@KellyLowder fijo!
JungHwan Min


2

J, 74 73 66 bytes

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

Pruébalo en línea!

Este es un verdadero desastre que ciertamente necesita más golf (por ejemplo, la eliminación de la definición de función explícita). Creo que el boxeo que he estado haciendo es especialmente lo que está haciendo aparecer el bytecount ya que realmente no sé lo que estoy haciendo allí (ha sido mucha prueba y error). Además, estoy bastante seguro de que hay algunos complementos que me estoy olvidando (por ejemplo, creo que _2,~_1,probablemente tiene uno incorporado).

Explicación (sin golf)

Preámbulo

Siéntate bien, porque esto no será una breve explicación. Irónicamente, un lenguaje breve se ha emparejado con una persona detallada.

Lo dividiré en algunas funciones

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode codifica el entero usando _1 y _2 en lugar de [y]
  • convert convierte una lista de _1 y _2 en una lista de 1 y 0
  • drop elimina el último 1 y ceros finales
  • decode convierte de una lista binaria a un número

Revisaré una llamada de muestra para 46, que se expresa en el formato no golfizado.

   decode drop convert encode 46
185

Codificar

Hay mucho que explicar aquí.

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

Tenga en cuenta que la definición de función explícita 3 : '[function]'evalúa la función como si estuviera en REPL con el argumento correcto reemplazando cada instancia de y(esto significa que puedo evitar tener que usar mayúsculas ( [:), atops ( @) y ats ( @:) a costa de unos pocos bytes).

Esto es lo que parece para cada iteración sucesiva en la 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 función hace uso de adversos ( ::) para anidar los valores entre "paréntesis" (los paréntesis utilizados aquí son -1 y -2). Básicamente, cada vez que factorizamos y convertimos a índices de números primos, _1 se antepone y _2 se agrega, que actúan como paréntesis. Cuando se llama a la función en esos elementos, solo los devuelve tal cual, ya que se q:producirá un error al intentar factorizar un número negativo. También es una suerte que q:no se equivoque al intentar factorizar 1 y en su lugar devuelve la matriz vacía (como se desee).

Convertir

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

Convertir es mucho más simple. Simplemente elimina todo el boxeo, así como el primer elemento, y luego convierte todo a 1s y 0s (simplemente agregando 2)

soltar

(}.~ >:@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

Esto invierte la lista, encuentra el primero y luego cae todos los valores hasta ese, luego invierte la lista nuevamente.

Descodificar

Decode es la función incorporada #.que toma una lista de 1s y 0s y la convierte en un número binario.


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

Pruébalo en línea!

Este es un enfoque directo siguiendo el algoritmo demostrado en la pregunta. La generación del índice principal es una complejidad exponencial, por lo que se agota el tiempo de espera para entradas más grandes

Explicación:

+%(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

Pruébalo en línea!

Explicación:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]define una lista infinita de tuplas de números primos y sus índices: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

La función (%)toma esta lista ry un número ny convierte el número en la representación de matriz de factores invertida. Esto se hace avanzando rhasta encontrar un primo que divide n. A continuación, determinar de forma recursiva la representación del índice de este primer y encerrarlo entre 0y 1y anteponer la representación de ndividido por el mejor momento.

Para n=46, esto produce la lista [0,0,0,1,1,0,0,1,1,1,0,1]de la que luego se eliminan los ceros iniciales ( snd.span(<1)) y el siguiente 1( tail). Posteriormente la lista se convierte a un número decimal multiplicando elemento a gota con una lista de potencias de dos y sumando la lista resultante: sum.zipWith((*).(2^))[0..].


0

JavaScript, 289 bytes

Los bytes son la suma del código JavaScript sin saltos de línea después de las comas (que se insertan solo para un mejor formato y legibilidad) (256 bytes) y los caracteres adicionales para el cambio de línea de comando, que se requiere cuando se usa 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))

Y una versión más larga y mejor legible:

'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));

Algunas breves explicaciones:

f es un algoritmo de factorización recursivo de cola puramente funcional.

ccuenta en qué lugar se produce el rnúmero primo pen la secuencia de números primos y devuelve [](si p=2y r=1) o factoriza y procesa más rmediante recursividad.

hes una pequeña función auxiliar que desafortunadamente es necesaria ya que mapllama a la función proporcionada con numberOfCurrentElementel segundo y wholeArrayel tercer argumento, anulando así los valores predeterminados proporcionados csi pasamos esta función directamente (me tomó algo de tiempo llegar después de esta trampa; reemplazar hpor su definición sería unos pocos bytes más largos).

stransforma la matriz generada en una cadena. Utilizamos blanken lugar de 0por lo que podemos utilizar trim()en o.

oes la función que se llamará con el valor de entrada ique devuelve la salida. Genera la representación de cadena binaria requerida por la especificación y la convierte en un número (decimal).

Editar: Chrome debe iniciarse chrome --js-flags="--harmony-tailcalls"para permitir la optimización de la recursividad de cola (consulte https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Esto también requiere usar el modo estricto.

La siguiente prueba muestra que el cálculo es un poco lento para algunos valores (el más largo es más de seis segundos para 10007mi computadora). Curiosamente, sin la optimización de la recursividad de la cola, el cálculo es mucho más rápido (sobre el factor 5) cuando no hay desbordamiento de la pila.

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

La última línea es una función sin nombre que calcula la codificación especificada. Pruébalo en línea!

Versión pre-golf

Este es el código que tenía antes de comenzar a jugar golf:

(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β

Pruébalo en línea!

Explicación:

Δ    }       # 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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.