Bir tamsayı kodla


33

Verilen pozitif tamsayı n > 2. Diziyi şu şekilde dönüştürürüz:

  1. 2Boş bir dizi döndürmek için eşitse
  2. Aksi halde n, yükselen sıralanan tüm asal çarpanların dizisini yaratın , daha sonra her eleman asal sayılar dizindeki dizini ile değiştirildi ve son olarak her elemanı diziye dönüştürdü.

Örneğin, sayıyı 46diziye dönüştürelim . İlk olarak, onu ana faktörlerin dizisine dönüştürün:

[2, 23]

Numara 23olduğunu 9böylece yerine, inci asal 2boş dizi ve 23birlikte [9]. Dizi şimdi olur:

[[], [9]]

Başbakan faktörler 9şunlardır 3ve 3bu nedenle,:

[[], [3, 3]]

Her ikisi için de aynısını yapın 3:

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

Ve sonunda:

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

Şimdi, onu kodlamak için, her açık braketi basitçe 1ve her kapanış braketiyle değiştiriyoruz 0, sonra tüm bitiş sıfırlarını çıkarıyoruz ve bir 1ucundan düşüyoruz. Bu bizim ikili sayımız. Yukarıdaki örneği kullanarak:

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

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

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

Şimdi sadece son üç sıfırı ve sonuncuyu bırakın 1. Numara olur 10111001ki 185ondalık. Beklenen çıktı budur. Dizideki ana dizinin ikili dönüştürme dirseklerine dahil edilmediğine dikkat edin.

Giriş

Pozitif tamsayı ndaha büyük 2.

Çıktı

Kodlanmış tam sayı n.

Kurallar ve IO formatı

  • Standart kurallar geçerlidir.
  • Giriş, dize veya sayı olabilir (dize olması durumunda, 10 tabanında olması gerekir).
  • Çıktı, dize veya sayı olabilir (dize olması durumunda, 10 tabanında olması gerekir).
  • Bu , bayt cinsinden en kısa cevap kazanır!

Test durumları

İstek üzerine daha fazla test durumu.

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

Kum havuzu


Sunulanları kaldırmanız gerekir, 2çünkü başvurularda bunu yapmanız gerekmemektedir.
Bay Xcoder

4
Asal yerleşik olmayan dilleri kopyalayın.
Bay Xcoder,

3
@ Paul. "[...] artan sırada yer alan ve tüm ana faktörlerin dizisini yaratır"

1
@Quelklef. ATP'yi uygulamak için çalışıyordum (sadece eğlence için, ciddi bir şey değil) ve iç içe dizileri kullanarak her sayıyı bir şekilde temsil etmeye çalıştım. Yani, bu kodlama geldiğim ilk fikir.

1
@WheatWizard. Tamsayı kelimesinin tam matematiksel anlamını kastetmiyorum . Onu bırakacağım. :-)

Yanıtlar:


12

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

@Zgarb sayesinde -7 bayt!

Zgarb sayesinde dolaylı olarak 4 bayt daha kaydedildi

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

Çevrimiçi deneyin!

Açıklama

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

Bence bu 27 byte için çalışması gerektiğini, ama dışarı TIO kez tür kesmesi sırasında ...
Zgarb

2
Aldırma, 25 bayt ve çalışıyor. Nihayet bir kullanım çantası φ, sabit nokta lambda!
Zgarb

Vay canına, şu ana kadar kullanım durumlarını hiç anlamadım, şimdiye kadar
H.PWiz

Çok hatlı programlar uygulanmadan önce çok erken bir zamanda Husk'a fixpoint lambda ekledik. Sanırım özyinelemeyle baş etmenin en iyi yolu olacağını düşündük. Ancak, böyle özel durumlarda bir bayttan tasarruf etmekten ayrı olarak oldukça karanlıklar.
Zgarb

`:0:1olabilir `Jḋ2.
Zgarb

7

Jöle ,  22 20  19 bayt

-1 Outgolfer Erik ( tsağdan değil her iki taraftan kuyruk sıfırları œr) sayesinde

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

2'den büyük bir tamsayı alan ve 0'dan büyük bir tamsayı döndüren monadik bir bağlantı (2, orijinal belirtime göre 0 değerini döndürür).

Çevrimiçi deneyin!

Nasıl?

Bu neredeyse tam olarak verilen tanımlamayı kopyalar, sadece ikili dizinin yaratılması için sıralı bir manipülasyonla ...

Æ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, evet, kesinlikle yapabilirim; Teşekkürler.
Jonathan Allan,

6

Python 2 , 212 177 bayt

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

Çevrimiçi deneyin!

Asal yerleşiklerin eksikliği, bayt sayısını gerçekten incitir ve daha büyük astarlarla TIO'da zaman aşımına uğrar. Xnor 'ın ilkellik kontrolünü kullanır .


Python 2 + gmpy2 , 175 bayt

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*

Çevrimiçi deneyin!

Bu versiyon daha büyük test durumlarında zaman aşımına uğramaz (10000 - 10008).


5

Mathematica, 125 119 bayt

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

Biraz farklı bir yaklaşım kullanır; asal endeksleri {1, index, 0}, ve 2'ye dönüştürür {1, 0}.

Wolfram Sandbox'ta dene

Kullanımı:

f = Flatten[ ...

f[10008]

1402478


Orijinal cevap
10008'de

1
@KellyLowder Sabit!
JungHwan Min 14:17


2

J, 74 73 66 bayt

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

Çevrimiçi deneyin!

Bu kesinlikle daha fazla golf oynamaya ihtiyaç duyan gerçek bir karmaşadır (örneğin, açık işlev tanımının kaldırılması gibi). Yaptığım boksun özellikle ne yaptığımı bilmediğim için özellikle bayt sayısını getiren şey olduğunu düşünüyorum (çok fazla deneme yanılma oldu). Ayrıca, unutacağım bazı yerleşikler olduğundan oldukça eminim (örneğin _2,~_1,, muhtemelen bir yerleşik varmış gibi hissediyorum ).

Açıklama (ungolfed)

önsöz

Arkanıza yaslanın, çünkü bu kısa bir açıklama olmayacak. İronik olarak, kısa bir dil ayrıntılı bir kişiyle eşleştirildi.

Bunu birkaç fonksiyona böleceğim

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode [ve] yerine _1 ve _2 kullanarak tam sayıyı kodlar
  • convert _1 ve _2 listesini 1 ve 0 listesine dönüştürür
  • drop son 1 ve sondaki sıfırı düşürür
  • decode bir ikili listeden bir sayıya dönüştürür

Ungall formatta ifade edilen 46 için yapılan örnek bir çağrıdan geçeceğim

   decode drop convert encode 46
185

kodlamak

Burada açıklanacak çok şey var.

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

Açık işlev tanımının 3 : '[function]', işlevi her örneği değiştiren doğru argümanla REPL'de olduğu gibi değerlendirdiğini unutmayın (bu, pahasına ycaps ( [:), atops ( @) ve ats ( @:) kullanmaktan kaçınabileceğim anlamına gelir . birkaç bayt).

46 girdideki ardışık her yineleme için nasıl göründüğü

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

Bu işlev ::, değerleri "parantez" içine yerleştirmek için adverse ( ) işlevini kullanır ( burada kullanılan parantez -1 ve -2'dir). Temel olarak, her çarpanlara ayırıp asal sayı endekslerine dönüştürdüğümüzde, _1 hazırlanır ve parantez görevi gören _2 eklenir. Fonksiyon bu elemanlar üzerinde çağrıldığında, sadece olduğu gibi döner, çünkü q:negatif bir sayıyı çarpanlara ayırmaya çalışırken hata verir. Ayrıca şanslı olduğunu q:mu değil 1 çarpanlarına çalışırken üzerine hata ve yerine (istendiği gibi) boş bir dizi döndürür.

Dönüştürmek

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

Dönüştürmek çok daha basittir. Sadece birinci kutunun yanı sıra tüm kutuyu da kaldırır ve sonra her şeyi 1s ve 0'lara dönüştürür (sadece 2 ekleyerek)

Düşürmek

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

Bu, listeyi tersine çevirir, ilkini bulur ve ardından tüm değerleri bu değere düşürür, ardından listeyi tekrar tersine çevirir.

Kod Çözme

Kod çözme, #.1s ve 0'ların listesini alan ve onu ikili bir sayıya dönüştüren yerleşik işlevdir .


2

Retina , 244 227 225 bayt

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

Çevrimiçi deneyin!

Bu, soruda gösterilen algoritmayı takip eden basit bir yaklaşımdır. Ana endeks üretimi üstel karmaşıklıktır, bu nedenle daha büyük girdiler için zaman aşımına uğrar

Açıklama:

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

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

Çevrimiçi deneyin!

Açıklama:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]asal küpe ve endekslerin sonsuz bir listesi tanımlar: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

İşlev (%), bu listeyi rve bir sayı alır ve sayıyı nters faktör dizi temsiline dönüştürür. Bu, rbölünen bir üssü bulana kadar adım adım yapılır n. Sonra yinelemeli bu asal endeksi temsilini belirlemek ve içine alın 0ve 1ve temsilini prepend no asal bölü.

İçin n=46, bu verimler listesi [0,0,0,1,1,0,0,1,1,1,0,1]daha sonra gelen sıfır (başka snd.span(<1)) ve sonraki 1( tail) bırakılır. Daha sonra liste iki üssü listesiyle öğeye göre çarparak bir ondalık sayıya dönüştürülecek ve elde edilen liste özetliyor edilir: sum.zipWith((*).(2^))[0..].


0

JavaScript, 289 bayt

Baytlar, virgüllerden sonra (yalnızca daha iyi biçimlendirme ve okunabilirlik için eklenir) (256 bayt) satır aralığı olmayan JavaScript kodunun toplamı ve Chrome (33 bayt) kullanılırken gereken komut satırı anahtarının ek karakterleridir.

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

Ve daha uzun, daha iyi okunabilir bir sürüm:

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

Bazı kısa açıklamalar:

f tamamen işlevsel bir kuyruk özyinelemeli faktoring algoritmasıdır.

csayımları yerde hiç rasal sayı pasal sayı ve geri dönüş ait bir sekans meydana gelir [](eğer p=2ve r=1) ya da factorizes ve daha farklı proseslere ryineleme vasıtasıyla.

hmapsağlanan fonksiyonu numberOfCurrentElementikinci ve wholeArrayüçüncü argüman olarak çağırmak için maalesef gerekli olan küçük bir yardımcı fonksiyondur , bu nedenle ceğer bu fonksiyonu doğrudan geçersek sağlanan varsayılan değerleri geçersiz kılar; htanımına göre değiştirilmesi birkaç byte daha uzun olacaktır).

sÜretilen diziyi bir dizgeye dönüştürür. Biz kullanmak blankyerine 0kullandığımız böylece trim()de o.

oiçıktıyı döndüren giriş değeriyle çağrılacak işlevdir . Belirtimin gerektirdiği ikili dize gösterimini oluşturur ve onu (ondalık) sayıya dönüştürür.

Düzenleme:chrome --js-flags="--harmony-tailcalls" Kuyruk özyineleme optimizasyonunu etkinleştirmek için Chrome ile başlatılmalıdır (bkz. Https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Bu da sıkı mod kullanılmasını gerektirir.

Aşağıdaki test, hesaplamanın bazı değerler için biraz yavaş olduğunu gösteriyor (en uzun zaman 10007bilgisayarım için altı saniyeden uzun ). İlginçtir ki, kuyruk özyinelemesinin optimizasyonu olmadan yığın taşması olmadığında hesaplama çok daha hızlıdır (yaklaşık faktör 5).

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 bayt

(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

Son satır, belirtilen kodlamayı hesaplayan adsız bir işlevdir. Çevrimiçi deneyin!

Golf öncesi versiyon

Golfe başlamadan önce sahip olduğum kod bu:

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

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

Çevrimiçi deneyin!

Açıklama:

Δ    }       # 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.