产生幸运数字


22

故事:

露西问乔治他的幸运数字是多少。经过深思熟虑,乔治回答说他有几个幸运数字。在短暂的困惑之后,露西问乔治他的第一个n幸运数字是什么。乔治然后要求您,他的伙伴,为他编写一个程序来为他完成工作。

挑战:

您将编写一个程序/函数,该程序/函数将从标准输入/函数参数接收一个字符串或整数n。然后,程序/函数将返回/输出第一个n 幸运数字。幸运数字通过一个筛子如下定义。

以正整数开头:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, ...

现在删除第二个数字:

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, ...

剩下的第二个数字是3,因此请删除第三个数字:

1, 3, 7, 9, 13, 15, 19, 21, 25, ...

现在,下一个剩余的数字是7,因此删除每七个数字:

1, 3, 7, 9, 13, 15, 21, 25, ...

接下来,删除第九个数字,依此类推。结果序列是幸运数字。

获奖情况:

与codegolf一样,最少的字节数获胜。

与往常一样,使用标准漏洞的提交将被取消资格。


8
我建议在帖子中包括定义以及前十个数字。
xnor 2015年

一个很酷的扩展是,对于检查的每个项目(3、7等),该操作将重复执行该次数。例如,对于3,删除第三个元素列表中的3次,第7件7倍,等等。(注意,这是不是序列但这个想法是一样的)
瑞恩

@Ryan我认为该序列将非常类似于自然数:)
TheNumberOne

@TheBestOne你这么认为吗?我较早发布到math.stackexchange:math.stackexchange.com/questions/1153889/…–
Ryan

@Ryan实际上,我误解了您的建议。正如您在有关math.se的问题中所说的那样,我认为这很有趣。
TheNumberOne

Answers:


16

Python 2,79

n=input()
L=range(1,2**n)
for r in L:r+=r<2;map(L.remove,L[r-1::r])
print L[:n]

在循环修改列表时遍历列表的魔力!

该列表L以所有整数开始,1直到足够高的值。代码遍历每个元素rL,采取一切的子列表r“个元素,并除去每个这些值的。结果,移除的值不会被迭代。最后,打印第一个n元素。

该表达式map(A.remove,B)是我一直在等待很长时间才能使用的技巧。它要求A.remove的每个元素B,这会导致将的所有元素B从中删除A。实际上,它需要列表差异,尽管它必须B是的子列表A。它需要Python 2,因为Python 3实际上不会评估地图。

第一个循环需要是特例,转换r来自12,作为r+=r<2

的足够高的上限2**n会使的值很大时程序非常慢n。使用n*n+1就足够了,但是要花一个字符。请注意,这n*n不适用于n=1


您只需要n**2数字,而不需要2**n
Optimizer

3
那是map您在那里的一种神奇用途。我想知道是否有更好的方法……
Sp3000 2015年

@Optimizer不幸的是,n**2+1除非n=1可以原谅。
xnor 2015年

地图的使用非常出色。就像使用有序集。也许还可以用来map(A.index,B)查找A中B元素的索引,map(A.count,B)查找A中B元素的数目,向A map(A.extend,B)添加平展的B列表。
逻辑骑士

13

Haskell,71 69字节

s(n:k)p=n:s[m|(i,m)<-zip[p..]k,i`mod`n>0](p+1)
f n=take n$1:s[3,5..]3

定义一个函数f。该表达式1:s[3,5..]3计算的是无限数量的幸运数字,f只需将其中的第一个n作为幸运数字即可take n

f 20
[1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79]

我可以使用并行列表理解从筛选中删除5个字节

s(n:k)p=n:s[m|m<-k|i<-[p..],i`mod`n>0](p+1)

但这需要将庞大的编译器标志传递-XParallelListComp给GHC才能启用扩展。

筛子的解释

s(n:k)p=               -- Sieving a list with head n and tail k with accumulator p is
 n:                    -- the head n, followed by
  s[m|                 -- the result of sieving the list of numbers m
    (i,m)<-zip[p..]k,  -- where (i,m) is drawn from [(p,k_0),(p+1,k_1),(p+2,k_2),..] and
    i`mod`n>0]         -- i does not divide n,
   (p+1)               -- using p+1 as the accumulator

基本思想是s(n:k)p产生(p-1)第一个幸运数字nn从无限尾部丢弃每个第一个数字k(偏移量p以抵消先前产生的数字),然后用累加器递归到该列表(p+1)。在中f,我们使用以开头的奇数初始化过程3,然后1将其固定在最前面,以获取准确的幸运数字。


12

蟒蛇2,71 69 67

起初,我认为这对于Python的数组切片将是一个巨大的挑战。但是,当我发现具有非1步长的片只能分配具有相同长度的另一个片时,遇到了绊脚石。但是在搜索了“ python remove slice”之后,我的信念得到了恢复:我发现了一个时髦的del语句,可以完美地解决问题。

n=input()
l=range(n*n+9)
for v in l:del l[v&~1::v or 2]
print l[:n]

旧版

n=input()
l=range(1,n*n+9)
for v in l:del l[v-1%v::v+1/v]
print l[:n]

-3000到2个字节。


10

> <> 121个 114 111字节

i2+:&:*1\
:})?v:2+>l{
nao2\r~1
)?vv>1+:&:&=?;:[{::nao}]$}l1-[01+}:l3-$%$l1-@@-{$[{~l1
3.\ ff+
!?:<]-1v
~]{43. >

我只想说几句话...

……“我的大脑疼。”


说明

> <>是2D深奥的编程语言,由于缺少数组,因此绝对不适合此任务。实际上,> <>中唯一的数据类型是int / float / char的奇怪混合,并且一切都发生在堆栈中。

以下是摘要:

Line 1:            i2+:&:*1\

i2+:&              Read a char as input (n) and add 2, copying n+2 into the register
:*                 Duplicate and multiply, giving (n+2)^2 on the stack
1\                 Push 1 and go to the next line

Line 2:            >l{:})?v:2+

l{:})?v            Go to the next line if the stack's length is greater than (n+2)^2
:2+                Otherwise duplicate the top of the stack and add 2 to it

Line 3:            \r~1nao2

r~                 Reverse the stack and pop; stack contains the first (n+2)^2 odd integers
1nao               Print 1 (special case)
2\                 Push 2 (let's call this "i" for "iterations") and go to the next line

Line 4:            >1+:&:&=?;:[{::nao}]$}l1-[01+}:l3-$%$l1-@@-{$[{~l1)?vv

1+                 Increment i
:&:&=?;            If i is equal to n+2 (+2 because we started at 2), halt
:[{::nao}]$}       Print the i-th element down (the next lucky number) and also
                   copy it to the top of the stack, while moving i to the bottom
l1-[               Move everything but i to a new stack
0                  Push 0 (let's call this "r" for recursion depth)

Sieve loop:

1+                 Increment r
}:l3-$%$l1-@@-{$[  Move everything up to the last element to be sieved out to a new stack
{~                 Remove said last element
1)?vv              If the length is 1, go to line 6 (sieving complete)
                   Otherwise go to line 5, which repeats this sieve loop by teleporting

Line 6:            :?!v1-]

:?!v1-]            Keep unrolling and decrementing r until r is 0

Line 7:            >~]{43.             

~]                 Pop r and unroll once more (to the stack where i waits)
43.                Loop, performing everything from line 4 all over again

这是一个模拟示例,大致演示了筛分的工作原理(这k是我们筛分的幸运数字):

[[15 13 11 9 7 5 3 1 k=3 r=0]]     -- move -->
[[15 13] [11 9 7 5 3 1 k=3 r=1]]   -- pop  -->
[[15 13] [9 7 5 3 1 k=3 r=1]]      -- move -->
[[15 13] [9 7] [5 3 1 k=3 r=2]]    -- pop  -->
[[15 13] [9 7] [3 1 k=3 r=2]]      -- move -->
[[15 13] [9 7] [3 1] [k=3 r=3]]    -- pop  -->
[[15 13] [9 7] [3 1] [r=3]]        (now we unroll)

7
仍然比Java更好;)
Optimizer

5
我喜欢这个事实,nao显然可以将其解释为“立即打印此东西”。
Zgarb 2015年

10

果酱-25

Lri{1$W%{1$\(1e>/+}/)+}/p

在线尝试

说明:

此实现不会从数组中连续删除数字,而是根据在删除之前要删除的数字来计算每个数字。
对于每个索引i(从0到n-1)和每个先前的幸运数字l,我们以相反的顺序将i递增i /(l-1),除了l = 1之外,我们使用1而不是0,并添加末尾为1。
例如,对于i = 4,我们拥有前4个数字[1 3 7 9],并计算:
4 + 4 /(9-1)= 4
4 + 4 /(7-1)= 4
4 + 4 /(3 -1)= 6
6 + 6/1 = 12
12 +1 = 13

L              empty array - the first 0 lucky numbers :)
ri             read and convert to integer (n)
{…}/           for each number (i) from 0 to n-1
    1$         copy the previous array
    W%         reverse the order
    {…}/       for each array element (l)
        1$     copy i
        \(     swap with l and decrement l
        1e>    use 1 if l=1
        /+     divide and add to i
    )+         increment and add the new lucky number to the array
p              pretty print

有趣的技术:)
TheNumberOne

6

Pyth:23 22字节

<u-G%@GhH+0GQ%2r1^hQ2Q

在线尝试:Pyth编译器/执行器

说明:

<u-G%@GhH+0GQ%2r1^hQ2Q    Q = input()
             %2r1^hQ2     create the list [1, 2, ..., (Q+1)^2-1][::2]
 u          Q%2r1^hQ2     G = [1, 2, ..., (Q+1)^2-1][::2]
                           modify G for each H in [0, 1, 2, ..., Q]:
  -G%:GhH+0G                  G = G - ([0] + G)[::G[H+1]]
                               (minus is remove in Pyth)
<                    Q    print the first Q elements of the resulting list

减少实际上计算的不仅仅是Q幸运数字(remove命令称为Q + 1次,Q-1应该足够了)。


5

R,58个字节

n=scan();s=r=1:n^2;for(j in 1:n)r=r[-max(2,r[j])*s];r[1:n]

带换行符:

n=scan()              #user input
s=r=1:n^2             #declare r and s simultaneously, both large enough to sieve
for(j in 1:n)
  r=r[-max(2,r[j])*s] #iteratively remove elements by position in vector
r[1:n]                #print

先前版本,62字节

function(n){
  s=r=1:n^2             #declare r and s simultaneously, both large enough to sieve
  for(j in 1:n)
    r=r[-max(2,r[j])*s] #iteratively remove elements by position in vector
  r[1:n]                #print
}

先前版本,78字节

n=as.numeric(readline())   #ask for user input and convert it to numeric
r=1:n^2                    #create a large enough vector to sieve
for(j in 1:n){             #loop
  r=r[-max(2,r[j])*1:n^2]  #iteratively remove elements by position in vector
}
r[1:n]                     #print

64个字节:更改n=as.numeric(readline())function(n){...}。这将创建一个可以分配和调用的功能对象。将花括号放在for循环中。
Alex A.

谢谢@Alex!虽然是66,但由于需要名称?
freekvd

提交时不需要名称。参见Matlab / Octave解决方案。R函数对象类似于其他语言中的未命名/ lambda函数,它们是有效的提交。
Alex A.

n=scan(n=1)
koekenbakker,2015年

2
这样可行!而且少了1个字符。如果我删除n = 1,它甚至更短,该函数将忽略第一个之后的n的所有元素。
freekvd15年

4

CJam,32个 30字节

3ri:N#,N{0\__I1e>)=%-+}fI(;N<p

接受来自STDIN的输入。

代码说明

3ri:N#,                          "Read the input in N and get first 3^N whole numbers";
       N{0\__I1e>)=%-+}fI        "Run the code block N times, storing index in I";
         0\__                    "Put 0 before the array and take 2 copies";
             I1e>)=              "Take min(2, I + 1) th index from the copy";
                   %             "Take every array[ min (2, I + 1)] element from the array";
                    -+           "Remove it from the list and prepend 0 to the list";
                         (;N<p   "Print number index 1 to N";

在这里在线尝试


4

Python 2中,105个 101字节

n=input()
L=range(-1,n*n+9,2)
i=2
while L[i:]:L=sorted(set(L)-set(L[L[i]::L[i]]));i+=1
print L[1:n+1]

只是一个简单的实现。

Pyth,39 36 35 32字节

J%2r1h^Q2VJI>JhN=J-J%@JhN+2J;<JQ

与上面的方法类似,但是事物是从0索引而不是1索引。在线尝试

感谢@Jakube指出节省了字节。


3

Mathematica,80个字节

(For[l=Range[#^2];i=1,(m=l[[i++]]~Max~2)<=Length@l,l=l~Drop~{m,-1,m}];l[[;;#]])&

定义的直接实现。与其他一些答案一样,从范围从1到开始,然后继续过滤。n2


3

Perl,86 81 78

86:

@a=(1..($k=<>)**2);for$n(@a){$i=1;@a=map{$i++%($n+($n<2))?$_:()}@a;$k-=$k&&print"$n "}

更新:显然,grep{...}它比map{...?$_:()} 81好:

@a=(1..($k=<>)**2);for$n(@a){$i=1;@a=grep{$i++%($n+($n<2))}@a;$k-=$k&&print"$n "}

更新:好的,现在实际上是单线的。我可以停下来 (?)78:

@a=(1..($k=<>)**2);for$n(@a){$k-=$i=$k&&print"$n ";@a=grep{$i++%($n+=$n<2)}@a}

3

八度,139 83 72

function r=l(n)r=1:2:n^2;for(i=2:n)h=r(i);r(h:h:end)=[];end;r=r(1:n);end

取消高尔夫:

function r=l(n)
  r=1:2:n^2;
  for(i=2:n)
    h=r(i);
    r(h:h:end)=[];
  end
r=r(1:n);  # reduce it to only N lucky numbers
end

2

J,60 52字节

   ({.}.@((>:@{.,]#~0<({~{.)|i.@#)@]^:[2,1+2*i.@*:@>:)) 8
1 3 7 9 13 15 21 25

说明(从右到左):

2,1+2*i.@*:@>:  generates the list 2 1 3 5 7 9... with (n+1)^2 odd numbers
^:[             repeats n times the following
@]                using the list
0<({~{.)|i.@#     is the remainder of the indexes of the lists elements with the first element positive (i.e. index divisible by first element)
]#~               keep those elements from the list
>:@{.,            concatenate a first element with the value of the current one +1
}.@             drop first element
{.              take the first n element

2,1+2*i.@*:@>:似乎太长了,但是我只能将其缩短1个字节,*:!使列表呈指数增长。


2

JavaScript(ES6)96 99

编辑在第一个循环中倒数-谢谢@DocMax

F=n=>(i=>{
  for(o=[1];--i;)o[i]=i-~i;
  for(;++i<n;)o=o.filter((x,j)=>++j%o[i]);
})(n*n)||o.slice(0,n)

不打高尔夫球

F=n=>{
  for (i = n*n, o = [1]; --i;)
    o[i] = i+i+1;
  for (; ++i < n; )
    o = o.filter((x, j) => (j+1) % o[i])
  return o.slice(0,n)
}

在Firefox / FireBug控制台中测试

F(57)

输出量

[1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99, 105, 111, 115, 127, 129, 133, 135, 141, 151, 159, 163, 169, 171, 189, 193, 195, 201, 205, 211, 219, 223, 231, 235, 237, 241, 259, 261, 267, 273, 283, 285, 289, 297, 303]

1
您可以通过在第一个循环中向下计数并在第二个循环中向上计数来保存1:F=n=>{for(o=[1],i=n*n;--i;)o[i]=2*i+1;for(;++i<n;o=o.filter((x,j)=>++j%o[i]));return o.slice(0,n)}
DocMax

您的空手在这里真的无济于事:P;)
Optimizer

@Optimizer ungolfed更新-也许仍然没有多大帮助,但至少现在的工作
edc65

我的意思是更多有关“仅格式更改将无济于事,请提供评论:)”的内容
Optimizer

2

Matlab,104个字节

function x=f(n)
k=1;N=n;x=0;while nnz(x)<n
x=1:N;m=1;while m-nnz(x)
m=x(x>m);x(m:m:end)=[];end
N=N+2;end

感谢@flawr提供了非常适当的意见和建议。

Matlab命令提示符下的示例:

>> f(40)
ans =
  Columns 1 through 22
     1     3     7     9    13    15    21    25    31    33    37    43    49    51    63    67    69    73    75    79    87    93
  Columns 23 through 40
    99   105   111   115   127   129   133   135   141   151   159   163   169   171   189   193   195   201

谢谢!我过去曾经用过,但往往会忘记
Luis Mendo 2015年

@flawr好点。这个答案比我的答案更重要!:-)
Luis Mendo

当然!我经常在StackOverflow上闲逛,但是那里的精神是一样的。我很感激!
路易斯·门多

好点子!我不确定我正在学习的所有内容对我的标准Matlab使用是否有帮助或实际上有害:-P
Luis Mendo 2015年

2
好吧,代码高尔夫与使用无关,而是与语言的滥用有关^^
漏洞

1

Bash + coreutils,136

我希望能再打下去,但是哦。并非每天都在shell脚本中传递给递归函数:

f(){
mapfile -tn$2 a
(($1>$2))&&{
tr \  \\n<<<${a[@]}
sed $[${a[-1]}-$2]~${a[-1]}d
}|f $1 $[$2+1]||echo ${a[@]}
}
yes|sed -n 1~2=|f $1 2

输出:

$ ./lucky.sh 23
1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99
$ 

Bash + coreutils,104

使用更直接的实现来缩短:

a=(`seq 1 2 $[3+$1**2]`)
for((;i++<$1;));{
a=($(tr \  \\n<<<${a[@]}|sed 0~${a[i]}d))
}
echo ${a[@]:0:$1}

1

出发326

package main
import"fmt"
func s(k, p int,in chan int)chan int{
    o := make(chan int)
    go func(){
        for p>0{
            o<-<-in;p--
        }
        for{
            <-in
            for i:=1;i<k;i++{o<-<-in}
        }
    }()
    return o
}
func main(){
    n := 20
    fmt.Print(1)
    c := make(chan int)
    go func(c chan int){
        for i:=3;;i+=2{c<-i}
    }(c)
    for i:=1;i<n;i++{
        v := <-c
        fmt.Print(" ", v)
        c = s(v, v-i-2, c)
    }
}

使用goroutine和管道制作筛子的直接实现。


7
此Code Golf,请添加一个字节数。
edc65

1

MATLAB,62个字符

n=input('');o=1:2:n^2;for i=2:n;o(o(i):o(i):end)=[];end;o(1:n)

一开始我误解了挑战-我的修订版实际上缩短了。


0

球拍196字节

产生高达n的幸运数字:

(λ(n)(let loop((l(filter odd?(range 1 n)))(i 1))(define x(list-ref l i))(set! l(for/list((j(length l))
#:unless(= 0(modulo(add1 j)x)))(list-ref l j)))(if(>= i(sub1(length l)))l(loop l(add1 i)))))

非高尔夫版本:

(define f
 (λ(n)
    (let loop ((l (filter odd? (range 1 n))) (i 1))
      (define x (list-ref l i))
      (set! l (for/list ((j (length l)) #:unless (= 0 (modulo (add1 j) x)))
                (list-ref l j)))
      (if (>= i (sub1 (length l)))
          l
          (loop l (add1 i)))))
  )

测试:

(f 100)

输出:

'(1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99)
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.