Codiere eine ganze Zahl

33

Bei positiver Ganzzahl n > 2. Wir konvertieren es wie folgt in ein Array:

  1. Wenn es gleich ist, wird 2ein leeres Array zurückgegeben
  2. Andernfalls erstellen Sie ein Array mit allen nPrimfaktoren, die aufsteigend sortiert sind. Anschließend wird jedes Element durch seinen Index in der Reihenfolge der Primzahlen ersetzt und schließlich jedes Element in ein Array konvertiert

Lassen Sie uns beispielsweise eine Zahl 46in ein Array konvertieren . Konvertieren Sie es zunächst in eine Reihe seiner Primfaktoren:

[2, 23]

Die Zahl 23ist die 9Primzahl. Ersetzen Sie sie 2durch ein leeres Array und 23durch [9]. Array wird jetzt:

[[], [9]]

Primfaktoren von 9sind 3und 3, also:

[[], [3, 3]]

Machen Sie dasselbe für beide 3:

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

Und schlussendlich:

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

Um es zu kodieren, ersetzen wir einfach jede offene Klammer mit 1und jede schließende Klammer mit 0, entfernen dann alle endenden Nullen und lassen eine 1vom Ende fallen. Dies ist unsere Binärzahl. Mit dem obigen Beispiel:

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

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

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

Nun einfach die letzten drei Nullen und die letzten fallen lassen 1. Die Zahl wird 10111001das ist 185in Dezimal. Das ist die erwartete Ausgabe. Beachten Sie, dass in der Konvertierung von Array zu Binär keine Klammern des Hauptarrays enthalten sind.

Eingang

Positive ganze Zahl ngrößer als 2.

Ausgabe

Codierte Ganzzahl n.

Regeln und IO-Format

  • Es gelten Standardregeln.
  • Die Eingabe kann eine Zeichenfolge oder eine Zahl sein (im Falle einer Zeichenfolge muss sie sich jedoch in der Basis 10 befinden).
  • Die Ausgabe kann eine Zeichenfolge oder eine Zahl sein (im Falle einer Zeichenfolge muss sie sich jedoch in der Basis 10 befinden).
  • Das ist , die kürzeste Antwort in Bytes gewinnt!

Testfälle

Weitere Testfälle auf Anfrage.

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

Sandkasten

H.PWiz
quelle
Sie sollten den Testfall mit entfernen, 2da die Einreichungen nicht zur Bearbeitung erforderlich sind.
Mr. Xcoder
4
Rippen Sie Sprachen, die keine eingebauten Primzahlen haben.
Mr. Xcoder
3
@Paul. "[...] Array aller Primfaktoren von n aufsteigend sortiert erstellen"
1
@Quelklef. Ich habe an der Implementierung von ATP gearbeitet (nur zum Spaß, nichts Ernstes) und irgendwie versucht, jede Zahl mit verschachtelten Arrays darzustellen. Diese Codierung ist also die erste Idee, die mir einfiel.
1
@ WheatWizard. Ich meine nicht den genauen mathematischen Sinn des Wortes Ganzzahl . Ich werde es verlassen. :-)

Antworten:

12

Schale , 35 31 30 29 26 25 24 22 20 19 15 Bytes

-7 Bytes dank @Zgarb!

Indirekt wurden dank Zgarb weitere 4 Bytes gespeichert

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

Probieren Sie es online!

Erklärung

     φ             -- 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
quelle
Ich denke, das sollte für 27 Bytes funktionieren, aber TIO
läuft
2
Macht nichts, 25 Bytes und arbeiten. Endlich ein Anwendungsfall für φden Fixpoint Lambda!
Zgarb
Wow, ich habe seine Anwendungsfälle bis jetzt noch nie wirklich verstanden
H.PWiz
Wir haben Husk sehr früh um Fixpoint-Lambdas erweitert, bevor mehrzeilige Programme implementiert wurden. Ich denke, wir dachten, sie wären der beste Weg, um mit Rekursionen umzugehen. Aber sie sind ziemlich dunkel, abgesehen davon, dass sie in solchen Sonderfällen ein Byte speichern.
Zgarb
`:0:1kann sein `Jḋ2.
Zgarb
7

Jelly ,  22 20  19 Bytes

-1 danke an Erik den Outgolfer (Schwanz Nullen von beiden Seiten t, anstatt von rechts œr)

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

Eine monadische Verknüpfung, die eine Ganzzahl größer als 2 und eine Ganzzahl größer als 0 zurückgibt (2 würde auch 0 gemäß der ursprünglichen Spezifikation zurückgeben).

Probieren Sie es online!

Wie?

Dies entspricht fast genau der angegebenen Beschreibung, nur mit einigen ordinalen Manipulationen für die Erstellung des binären Arrays ...

Æ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
quelle
Ah ja, ich kann definitiv; Vielen Dank.
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

Probieren Sie es online!

Das Fehlen von eingebauten Primzahlen schadet der Byteanzahl wirklich und es tritt bei TIO mit größeren Primzahlen eine Zeitüberschreitung auf. Verwendet die Primalitätsprüfung von xnor .


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*

Probieren Sie es online!

Diese Version läuft bei größeren Testfällen (z. B. 10000 - 10008) nicht ab.

notjagan
quelle
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&

Verwendet einen etwas anderen Ansatz; konvertiert Prime-Indizes in {1, index, 0}und 2 in {1, 0}.

Probieren Sie es auf Wolfram Sandbox

Verwendung:

f = Flatten[ ...

f[10008]

1402478

JungHwan min
quelle
Die ursprüngliche Antwort funktioniert auf 10008, aber diese schlägt fehl
Kelly Lowder
1
@ KellyLowder behoben!
JungHwan Min
2

J, 74 73 66 Bytes

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

Probieren Sie es online!

Dies ist ein echtes Durcheinander, das sicherlich weiteren Golfsport erfordert (z. B. das Entfernen der expliziten Funktionsdefinition). Ich denke, dass das Boxen, das ich gemacht habe, besonders das ist, was das bytecount aufwirft, da ich wirklich nicht weiß, was ich dort mache (es war eine Menge Versuch und Irrtum). Außerdem bin ich mir ziemlich sicher, dass es einige integrierte Funktionen gibt, die ich vergesse (z. B. habe ich _2,~_1,wahrscheinlich eine integrierte Funktion).

Erklärung (ungolfed)

Präambel

Lehnen Sie sich fest zurück, denn dies wird keine kurze Erklärung sein. Ironischerweise wurde eine knappe Sprache mit einer wortreichen Person gepaart.

Ich werde dies in einige Funktionen aufteilen

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode codiert die Ganzzahl mit _1 und _2 anstelle von [und]
  • convert wandelt eine Liste von _1 und _2 in eine Liste von 1 und 0 um
  • drop Lässt die letzte 1 und nachfolgende Nullen fallen
  • decode wandelt von einer binären Liste in eine Zahl um

Ich werde einen Beispielanruf für 46 durchgehen, der im ungolfed-Format fertig ist

   decode drop convert encode 46
185

Kodieren

Hier gibt es viel zu erklären.

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

Beachten Sie, dass die explizite Funktionsdefinition 3 : '[function]'die Funktion so auswertet, als befände sie sich auf der REPL, wobei das richtige Argument jede Instanz von ersetzt y(dies bedeutet, dass die Verwendung von caps ( [:), atops ( @) und ats ( @:) auf Kosten von vermieden werden kann ein paar Bytes).

So sieht es bei jeder Iteration der Eingabe von 46 aus

┌─────────┐    ┌──┬─────┬─────────┬──┐    ┌──┬──┬──┬──┬───────┬───────┬──┬──┐
│_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

Diese Funktion verwendet advers ( ::), um die Werte in "Klammern" zu verschachteln (die hier verwendeten Klammern sind -1 und -2). Grundsätzlich wird bei jeder Faktorisierung und Umwandlung in Primzahlindizes _1 vorangestellt und _2 angehängt, die als Klammern fungieren. Wenn die Funktion für diese Elemente aufgerufen wird, werden sie nur so zurückgegeben, wie sie sind, da q:beim Versuch, eine negative Zahl zu faktorisieren, ein Fehler auftritt. Es ist auch das Glück , das q:sich nicht auf einem Fehler beim 1 faktorisieren und stattdessen gibt das leere Feld (wie gewünscht).

Konvertieren

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

Konvertieren ist viel einfacher. Es entfernt nur alle Boxing-Elemente sowie das erste Element und konvertiert dann alles in 1s und 0s (einfach durch Hinzufügen von 2).

Fallen

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

Dies kehrt die Liste um, findet die erste und löscht dann alle Werte bis zu dieser und kehrt die Liste erneut um.

Dekodieren

Decode ist die eingebaute Funktion, #.die eine Liste von Einsen und Nullen aufnimmt und in eine Binärzahl umwandelt.

cole
quelle
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

Probieren Sie es online!

Dies ist ein direkter Ansatz, der dem in der Frage gezeigten Algorithmus folgt. Die Erzeugung des Primärindex ist exponentiell komplex, sodass bei größeren Eingaben eine Zeitüberschreitung auftritt

Erläuterung:

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

Probieren Sie es online!

Erläuterung:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]definiert eine unendliche Liste von Tupeln von Primzahlen und deren Indizes: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

Die Funktion (%)nimmt diese Liste rund eine Zahl nund konvertiert die Zahl in die umgekehrte Faktor-Array-Darstellung. Dies geschieht, indem rwir durchlaufen, bis wir eine Primzahl finden, die sich teilt n. Wir bestimmen dann rekursiv die Darstellung des Index dieses Prims und schließen ihn in 0und ein 1und stellen die Darstellung ngeteilt durch diesen Prim vor.

Für n=46ergibt dies die Liste , [0,0,0,1,1,0,0,1,1,1,0,1]aus der dann die führenden Nullen ( snd.span(<1)) und die nächste 1( tail) werden gelöscht. Danach wird die Liste in eine Dezimalzahl durch elementweise Multiplikation mit einer Liste von Zweierpotenzen umgewandelt und die resultierende Liste zusammenfassend: sum.zipWith((*).(2^))[0..].

Laikoni
quelle
0

JavaScript, 289 Bytes

Die Bytes sind die Summe des JavaScript-Codes ohne Zeilenumbrüche nach den Kommas (die nur zur besseren Formatierung und Lesbarkeit eingefügt werden) (256 Bytes) und der zusätzlichen Zeichen für den Befehlszeilenschalter, der bei Verwendung von Chrome erforderlich ist (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))

Und eine längere, besser lesbare Version:

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

Einige kurze Erklärungen:

f ist ein rein funktionaler Algorithmus zur rekursiven Faktorisierung des Schwanzes.

czählt an welcher Stelle rdie Primzahl pin der Folge der Primzahlen vorkommt und entweder [](wenn p=2und r=1) zurückgibt oder rdurch Rekursion zerlegt und weiterverarbeitet .

hist eine kleine Hilfsfunktion, die leider notwendig ist, da sie mapdie angegebene Funktion numberOfCurrentElementals zweites und wholeArrayals drittes Argument aufruft und somit die angegebenen Standardwerte überschreibt, cwenn wir diese Funktion direkt übergeben würden. Ersetzen hdurch seine Definition wäre einige Bytes länger.

stransformiert das generierte Array in einen String. Wir verwenden blankstatt , 0so dass wir verwenden können , trim()in o.

oist die Funktion, die mit dem Eingabewert aufgerufen werden soll, der idie Ausgabe zurückgibt. Es generiert die für die Spezifikation erforderliche binäre Zeichenfolgendarstellung und konvertiert sie in eine (Dezimal-) Zahl.

Bearbeiten: Chrome muss gestartet werden chrome --js-flags="--harmony-tailcalls", damit die Schwanzrekursion optimiert werden kann (siehe https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Dies erfordert auch die Verwendung des Strict-Modus.

Der folgende Test zeigt, dass die Berechnung für einige Werte etwas langsam ist (der längste dauert 10007auf meinem Computer mehr als sechs Sekunden ). Interessanterweise ist die Berechnung ohne Optimierung der Schwanzrekursion viel schneller (ungefähr Faktor 5), wenn kein Stapelüberlauf vorliegt.

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>');
}
Fabian
quelle
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

Die letzte Zeile ist eine unbenannte Funktion, die die angegebene Codierung berechnet. Probieren Sie es online!

Pre-Golf-Version

Dies ist der Code, den ich hatte, bevor ich anfing, Golf zu spielen:

(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
quelle
0

05AB1E , 18 Bytes

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

Probieren Sie es online!

Erläuterung:

Δ    }       # 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
Grimmig
quelle