In n số lạ


12

Một số lạ là một số mà tổng các ước số thích hợp lớn hơn chính số đó và không có tập con nào của các ước số thích hợp tổng với số đó.

Ví dụ:

70 là một số lạ bởi vì các ước số thích hợp của nó (1, 2, 5, 7, 10, 14 và 35) tổng bằng 74, lớn hơn 70 và không có sự kết hợp nào của các số này với 70.

18 không phải là một con số kỳ lạ bởi vì các ước số thích hợp của nó (1, 2, 3, 4, 6, 9) tổng bằng 25, lớn hơn 18, nhưng 3, 6 và 9 tổng thành 18.

Nhiệm vụ của bạn là viết chương trình ngắn nhất mà đầu vào thông qua std-in bất kỳ số n và tính toán và in vào một tập tin hoặc std-out đầu tiên n số lạ với phân tách dòng mới. Không có mã hóa cứng của các câu trả lời được cho phép (xin lỗi vì đã không chỉ định điều này ngay từ đầu).

Để biết thêm ví dụ, xem trang này: http://mathworld.wolfram.com/ WeirdNumber.html


1
Khi câu hỏi này nằm trong hộp cát, tôi đã không nhận xét rằng bạn nên thêm quy tắc "không mã hóa cứng" vì nó đã có sẵn từ "tính toán". Tôi khuyến khích mọi người hạ cấp và gắn cờ là câu trả lời không có chất lượng hoặc chất lượng thấp cho bất kỳ câu trả lời nào không cố gắng tính kết quả. ( Thảo luận meta có liên quan ).
Peter Taylor

Câu trả lời:


2

Toán học 99 94 87

Không gian không cần thiết. Chậm!:

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

Với chi phí của một vài ký tự, đây là phiên bản nhanh hơn, chỉ kiểm tra các số chẵn và bỏ qua bội số 6không bao giờ là lạ:

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

nó vẫn còn quá chậm cho bất kỳ mục đích hữu ích nào. Tìm hai số đầu tiên trong vài giây nhưng càng ngày càng chậm khi số lần chia tăng.


Tôi đã loay hoay với một giải pháp tương tự khai thác thực tế là những con số kỳ lạ không phải là giả, nhưng bạn đã hiểu nó nhiều hơn tôi đã từng quản lý. Rất đẹp!
Jonathan Van Matre

@JonathanVanMatre Cảm ơn bạn :)
Tiến sĩ belisarius

4

Haskell - 129

Tôi chắc chắn có rất nhiều để chơi golf ở đây, nhưng vì sự cạnh tranh có vẻ thấp nên bây giờ tôi sẽ ném nó vào.

Đừng thử chạy cái này, tôi chỉ đợi hai yếu tố đầu tiên, thứ ba sẽ bắt đầu mất vài phút.

(%)=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
Đó là lần thứ hai ai đó ở Haskell tốt hơn tôi ở Sage, chết tiệt: D
yo '

2

Python 2.7 (255 byte)

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 byte

$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";}

Và đây là mã nguồn gốc:

$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";
}

Bạn sẽ lưu ý rằng phải mất một thời gian để xuất các số vì nó đang thực hiện xác minh bạo lực (tuy nhiên bạn sẽ nhận được tới 70 khá nhanh).


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}

Phiên bản không chơi gôn:

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
}

Điều này mất một thời gian do sức mạnh vũ phu.


1

Hồng ngọc - 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}

Ruby Với ActiveSupport - 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}

Thực sự rất chậm và tôi gần như chắc chắn vẫn còn chỗ để chơi gôn ...


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

đầu vào:

1000

đầu ra:

70
836

1

SageMath: 143 131 byte

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

Nó thậm chí còn không được đánh gôn, không có quá nhiều để chơi golf trong mã. Điều lớn nhất là bạn nên làm bài kiểm tra 2*x>=sum(l)trước, nó sẽ tiết kiệm rất nhiều thời gian tính toán. Người ta phải nhận ra rằng maxtrên booleans là orĐiều thứ hai w(x)Falsedành cho những số lạ và những số Truekhông lạ. Phiên bản bị đánh cắp:

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

Đây không phải là tất cả giải pháp của tôi vì tôi đã phải yêu cầu SO giúp đỡ tính toán tổng của các tập hợp con, nhưng mọi thứ khác là của tôi:

#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++;}}

Phiên bản dài:

#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++;
    }
}

Hiện tại nó chỉ tính được hai số đầu tiên (70 và 836). Tôi đã giết nó sau đó.


Sẽ rất tốt để đăng một phiên bản có thể đọc được, đặc biệt là khi bạn thực hiện dưới dạng một lớp lót;)
yo '

@tohecz Chắc chắn, hãy để tôi chỉnh sửa nó.

@tohecz Tôi xong rồi.

1

Perl, 173

Hãy để tôi thêm một giải pháp vô dụng. Giải pháp này chậm đến mức thậm chí không thể xuất ra bất cứ thứ gì qua số lạ đầu tiên. Tôi dám nói đó là cách chậm nhất trong tất cả các giải pháp ở đây.

$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++}

Bản giới thiệu

Mã tương tự được viết bằng Java (mà tôi thấy thoải mái hơn) thậm chí không thể nhận ra số lạ thứ 2 (836) và tôi đã đưa số trực tiếp vào phương thức kiểm tra (thay vì lặp và kiểm tra mọi số).

Cốt lõi của giải pháp này nằm trong regex:

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

Và cách chuỗi được thiết lập gấp 3 lần số mà chúng tôi đang kiểm tra.

Độ dài của chuỗi được thiết lập bằng 3 lần số mà chúng tôi đang kiểm tra i: 2 đầu tiên ilà để tổng hợp các yếu tố và 1 cuối cùng iđược dành riêng để kiểm tra xem một số có phải là một yếu tố hay không i.

(?=(.+)\1{2}$) được sử dụng để nắm bắt số lượng mà chúng tôi đang kiểm tra.

((.+)(?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$))(?=.*(?=\1$)\3+$))+phù hợp với các yếu tố của số lượng. Lặp lại sau sẽ phù hợp với một yếu tố nhỏ hơn so với lần lặp trước đó.

  • Chúng ta có thể thấy rằng 2 phần này (.+)(?=.*(?=\1$)\3+$)cùng nhau chọn một yếu tố của số được kiểm tra.
  • (?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$)) đảm bảo rằng hệ số được chọn nhỏ hơn số được kiểm tra trong lần lặp đầu tiên và nhỏ hơn hệ số trước trong các lần lặp tiếp theo.

Regex cố gắng khớp nhiều yếu tố của số có thể trong giới hạn 2 i. Nhưng chúng tôi không quan tâm đến giá trị thực của tổng các ước, chúng tôi chỉ quan tâm xem số lượng có nhiều không.

Sau đó, regex thứ 2, là regex đầu tiên \1{2}$được thêm vào. Do đó, biểu thức chính quy đảm bảo tổng (một số) yếu tố của số được kiểm tra bằng chính số đó:

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

Ràng buộc được thêm vào sẽ khiến công cụ regex thực hiện tìm kiếm quay lui trên tất cả các tập hợp con của các yếu tố có thể, vì vậy nó sẽ cực kỳ chậm.


1

Perl, 176 174 byte

$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++}

Số lượng các số lạ được mong đợi trong STDIN và các số được tìm thấy được in thành STDOUT.

Phiên bản ung dung

#!/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__

Hạn chế

  • Chậm, vũ phu.
  • Số lượng các ước cho một số được giới hạn ở "bitness" của các số nguyên trong Perl.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.