พิมพ์ตัวเลขแปลก ๆ


12

ตัวเลขแปลก ๆ คือตัวเลขที่ผลรวมของตัวหารที่ถูกต้องมากกว่าจำนวนตัวเองและไม่มีส่วนย่อยของตัวหารที่ถูกต้องรวมกับจำนวนนั้น

ตัวอย่าง:

70 เป็นตัวเลขแปลก ๆ เนื่องจากตัวหารที่เหมาะสม (1, 2, 5, 7, 10, 14 และ 35) รวมเป็น 74 ซึ่งมากกว่า 70 และไม่มีการรวมกันของตัวเลขเหล่านี้รวมถึง 70

18 ไม่ใช่ตัวเลขแปลกเพราะตัวหารที่เหมาะสม (1, 2, 3, 4, 6, 9) รวมเป็น 25 ซึ่งมากกว่า 18 แต่ 3, 6, และ 9 รวมถึง 18

งานของคุณคือการเขียนโปรแกรมที่สั้นที่สุดที่ปัจจัยการผลิตผ่านมาตรฐานในหมายเลขใด ๆnและคำนวณและพิมพ์ไปยังแฟ้มหรือแรก STD-ออกnหมายเลขแปลกแยกกับการขึ้นบรรทัดใหม่ ไม่อนุญาตให้เขียนโค้ดคำตอบอย่างหนัก (ขออภัยที่ไม่ได้ระบุสิ่งนี้ในตอนแรก)

สำหรับตัวอย่างเพิ่มเติมดูหน้านี้: http://mathworld.wolfram.com/WeirdNumber.html


1
เมื่อคำถามนี้อยู่ในแซนด์บ็อกซ์ฉันไม่ได้แสดงความคิดเห็นว่าคุณควรเพิ่มกฎ "ไม่เข้ารหัสยาก" เพราะมีอยู่ในคำว่า "คำนวณ" แล้ว ฉันขอแนะนำให้ผู้คนลงคะแนนและตั้งค่าสถานะว่าไม่ใช่คำตอบหรือคำตอบที่มีคุณภาพต่ำซึ่งไม่ได้พยายามคำนวณผลลัพธ์ ( การสนทนาเมตาที่เกี่ยวข้อง )
Peter Taylor

คำตอบ:


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

มันยังช้าเกินไปสำหรับวัตถุประสงค์ที่มีประโยชน์ใด ๆ ค้นหาสองคนแรกในไม่กี่วินาที แต่ช้าลงและช้าลงเมื่อจำนวนตัวหารเพิ่มขึ้น


ฉันเล่นซอกับวิธีการที่คล้ายกันซึ่งใช้ประโยชน์จากความจริงที่ว่าตัวเลขแปลก ๆ นั้นไม่ได้เป็นของปลอม แต่คุณได้นักกอล์ฟมากเกินกว่าที่ฉันจะจัดการได้ ดีมาก!
Jonathan Van Matre

@JonathanVanMatre ขอบคุณ :)
ดร. เบลิซาเรีย

4

Haskell - 129

ฉันแน่ใจว่ามีสนามกอล์ฟมากมายที่นี่ แต่เนื่องจากการแข่งขันดูต่ำสำหรับตอนนี้ฉันจะโยนมันเข้าไป

อย่าพยายามเรียกใช้สิ่งนี้แม้ว่าฉันจะจัดการแค่สององค์ประกอบแรกเท่านั้นส่วนที่สามจะเริ่มใช้เวลาไม่กี่นาที

(%)=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, เจ้ากรรม: D
yo '22

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}

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

ช้าจริง ๆ และฉันเกือบจะแน่ใจว่ายังคงมีห้องสำหรับเล่นกอล์ฟ ...


1

สมอลล์ทอล์ค, 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ใน booleans คือ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++;
    }
}

ขณะนี้มีการคำนวณสองครั้งแรกเท่านั้น (70 และ 836) ฉันฆ่ามันหลังจากนั้น


มันจะดีที่จะโพสต์รุ่นที่สามารถอ่านได้เป็นอย่างดีโดยเฉพาะอย่างยิ่งนับตั้งแต่ที่คุณทำให้มันเป็นหนึ่งซับ;)
โย'

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

การสาธิต

รหัสเดียวกันที่เขียนด้วยภาษาจาวา (ซึ่งฉันรู้สึกสบายใจกว่า) ไม่สามารถจำเลขแปลกที่สองได้ (836) และฉันป้อนหมายเลขโดยตรงไปยังวิธีการตรวจสอบ (แทนที่จะวนซ้ำและตรวจสอบทุกหมายเลข)

หลักของการแก้ปัญหานี้อยู่ใน regex:

^(?=(.+)\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.+$)) ตรวจสอบให้แน่ใจว่าปัจจัยที่เลือกมีขนาดเล็กกว่าจำนวนที่ถูกตรวจสอบในการทำซ้ำครั้งแรกและมีขนาดเล็กกว่าปัจจัยก่อนหน้าในการทำซ้ำที่ตามมา

regex พยายามที่จะตรงกับหลายปัจจัยเป็นจำนวนเท่าที่จะสามารถอยู่ภายใต้วงเงินของ i2 แต่เราไม่สนใจมูลค่าที่แท้จริงของผลรวมของตัวหารเราแค่สนใจว่าจำนวนนั้นมีมากมาย

จากนั้น regex ที่ 2 ซึ่งเป็น regex แรกที่\1{2}$เพิ่มเข้ามา ดังนั้น regex ทำให้แน่ใจว่าผลรวมของ (บางส่วน) ของจำนวนที่จะตรวจสอบมีค่าเท่ากับจำนวนตัวเอง:

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

ข้อ จำกัด ที่เพิ่มเข้ามานั้นจะทำให้เอ็นจิน regex ทำการค้นหาย้อนรอยบนปัจจัยย่อยที่เป็นไปได้ทั้งหมดดังนั้นมันจะช้ามาก


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__

ข้อ จำกัด

  • ช้ากำลังดุร้าย
  • จำนวนตัวหารสำหรับจำนวนนั้นถูก จำกัด ที่ "bitness" ของจำนวนเต็มใน Perl
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.