Encode bilangan bulat

33

Diberikan bilangan bulat positif n > 2. Kami mengonversinya menjadi array sebagai berikut:

  1. Jika sama dengan 2mengembalikan array kosong
  2. Jika tidak, buat array semua nfaktor utama yang diurutkan naik, lalu setiap elemen ganti dengan indeksnya dalam urutan bilangan prima dan akhirnya konversi setiap elemen menjadi array

Misalnya, mari kita konversi angka 46menjadi array. Pertama, konversikan ke berbagai faktor utamanya:

[2, 23]

Jumlah 23ini 9prime th, jadi ganti 2dengan array kosong dan 23dengan [9]. Array sekarang menjadi:

[[], [9]]

Faktor utama 9adalah 3dan 3, jadi:

[[], [3, 3]]

Lakukan hal yang sama untuk keduanya 3:

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

Dan akhirnya:

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

Sekarang, untuk menyandikannya, kita cukup mengganti masing-masing braket terbuka dengan 1dan setiap braket penutup 0, lalu hapus semua nol akhir dan jatuhkan satu 1dari ujungnya. Ini adalah nomor biner kami. Menggunakan contoh di atas:

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

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

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

Sekarang cukup masukkan tiga nol terakhir dan terakhir 1. Angka menjadi 10111001yang 185dalam desimal. Itu adalah output yang diharapkan. Perhatikan bahwa dalam kurung konversi array ke biner dari array utama tidak termasuk.

Memasukkan

Bilangan bulat positif nlebih besar dari 2.

Keluaran

Integer yang dikodekan n.

Aturan dan format IO

  • Aturan standar berlaku.
  • Input dapat berupa string atau angka (tetapi jika string harus dalam basis 10).
  • Output dapat berupa string atau angka (tetapi jika string harus dalam basis 10).
  • Ini adalah , jawaban terpendek dalam byte menang!

Uji kasus

Lebih banyak kasus uji berdasarkan permintaan.

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

Bak pasir

H.Piz
sumber
Anda harus menghapus test case 2karena kiriman tidak diperlukan untuk menanganinya.
Tn. Xcoder
4
Rip bahasa yang tidak memiliki bawaan bawaan.
Tn. Xcoder
3
@ Paul. "[...] buat larik semua faktor utama yang diurutkan naik"
1
@Quelklef. Saya sedang mengerjakan implementasi ATP (hanya untuk bersenang-senang, tidak ada yang serius) dan saya mencoba merepresentasikan setiap angka menggunakan nested array. Jadi, pengkodean ini adalah ide pertama yang saya buat.
1
@WheatWizard. Maksud saya bukan arti matematis yang tepat dari kata integer . Saya akan meninggalkannya. :-)

Jawaban:

12

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

-7 byte terima kasih kepada @Zgarb!

Menyimpan tambahan 4 byte, secara tidak langsung, berkat Zgarb

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

Cobalah online!

Penjelasan

     φ             -- 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.Piz
sumber
Saya pikir ini harus bekerja selama 27 byte, tetapi TIO habis saat inferensi jenis ...
Zgarb
2
Sudahlah, 25 byte dan berfungsi. Akhirnya sebuah use case untuk φ, fixpoint lambda!
Zgarb
Wow, saya tidak pernah benar-benar mengerti kasus penggunaannya, sampai sekarang
H.PWiz
Kami menambahkan lambpoint fixpoint ke Husk sangat awal, sebelum program multi-line dilaksanakan. Saya kira kami pikir mereka akan menjadi cara terbaik untuk menangani rekursi. Tetapi mereka cukup jelas selain menyimpan satu byte dalam kasus khusus seperti ini.
Zgarb
`:0:1bisa `Jḋ2.
Zgarb
7

Jelly ,  22 20  19 byte

-1 berkat Erik the Outgolfer (angka nol ekor dari kedua sisi t,, bukan dari kanan œr)

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

Tautan monadik yang mengambil bilangan bulat lebih besar dari 2 dan mengembalikan bilangan bulat lebih besar dari 0 (2 akan mengembalikan 0 sesuai dengan spesifikasi asli juga).

Cobalah online!

Bagaimana?

Ini hampir persis mereplikasi deskripsi yang diberikan, hanya dengan beberapa manipulasi ordinal untuk pembuatan array biner ...

Æ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
sumber
Ah, ya, saya pasti bisa; Terima kasih.
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

Cobalah online!

Kurangnya prime builtin benar-benar menyakiti jumlah byte, dan itu kali keluar pada TIO dengan bilangan prima yang lebih besar. Penggunaan XNOR 's cek primality.


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*

Cobalah online!

Versi ini tidak berhenti pada kasus uji yang lebih besar (yaitu 10.000 - 1.0008).

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

Menggunakan pendekatan yang sedikit berbeda; mengkonversi indeks utama menjadi {1, index, 0}, dan 2 menjadi {1, 0}.

Cobalah di Wolfram Sandbox

Pemakaian:

f = Flatten[ ...

f[10008]

1402478

JungHwan Min
sumber
Jawaban orisinal berfungsi pada 10008, tetapi yang ini gagal
Kelly Lowder
1
@KellyLowder Diperbaiki!
JungHwan Min
2

Jelly , 35 byte

ÆfẎW€ÆC2,“”y¹ß€Ṇ?
ÇŒṘḊ⁾][iЀḟ0t1Ṗ’Ḅ

Cobalah online!

Erik the Outgolfer
sumber
2

J, 74 73 66 byte

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

Cobalah online!

Ini adalah kekacauan nyata yang tentunya membutuhkan golf lebih lanjut (misalnya, penghapusan definisi fungsi eksplisit). Saya pikir tinju yang telah saya lakukan adalah terutama apa yang memunculkan bytecount karena saya benar-benar tidak tahu apa yang saya lakukan di sana (sudah banyak trial and error). Juga, saya cukup yakin bahwa ada beberapa built-in yang saya lupakan (misalnya saya merasa _2,~_1,mungkin memiliki built-in).

Penjelasan (ungolfed)

Pembukaan

Duduk santai, karena ini tidak akan menjadi penjelasan singkat. Ironisnya, bahasa singkat telah dipasangkan dengan orang yang bertele-tele.

Saya akan membagi ini menjadi beberapa fungsi

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode mengkodekan integer menggunakan _1 dan _2 alih-alih [dan]
  • convert mengonversi daftar _1 dan _2 menjadi daftar 1 dan 0
  • drop menjatuhkan 1 terakhir dan membuntuti nol
  • decode mengkonversi dari daftar biner ke angka

Saya akan berjalan melalui panggilan sampel untuk 46, yang dinyatakan dalam format ungolfed selesai

   decode drop convert encode 46
185

Menyandi

Ada banyak hal untuk dijelaskan di sini.

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

Perhatikan bahwa definisi fungsi eksplisit 3 : '[function]'mengevaluasi fungsi seolah-olah berada pada REPL dengan argumen yang tepat menggantikan setiap instance dari y(ini berarti bahwa saya dapat menghindari harus menggunakan caps ( [:), atops ( @), dan ats ( @:) dengan biaya beberapa byte).

Inilah yang terlihat untuk setiap iterasi berturut-turut pada input 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

Fungsi ini menggunakan merugikan ( ::) untuk bersarang nilai dalam "tanda kurung" (tanda kurung yang digunakan di sini adalah -1 dan -2). Pada dasarnya, setiap kali kami memfaktisasi dan mengonversikan ke indeks bilangan prima, _1 diawali dan _2 ditambahkan, yang bertindak sebagai tanda kurung. Ketika fungsi dipanggil pada elemen-elemen itu, ia hanya mengembalikannya apa adanya karena q:akan kesalahan saat mencoba memfaktorkan bilangan negatif. Ini juga beruntung bahwa q:tidak tidak kesalahan berusaha untuk pd 1 dan bukannya mengembalikan array kosong (seperti yang diinginkan).

Mengubah

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

Konversi jauh lebih sederhana. Itu hanya menghapus semua tinju, serta elemen pertama, dan kemudian mengubah semuanya menjadi 1 dan 0 (hanya dengan menambahkan 2)

Penurunan

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

Ini membalikkan daftar, menemukan yang pertama dan kemudian menjatuhkan semua nilai hingga yang itu, lalu membalikkan daftar lagi.

Membaca sandi

Decode adalah fungsi #.bawaan yang mengambil daftar 1s dan 0s dan mengubahnya menjadi angka biner.

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

Cobalah online!

Ini adalah pendekatan lurus ke depan mengikuti algoritma yang ditunjukkan dalam pertanyaan. Generasi indeks utama adalah kompleksitas eksponensial sehingga akan habis untuk input yang lebih besar

Penjelasan:

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

Cobalah online!

Penjelasan:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]mendefinisikan daftar tak terbatas tupel bilangan prima dan indeks mereka: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

Fungsi (%)mengambil daftar ini rdan angka ndan mengubah angka menjadi representasi array faktor terbalik. Ini dilakukan dengan melangkah maju rsampai kita menemukan prime yang membelah n. Kami kemudian rekursif menentukan representasi dari indeks utama ini dan membungkusnya dengan 0dan 1dan tambahkan representasi ndibagi dengan perdana itu.

Sebab n=46, ini menghasilkan daftar [0,0,0,1,1,0,0,1,1,1,0,1]yang kemudian nol depan ( snd.span(<1)) dan berikutnya 1( tail) dijatuhkan. Setelah itu daftar dikonversi ke angka desimal oleh mengalikan elemen-bijaksana dengan daftar kekuatan dua dan menyimpulkan daftar yang dihasilkan: sum.zipWith((*).(2^))[0..].

Laikoni
sumber
0

JavaScript, 289 byte

Bytes adalah jumlah dari kode JavaScript tanpa linebreak setelah koma (yang dimasukkan hanya untuk pemformatan dan keterbacaan yang lebih baik) (256 byte) dan karakter tambahan untuk saklar baris perintah, yang diperlukan saat menggunakan 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))

Dan versi yang lebih panjang, lebih baik dibaca:

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

Beberapa penjelasan singkat:

f adalah algoritma faktorisasi ekor-rekursif murni fungsional.

cmenghitung di mana tempat rbilangan prima pterjadi dalam urutan bilangan prima dan mengembalikan baik [](jika p=2dan r=1) atau membuat faktor dan proses lebih lanjut rdengan cara rekursi.

hadalah fungsi pembantu kecil yang sayangnya diperlukan sebagai mapmemanggil fungsi yang disediakan dengan numberOfCurrentElementsebagai wholeArrayargumen kedua dan ketiga, sehingga mengesampingkan nilai default yang disediakan cjika kita akan meneruskan fungsi ini secara langsung (butuh beberapa waktu untuk mendapatkan setelah jebakan ini; mengganti hdengan definisinya akan lebih lama beberapa byte).

smentransformasikan array yang dihasilkan menjadi string. Kami menggunakan blankalih-alih 0agar kami dapat menggunakannya trim()di o.

oadalah fungsi yang dipanggil dengan nilai input iyang mengembalikan output. Ini menghasilkan representasi string biner yang diperlukan oleh spesifikasi dan mengubahnya menjadi angka (desimal).

Sunting: Chrome harus dimulai dengan chrome --js-flags="--harmony-tailcalls"untuk mengaktifkan optimasi rekursi ekor (lihat https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Ini juga mengharuskan menggunakan mode ketat.

Tes berikut menunjukkan bahwa perhitungannya agak lambat untuk beberapa nilai (yang terpanjang lebih dari enam detik untuk 10007komputer saya). Menariknya, tanpa optimasi rekursi ekor perhitungannya jauh lebih cepat (sekitar faktor 5) ketika tidak ada stack overflow.

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

Baris terakhir adalah fungsi tanpa nama yang menghitung pengkodean yang ditentukan. Cobalah online!

Versi pra-golf

Ini adalah kode yang saya miliki sebelum mulai bermain 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
sumber
0

05AB1E , 18 byte

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

Cobalah online!

Penjelasan:

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