n個の奇妙な数字を印刷する


12

奇妙な数とは、適切な約数の合計が数自体より大きく、適切な約数のサブセットがその数に加算されない数です。

例:

70は、その適切な除数(1、2、5、7、10、14、および35)の合計が70を超える74であり、これらの数値の合計が70にならないため、奇妙な数字です。

18は、適切な除数(1、2、3、4、6、9)の合計が25であり、18より大きいが、3、6、および9の合計が18であるため、奇妙な数字ではありません。

あなたのタスクは、std-inで任意の数nを入力し、計算してファイルに出力するか、改行区切りで最初のn個の奇妙な数字をstd-outする最も短いプログラムを書くことです。回答のハードコーディングは許可されていません(最初にこれを指定しなかったため申し訳ありません)。

他の例については、次のページを参照してください:http : //mathworld.wolfram.com/WeirdNumber.html


1
この質問がサンドボックスにあったとき、「計算する」という言葉の中に既にあるので、「ハードコーディングなし」のルールを追加すべきだとコメントしませんでした。私は、結果を計算しようとしない回答に対して、非投票または低品質のフラグを立て、フラグを立てることを推奨します。(関連するメタディスカッション)。
— ピーターテイラー14

回答:


2

Mathematica 99 94 87

スペースは必要ありません。スロー!:

j = i = 0;
While[j<#, i++; If[Union@Sign[Tr /@ Subsets@Most@Divisors@i-i]=={-1, 1}, j++; Print@i]]&

数文字を犠牲にして、これは偶数のみをチェックし、6それの倍数をスキップする奇妙なことのない高速バージョンです:

j = i = 0;
While[j < #, 
      i += 2; If[Mod[i, 6] != 0 && Union@Sign[Tr /@ Subsets@Most@Divisors@i - i] == {-1, 1}, 
                 j++; Print@i]] &@3

有用な目的にはまだ遅すぎます。数秒で最初の2つを見つけますが、除数の数が増えるにつれて、徐々に遅くなります。


奇妙な数字は擬似完璧ではないという事実を利用して、同様の解決策をいじっていましたが、あなたは私がまだ管理できなかったよりもはるかにゴルファーになりました。非常に素晴らしい!
— ジョナサンヴァンマトレ14

@JonathanVanMatreありがとう:)
— ベリサリウス博士14

4

ハスケル-129

ここにはゴルフがたくさんあると確信していますが、今のところ競争が少ないように見えるので、これを投げ込みます。

ただし、これを実行しようとしないでください。最初の2つの要素のみを待機し、3番目の要素は数分かかります。

(%)=filter
w n=take n$e%[1..]
e x=let d=((==0).mod x)%[1..x-1]in sum d>x&&all((/=x).sum)(i d)
i[]=[[]]
i(y:z)=map(y:)(i z)++(i z)

1
Haskellの誰かがSageの私よりも優れているのは2度目です。いまいましい:D
— yo

2

Python 2.7(255バイト)

import itertools as t
a=int(raw_input())
n=1
while a>0:
    d=[i for i in range(1,n/2+1) if not n%i]
    if all([n not in map(sum,t.combinations(d,i)) for i in range(len(d))]+[sum(d)>n]):
        print n
        a-=1
    n+=1

1

PHP、267バイト

$n=$x=0;while($n<$argv[1]){$x++;for($i=1,$s=0,$d=array();$i<$x;$i++){if($x%$i){continue;}$s+=$i;$d[]=$i;}if($s<$x){continue;}$t=pow(2,$m=count($d));for($i=0;$i<$t;$i++){for($j=0,$s=0;$j<$m;$j++){if(pow(2,$j)&$i){$s+=$d[$j];}}if($s==$x){continue 2;}}$n++;print"$x\n";}

元のソースコードは次のとおりです。

$n = 0;
$x = 0;

while ($n < $argv[1]) {
    $x++;

    for ($i = 1, $sum = 0, $divisors = array(); $i < $x; $i++) {
        if ($x % $i) {
            continue;
        }

        $sum += $i;
        $divisors[] = $i;
    }

    if ($sum < $x) {
        continue;
    }

    $num = count($divisors);
    $total = pow(2, $num);

    for ($i = 0; $i < $total; $i++) {  
        for ($j = 0, $sum = 0; $j < $num; $j++) { 
            if (pow(2, $j) & $i) {
                $sum += $divisors[$j];
            }
        }

        if ($sum == $x) {
            continue 2;
        }
    }

    print "$x\n";
}

ブルートフォース検証を実行しているため、数値を出力するのに時間がかかることに注意してください(ただし、70に達するのはかなり速いはずです)。


1

R、164

r=0;x=1;n=scan();while(r<n){i=which(!x%%(2:x-1));if(sum(i)-1&&!any(unlist(lapply(2:sum(i|T),function(o)colSums(combn(i,o))==x)))&sum(i)>x){r=r+1;cat(x,"\n")};x=x+1}

非ゴルフバージョン:

r = 0
x = 1
n = scan()
while(r < n) {
  i = which(!x %% (2:x - 1))
  if( sum(i) - 1 &&
       !any(unlist(lapply(2:sum(i | T),
                          function(o) colSums(combn(i, o)) == x))) &
       sum(i) > x
     ){ r = r + 1
        cat(x, "\n")
  }
  x = x + 1
}

これにはブルートフォースのために時間がかかります。


1

ルビー-152

x=2;gets.to_i.times{x+=1 while((a=(1..x/2).find_all{|y|x%y==0}).reduce(:+)<=x||(1..a.size).any?{|b|a.combination(b).any?{|c|c.reduce(:+)==x}});p x;x+=1}

ActiveSupportを使用したRuby-138

x=2;gets.to_i.times{x+=1 while((a=(1..x/2).find_all{|y|x%y==0}).sum<=x||(1..a.size).any?{|b|a.combination(b).any?{|c|c.sum==x}});p x;x+=1}

本当に遅いし、ゴルフの余地はまだあると確信しています...


1

Smalltalk、143

((1to:(Integer readFrom:Stdin))reject:[:n||d|d:=(1to:n//2)select:[:d|(n\\d)=0].d sum<n or:[(PowerSet for:d)contains:[:s|s sum=n]]])map:#printCR

入力:

1000

出力:

70
836

1

SageMath:143 131バイト

x=1
def w():
 l=x.divisors()
 return 2*x>=sum(l)or max(2*x==sum(i)for i in subsets(l))
while n:
 while w():x+=1
 print x;n-=1;x+=1

それはさらに、ゴルフをしていなくても、コードでとにかくゴルフするのはあまりありません。最大のことは、2*x>=sum(l)最初にテストを行う必要があることです。これにより、計算時間が大幅に節約されます。一つは、ということを理解しなければならないmaxブール値であるor第二事はつまりw(x)あるFalse不思議数のためとTrue非不思議数のために。ゴルフされていないバージョン:

def w(x) :
 Divisors = x.divisors()
 return 2*x >= sum(Divisors) or max ( sum(SubS) == 2*x for SubS in subsets(Divisors) )

x=1

for k in xrange(n) :
 while w(x) : x += 1
 print x
 x += 1

1

C ++-458

サブセットの合計を計算するためにSOに頼まなければならなかったので、これは私のすべてのソリューションではありませんが、他のすべては私のものです:

#include<iostream>
#include<vector>
using namespace std;
#define v vector<int>
#define r return
#define c const_iterator
v x(int i){v d;for(int k=1;k<i;k++)if(i%k==0)d.push_back(k);r d;}bool u(v::c i,v::c e,int s){if(s==0)r 0;if(i==e)r 1;r u(i+1,e,s-*i)&u(i+1,e,s);}bool t(v&d,int i){bool b=u(d.begin(),d.end(),i);if(b)cout<<i<<endl;r b;}int main(){v d;int n;cin>>n;for(int i=2,j=0;j<n;i++){d=x(i);int l=0;for(int k=0;k<d.size();k++)l+=d[k];if(l>i)if(t(d,i))j++;}}

ロングバージョン:

#include<iostream>
#include<vector>
using namespace std;

vector<int> divisors(int i) {

    vector<int> divs;
    for(int k = 1; k < i; k++)
        if(i%k==0)
            divs.push_back(k);
    return divs;
}

bool u(vector<int>::const_iterator vi, vector<int>::const_iterator end, int s) {

    if(s == 0) return 0;
    if(vi == end) return 1;
    return u(vi + 1, end, s - *vi) & u(vi + 1, end, s);
}

bool t(vector<int>&d, int i) {

    bool b = u(d.begin(), d.end(), i);
    if(b) cout<< i << endl;
    return b;
}

int main() {

    vector<int> divs;
    int n;
    cin>>n;

    for(int i = 2, j = 0; j < n; i++) {
        divs = divisors(i);

        int sum_divs = 0;
        for(int k = 0; k < divs.size(); k++)
            sum_divs += divs[k];

        if(sum_divs > i)
            if(t(divs, i))
                j++;
    }
}

現在、最初の2つ(70と836)のみを計算しています。その後、私はそれを殺しました。


特にワンライナーとして作成しているため、読みやすいバージョンを投稿するのもいいでしょう;)
— yo

@tohecz確かに、編集させてください。

@toheczできました。

1

Perl、173

別の役に立たないソリューションを追加しましょう。このソリューションは非常に遅いため、最初の奇妙な数値を超えて出力することさえできません。ここでのすべてのソリューションの中で最も遅いと言ってよいでしょう。

$n=<>;$i=2;while($n){$b=qr/^(?=(.+)\1{2}$)((.+)(?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$))(?=.*(?=\1$)\3+$))+/;$_='x'x3x$i;if(/$b/&&($+[0]>$i)&&!/$b\1{2}$/){print"$i\n";$n--}$i++}

デモ

Javaで書かれた同じコード(私はより快適です)は2番目の奇妙な数字(836)を認識することさえできません、そして私はすでに(すべての数字をループしてチェックするのではなく)チェックメソッドに直接数字を与えました。

このソリューションの中心は正規表現にあります。

^(?=(.+)\1{2}$)((.+)(?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$))(?=.*(?=\1$)\3+$))+

そして、文字列がどのように設定されているかは、チェックする数値の3倍になります。

文字列の長さは、チェックする数値の3倍になるように設定されますi。最初の2 iは因子の合計に一致し、最後の1 iは数値が因子であるかどうかを確認するために予約されていiます。

(?=(.+)\1{2}$) チェックしている番号をキャプチャするために使用されます。

((.+)(?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$))(?=.*(?=\1$)\3+$))+数値の因子と一致します。後の反復は、前の反復よりも小さい係数に一致します。

  • 我々は、これらの2つの部分ことがわかります(.+)と(?=.*(?=\1$)\3+$)一緒にビーイングがチェック数の係数を選択します。
  • (?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$)) 選択された係数が、最初の反復でチェックされている数よりも小さく、後続の反復で以前の係数よりも小さいことを確認します。

正規表現は、2の制限内で可能な限り多くの数の因子と一致しようとしiます。ただし、除数の合計の実際の値は気にしません。数値が豊富かどうかだけを気にします。

次に、\1{2}$追加された最初の正規表現である2番目の正規表現。その結果、正規表現は、チェック対象の数値の(一部の)要因の合計が数値自体と等しくなるようにします。

^(?=(.+)\1{2}$)((.+)(?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$))(?=.*(?=\1$)\3+$))+\1{2}$

追加された制約により、正規表現エンジンは要因のすべての可能なサブセットに対してバックトラッキング検索を実行するため、非常に遅くなります。


1

Perl、176 174バイト

$n=<>;$i=9;X:while($n){@d=grep{!($i%$_)}1..$i-1;$l=0;map{$a=$_;$s=0;$s+=$d[$_]for grep{2**$_&$a}0..@d-1;$i++,next X if$s==$i;$l=1 if$s>$i}0..2**@d-1;$n--,print$i,$/if$l;$i++}

STDINには奇妙な数字の数が予想され、見つかった数字はSTDOUTに出力されます。

非ゴルフバージョン

#!/usr/bin/env perl
use strict;
$^W=1;

# read number from STDIN
my $n=<>;
# $i is the loop variable that is tested for weirdness
my $i=9; # better start point is 70, the smallest weird number
# $n is the count of numbers to find
X: while ($n) {
    # find divisors and put them in array @divisors
    my @divisors = grep{ !($i % $_) } 1 .. $i-1; # better: 1 .. int sqrt $i
    # $large remembers, if we have found a divisor sum greater than the number
    my $large = 0;
    # looping through all subsets. The subset of divisors is encoded as
    # bit mask for the divisors array.
    map {
        my $subset = $_;
        # calculate the sum for the current subset of divisors
        my $sum = 0;
        map { $sum += $divisors[$_] }
            grep { 2**$_ & $subset }
                0 .. @divisors-1;
        # try next number, if the current number is pseudoperfect
        $i++, next X if $sum == $i; # better: $i+=2 to skip even numbers
        $large = 1 if $sum > $i;
    } 0 .. 2**@divisors - 1;
    # print weird number, if we have found one
    $n--, print "$i\n" if $large;
    $i++; # better: $i+=2 to skip even numbers
}
__END__

制限事項

  • ゆっくり、総当たり。
  • 数値の除数のカウントは、Perlの整数の「ビット数」に制限されています。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.