Encoder un entier

33

Étant donné entier positif n > 2. Nous le convertissons en un tableau comme suit:

  1. S'il est égal à 2retourner un tableau vide
  2. Sinon, créez un tableau de tous nles facteurs premiers triés par ordre croissant, puis chaque élément est remplacé par son index dans la séquence des nombres premiers et convertit finalement chaque élément en tableau.

Par exemple, permet de convertir un nombre 46en tableau. Tout d’abord, convertissez-le en un tableau de ses facteurs premiers:

[2, 23]

Le nombre 23est 9th prime, alors remplacez-le 2par un tableau vide et 23par [9]. Le tableau devient maintenant:

[[], [9]]

Les facteurs premiers 9sont 3et 3, donc:

[[], [3, 3]]

Faites la même chose pour les deux 3:

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

Et enfin:

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

Maintenant, pour l'encoder, nous remplaçons simplement chaque crochet ouvert par 1et chaque crochet de fermeture 0, puis supprimons tous les zéros 1finals et en supprimons un de la fin. Ceci est notre nombre binaire. En utilisant l'exemple ci-dessus:

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

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

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

Maintenant, supprimez simplement les trois derniers zéros et le dernier 1. Le nombre devient 10111001ce qui est 185en décimal. C'est la sortie attendue. Notez que dans un tableau, les crochets de conversion du tableau principal ne sont pas inclus.

Contribution

Nombre entier positif nsupérieur à 2.

Sortie

Entier codé n.

Règles et format IO

  • Les règles standard s'appliquent.
  • L'entrée peut être une chaîne ou un nombre (mais dans le cas d'une chaîne, il doit être en base 10).
  • La sortie peut être une chaîne ou un nombre (mais dans le cas d'une chaîne, elle doit être en base 10).
  • C'est , la réponse la plus courte en octets gagne!

Cas de test

Plus de cas de test sur demande.

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

bac à sable

H.PWiz
la source
Vous devez supprimer le cas de test avec 2car les soumissions ne sont pas nécessaires pour le gérer.
M. Xcoder
4
Les langages d'extraction qui n'ont pas d'intégrateurs principaux.
M. Xcoder
3
@Paul. "[...] crée un tableau de tous les facteurs premiers de n classés par ordre croissant"
1
@Quelklef. Je travaillais sur la mise en œuvre d' ATP (juste pour le plaisir, rien de grave) et j'ai essayé de représenter en quelque sorte chaque nombre à l'aide de tableaux imbriqués. Donc, cet encodage est la première idée que je suis venu avec.
1
@ WheatWizard. Je ne parle pas du sens mathématique précis du mot entier . Je vais le quitter. :-)

Réponses:

12

Husk , 35 31 30 29 26 25 24 22 20 19 15 octets

-7 octets grâce à @Zgarb!

Économisé 4 octets supplémentaires, indirectement, grâce à Zgarb

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

Essayez-le en ligne!

Explication

     φ             -- 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
H.PWiz
la source
Je pense que cela devrait fonctionner pour 27 octets, mais TIO
expire
2
Qu'à cela ne tienne, 25 octets et en état de marche. Enfin, un cas d’utilisation pour φle point de fixation lambda!
Zgarb
Wow, je n'ai jamais vraiment compris ses cas d'utilisation, jusqu'à présent
H.PWiz
Nous avons ajouté le point de fixation lambdas à Husk très tôt, avant la mise en œuvre de programmes multilignes. Je suppose que nous pensions que ce serait le meilleur moyen de gérer la récursivité. Mais ils sont assez obscurs en dehors de la sauvegarde d’un octet dans des cas spéciaux comme celui-ci.
Zgarb
`:0:1peut être `Jḋ2.
Zgarb
7

Jelly ,  22 20  19 octets

-1 grâce à Erik the Outgolfer (zéros de la queue des deux côtés tplutôt que de la droite œr)

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

Un lien monadique prenant un entier supérieur à 2 et renvoyant un entier supérieur à 0 (2 renverrait également 0 conformément à la spécification d'origine).

Essayez-le en ligne!

Comment?

Ceci reproduit presque exactement la description donnée, juste avec quelques manipulations ordinales pour la création du tableau binaire ...

Æ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
Jonathan Allan
la source
Ah oui, je le peux vraiment; Merci.
Jonathan Allan
6

Python 2 , 212 177 octets

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

Essayez-le en ligne!

L'absence de nombres premiers prime nuit vraiment au nombre d'octets, et le délai d'attente de TIO avec des nombres premiers plus grands est dépassé. Les utilisations xnor de » chèque de primalité.


Python 2 + gmpy2 , 175 octets

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*

Essayez-le en ligne!

Cette version n’a pas de délai d’expiration pour les cas de test plus volumineux (c’est-à-dire 10000 - 10008).

notjagan
la source
5

Mathematica, 125 119 octets

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

Utilise une approche légèrement différente; convertit les indices premiers en {1, index, 0}et 2 en {1, 0}.

Essayez-le sur Wolfram Sandbox

Usage:

f = Flatten[ ...

f[10008]

1402478

JungHwan Min
la source
La réponse originale fonctionne sur 10008, mais celle-ci échoue
Kelly Lowder
1
@KellyLowder Fixé!
JungHwan Min
2

J, 74 73 66 octets

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

Essayez-le en ligne!

C’est un véritable gâchis qui a certainement besoin de jouer plus avant (par exemple, la suppression de la définition de fonction explicite). Je pense que la boxe que j’ai pratiquée est particulièrement importante, car je ne sais vraiment pas ce que je fais ici (c’est beaucoup d’essais et d’erreur). De plus, je suis quasiment sûr qu'il y a des éléments intégrés que j'oublie (par exemple, j'ai l'impression qu'il _2,~_1,a probablement un élément intégré).

Explication (non golfée)

Préambule

Asseyez-vous bien car cela ne sera pas une explication brève. Ironiquement, un langage laconique a été associé à une personne verbeuse.

Je vais diviser cela en quelques fonctions

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode code l'entier en utilisant _1 et _2 au lieu de [et]
  • convert convertit une liste de _1 et _2 en une liste de 1 et 0
  • drop supprime le dernier 1 et les derniers zéros
  • decode convertit d'une liste binaire en un nombre

Je vais passer en revue un exemple d'appel pour 46, qui est exprimé dans le format non-golfé est fait

   decode drop convert encode 46
185

Encoder

Il y a beaucoup à expliquer ici.

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

Notez que la définition de fonction explicite 3 : '[function]'évalue la fonction comme si elle figurait dans la REPL avec le bon argument remplaçant chaque instance de y(cela signifie que je peux éviter de devoir utiliser caps ( [:), atops ( @) et ats ( @:) au prix de quelques octets).

Voici à quoi cela ressemble pour chaque itération successive sur l’entrée 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

Cette fonction utilise adverse ( ::) pour imbriquer les valeurs entre "parenthèses" (les parenthèses utilisées ici sont -1 et -2). Fondamentalement, chaque fois que nous factorisons et convertissons en indices de nombre premier, _1 est ajouté au début et _2 est ajouté, qui agissent comme des crochets. Lorsque la fonction est appelée sur ces éléments, elle les renvoie tels quels, car une q:erreur est commise lors de la factorisation d’un nombre négatif. Il est également heureux de q:ne pas commettre d'erreur en essayant de factoriser 1 et de renvoyer le tableau vide (comme vous le souhaitez).

Convertir

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

Convert est beaucoup plus simple. Il supprime simplement toute la boxe, ainsi que le premier élément, puis convertit tout en 1 et 0 (simplement en ajoutant 2)

Laissez tomber

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

Cela inverse la liste, trouve le premier, puis supprime toutes les valeurs jusqu'à celle-ci, puis inverse à nouveau la liste.

Décoder

Decode est la fonction intégrée #.qui prend une liste de 1 et de 0 et la convertit en un nombre binaire.

Cole
la source
2

Retina , 244 227 225 octets

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

Essayez-le en ligne!

C'est une approche simple suivant l'algorithme démontré dans la question. La génération de l’indice principal est une complexité exponentielle, de sorte qu’elle expire pour des entrées plus importantes

Explication:

+%(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
PunPun1000
la source
1

Haskell , 162 160 155 octets

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

Essayez-le en ligne!

Explication:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]définit une liste infinie de tuples de nombres premiers et leurs indices: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

La fonction (%)prend cette liste ret un nombre net convertit ce nombre en représentation sous forme de tableau de facteurs inversé. Cela se fait en passant à travers rjusqu'à ce que nous trouvions un nombre premier qui divise n. Nous déterminons récursive alors la représentation de l'indice de ce premier et l' enferment dans 0et 1et PREPEND la représentation ndivisée par ce premier.

Car n=46, ceci donne la liste à [0,0,0,1,1,0,0,1,1,1,0,1]partir de laquelle les zéros ( snd.span(<1)) et next 1( tail) sont supprimés. Ensuite , la liste est convertie en un nombre décimal en multipliant-élément par élément avec une liste des pouvoirs de deux et résumant la liste des résultats: sum.zipWith((*).(2^))[0..].

Laikoni
la source
0

JavaScript, 289 octets

Les octets sont la somme du code JavaScript sans les sauts de ligne après les virgules (insérées uniquement pour améliorer le formatage et la lisibilité) (256 octets) et les caractères supplémentaires du commutateur de ligne de commande, requis lors de l'utilisation de Chrome (33 octets).

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

Et une version plus longue et plus lisible:

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

Quelques brèves explications:

f est un algorithme de factorisation récursif purement fonctionnel.

ccompte à quel endroit rle nombre premier papparaît dans la séquence des nombres premiers et retourne [](si p=2et r=1) ou factorise et traite ultérieurement au rmoyen de la récursion.

hest une petite fonction d'assistance qui est malheureusement nécessaire car elle mapappelle la fonction fournie avec numberOfCurrentElementles deuxième et wholeArraytroisième arguments, remplaçant ainsi les valeurs par défaut spécifiées dans csi nous passons directement cette fonction (il m'a fallu un certain temps pour en arriver à ce piège; remplaçant hpar sa définition serait plus long de quelques octets).

stransforme le tableau généré en une chaîne. Nous utilisons blankau lieu de 0afin que nous puissions utiliser trim()dans o.

oest la fonction à appeler avec la valeur d'entrée iqui renvoie la sortie. Il génère la représentation sous forme de chaîne binaire requise par la spécification et la convertit en un nombre (décimal).

Éditer: Chrome doit être démarré avec chrome --js-flags="--harmony-tailcalls"pour activer l'optimisation de la récursion de la queue (voir https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Cela nécessite également l'utilisation du mode strict.

Le test suivant montre que le calcul est un peu lent pour certaines valeurs (la plus longue dure plus de six secondes pour 10007sur mon ordinateur). Fait intéressant, sans optimisation de la récursion finale, le calcul est beaucoup plus rapide (environ le facteur 5) en l'absence de débordement de pile.

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>');
}
Fabien
la source
0

tinylisp , 209 octets

(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 dernière ligne est une fonction non nommée qui calcule le codage spécifié. Essayez-le en ligne!

Version pré-golf

Voici le code que j'avais avant de commencer à jouer au 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)))))))
DLosc
la source
0

05AB1E , 18 octets

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

Essayez-le en ligne!

Explication:

Δ    }       # 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
Grimmy
la source