编码一个整数


33

给定正整数n > 2。我们将其转换为数组,如下所示:

  1. 如果等于则2返回一个空数组
  2. 否则,创建所有n升序排列的所有素数的数组,然后将每个元素替换为其素数序列中的索引,最后将每个元素转换为数组

例如,让我们将数字转换46为数组。首先,将其转换为主要因子数组:

[2, 23]

号码239个质数,所以更换2空数组并23[9]。数组现在变为:

[[], [9]]

的主要因子933,因此:

[[], [3, 3]]

对两个都做相同的事情3

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

最后:

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

现在,要对其进行编码,我们只需用替换每个开括号,1并将每个闭括号替换为0,然后删除所有结尾的零,并1从结尾删除一个。这是我们的二进制数。使用上面的示例:

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

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

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

现在只需丢弃最后三个零和最后一个1。数目变为10111001这是185十进制。那是预期的输出。请注意,从数组到二进制的转换不包括主数组的括号。

输入项

n大于的正整数2

输出量

编码的整数n

规则和IO格式

  • 适用标准规则。
  • 输入可以是字符串或数字(但如果是字符串,则必须以10为底)。
  • 输出可以是字符串或数字(但如果是字符串,则必须以10为底)。
  • 这是,最短的答案以字节为单位!

测试用例

根据要求提供更多测试用例。

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

沙盒


您应该使用删除测试用例,2因为不需要提交来处理它。
Xcoder先生17年

4
没有主要内置语言的翻录语言。
Xcoder先生17年

3
@保罗。“ [...]创建所有n个素数按升序排列的数组”

1
@奎克尔夫 我当时正在实施ATP(只是为了好玩,没什么大不了的),我试图以某种方式使用嵌套数组表示每个数字。因此,这种编码是我想到的第一个想法。

1
@WheatWizard。我不是说整数这个词的精确数学意义。我要离开它。:-)

Answers:


12

外壳35 31 30 29 26 25 24 22 20 19 15字节

-7个字节感谢@Zgarb!

借助Zgarb,间接节省了额外的4个字节

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

在线尝试!

讲解

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

我认为应该适用于27个字节,但是在类型推断期间TIO超时...
Zgarb

2
没关系,25个字节并且可以工作。最后是一个用例φ,定点lambda!
Zgarb

哇,我从来没有真正了解过它的用例,直到现在
H.PWiz

在实施多行程序之前,我们很早就向Husk添加了fixpoint lambda。我想我们认为它们将是处理递归的最佳方法。但是除了在这种特殊情况下节省一个字节之外,它们还很晦涩。
Zgarb

`:0:1可以`Jḋ2
Zgarb

7

果冻 22 20  19 字节

-1感谢Outgolfer的埃里克(两边都是零t,而不是右边是œr

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

单链链接采用大于2的整数并返回大于0的整数(按照原始规范,2也将返回0)。

在线尝试!

怎么样?

这几乎完全复制了给定的描述,只是通过一些序数操作来创建二进制数组。

Æ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

啊,是的,我绝对可以;谢谢。
乔纳森·艾伦,

6

Python 2中212个 177字节

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

在线尝试!

缺少质数内建函数确实会损害字节数,并且在具有较大质数的TIO上会超时。使用xnor素数检查。


Python 2 + gmpy2,175字节

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*

在线尝试!

对于较大的测试用例(例如10000-10008),此版本不会超时。


5

Mathematica,125 119字节

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

使用略有不同的方法;将素数索引转换为{1, index, 0},将2 转换为{1, 0}

在Wolfram Sandbox上尝试

用法:

f = Flatten[ ...

f[10008]

1402478


原始答案适用于10008,但这一答案失败
Kelly Lowder

1
@KellyLowder固定!
JungHwan Min


2

J,74 73 66字节

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

在线尝试!

这确实是一团糟,当然需要进一步打高尔夫球(例如,删除显式功能定义)。我认为我一直在进行的拳击特别是提高字节数的原因,因为我真的不知道自己在做什么(这是很多试验和错误)。另外,我非常确定我会忘记一些内置功能(例如,我感觉_2,~_1,可能具有内置功能)。

说明(无胶体)

前言

请稍等,因为这不是简短的解释。具有讽刺意味的是,简洁的语言已与冗长的人配对。

我将其分为几个功能

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode 使用_1和_2而不是[和]编码整数
  • convert 将_1和_2的列表转换为1和0的列表
  • drop 删除最后一个1和尾随零
  • decode 从二进制列表转换为数字

我将逐步完成对46的示例调用,该调用以ungolfed格式表示

   decode drop convert encode 46
185

编码

这里有很多解释。

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

请注意,显式函数定义3 : '[function]'就像在REPL上一样使用右参数替换函数的每个实例来评估函数y(这意味着我可以避免不得不使用caps([:),atops(@)和ats(@:),而代价是几个字节)。

这是输入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

此函数利用不利(::)来将值嵌套在“括号”中(此处使用的括号为-1和-2)。基本上,每次我们分解并转换为质数指数时,都会在_1之前加上_2后面加上括号。在这些元素上调用该函数时,它仅按原样返回它们,因为q:在尝试分解负数时会出错。这也是幸运的q:没有上试图因式分解1错误,而是返回空数组(如需要)。

兑换

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

转换要简单得多。它只删除所有装箱以及第一个元素,然后将所有内容转换为1和0(只需添加2)

下降

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

这将反转该列表,找到第一个,然后将所有值降低到该值,然后再次反转该列表。

解码

解码是内置函数#.,它接受1和0的列表并将其转换为二进制数。


2

视网膜244个 227 225字节

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

在线尝试!

这是遵循问题中演示的算法的直接方法。质数指数的生成是指数复杂性,因此对于较大的输入将超时

说明:

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

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

在线尝试!

说明:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]定义素数元组及其索引的无限列表:[(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...]

该函数(%)获取此列表r和一个数字n,并将该数字转换为反向因子数组表示形式。这是通过逐步完成,r直到找到一个可分解的质数来完成的n。然后,我们递归确定该素数的索引表示形式并将其括起来,01n除以该素数的表示形式之前。

对于n=46,这将产生一个列表[0,0,0,1,1,0,0,1,1,1,0,1],然后从列表中删除前导零(snd.span(<1))和下一个1tail)。之后,通过逐元素乘以2的幂的列表并将结果列表相加,将列表转换为十进制数sum.zipWith((*).(2^))[0..]


0

JavaScript,289字节

字节数是JavaScript代码的总和,逗号后没有换行符(仅插入这些字符是为了提高格式和可读性)(256字节),以及命令行开关的附加字符(使用Chrome时需要此字符)(33字节)。

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

以及更长,更易读的版本:

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

一些简短的解释:

f 是一种纯函数式尾递归分解算法。

c计算r素数p在素数序列中出现的位置,并通过递归返回[](if p=2r=1)或分解并进一步处理r

h是一个小的辅助函数,不幸的是,使用第二个参数和第三个参数map调用提供的函数是必需的,因此如果我们直接传递此函数,则将覆盖提供的默认值(花了我一些时间才能克服此陷阱;根据其定义替换将长几个字节)。numberOfCurrentElementwholeArraych

s将生成的数组转换为字符串。我们使用blank代替0以便可以trim()在中使用o

o是要使用输入值调用的函数,该函数i返回输出。它生成规范所需的二进制字符串表示形式,并将其转换为(十进制)数字。

编辑:必须启动Chrome才能chrome --js-flags="--harmony-tailcalls"启用尾递归优化(请参阅https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html)。这也需要使用严格模式。

以下测试表明,对于某些值,计算有些慢(10007在我的计算机上,最长的时间超过6秒)。有趣的是,如果没有优化堆栈尾递归,那么在没有堆栈溢出的情况下,计算速度会更快(约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个字节

(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

最后一行是一个未命名的函数,用于计算指定的编码。在线尝试!

高尔夫球前版本

这是我开始打高尔夫之前的代码:

(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个字节

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

在线尝试!

说明:

Δ    }       # 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.