ラッキーナンバーを生成


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つおきの数字を削除します。

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

残りの2番目の数値は3なので、3番目ごとに削除します。

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

次の残りの数字は7なので、7番目ごとに削除します。

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

次に、9番目ごとに番号を削除します。結果のシーケンスはラッキーナンバーです。

受賞:

codegolfの場合と同様に、バイト数が最も少なくなります。

いつものように、標準の抜け穴を使用した提出は失格となります。


8
最初の10個ほどの数字だけでなく、投稿に定義を含めることをお勧めします。
-xnor

クールな拡張機能は、検査される各アイテム(3、7など)に対してその回数だけその操作を実行することです。たとえば、3の場合、リストの3番目の要素を3回、7番目の要素を7回など削除します(これはシーケンスではなく、考え方は同じです)
ライアン

@Ryan私はそのシーケンスが自然数に著しく似ていると思う:)
TheNumberOne

@TheBestOneそう思う?以前math.stackexchangeに投稿しました:math.stackexchange.com/questions/1153889/…-
ライアン

@Ryan実際、私はあなたの提案を誤って解釈しました。math.seの質問でそれを述べたように、私はそれが面白いと思います。
-TheNumberOne

回答:


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、十分に高い値になります。コードはの各要素rを反復処理しL、すべてのr'th要素のサブリストを取得し、それらの各値を削除します。その結果、削除された値は繰り返し処理されません。最後に、最初のn要素を印刷します。

この表現map(A.remove,B)は、私が長い間使用するのを待っていたトリックです。のA.remove各要素を呼び出しますB。これにより、のすべての要素がBから削除されAます。のBサブリストである必要がありますが、事実上、リストの違いを取りますA。Python 3は実際にマップを評価しないため、Python 2が必要です。

からに変換rする1には2、最初のループを特殊なケースにする必要がありますr+=r<2

の上限が十分2**nに大きいため、の値が大きい場合、プログラムは非常に遅くなりますn。使用するn*n+1だけで十分ですが、コストがかかります。n*nは機能しないことに注意してくださいn=1


必要なのはn**2数字だけで、2**n
オプティマイザー

3
それはmapあなたがそこに持っている1つの驚くべき使用です。より良い方法があるかどうか疑問に思っていた
...- Sp3000

@Optimizer残念ながら、n**2+1ケースn=1が許されない限り、。
xnor

そのマップの使用は素晴らしいです。順序付きセットを使用するように。おそらくmap(A.index,B)、AのBの要素のインデックスを検索したり、AのBの要素のmap(A.count,B)数を検索したり、map(A.extend,B)平坦化されたBリストをAに追加したりするのにも使用できます。
ロジックナイト

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)thラッキーナンバーを生成し、無限テールからnすべてのnthナンバーをドロップしkp以前に生成されたナンバーを相殺するため)、accumulatorを使用してそのリストに再帰し(p+1)ます。ではf、から始まる奇数でプロセスを初期化し、先頭に3タック1し、正確にラッキーナンバーを取得します。


12

Python 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]

Sp3000のおかげで-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よりも優れています;)
オプティマイザー

5
nao「今すぐこのことを印刷する」と解釈できるという事実が好きです。
ズガルブ

10

CJam-25

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

オンラインで試す

説明:

この実装は、配列から連続して数字を削除するのではなく、その前に削除された数に基づいて各数字を計算します。
各インデックスi(0〜n-1)および以前の各ラッキーナンバーlについて、逆順で、iをi /(l-1)ずつインクリメントします。ただし、l = 1の場合は0の代わりに1を使用し、最後に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 Compiler / Executor

説明:

<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

reduceは実際に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ループに中括弧をドロップします。
アレックスA.

ありがとう@Alex!名前が必要なので、それは66ですが?
freekvd

提出のための名前は必要ありません。Matlab / Octaveソリューションをご覧ください。R関数オブジェクトは、有効な送信である他の言語の無名/ラムダ関数に似ています。
アレックスA.

どうn=scan(n=1)
koekenbakker

2
動作します!そして、1文字少ないです。n = 1をドロップすると、さらに短くなり、関数は最初のn以降のすべての要素を無視します。
freekvd

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

上記のアプローチに似ていますが、物事は1インデックスではなく0インデックスです。オンラインでお試しください

バイトの節約を指摘してくれた@Jakubeに感謝します。


3

Mathematica、80バイト

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

定義の簡単な実装。他のいくつかの答えとして、1to からの範囲で始まり、フィルタリングを続けます。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 "}

更新:OK、実際には1行でした。やめる (?)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
最初のループでカウントダウンし、2番目のループでカウントアップすることで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 ungolfedが更新されました-まだあまり役に立たないかもしれませんが、少なくとも現在は動作しています
-edc65

「フォーマットの変更は役に立たないので、コメントを入力してください:)」の行にもっと意味があります
オプティマイザー

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

ありがとう!私はそれを過去に使用しましたが、忘れがちです
ルイスメンドー

@flawr良い点。この答えは私の答えよりもあなたのものになりつつあります!:-)
ルイスメンドー

もちろん!StackOverflowに頻繁に出かけますが、それは同じ精神です。それは有り難いです!
ルイスメンドー

いい視点ね!私が学んでいるこれらすべてが私の標準的なMatlabの使用に役立つか、実際に有害であるかどうかはわかりませんが、-P
Luis Mendo

2
codegolfは使用についてではなく、言語の悪用についてです^^
flawr

1

Bash + coreutils、136

これをもっと下にゴルフしたいと思っていましたが、まあ。シェルスクリプトで再帰関数にパイプする毎日ではありません。

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

Go、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)
    }
}

ゴルーチンとパイプを使用してふるいを作成する簡単な実装。


7
このコードは、バイトカウントを追加してください。
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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.