Codifica un numero intero


33

Dato intero positivo n > 2. Lo convertiamo in un array come segue:

  1. Se è uguale a 2restituire un array vuoto
  2. Altrimenti crea una matrice di tutti ni fattori primi ordinati in ordine crescente, quindi ogni elemento sostituisce con il suo indice in sequenza numeri primi e infine converte ogni elemento in matrice

Ad esempio, consente di convertire il numero 46in array. In primo luogo, convertilo in matrice dei suoi fattori primi:

[2, 23]

Il numero 23è 9il primo, quindi sostituiscilo 2con un array vuoto e 23con [9]. La matrice ora diventa:

[[], [9]]

I fattori primi di 9sono 3e 3, quindi:

[[], [3, 3]]

Fai lo stesso per entrambi 3:

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

E infine:

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

Ora, per codificarlo, sostituiamo semplicemente ogni parentesi aperta con 1e ogni parentesi chiusa con 0, quindi rimuoviamo tutti gli zeri finali e ne rilasciamo uno 1dalla fine. Questo è il nostro numero binario. Utilizzando l'esempio sopra:

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

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

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

Ora trascina semplicemente gli ultimi tre zeri e l'ultimo 1. Il numero diventa 10111001che è 185in decimale. Questo è l'output previsto. Si noti che tra parentesi di conversione da array a binari dell'array principale non sono inclusi.

Ingresso

Numero intero positivo nmaggiore di 2.

Produzione

Numero intero codificato n.

Regole e formato IO

  • Si applicano le regole standard.
  • L'input può essere stringa o numero (ma in caso di stringa deve essere nella base 10).
  • L'output può essere stringa o numero (ma in caso di stringa deve essere nella base 10).
  • Questo è , vince la risposta più breve in byte!

Casi test

Altri casi di test su richiesta.

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

sandbox


È necessario rimuovere il caso di test 2poiché gli invii non sono necessari per gestirlo.
Mr. Xcoder

4
Copia i linguaggi che non hanno incorporati primi.
Mr. Xcoder,

3
@Paolo. "[...] crea una matrice di tutti i fattori primi n ordinati in ordine crescente"

1
@Quelklef. Stavo lavorando all'implementazione dell'ATP (solo per divertimento, niente di grave) e ho cercato di rappresentare in qualche modo ogni numero usando array nidificati. Quindi, questa codifica è la prima idea che mi è venuta in mente.

1
@WheatWizard. Non intendo il preciso senso matematico della parola numero intero . Lo lascerò. :-)

Risposte:


12

Buccia , 35 31 30 29 26 25 24 22 20 19 15 byte

-7 byte grazie a @Zgarb!

Risparmiato altri 4 byte, indirettamente, grazie a Zgarb

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

Provalo online!

spiegazione

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

Penso che questo dovrebbe funzionare per 27 byte, ma TIO volte su durante inferenza di tipo ...
Zgarb

2
Poco male, 25 byte e funzionante. Finalmente un caso d'uso per φ, il fixpoint lambda!
Zgarb,

Wow, non ho mai veramente capito i suoi casi d'uso, fino ad ora
H.PWiz

Abbiamo aggiunto Lambpoint Fixpoint a Husk molto presto, prima dell'implementazione dei programmi multilinea. Immagino che abbiamo pensato che sarebbero stati il ​​modo migliore per gestire la ricorsione. Ma sono piuttosto oscuri oltre a salvare un byte in casi speciali come questo.
Zgarb,

`:0:1può essere `Jḋ2.
Zgarb,

7

Gelatina ,  22 20  19 byte

-1 grazie a Erik the Outgolfer (zeri di coda da entrambi i lati t, anziché da destra œr)

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

Un collegamento monadico che prende un numero intero maggiore di 2 e restituisce un numero intero maggiore di 0 (2 restituirebbe 0 secondo le specifiche originali).

Provalo online!

Come?

Questo replica quasi esattamente la descrizione fornita, solo con qualche manipolazione ordinale per la creazione dell'array binario ...

Æ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ì, sicuramente posso; Grazie.
Jonathan Allan,

6

Python 2 , 212 177 byte

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

Provalo online!

La mancanza di builtin primi danneggia davvero il conteggio dei byte e si verifica un timeout su TIO con numeri primi più grandi. Utilizza il controllo di primalità di xnor .


Python 2 + gmpy2 , 175 byte

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*

Provalo online!

Questa versione non scade nei casi di test più grandi (ovvero 10000 - 10008).


5

Mathematica, 125 119 byte

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

Utilizza un approccio leggermente diverso; converte gli indici primi in {1, index, 0}e 2 in {1, 0}.

Provalo su Wolfram Sandbox

Uso:

f = Flatten[ ...

f[10008]

1402478


La risposta originale funziona su 10008, ma questa fallisce
Kelly Lowder,

1
@KellyLowder Risolto!
JungHwan Min


2

J, 74 73 66 byte

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

Provalo online!

Questo è un vero casino che ha certamente bisogno di ulteriore golf (ad es. Rimozione della definizione di funzione esplicita). Penso che il pugilato che ho fatto sia soprattutto ciò che sta facendo emergere il bytecount dal momento che davvero non so cosa sto facendo lì (è stato un sacco di tentativi ed errori). Inoltre, lo sono abbastanza sicuro che ci sono alcuni built-in di cui mi sto dimenticando (ad esempio, penso che _2,~_1,probabilmente abbia un built-in).

Spiegazione (non golfizzato)

Preambolo

Siediti, perché questa non sarà una breve spiegazione. Ironia della sorte, una lingua concisa è stata abbinata a una persona prolissa.

Dividerò questo in alcune funzioni

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode codifica il numero intero usando _1 e _2 anziché [e]
  • convert converte un elenco di _1 e _2 in un elenco di 1 e 0
  • drop rilascia l'ultimo 1 e zeri finali
  • decode converte da un elenco binario in un numero

Esaminerò una chiamata di esempio per 46, che viene espressa in formato non golfato

   decode drop convert encode 46
185

Codificare

C'è molto da spiegare qui.

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

Si noti che la definizione di funzione esplicita 3 : '[function]'valuta la funzione come se fosse sulla REPL con l'argomento giusto che sostituisce ogni istanza di y(ciò significa che posso evitare di usare caps ( [:), atops ( @) e ats (@: ) al costo di pochi byte).

Ecco come appare per ogni iterazione successiva sull'input di 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

Questa funzione utilizza avverso ( ::) per annidare i valori tra "parentesi" (le parentesi qui utilizzate sono -1 e -2). Fondamentalmente, ogni volta che fattorizziamo e convertiamo in indici di numeri primi, _1 viene anteposto e _2 viene aggiunto, che fungono da parentesi. Quando la funzione viene chiamata su quegli elementi, li restituisce così com'è poiché si q:verificherà un errore nel tentativo di fattorizzare un numero negativo. È anche fortunato che q:non si verifichi un errore nel tentativo di fattorizzare 1 e invece restituisce l'array vuoto (come desiderato).

Convertire

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

Convert è molto più semplice. Rimuove solo tutto il pugilato, così come il primo elemento, quindi converte tutto in 1 e 0 (semplicemente aggiungendo 2)

Far cadere

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

Ciò inverte l'elenco, trova il primo e quindi elimina tutti i valori fino a quello, quindi inverte nuovamente l'elenco.

Decodificare

La decodifica è la funzione integrata #.che accetta un elenco di 1 e 0 e lo converte in un numero binario.


2

Retina , 244 227 225 byte

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

Provalo online!

Questo è un approccio diretto che segue l'algoritmo dimostrato nella domanda. La generazione dell'indice principale è una complessità esponenziale, quindi scadrà per input più grandi

Spiegazione:

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

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

Provalo online!

Spiegazione:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]definisce un elenco infinito di tuple di primi e dei loro indici: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

La funzione (%)accetta questo elenco re un numeron e converte il numero nella rappresentazione inversa di array di fattori. Questo viene fatto avanzando rfino a quando non troviamo un numero primo che si divide n. Abbiamo poi ricorsivamente determinare la rappresentazione della indice di questo primo e racchiuderlo 0e 1e anteporre la rappresentazione dellan divisa per quella primaria.

Per n=46, questo produce l'elenco [0,0,0,1,1,0,0,1,1,1,0,1]da cui poi gli zeri iniziali ( snd.span(<1)) e il successivo 1(tail eliminati ). In seguito l'elenco viene convertito in un numero decimale moltiplicando elemento-saggio con un elenco di potenze di due e riassumendo la lista risultante: sum.zipWith((*).(2^))[0..].


0

JavaScript, 289 byte

I byte sono la somma del codice JavaScript senza interruzioni di riga dopo le virgole (che vengono inseriti solo per una migliore formattazione e leggibilità) (256 byte) e i caratteri aggiuntivi per l'opzione della riga di comando, che è necessario quando si utilizza Chrome (33 byte).

'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 una versione più lunga e meglio leggibile:

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

Alcune brevi spiegazioni:

f è un algoritmo di fattorizzazione ricorsivo della coda puramente funzionale.

cconta in quale posizione si trova ril numero primo pnella sequenza dei numeri primi e restituisce [](se p=2e r=1) o fattorizza e procede ulteriormente rmediante ricorsione.

hè una piccola funzione di aiuto che purtroppo è necessaria come mapchiama la funzione fornita con numberOfCurrentElementcome secondo e wholeArraycome terzo argomento, sovrascrivendo così i valori predefiniti forniti cse passassimo direttamente questa funzione (mi ci è voluto un po 'di tempo per ottenere dopo questa insidia; sostituendo hcon la sua definizione sarebbe qualche byte più lungo).

strasforma l'array generato in una stringa. Usiamo blankinvece di 0così che possiamo usare trim()in o.

oè la funzione da chiamare con il valore di input iche restituisce l'output. Genera la rappresentazione di stringa binaria richiesta dalla specifica e la converte in un numero (decimale).

Modifica: Chrome deve essere avviato con chrome --js-flags="--harmony-tailcalls"per consentire l'ottimizzazione della ricorsione della coda (consultare https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Ciò richiede anche l'utilizzo della modalità rigorosa.

Il seguente test mostra che il calcolo è un po 'lento per alcuni valori (il più lungo è più di sei secondi per 10007il mio computer). È interessante notare che, senza l'ottimizzazione della ricorsione della coda, il calcolo è molto più veloce (circa il fattore 5) quando non c'è overflow dello stack.

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 byte

(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

L'ultima riga è una funzione senza nome che calcola la codifica specificata. Provalo online!

Versione pre-golf

Questo è il codice che avevo prima di iniziare a giocare a 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 byte

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

Provalo online!

Spiegazione:

Δ    }       # 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
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.