Cetak dan nomor ganjil

12

Angka aneh adalah angka dimana jumlah pembagi yang tepat lebih besar dari jumlah itu sendiri dan tidak ada bagian dari pembagi yang tepat jumlah ke nomor itu.

Contoh:

70 adalah angka aneh karena pembagi yang tepat (1, 2, 5, 7, 10, 14, dan 35) berjumlah 74, yang lebih besar dari 70, dan tidak ada kombinasi angka-angka ini yang berjumlah 70.

18 bukan angka aneh karena pembagi yang tepat (1, 2, 3, 4, 6, 9) berjumlah 25, yang lebih besar dari 18, tetapi 3, 6, dan 9 berjumlah 18.

Tugas Anda adalah untuk menulis program terpendek yang input melalui std-in sejumlah n dan menghitung dan mencetak ke file atau std-out pertama n nomor aneh dengan pemisahan baris baru. Tidak ada pengkodean keras atas jawaban yang diizinkan (maaf karena tidak menentukan ini di awal).

Untuk lebih banyak contoh, lihat halaman ini: http://mathworld.wolfram.com/WeirdNumber.html


sumber
1
Ketika pertanyaan ini ada di kotak pasir, saya tidak berkomentar bahwa Anda harus menambahkan aturan "no-hard-coding" karena sudah ada di kata "menghitung". Saya mendorong orang-orang untuk downvote dan menandai sebagai jawaban yang tidak menjawab atau berkualitas rendah yang tidak mencoba untuk menghitung hasilnya. ( Diskusi meta yang relevan ).
Peter Taylor

Jawaban:

2

Mathematica 99 94 87 87

Spasi tidak diperlukan. Lambat!:

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

Dengan mengorbankan beberapa karakter, ini adalah versi yang lebih cepat yang hanya memeriksa angka genap dan melompati kelipatan 6yang tidak pernah aneh:

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

masih terlalu lambat untuk tujuan apa pun yang bermanfaat. Menemukan dua yang pertama dalam beberapa detik tetapi menjadi lebih lambat dan lebih lambat karena jumlah pembagi meningkat.

Belisarius
sumber
Saya mengutak-atik solusi serupa mengeksploitasi fakta bahwa angka-angka aneh tidak pseudoperfect, tetapi Anda mendapatkannya jauh lebih golf daripada yang saya berhasil. Sangat bagus!
Jonathan Van Matre
@JonathanVanMatre Terima kasih :)
Dr. belisarius
4

Haskell - 129

Saya yakin ada banyak golf di sini, tetapi karena kompetisi tampaknya rendah untuk saat ini saya akan memasukkan ini.

Jangan coba-coba menjalankan ini, saya hanya bisa menunggu dua elemen pertama, ketiga akan mulai mengambil menit.

(%)=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)
shiona
sumber
1
Itu kedua kalinya seseorang di Haskell lebih baik daripada saya di Sage, sialan: 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
Elisa
sumber
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";}

Dan inilah kode sumber aslinya:

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

Anda akan mencatat bahwa butuh beberapa waktu untuk menampilkan angka-angka karena sedang melakukan verifikasi brute-force (Anda harus mencapai 70 dengan sangat cepat).

Razvan
sumber
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}

Versi tidak golf:

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
}

Ini membutuhkan waktu karena kekuatan kasar.

Sven Hohenstein
sumber
1

Ruby - 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 Dengan 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}

Sangat lambat dan saya hampir yakin masih ada ruang untuk bermain golf ...

fgp
sumber
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

memasukkan:

1000

keluaran:

70
836
blabla999
sumber
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

Lebih dari itu bahkan tidak golf, tidak ada terlalu banyak golf di dalam kode. Yang terbesar adalah Anda harus melakukan tes 2*x>=sum(l)terlebih dahulu, itu akan menghemat banyak waktu perhitungan. Kita harus menyadari bahwa maxpada boolean adalah yang orkedua w(x)adalah Falseuntuk bilangan ganjil dan Trueuntuk bilangan non-ganjil. Versi tidak disatukan:

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
yo'
sumber
1

C ++ - 458

Ini bukan semua solusi saya karena saya harus meminta SO untuk membantu menghitung jumlah himpunan bagian, tetapi yang lainnya milik saya:

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

Versi panjang:

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

Saat ini hanya menghitung dua yang pertama (70 dan 836). Saya membunuhnya setelah itu.


sumber
Akan lebih baik untuk memposting versi yang dapat dibaca juga, terutama karena Anda menjadikannya sebagai one-liner;)
yo '
@tohecz Tentu, izinkan saya mengeditnya.
@tohecz saya sudah selesai.
1

Perl, 173

Biarkan saya menambahkan solusi lain yang tidak berguna. Solusi ini sangat lambat sehingga bahkan tidak bisa menghasilkan apa pun melewati angka ganjil pertama. Saya berani mengatakan itu adalah yang paling lambat dari semua solusi di sini.

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

Demo

Kode yang sama ditulis dalam Java (yang saya lebih nyaman dengan) bahkan tidak dapat mengenali nomor aneh ke-2 (836), dan saya sudah memberi makan nomor langsung ke metode pemeriksaan (alih-alih perulangan dan memeriksa setiap nomor).

Inti dari solusi ini terletak pada regex:

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

Dan bagaimana string diatur menjadi 3 kali angka yang kita periksa.

Panjang string diatur menjadi 3 kali angka yang kami periksa i: 2 pertama iuntuk mencocokkan jumlah faktor dan 1 terakhir idicadangkan untuk memeriksa apakah angka merupakan faktor i.

(?=(.+)\1{2}$) digunakan untuk menangkap nomor yang kami periksa.

((.+)(?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$))(?=.*(?=\1$)\3+$))+cocok dengan faktor-faktor nomor. Nanti iterasi akan cocok dengan faktor yang lebih kecil dari iterasi sebelumnya.

  • Kita dapat melihat bahwa 2 bagian ini (.+)dan (?=.*(?=\1$)\3+$)bersama - sama memilih faktor jumlah yang diperiksa.
  • (?=.*(?(2)(?=\2$)\3.+$|(?=\1$)\3.+$)) memastikan bahwa faktor yang dipilih lebih kecil dari jumlah yang diperiksa dalam iterasi pertama, dan lebih kecil dari faktor sebelumnya dalam iterasi berikutnya.

Regex mencoba untuk mencocokkan sebanyak mungkin faktor angka yang ada dalam batas 2 i. Tapi kami tidak peduli tentang nilai sebenarnya dari jumlah pembagi, kami hanya peduli apakah jumlahnya banyak.

Kemudian regex ke-2, yang merupakan regex pertama dengan \1{2}$ditambahkan. Akibatnya, regex memastikan jumlah (beberapa) faktor dari jumlah yang diperiksa sama dengan jumlah itu sendiri:

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

Batasan yang ditambahkan akan menyebabkan mesin regex melakukan penelusuran mundur pada semua subset faktor yang mungkin, sehingga akan sangat lambat.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
sumber
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++}

Jumlah angka aneh diharapkan dalam STDIN dan angka yang ditemukan dicetak ke STDOUT.

Versi tidak disatukan

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

Keterbatasan

  • Lambat, kekuatan kasar.
  • Hitungan pembagi untuk angka terbatas pada "bitness" dari bilangan bulat di Perl.
Heiko Oberdiek
sumber